bool OpenDebugLog(const char *path) { PLOG(PL_INFO,"ProtoDebug>OpenDebugLog: debug log is being set to \"%s\"\n",path); #ifdef OPNET // JPH 4/26/06 if ('\0' == *path) return false; #endif // OPNET CloseDebugLog(); FILE* ptr = fopen(path, "w+"); if (ptr) { #if defined(WIN32) && !defined(SIMULATE) FILE* debugLog = DebugLog(); if ((0 != DebugLevel()) && ((debugLog == stdout) || (debugLog == stderr))) CloseDebugWindow(); #endif // WIN32 && !SIMULATE DebugLog(true, ptr); return true; } else { #if defined(WIN32) && !defined(SIMULATE) FILE* debugLog = DebugLog(); if ((0 != DebugLevel()) && (debugLog != stdout) && (debugLog != stderr)) OpenDebugWindow(); #endif // WIN32 && !SIMULATE DebugLog(true, stderr); PLOG(PL_ERROR, "OpenDebugLog: Error opening debug log file: %s\n", path); return false; } } // end OpenLogFile()
/** * @brief Display string if statement's debug level is large enough */ void DMSG(unsigned int level, const char *format, ...) { if (level <= DebugLevel()) { FILE* debugLog = DebugLog(); va_list args; va_start(args, format); #ifdef _WIN32_WCE if (debug_window.IsOpen() && ((stderr == debugLog) || (stdout == debugLog))) { char charBuffer[2048]; charBuffer[2048] = '\0'; int count = _vsnprintf(charBuffer, 2047, format, args); #ifdef _UNICODE wchar_t wideBuffer[2048]; count = mbstowcs(wideBuffer, charBuffer, count); count *= sizeof(wchar_t); const char* theBuffer = (char*)wideBuffer; #else const char* theBuffer = charBuffer; #endif // if/else _UNICODE debug_window.Print(theBuffer, count); } else #endif // _WIN32_WCE { vfprintf(debugLog, format, args); fflush(debugLog); } va_end(args); } } // end DMSG();
void SetDebugLevel(unsigned int level) { unsigned int debugLevel = DebugLevel(); #if defined(WIN32) && !defined(SIMULATE) FILE* debugLog = DebugLog(); if (0 != level) { if (!debugLevel && ((stderr == debugLog) || (stdout == debugLog))) OpenDebugWindow(); } else { if (debugLevel && ((stderr == debugLog) || (debugLog == stdout))) CloseDebugWindow(); } #endif // WIN32 DebugLevel(true, level); // this sets the underlying static "debug_level" state variable if (level != debugLevel) PLOG(PL_INFO,"ProtoDebug>SetDebugLevel: debug level changed from %d to %d\n", debugLevel, level); } // end SetDebugLevel()
void CloseDebugLog() { FILE* debugLog = DebugLog(); if (debugLog && (debugLog != stderr) && (debugLog != stdout)) { fclose(debugLog); #if defined(WIN32) && !defined(SIMULATE) if (0 != DebugLevel()) OpenDebugWindow(); #endif // WIN32 && !SIMULATE } #ifndef SIMULATE if (debug_pipe.IsOpen()) debug_pipe.Close(); #endif // !SIMULATE DebugLog(true, stderr); } // end CloseDebugLog()
unsigned int GetDebugLevel() { return DebugLevel(); }
/** * @brief Provides a basic logging facility for Protlib that uses the typical logging levels * to allow different levels for logging and run-time debugging of protolib applications. */ void PLOG(ProtoDebugLevel level, const char *format, ...) { if (((unsigned int)level <= DebugLevel()) || (PL_ALWAYS == level)) { va_list args; va_start(args, format); const char * header = ""; switch(level) { // Print out the Logging Type before the message case PL_FATAL: header = "Proto Fatal: "; break; case PL_ERROR: header = "Proto Error: "; break; case PL_WARN: header = "Proto Warn: "; break; case PL_INFO: header = "Proto Info: "; break; case PL_DEBUG: header = "Proto Debug: "; break; case PL_TRACE: header = "Proto Trace: "; break; case PL_DETAIL: header = "Proto Detail: "; break; case PL_MAX: header = "Proto Max: "; break; default: break; } size_t headerLen = strlen(header); FILE* debugLog = DebugLog(); #ifdef _WIN32_WCE if (debug_window.IsOpen() && !debug_pipe.IsOpen() && ((stderr == debugLog) || (stdout == debugLog))) { char charBuffer[8192]; charBuffer[8192] = '\0'; int count = _vsnprintf(charBuffer, 8191, format, args); #ifdef _UNICODE wchar_t wideBuffer[8192]; count = mbstowcs(wideBuffer, charBuffer, count); count *= sizeof(wchar_t); const char* theBuffer = (char*)wideBuffer; #else const char* theBuffer = charBuffer; #endif // if/else _UNICODE debug_window.Print(theBuffer, count); } else #endif // _WIN32_WCE #ifndef SIMULATE if (debug_pipe.IsOpen()) #else if (false)//always fails for simulation #endif // if/else n SIMULATE { char buffer[8192]; buffer[8191] = '\0'; #ifdef _WIN32_WCE unsigned int count = (unsigned int)_vsnprintf(buffer, 8191, format, args) + 1; #else #ifdef WIN32 strcpy(buffer, header); unsigned int count = (unsigned int)_vsnprintf(buffer + headerLen, 8191-headerLen, format, args) + 1; count += (unsigned int)headerLen; #else strcpy(buffer, header); unsigned int count = (unsigned int)vsnprintf(buffer + headerLen, 8191-headerLen, format, args) + 1; count += headerLen; #endif #endif // if/else _WIN32_WCE if (count > 8192) count = 8192; #ifndef SIMULATE if (!debug_pipe.Send(buffer, count)) #else if (true) #endif //if/else n SIMULATE { // We have no recourse but to go to stderr here fprintf(stderr, "PLOG() error: unable to send to debug pipe!!!\n"); vfprintf(stderr, format, args); fflush(stderr); } } else { #ifdef __ANDROID__ android_LogPriority prio; switch(level) { case PL_FATAL: prio = ANDROID_LOG_FATAL; break; case PL_ERROR: prio = ANDROID_LOG_ERROR; break; case PL_WARN: prio = ANDROID_LOG_WARN; break; case PL_INFO: prio = ANDROID_LOG_INFO; break; case PL_DEBUG: prio = ANDROID_LOG_DEBUG; break; case PL_TRACE: prio = ANDROID_LOG_VERBOSE; case PL_DETAIL: /* explicit fallthrough */ case PL_MAX: /* explicit fallthrough */ case PL_ALWAYS: /* explicit fallthrough */ default: prio = ANDROID_LOG_DEFAULT; break; } __android_log_vprint(prio, "protolib", format, args); #else fprintf(debugLog, "%s", header); vfprintf(debugLog, format, args); fflush(debugLog); #endif } va_end(args); } } // End PLOG
void DebugPreflight(const char *logname, bool redirect, int level, int perms) { // If we've preflighted already, just return if (gPreflighted) return; _DebugEnter(); if (!gOutputFILE) gOutputFILE = stderr; if (!gOutputFileNo) gOutputFileNo = STDERR_FILENO; // Ignore logfile directives on iOS -- we always go to stderr #if !TARGET_OS_IPHONE if (logname && *logname) { char buffer[PATH_MAX*2+1] = {0}; // Determine where the log file will go if (*logname != '/') { const char * home = getenv("HOME"); if (! geteuid()) strcpy(buffer, "/var/log/"); else if (home) { #if __APPLE__ snprintf(buffer, sizeof(buffer), "%s/Library/Logs/", home); #else snprintf(buffer, sizeof(buffer), "%s/log/", home); #endif // __APPLE__ mkdir(buffer, 0700); } } strncat(buffer, logname, sizeof(buffer)-strlen(buffer)-1); if (! strstr(logname, ".log") && ! strstr(logname, ".txt")) strncat(buffer, ".log", sizeof(buffer)-strlen(buffer)-1); // Close the previous file if (gOutputFILE && (gOutputFILE != stderr)) fclose(gOutputFILE); if ((strlen(buffer) <= PATH_MAX) && (gOutputFILE = fopen(buffer, "a"))) { // Open a new file and use it's file descriptor for our logging setvbuf(gOutputFILE, NULL, _IOLBF, 0); gOutputFileNo = fileno(gOutputFILE); fchmod(gOutputFileNo, (perms) ? perms : 0600); } else { // Default back to stderr gOutputFILE = stderr; gOutputFileNo = STDERR_FILENO; } } #endif // !TARGET_OS_IPHONE if (!gPreflighted) { time_t now; char stamp[26] = ""; char name[PATH_MAX] = ""; char vers[32] = ""; CFStringRef cfstr = NULL; // Print a pretty header time(&now); ctime_r(&now, stamp); strtok(stamp, "\n"); fprintf(gOutputFILE, "--- Log opened %s ---\n", stamp); #if TARGET_OS_MAC || TARGET_OS_IPHONE if ((cfstr = (CFStringRef) CFBundleGetValueForInfoDictionaryKey( CFBundleGetMainBundle(), CFSTR("CFBundleName")))) CFStringGetCString(cfstr, name, sizeof(name), kCFStringEncodingUTF8); if ((cfstr = (CFStringRef) CFBundleGetValueForInfoDictionaryKey( CFBundleGetMainBundle(), CFSTR("CFBundleVersion")))) CFStringGetCString(cfstr, vers, sizeof(vers), kCFStringEncodingUTF8); if (*name) fprintf(gOutputFILE, "--- %s %s ---\n", name, vers); #endif // TARGET_OS_MAC || TARGET_OS_IPHONE #if TARGET_OS_MAC && !TARGET_CPU_ARM && !TARGET_CPU_ARM64 else { // Handle non-bundle processes (daemons, command-line tools) proc_name(getpid(), name, (uint32_t) sizeof(name)); if (*name) #if defined(VERSION) fprintf(gOutputFILE, "--- %s %s ---\n", name, VERSION); #else fprintf(gOutputFILE, "--- %s ---\n", name); #endif // VERSION } #endif // TARGET_OS_MAC && !TARGET_CPU_ARM && !TARGET_CPU_ARM64 // Ensure this has been preflighted as well if (gDebugLevel == 1) SetDebugLevel(level); else DebugLevel(); gPreflighted = true; } CLEANUP: _DebugLeave(); }