/************************************************************************/ /* SISCO SOFTWARE MODULE HEADER *****************************************/ /************************************************************************/ /* (c) Copyright Systems Integration Specialists Company, Inc., */ /* 1993-2008, All Rights Reserved */ /* */ /* MODULE NAME : slog.c */ /* PRODUCT(S) : SLOG */ /* */ /* MODULE DESCRIPTION : */ /* */ /* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */ /* */ /* MODIFICATION LOG : */ /* Date Who Rev Comments */ /* -------- --- ------ ------------------------------------------- */ /* 03/27/08 EJV 61 Use S_MAX_PATH instead of MAX_PATH. */ /* slog_get_index_file_name: added destLen param*/ /* and changed to return result. */ /* 02/06/08 EJV 60 Moved MAX_PATH define to sysincs.h */ /* _slogSetTimeTextElapsed _WIN32 only. */ /* 12/14/07 DSF 59 Added sNonStandardLogMode to support .NET */ /* Logger class */ /* 11/16/07 MDE 58 Fixed LINUX compile problems */ /* 10/23/07 MDE 57 Added ElapsedTime option for Windows */ /* 01/15/07 EJV 56 Chg S_LOCK_RESOURCES to S_LOCK_UTIL_RESOURCES*/ /* 01/08/07 EJV 55 slogIpcStop: added lc param. */ /* 09/13/06 DSF 54 No calls to ExceptionReport */ /* 08/18/06 JRB 53 Chk _slog_remote_fun along with other ptrs. */ /* 08/02/06 EJV 52 Corr: chg logMissed to ST_INT to avoid */ /* repeated logging when IPC_LOG_EN is set. */ /* 06/20/06 RLH 51 Added parameter checks and other robustness */ /* features to _slogXML */ /* 03/14/06 CRM 50 Added _slogXML to log XML strings */ /* 02/13/06 DSF 49 Migrate to VS.NET 2005 */ /* 01/23/06 EJV 48 doSlog: clarified buf overrun log for WIN32. */ /* 11/01/05 EJV 47 slog_end: added S_LOCK_RESOURCES. */ /* 10/31/05 MDE 46 Tweaked slog_end to stop IPC, disable */ /* 10/31/05 MDE 45 Default logging now disabled, log missed */ /* 10/21/05 MDE 44 Fixed slog_end path size */ /* 08/10/05 MDE 43 Added slog_start, slog_end */ /* 08/02/05 MDE 42 Fixed compile warning */ /* 05/23/05 EJV 40 doSlog corr: replaced LOG_IPC_EN with */ /* LOG_IPC_LISTEN_EN || LOG_IPC_CALL_EN */ /* Moved sock_debug_sel to gensock2.c */ /* Moved gs_debug_sel to glbsem.c */ /* 04/21/05 EJV 39 doSlog: use vsnprintf on Linux; */ /* Reworked the code assembling log in msg_buf.*/ /* 02/23/05 JRB 38 slogSetTimeText: fix for VXWORKS. */ /* 01/26/05 JRB 37 Move clnp_debug_sel to lean_var.c */ /* 01/24/05 MDE 36 Fixed tweak */ /* 01/20/05 MDE 35 Minor tweak for fileName & logtype checks */ /* 11/22/04 JRB 34 Add & use slog_max_msg_size_set funct. */ /* Ignore sl_max_msg_size if chged after first log.*/ /* Del static slog_buf, use new lc->msg_buf. */ /* slogDelBuf: add (LOG_CTRL *) arg. */ /* 08/04/04 EJV 33 Del slogTime, slogMs global variables. */ /* 07/09/04 EJV 32 All systems: one time/date format in slog hdr*/ /* 06/24/04 DSF 31 For Windows, log milliseconds */ /* 05/18/04 MDE 30 Removed LOG_IPC_SUPPORT #ifdef's */ /* 05/13/04 EJV 29 Added slogSetHdr, slogHdr. */ /* 03/11/04 GLB 28 Remove "thisFileName" */ /* 02/10/04 KCR 27 Added slogDelBuf() */ /* 01/12/04 EJV 26 Moved sock_debug_sel from gensock2.c */ /* 10/24/03 JRB 25 Move gs_debug_sel from glbsem.c to here. */ /* Move clnp_debug_sel to here. */ /* 10/13/03 EJV 24 Del MSOS2 (old), _WINDOWS. */ /* 05/07/03 DSF 23 Added support for sErrLogCtrl */ /* 03/28/02 EJV 22 vnsprintf: use it on Tru64 UNIX v5.0 and up */ /* 02/11/02 DSF 21 Call ExpRaiseDebugException () to log the */ /* call stack */ /* 10/18/01 JRB 20 Fix sprintf calls. */ /* 09/28/01 EJV 19 Added vnsprintf for systems that support it. */ /* 05/18/00 JRB 18 More Lint cleanup. */ /* 04/19/00 JRB 17 Lint cleanup. */ /* 09/24/99 JRB 16 added: #include "sysincs.h" */ /* 09/13/99 MDE 15 Added SD_CONST modifiers */ /* 07/15/99 RKR 14 16-bit version needs stdarg.h */ /* 04/14/99 MDE 13 Removed unnecessary include files */ /* 11/11/98 DSF 12 Minor changes to _slog_dyn_log_fun */ /* 10/08/98 MDE 11 Migrated to updated SLOG interface */ /* 08/25/98 IKE 10 Prevent buffer overrun by vsprintf for some */ /* platforms */ /* 08/13/98 MDE 09 Now log buffer overruns */ /* 06/15/98 MDE 08 Changes to allow compile under C++ */ /* 06/02/98 DSF 07 LOG_TIME_EN on by default */ /* 01/09/98 EJV 06 SUN Solaris 2.5 uses now ANSI vsprintf */ /* 11/05/97 DSF 05 Added SYSTIME_EN */ /* 10/06/97 DSF 04 Added thisFileName */ /* 09/12/97 DSF 03 Expose slogSetTimeText () */ /* 08/19/97 DSF 02 Initialize sLogCtrlDefault to default */ /* settings */ /* 05/27/97 DSF 01 Added IPC logging capability */ /* 04/02/97 DTL 7.00 MMSEASE 7.0 release. See MODL70.DOC for */ /* history. */ /************************************************************************/ #if defined(__OS2__) #pragma data_seg(alldata) #define INCL_BASE #define INCL_DOS #define INCL_DOSMISC #define INCL_ERRORS #define INCL_DOSPROCESS #define INCL_DOSQUEUES #define INCL_DOSSEMAPHORES #define INCL_DOSMEMMGR #define INCL_DOSFILEMGR #define INCL_DOSDATETIME #define INCL_DOSDEVICES #include #include #endif #include "glbtypes.h" #include "sysincs.h" #include "glbsem.h" #include "slog.h" #include "stime.h" #include "str_util.h" #include "sx_defs.h" #if defined (_WIN32) #include #endif #define XML_NO_TAG 0 #define XML_DOCUMENT 1 #define XML_COMMENT 2 #define XML_START 3 #define XML_END 4 #define XML_EMPTY 5 ST_CHAR *_slogXMLLogTypeStr = "SLOGXML"; /************************************************************************/ /* Other prototypes. */ /************************************************************************/ static ST_VOID doSlog (LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_CHAR *SD_CONST format, va_list ap); ST_VOID slogSetTimeText (LOG_CTRL *lc); #if defined (_WIN32) static ST_VOID _slogSetTimeTextElapsed (LOG_CTRL *lc); #endif /************************************************************************/ /* Global variables used by the SLOG library. */ /************************************************************************/ LOG_CTRL *sErrLogCtrl = NULL; LOG_CTRL sLogCtrlDefault = {LOG_TIME_EN, {1000000, "mms.log", FIL_CTRL_WIPE_EN | FIL_CTRL_WRAP_EN | FIL_CTRL_MSG_HDR_EN, 0, 0, NULL}}; LOG_CTRL *sLogCtrl = &sLogCtrlDefault; ST_CHAR slogTimeText[TIME_BUF_LEN]; ST_INT sl_max_msg_size = MAX_LOG_SIZE; ST_UINT32 slogRemoteFlags; ST_BOOLEAN sNonStandardLogMode = SD_FALSE; ST_VOID (*slog_service_fun) (ST_VOID); ST_CHAR *_slogAlwaysLogTypeStr = "SLOGALWAYS"; /* dynamic logging function */ ST_VOID (*slog_dyn_log_fun) (LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); ST_VOID (*_slog_dyn_log_fun) (LOG_CTRL *lc, SD_CONST ST_CHAR *timeStr, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); /* remote logging function */ /* Assign to this fun pointer a function which handles the logging to */ /* remote log file. For the slog_remote_flags parameter reference the */ /* description for slog_remote_fun function. */ ST_VOID (*slog_remote_fun) (ST_UINT32 slog_remote_flags, LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); ST_VOID (*_slog_remote_fun) (ST_UINT32 slog_remote_flags, LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_INT bufLen, SD_CONST ST_CHAR *buf); /************************************************************************/ /* _slog */ /* Main general message logging function, typically called via macro */ /* Just print the message to be logged, pass to memory & file logging */ /* functions if enabled */ /************************************************************************/ ST_VOID _slogc (LOG_CTRL *lc, SD_CONST ST_CHAR *format, ...) { va_list ap; va_start (ap, format); doSlog (lc, SLOG_CONT, NULL, NULL, 0, format, ap); va_end(ap); } ST_VOID _slog (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_CHAR *format, ...) { va_list ap; va_start (ap, format); doSlog (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, format, ap); va_end(ap); } /************************************************************************/ /* slog */ /************************************************************************/ ST_VOID slog (LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_CHAR *format, ...) { va_list ap; va_start (ap, format); doSlog (lc, logType, NULL, sourceFile, lineNum, format, ap); va_end(ap); } /************************************************************************/ /* slogx */ /* Extended message logging function. */ /* Same as slog, except one more argument to determine if this type of */ /* logging is enabled. This function allows one macro to be used */ /* for any number of arguments. */ /* This function is designed so that the first 5 arguments are passed */ /* to this function via macro. For example: */ /* #define SLOG_ACSE_IND s_debug_sel & ACSE_IND_PRINT, s_sLogCtrl,\ */ /* ACSE_IND_PRINT_TYPE,THISFILE,__LINE__ */ /* slogx (SLOG_ACSE_IND, "Indication PDU ptr=" S_FMT_PTR ", len=%d", ptr, len); */ /************************************************************************/ ST_VOID slogx (ST_UINT32 doit, LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_CHAR *format, ...) { va_list ap; /* Make sure "doit" flag is set. */ if (!doit) return; va_start (ap, format); doSlog (lc, logType, NULL, sourceFile, lineNum, format, ap); va_end(ap); } /************************************************************************/ /* doSlog */ /* Main logging function, called from slog or slogx. */ /* Just print the message to be logged, pass to memory & file logging */ /* functions if enabled */ /************************************************************************/ #define SLOG_MISSED_LOG_MSG "Warning: SLOG Log messages missed" static ST_VOID doSlog (LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, SD_CONST ST_CHAR *SD_CONST format, va_list ap) { ST_INT count; ST_CHAR tmpBuf[128]; static ST_INT logMissed = 0; static ST_CHAR *missedSourceFile; static ST_INT missedLineNum; S_GS_INIT (); S_LOCK_UTIL_RESOURCES (); /* Make sure the LOG_CTRL pointer is not NULL */ if (!lc) { S_UNLOCK_UTIL_RESOURCES (); return; } /* Check to see if any logging is enabled AND dynamic user logging */ /* function pointer not set */ if (!(lc->logCtrl & (LOG_FILE_EN | LOG_MEM_EN | LOG_IPC_EN)) && !slog_dyn_log_fun && !_slog_dyn_log_fun && !slog_remote_fun && !_slog_remote_fun) { if (logMissed == 0) { logMissed = 1; missedSourceFile = sourceFile; missedLineNum = lineNum; } S_UNLOCK_UTIL_RESOURCES (); return; } /* Allocate a slog_buffer the first time this function is called. This */ /* allows us to make the size of the slog message buffer larger than */ /* the default. */ if (lc->msg_buf == NULL) { /* NOTE: this code only for backward compatibility with apps that */ /* control buffer size by setting the global var "sl_max_msg_size". */ /* New apps should call "slog_max_msg_size_set" directly. */ /* Use value of sl_max_msg_size NOW. Don't care if user changes it later.*/ if (slog_max_msg_size_set (lc, sl_max_msg_size) != SD_SUCCESS) { fprintf(stderr, "\nslog: error setting max msg size"); S_UNLOCK_UTIL_RESOURCES (); return; } } /* It is OK to pass in a NULL format string when using the dynamic */ /* logging functions - no vsprintf if so */ if (format == NULL) { /* make buf a zero length string just in case */ count = 0; lc->msg_buf[0] = 0; } else { #if defined(_WIN32) count = _vsnprintf(lc->msg_buf,lc->max_msg_size,format,ap); #elif defined(__QNX__) && defined(__WATCOMC__) count = _vbprintf(lc->msg_buf,lc->max_msg_size,format,ap); #elif defined(_AIX) || defined(sun) || defined(_hpux) || defined(__alpha) || defined(linux) count = vsnprintf(lc->msg_buf,lc->max_msg_size,format,ap); #else /* other systems: VXWORKS, ... */ count = vsprintf (lc->msg_buf, format, ap); #endif lc->msg_buf[lc->max_msg_size-1] = 0; /* terminate the buffer, Win and UNIX */ /* functions don't behave the same */ /* NOTE: On _WIN32 count could be negative because of error or too small buffer. */ /* On other systems count is negative because of error, too small buffer is */ /* indicated by return of count larger than buf_size supplied to the function.*/ #if defined(_WIN32) if (count < 0) { sprintf (tmpBuf,"*** LOG ERROR: LOG BUFFER OVERRUN (lc->max_msg_size=%d bytes) or _vsnprintf function error", lc->max_msg_size); strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); count = strlen (lc->msg_buf); /* count = len of this log message */ } #else /* !defined(_WIN32) */ if (count < 0) { sprintf (tmpBuf,"*** LOG ERROR: _vbprintf(QNX), vsnprintf(UNIX,LINUX), or vsprintf(other sys) function failed"); strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); count = strlen (lc->msg_buf); /* count = len of this log message */ } else if (count >= lc->max_msg_size) { sprintf (tmpBuf,"*** LOG ERROR: LOG BUFFER OVERRUN: message len=%d bytes (lc->max_msg_size=%d bytes)", count, lc->max_msg_size); strncpy_safe (lc->msg_buf, tmpBuf, lc->max_msg_size-1); count = strlen (lc->msg_buf); /* set count to len of this log message */ } #endif /* !defined(_WIN32) */ count++; /* allow for null terminator */ } /* If time stamping is desired, get the time string from the user */ if (lc->logCtrl & LOG_TIME_EN) slogSetTimeText (lc); else slogTimeText[0] = 0; /* Init to empty time/date string. */ /* Check for type for special logging ('continuation' or dynamic */ /* logging format commands) - */ /* All standard log types are >= 0 */ /* Continuation logging is SLOG_CONT (-1) */ /* Dynamic logging format commands are other negative numbers, */ /* reserved are - */ /* SLOG_DYN_PAUSE = -10 */ /* SLOG_DYN_LF = -11 */ /* SLOG_DYN_CLRSCR = -12 */ if (logType >=0 || logType == SLOG_CONT) { if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ { if (logMissed == 1) { logMissed = 2; /* to prevent logging this msg again */ /* when slogIpc turns off all masks */ slogFile (lc, 0, "INTERNAL_SLOG", missedSourceFile, missedLineNum, strlen (SLOG_MISSED_LOG_MSG), SLOG_MISSED_LOG_MSG); } slogFile (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); } if (lc->logCtrl & LOG_MEM_EN) /* File Logging enabled */ slogMem (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); } if ((lc->logCtrl & LOG_IPC_LISTEN_EN) || (lc->logCtrl & LOG_IPC_CALL_EN)) /* IPC Logging enabled (listen, calling, or both modes) */ slogIpc (lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); /* If the user has set up a dynamic log display function, call it */ if (slog_dyn_log_fun) (*slog_dyn_log_fun)(lc, logType, sourceFile, lineNum, count, lc->msg_buf); if (_slog_dyn_log_fun) (*_slog_dyn_log_fun)(lc, slogTimeText, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); /* If the user has set up a remote logging function, call it */ if (slog_remote_fun) { (*slog_remote_fun)(slogRemoteFlags, lc, logType, sourceFile, lineNum, count, lc->msg_buf); } if (_slog_remote_fun) { (*_slog_remote_fun)(slogRemoteFlags, lc, logType, logTypeStr, sourceFile, lineNum, count, lc->msg_buf); } S_UNLOCK_UTIL_RESOURCES (); } /************************************************************************/ /* slogSetTimeText */ /* Set the time string per the lc control information */ /************************************************************************/ ST_VOID slogSetTimeText (LOG_CTRL *lc) { slogTimeText[0] = 0; /* Init to empty. */ if (lc->logCtrl & LOG_TIME_EN) { #if defined (_WIN32) SYSTEMTIME systime; if ((lc->logCtrl & LOG_ELAPSEDTIME_EN) == 0) { GetLocalTime (&systime); sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d.%03d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds); } else _slogSetTimeTextElapsed (lc); #elif defined (VXWORKS) /* Does not support gettimeofday. */ time_t curTime; struct tm *locTime; curTime = time (NULL); locTime = localtime (&curTime); sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d", locTime->tm_year+1900, locTime->tm_mon+1, locTime->tm_mday, locTime->tm_hour, locTime->tm_min, locTime->tm_sec); #else /* UNIX, Linux, QNX,... */ struct timeval tp; time_t curTime; struct tm *locTime; gettimeofday (&tp, NULL); curTime = (time_t) tp.tv_sec; locTime = localtime (&curTime); sprintf (slogTimeText, "%04d-%02d-%02d %02d:%02d:%02d.%03ld", locTime->tm_year+1900, locTime->tm_mon+1, locTime->tm_mday, locTime->tm_hour, locTime->tm_min, locTime->tm_sec, tp.tv_usec/1000); #endif /* UNIX, Linux, QNX,... */ } } /************************************************************************/ #if defined (_WIN32) static ST_VOID _slogSetTimeTextElapsed (LOG_CTRL *lc) { static ST_BOOLEAN firstTime = SD_TRUE; static LARGE_INTEGER ticksPerSec; static LARGE_INTEGER startTicks; static double dTicksPerSec; LARGE_INTEGER ticks; double dDeltaTicks; double dSec; if (firstTime == SD_TRUE) { /* See if supported, and if so how many ticks per second */ if (QueryPerformanceFrequency(&ticksPerSec)) { /* Mark the start of time for us */ QueryPerformanceCounter (&startTicks); /* We want to work with double precision floating point */ dTicksPerSec = (double) ticksPerSec.QuadPart; } else { strncpy_safe (slogTimeText, "Elapsed Time Not Available", sizeof (slogTimeText) - 1); return; } firstTime = SD_FALSE; } /* Get the current tick count */ QueryPerformanceCounter (&ticks); /* Get delta from start of logging */ dDeltaTicks = (double) (ticks.QuadPart - startTicks.QuadPart); /* Calculate the elapsed time */ dSec = dDeltaTicks/dTicksPerSec; sprintf (slogTimeText, "%.6f", dSec); } #endif /* defined (_WIN32) */ /************************************************************************/ /* slogTrimFileName */ /************************************************************************/ ST_VOID slogTrimFileName (ST_CHAR *dest, SD_CONST ST_CHAR *fullName) { ST_INT i,s; ST_CHAR c; s = 0; i = 0; while ((c = fullName[i])) { if (c == '\\' || c == '/' || c == ':' || c == ']' ) s = i+1; /* remember the last path seperator character position */ i++; } strncpy (dest,&fullName[s], SLOG_MAX_FNAME); dest[SLOG_MAX_FNAME] = 0; } /************************************************************************/ /* slogSetHdr */ /* Set the header string per the lc control information. */ /* The slogHdr needs to be SLOG_MAX_HDR+1 bytes long (in worst case). */ /************************************************************************/ ST_VOID slogSetHdr (LOG_CTRL *lc, SD_CONST ST_INT logType, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, ST_CHAR *slogHdr, ST_CHAR *lineBreak) { ST_CHAR fname[SLOG_MAX_FNAME+1]; ST_CHAR tmp[SLOG_MAX_FNAME+14+1]; /* 14 for line nubmer & () */ sprintf (slogHdr, lineBreak); if ((lc->fc.ctrl & FIL_CTRL_MSG_HDR_EN) && (logType != SLOG_CONT)) { if (!(lc->logCtrl & LOG_NO_HEADER_CR)) strcat (slogHdr, lineBreak); if (lc->logCtrl & LOG_TIME_EN) /* user wants time stamp */ { strcat (slogHdr, slogTimeText); strcat (slogHdr, " "); } if (!(lc->logCtrl & LOG_LOGTYPE_SUPPRESS)) { if (logTypeStr != NULL && logTypeStr[0] != 0) { strncat (slogHdr, logTypeStr, min (strlen(logTypeStr), SLOG_MAX_LOGTYPESTR)); strcat (slogHdr, " "); } else { sprintf (tmp, "LogType:% 2d ", logType); strcat (slogHdr, tmp); } } if ((sourceFile != NULL && sourceFile[0] != 0) && !(lc->logCtrl & LOG_FILENAME_SUPPRESS)) { slogTrimFileName (fname, sourceFile); sprintf (tmp, "(%s %d) ", fname, lineNum); strcat (slogHdr, tmp); } if (!(lc->logCtrl & LOG_NO_HEADER_CR)) { strcat (slogHdr, lineBreak); strcat (slogHdr," "); } } if (logType == SLOG_CONT) strcat (slogHdr," "); } /************************************************************************/ /* dumpCallingStack */ /************************************************************************/ #if defined(MSDOS) && !defined(_WINDOWS) ST_VOID main (ST_VOID); #endif ST_VOID slogCallStack (LOG_CTRL *lc, SD_CONST ST_CHAR *txt) { #if !defined(CODAN) #if defined(MSDOS) && !defined(TC) static ST_UINT32 ptr_to_abs (ST_VOID *ptr); ST_UINT16 os,sg; ST_UINT16 os2,sg2; ST_UINT16 os3,sg3; ST_UINT16 os4,sg4; ST_UINT16 os5,sg5; #endif /* For DOS we can save the caller's return address */ #if defined(MSDOS) && !defined(TC) _asm { push si ; save SI mov si, bp ; first BP frame mov ax, ss:[si+2] ; get return address "offset" from stack mov os, ax ; store in "offset" variable mov ax, ss:[si+4] ; get return address "segment" from stack mov sg, ax ; store in "segment" variable mov si, ss:[si] ; second BP frame mov ax, ss:[si+2] ; get return address "offset" from stack mov os2, ax ; store in "offset" variable mov ax, ss:[si+4] ; get return address "segment" from stack mov sg2, ax ; store in "segment" variable mov si, ss:[si] ; third BP frame mov ax, ss:[si+2] ; get return address "offset" from stack mov os3, ax ; store in "offset" variable mov ax, ss:[si+4] ; get return address "segment" from stack mov sg3, ax ; store in "segment" variable mov si, ss:[si] ; fourth BP frame mov ax, ss:[si+2] ; get return address "offset" from stack mov os4, ax ; store in "offset" variable mov ax, ss:[si+4] ; get return address "segment" from stack mov sg4, ax ; store in "segment" variable mov si, ss:[si] ; fifth BP frame mov ax, ss:[si+2] ; get return address "offset" from stack mov os5, ax ; store in "offset" variable mov ax, ss:[si+4] ; get return address "segment" from stack mov sg5, ax ; store in "segment" variable pop si ; restore SI } #endif #endif if (txt != NULL) slog(lc, 0, NULL, 0, "%s", txt); #if defined(MSDOS) && !defined(TC) slog(lc,SLOG_CONT,NULL,0,"Calling Address (1st frame): 0x%04X:%04X (0x%lX)", sg,os,((ST_UINT32)sg << 4) + (ST_UINT32)os); slog(lc,SLOG_CONT,NULL,0,"Calling Address (2nd frame): 0x%04X:%04X (0x%lX)", sg2,os2,((ST_UINT32)sg2 << 4) + (ST_UINT32)os2); slog(lc,SLOG_CONT,NULL,0,"Calling Address (3rd frame): 0x%04X:%04X (0x%lX)", sg3,os3,((ST_UINT32)sg3 << 4) + (ST_UINT32)os3); slog(lc,SLOG_CONT,NULL,0,"Calling Address (4th frame): 0x%04X:%04X (0x%lX)", sg4,os4,((ST_UINT32)sg4 << 4) + (ST_UINT32)os4); slog(lc,SLOG_CONT,NULL,0,"Calling Address (5th frame): 0x%04X:%04X (0x%lX)", sg5,os5,((ST_UINT32)sg5 << 4) + (ST_UINT32)os5); slog(lc,SLOG_CONT,NULL,0,"Main Address : %08lx (0x%lX)", main,ptr_to_abs ((ST_VOID *)main)); #endif #if !defined(CODAN) #endif } /************************************************************************/ /* ptr_to_abs (ptr) */ /* Convert buffer address to long real address */ /************************************************************************/ #if defined(MSDOS) && !defined(TC) static ST_UINT32 ptr_to_abs (ST_VOID *ptr) { ST_UINT32 temp1; ST_UINT32 temp2; temp1 = (ST_UINT32) ptr; temp2 = temp1 >> 12; /* Microsoft/Xenix use seg/off */ temp1 &= 0xFFFF; temp2 &= 0xFFFF0; return (temp1 + temp2); /* find real address */ } #endif /************************************************************************/ /* slog */ /************************************************************************/ ST_VOID slogDelBuf (LOG_CTRL *lc) { S_LOCK_UTIL_RESOURCES (); if (lc->msg_buf) free (lc->msg_buf); lc->msg_buf = NULL; S_UNLOCK_UTIL_RESOURCES (); } /************************************************************************/ /* slog_max_msg_size_set */ /* Set the maximum message size and allocate a buffer of this size. */ /* This function sets "max_msg_size" and "msg_buf" in LOG_CTRL. */ /************************************************************************/ ST_RET slog_max_msg_size_set (LOG_CTRL *lc, ST_INT max_msg_size) { ST_RET retcode = SD_SUCCESS; S_LOCK_UTIL_RESOURCES (); lc->max_msg_size = max_msg_size; /* save size in LOG_CTRL */ if (lc->msg_buf != NULL) free (lc->msg_buf); /* buf already allocated by previous call, so free it first*/ /* Alloc "lc->msg_buf". chk_malloc calls slog so use malloc here! */ /* This is the only place "lc->msg_buf" is allocated. */ lc->msg_buf = (ST_CHAR *) malloc (lc->max_msg_size + 1); if (lc->msg_buf == NULL) { /* this should almost never happen */ lc->max_msg_size = 0; /* no buffer so can't log anything */ retcode = SD_FAILURE; } S_UNLOCK_UTIL_RESOURCES (); return (retcode); } /************************************************************************/ /* slog_start */ /************************************************************************/ ST_RET slog_start (LOG_CTRL *lc, ST_INT max_msg_size) { ST_RET rc; rc = slog_max_msg_size_set (lc, max_msg_size); rc = slogIpcInit (lc); return (rc); } /************************************************************************/ /* slog_end */ /************************************************************************/ ST_RET slog_end (LOG_CTRL *lc) { ST_CHAR idxFileName[S_MAX_PATH]; FILE *fh; ST_RET rc; slogIpcStop (lc); rc = slog_get_index_file_name (lc, idxFileName, sizeof(idxFileName)); S_LOCK_UTIL_RESOURCES (); if (rc == SD_SUCCESS) { fh = fopen (idxFileName,"w+"); if (fh) { fprintf (fh,"%ld", lc->fc.wipeFilePos); fclose (fh); rc = SD_SUCCESS; } else rc = SD_FAILURE; } /* No more file or IPC logging after end ... */ lc->logCtrl &= ~(LOG_FILE_EN | LOG_IPC_EN); S_UNLOCK_UTIL_RESOURCES (); return (rc); } /************************************************************************/ /* _slogXML */ /* Formats XML strings and logs them if file logging is enabled. */ /************************************************************************/ ST_VOID _slogXML (LOG_CTRL *lc, SD_CONST ST_CHAR *SD_CONST logTypeStr, SD_CONST ST_CHAR *SD_CONST sourceFile, SD_CONST ST_INT lineNum, ST_UINT numBytes, SD_CONST ST_CHAR *textData) { ST_UINT filCtrlSave; ST_UINT tabLevel = 0; ST_UINT index, i, j; ST_CHAR xmlBuffer[SX_MAX_ELEM_LEN+1]; ST_INT eleLength[SX_MAX_XML_NEST]; ST_INT prevTag; ST_INT tag = XML_NO_TAG; S_GS_INIT (); S_LOCK_UTIL_RESOURCES (); /* Make sure the LOG_CTRL and textData pointers are not NULL */ if ((!lc) || (!textData)) { S_UNLOCK_UTIL_RESOURCES (); return; } /* Check to see if any logging is enabled AND dynamic user logging */ /* function pointer not set */ if (!(lc->logCtrl & LOG_FILE_EN) && !slog_dyn_log_fun && !_slog_dyn_log_fun && !slog_remote_fun && !_slog_remote_fun) { S_UNLOCK_UTIL_RESOURCES (); return; } /* Remember the state of the wipe/wrap/header enable flags */ /* so that we can restore them later */ filCtrlSave = lc->fc.ctrl & (FIL_CTRL_WIPE_EN | FIL_CTRL_WRAP_EN | FIL_CTRL_MSG_HDR_EN); if (!numBytes) { lc->fc.ctrl |= (filCtrlSave & FIL_CTRL_WIPE_EN); } if (lc->logCtrl & LOG_FILE_EN) /* File Logging enabled */ { for (i=0; i= SX_MAX_XML_NEST) /* Log error if maximum nesting level is exceeded */ { slogFile (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, 0, "XML nesting exceeds maximum level"); break; } if (eleLength[tabLevel] >= SX_MAX_ELEM_LEN) /* Log error if maximum element length is exceeded */ { slogFile (lc, SLOG_NORMAL, logTypeStr, sourceFile, lineNum, 0, "XML element exceeds maximum length"); break; } eleLength[tabLevel]++; /* Skip control characters */ /* cast the chars as ST_UCHAR so data > 0x7F will not look negative */ if (iscntrl((ST_UCHAR) textData[i]) || (textData[i] == ' ' && index == 0)) { index = 0; continue; } /* Determine tag value */ if (textData[i] == '/' && textData[i+1] == '>') tag = XML_EMPTY; if (textData[i] == '<') { prevTag = tag; if (textData[i] == '<' && textData[i+1] == '?') tag = XML_DOCUMENT; else if (textData[i] == '<' && textData[i+1] == '!') tag = XML_COMMENT; else if (textData[i] == '<' && textData[i+1] == '/') tag = XML_END; else if(textData[i] == '<') tag = XML_START; /* Increment/decrement tabLevel */ if (prevTag == XML_START && (tag == XML_START || tag == XML_COMMENT)) tabLevel++; else if (tag == XML_END && (prevTag == XML_END || prevTag == XML_EMPTY)) tabLevel--; /* Format tab level */ if (index == 0) { xmlBuffer[0] = '\0'; if (tabLevel) { for (j=0; j' && ( textData[i+1] == '<' || textData[i+1] == ' ' || iscntrl ((ST_UCHAR) textData[i+1]) || i == numBytes-1 || tag != XML_START)) { slogFile (lc, SLOG_CONT, logTypeStr, sourceFile, lineNum, strlen(xmlBuffer), xmlBuffer); index = 0; /* If the user has set up a dynamic log display function, call it */ if (slog_dyn_log_fun) { (*slog_dyn_log_fun)(lc, SLOG_CONT, NULL, 0, strlen(xmlBuffer), xmlBuffer); } if (_slog_dyn_log_fun) { (*_slog_dyn_log_fun)(lc, slogTimeText, SLOG_CONT, NULL, NULL, 0, strlen(xmlBuffer), xmlBuffer); } /* If the user has set up a remote logging function, call it */ if (slog_remote_fun) { (*slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, 0, strlen(xmlBuffer), xmlBuffer); } if (_slog_remote_fun) { (*_slog_remote_fun)(slogRemoteFlags, lc, SLOG_CONT, NULL, NULL, 0, strlen(xmlBuffer), xmlBuffer); } } } } /* All done, restore the flag state bits */ lc->fc.ctrl |= filCtrlSave; S_UNLOCK_UTIL_RESOURCES (); }