static void error(Pk11Install_Error errcode, ...) #endif { va_list ap; char *errstr; Pk11Install_ErrorHandler handler; if (!errorHandlerLock) { errorHandlerLock = PR_NewLock(); } PR_Lock(errorHandlerLock); handler = errorHandler; PR_Unlock(errorHandlerLock); if (handler) { #ifdef OSF1 va_start(ap); errstr = PR_vsmprintf(errorString[va_arg(ap, Pk11Install_Error)], ap); #else va_start(ap, errcode); errstr = PR_vsmprintf(errorString[errcode], ap); #endif handler(errstr); PR_smprintf_free(errstr); va_end(ap); } }
void Print(const char* aName, LogLevel aLevel, const char* aFmt, va_list aArgs) { const size_t kBuffSize = 1024; char buff[kBuffSize]; char* buffToWrite = buff; // For backwards compat we need to use the NSPR format string versions // of sprintf and friends and then hand off to printf. va_list argsCopy; va_copy(argsCopy, aArgs); size_t charsWritten = PR_vsnprintf(buff, kBuffSize, aFmt, argsCopy); va_end(argsCopy); if (charsWritten == kBuffSize - 1) { // We may have maxed out, allocate a buffer instead. buffToWrite = PR_vsmprintf(aFmt, aArgs); charsWritten = strlen(buffToWrite); } // Determine if a newline needs to be appended to the message. const char* newline = ""; if (charsWritten == 0 || buffToWrite[charsWritten - 1] != '\n') { newline = "\n"; } FILE* out = mOutFile ? mOutFile : stderr; // This differs from the NSPR format in that we do not output the // opaque system specific thread pointer (ie pthread_t) cast // to a long. The address of the current PR_Thread continues to be // prefixed. // // Additionally we prefix the output with the abbreviated log level // and the module name. if (!mAddTimestamp) { fprintf_stderr(out, "[%p]: %s/%s %s%s", PR_GetCurrentThread(), ToLogStr(aLevel), aName, buffToWrite, newline); } else { PRExplodedTime now; PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); fprintf_stderr( out, "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%p]: %s/%s %s%s", now.tm_year, now.tm_month + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec, PR_GetCurrentThread(), ToLogStr(aLevel), aName, buffToWrite, newline); } if (mIsSync) { fflush(out); } if (buffToWrite != buff) { PR_smprintf_free(buffToWrite); } }
void js_ReportErrorVA(JSContext *cx, const char *format, va_list ap) { JSStackFrame *fp; JSErrorReport report, *reportp; char *last; fp = cx->fp; if (fp && fp->script && fp->pc) { report.filename = fp->script->filename; report.lineno = js_PCToLineNumber(fp->script, fp->pc); /* XXX should fetch line somehow */ report.linebuf = NULL; report.tokenptr = NULL; reportp = &report; } else { reportp = NULL; } last = PR_vsmprintf(format, ap); if (!last) return; js_ReportErrorAgain(cx, last, reportp); free(last); }
void sbDeviceXMLInfo::LogIfFailed(nsresult aRV, const char * aPrintf, ...) { // Do nothing if no failure if (NS_SUCCEEDED(aRV)) { return; } // Check logging pref: if (!mLogDeviceInfo) { return; } // Resolve the args to a string va_list etc; va_start(etc, aPrintf); char *why = PR_vsmprintf(aPrintf ? aPrintf : "while loading device info", etc); va_end(etc); // Compose the error message nsString msg(NS_LITERAL_STRING("sbDeviceXMLInfo ")); msg.AppendLiteral( sbDeviceUtils::GetDeviceIdentifier(mDevice).BeginReading()); msg.AppendLiteral(":\nERROR [0x"); msg.AppendInt(aRV, 16); msg.AppendLiteral("]\n"); msg.Append(NS_ConvertUTF8toUTF16(why)); PR_smprintf_free(why); // Log the error message sbErrorConsole::Error("sbDeviceXMLInfo", msg); }
/** * Output a string to the user. This method is really only meant to be used to * output last-ditch error messages designed for developers NOT END USERS. * * @param isError * Pass true to indicate severe errors. * @param fmt * printf-style format string followed by arguments. */ static void Output(PRBool isError, const char *fmt, ... ) { va_list ap; va_start(ap, fmt); #if (defined(XP_WIN) && !MOZ_WINCONSOLE) || defined(WINCE) char *msg = PR_vsmprintf(fmt, ap); if (msg) { UINT flags = MB_OK; if (isError) flags |= MB_ICONERROR; else flags |= MB_ICONINFORMATION; wchar_t wide_msg[2048]; MultiByteToWideChar(CP_ACP, 0, msg, -1, wide_msg, sizeof(wide_msg) / sizeof(wchar_t)); MessageBoxW(NULL, wide_msg, L"XULRunner", flags); PR_smprintf_free(msg); } #else vfprintf(stderr, fmt, ap); #endif va_end(ap); }
void nsTSubstring_CharT::AppendPrintf( const char* format, ...) { char *buf; va_list ap; va_start(ap, format); buf = PR_vsmprintf(format, ap); AppendASCII(buf); PR_smprintf_free(buf); va_end(ap); }
void sbDeviceXMLInfo::LogArgs(const char * aFmt, va_list aArgs) { char *msg = PR_vsmprintf(aFmt, aArgs); sbErrorConsole::Message( "sbDeviceXMLInfo %s:\n%s", sbDeviceUtils::GetDeviceIdentifier(mDevice).BeginReading(), msg); PR_smprintf_free(msg); }
void log_print(const PRLogModuleInfo* aModule, LogLevel aLevel, const char* aFmt, ...) { va_list ap; va_start(ap, aFmt); char* buff = PR_vsmprintf(aFmt, ap); PR_LogPrint("%s", buff); PR_smprintf_free(buff); va_end(ap); }
// log a message to remote server with a user token id given // for the remote server to fill in with user token details. am_status_t Log::rlog(ModuleId module, int remote_log_level, const char *user_sso_token, const char *format, ...) throw() { am_status_t status = AM_SUCCESS; char *logMsg = NULL; std::string logMessage; bool cookieEncoded = false; if (rmtLogSvc == NULL || !remoteInitialized) { status = AM_SERVICE_NOT_INITIALIZED; } else { std::va_list args; va_start(args, format); logMsg = PR_vsmprintf(format, args); logMessage = logMsg; if (logMsg != NULL) { if (logMsg[0] == '\0') { Log::log(Log::ALL_MODULES, Log::LOG_WARNING, "Log Record Message is empty"); return status; } try { LogRecord logRecord( static_cast<LogRecord::Level>(remote_log_level), logMessage); std::string userSSOToken = user_sso_token; cookieEncoded = userSSOToken.find('%') != std::string::npos; if (cookieEncoded) { userSSOToken = Http::decode(std::string(user_sso_token)); } logRecord.populateTokenDetails(userSSOToken); status = rmtLogSvc->sendLog("", logRecord, ""); } catch (std::exception& exs) { status = AM_FAILURE; } catch (...) { status = AM_FAILURE; } PR_smprintf_free(logMsg); } va_end(args); } return status; }
/* * Log url access audit message. This calls doLocalAuditLog() * or doRemoteAuditLog() or both methods based on * log.disposition property value. */ am_status_t Log::auditLog(const char* auditDisposition, bool localAuditLogRotate, long localAuditFileSize, ModuleId module, int remoteLogLevel, const char *userSSOToken, const char *format, ...) { am_status_t status = AM_SUCCESS; char *logMsg = NULL; std::va_list args; va_start(args, format); logMsg = PR_vsmprintf(format, args); if(logMsg != NULL) { if ((strcasecmp(auditDisposition, AUDIT_DISPOSITION_REMOTE) == 0) || (strcasecmp(auditDisposition, AUDIT_DISPOSITION_ALL) == 0)) { status = doRemoteAuditLog(module, remoteLogLevel, userSSOToken, logMsg ); } if (status != AM_SUCCESS || (strcasecmp(auditDisposition, AUDIT_DISPOSITION_LOCAL) == 0) || (strcasecmp(auditDisposition, AUDIT_DISPOSITION_ALL) == 0)) { try { doLocalAuditLog(module, Log::LOG_INFO, logMsg, localAuditLogRotate, localAuditFileSize); } catch(...) { status = AM_FAILURE; } } PR_smprintf_free(logMsg); } if (status != AM_SUCCESS) { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::auditLog(): Both local and remote audit logging failed."); } return status; }
PR_IMPLEMENT(PRUint32) PR_vfprintf(PRFileDesc* fd, const char *fmt, va_list ap) { /* XXX this could be better */ PRUint32 rv, len; char* msg = PR_vsmprintf(fmt, ap); len = strlen(msg); #ifdef XP_OS2 /* * OS/2 really needs a \r for every \n. * In the future we should try to use scatter-gather instead of a * succession of PR_Write. */ if (isatty(PR_FileDesc2NativeHandle(fd))) { PRUint32 last = 0, idx; PRInt32 tmp; rv = 0; for (idx = 0; idx < len+1; idx++) { if ((idx - last > 0) && (('\n' == msg[idx]) || (idx == len))) { tmp = PR_Write(fd, msg + last, idx - last); if (tmp >= 0) { rv += tmp; } last = idx; } /* * if current character is \n, and * previous character isn't \r, and * next character isn't \r */ if (('\n' == msg[idx]) && ((0 == idx) || ('\r' != msg[idx-1])) && ('\r' != msg[idx+1])) { /* add extra \r */ tmp = PR_Write(fd, "\r", 1); if (tmp >= 0) { rv += tmp; } } } } else { rv = PR_Write(fd, msg, len); } #else rv = PR_Write(fd, msg, len); #endif PR_DELETE(msg); return rv; }
char * slapi_ch_smprintf(const char *fmt, ...) { char *p = NULL; va_list ap; if (NULL == fmt) { return NULL; } va_start(ap, fmt); p = PR_vsmprintf(fmt, ap); va_end(ap); return p; }
void nsChromeRegistry::LogMessage(const char* aMsg, ...) { nsCOMPtr<nsIConsoleService> console (do_GetService(NS_CONSOLESERVICE_CONTRACTID)); if (!console) return; va_list args; va_start(args, aMsg); char* formatted = PR_vsmprintf(aMsg, args); va_end(args); if (!formatted) return; console->LogStringMessage(NS_ConvertUTF8toUTF16(formatted).get()); PR_smprintf_free(formatted); }
/* This implementation is the same as PR_smprintf. The above comment does not apply to this function for now. see [150809] for more details. WARNING - with this fix, this means we are now mixing PR_Malloc with slapi_ch_free. Which is ok for now - they both use malloc/free from the operating system. But if this changes in the future, this function will have to change as well. */ char * slapi_ch_smprintf(const char *fmt, ...) { char *p = NULL, *q = NULL; va_list ap; if (NULL == fmt) { return NULL; } va_start(ap, fmt); p = PR_vsmprintf(fmt, ap); va_end(ap); q = slapi_ch_strdup (p); /* ugly ...; hope there's any better way */ free(p); return q; }
/** * Output a string to the user. This method is really only meant to be used to * output last-ditch error messages designed for developers NOT END USERS. * * @param isError * Pass true to indicate severe errors. * @param fmt * printf-style format string followed by arguments. */ static void Output(PRBool isError, const char *fmt, ... ) { va_list ap; va_start(ap, fmt); #if defined(XP_WIN) && !MOZ_WINCONSOLE char *msg = PR_vsmprintf(fmt, ap); if (msg) { UINT flags = MB_OK; if (isError) flags |= MB_ICONERROR; else flags |= MB_ICONINFORMATION; MessageBox(NULL, msg, "XULRunner", flags); PR_smprintf_free(msg); } #else vfprintf(stderr, fmt, ap); #endif va_end(ap); }
Result Context::createErrorResultv(const char *fmt, va_list args) { if (fmt == NULL) return Result::out_of_memory; char *s = PR_vsmprintf(fmt, args); if (s == NULL) return Result::out_of_memory; int len = strlen(s); char *p = (char *) pool_malloc(pool, len + 1); if (p == NULL) { PR_Free(s); return Result::out_of_memory; } memcpy(p, s, len); p[len] = '\0'; PR_Free(s); return Result(RESULT_ERROR, PR_FALSE, -1, pool, p, len); }
void nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, PRUint32 aLineNumber, PRUint32 flags, const char* aMsg, ...) { nsresult rv; nsCOMPtr<nsIConsoleService> console (do_GetService(NS_CONSOLESERVICE_CONTRACTID)); nsCOMPtr<nsIScriptError> error (do_CreateInstance(NS_SCRIPTERROR_CONTRACTID)); if (!console || !error) return; va_list args; va_start(args, aMsg); char* formatted = PR_vsmprintf(aMsg, args); va_end(args); if (!formatted) return; nsCString spec; if (aURL) aURL->GetSpec(spec); rv = error->Init(NS_ConvertUTF8toUTF16(formatted).get(), NS_ConvertUTF8toUTF16(spec).get(), nsnull, aLineNumber, 0, flags, "chrome registration"); PR_smprintf_free(formatted); if (NS_FAILED(rv)) return; console->LogMessage(error); }
/* * This function takes an error code and associated error data * and creates a string containing a textual description of * what the error is and why it happened. * * The returned string is allocated and thus should be freed * once it has been used. */ PUBLIC char * NET_ExplainErrorDetails (int code, ...) { va_list args; char *msg = 0; int sub_error; va_start (args, code); if (IS_SSL_ERROR(code) || IS_SEC_ERROR(code)) { const char *s = XP_GetString(code); msg = (s ? XP_STRDUP(s) : 0); } if (!msg) switch(code) { case MK_INTERRUPTED: case MK_USE_FTP_INSTEAD: case MK_USE_COPY_FROM_CACHE: case MK_MAILTO_NOT_READY: case MK_UNABLE_TO_LOGIN: case MK_UNABLE_TO_CONVERT: case MK_IMAGE_LOSSAGE: /* image library generic error */ case MK_ERROR_SENDING_DATA_COMMAND: case MK_OFFLINE: msg = NULL; break; case MK_REDIRECT_ATTEMPT_NOT_ALLOWED: case MK_SERVER_TIMEOUT: case MK_CONNECTION_TIMED_OUT: case MK_OUT_OF_MEMORY: case MK_TIMEBOMB_URL_PROHIBIT: case MK_TIMEBOMB_MESSAGE: case MK_RELATIVE_TIMEBOMB_MESSAGE: case MK_NO_WAIS_PROXY: case MK_CREATING_NEWSRC_FILE: case MK_NNTP_SERVER_NOT_CONFIGURED: case MK_NNTP_NEWSGROUP_SCAN_ERROR: case MK_ZERO_LENGTH_FILE: case MK_BAD_CONNECT: case MK_UNABLE_TO_USE_PASV_FTP: case MK_UNABLE_TO_CHANGE_FTP_MODE: case MK_UNABLE_TO_FTP_CWD: case MK_UNABLE_TO_SEND_PORT_COMMAND: case MK_UNABLE_TO_ACCEPT_SOCKET: case MK_UNABLE_TO_CONNECT2: case MK_BAD_NNTP_CONNECTION: case MK_NNTP_SERVER_ERROR: case MK_SERVER_DISCONNECTED: case MK_NEWS_ITEM_UNAVAILABLE: case MK_UNABLE_TO_OPEN_NEWSRC: case MK_COULD_NOT_LOGIN_TO_SMTP_SERVER: case MK_MSG_NO_SMTP_HOST: case MK_COULD_NOT_GET_USERS_MAIL_ADDRESS: case MK_UNABLE_TO_CONNECT_TO_PROXY: case MK_UNABLE_TO_LOCATE_PROXY: case MK_DISK_FULL: case MK_PRINT_LOSSAGE: case MK_SECURE_NEWS_PROXY_ERROR: case MK_SIGNATURE_TOO_LONG: case MK_SIGNATURE_TOO_WIDE: case MK_POP3_SERVER_ERROR: case MK_POP3_USERNAME_UNDEFINED: case MK_POP3_PASSWORD_UNDEFINED: case MK_POP3_USERNAME_FAILURE: case MK_POP3_PASSWORD_FAILURE: case MK_POP3_NO_MESSAGES: case MK_POP3_LIST_FAILURE: case MK_POP3_LAST_FAILURE: case MK_POP3_RETR_FAILURE: case MK_POP3_DELE_FAILURE: case MK_POP3_OUT_OF_DISK_SPACE: case MK_POP3_MESSAGE_WRITE_ERROR: case MK_MIME_NO_SENDER: case MK_MIME_NO_RECIPIENTS: case MK_MIME_NO_SUBJECT: case MK_MIME_ERROR_WRITING_FILE: case MK_MIME_MULTIPART_BLURB: case MK_MSG_CANT_COPY_TO_SAME_FOLDER: case MK_MSG_CANT_COPY_TO_QUEUE_FOLDER: case MK_MSG_CANT_COPY_TO_QUEUE_FOLDER_OLD: case MK_MSG_CANT_COPY_TO_DRAFTS_FOLDER: case MK_MSG_CANT_CREATE_FOLDER: case MK_MSG_FOLDER_ALREADY_EXISTS: case MK_MSG_FOLDER_NOT_EMPTY: case MK_MSG_CANT_DELETE_FOLDER: case MK_MSG_CANT_CREATE_INBOX: case MK_MSG_CANT_CREATE_MAIL_DIR: case MK_MSG_NO_POP_HOST: case MK_MSG_MESSAGE_CANCELLED: case MK_MSG_FOLDER_UNREADABLE: case MK_MSG_FOLDER_SUMMARY_UNREADABLE: case MK_MSG_TMP_FOLDER_UNWRITABLE: case MK_MSG_ID_NOT_IN_FOLDER: case MK_MSG_NEWSRC_UNPARSABLE: case MK_MSG_NO_RETURN_ADDRESS: case MK_MSG_ERROR_WRITING_NEWSRC: case MK_MSG_ERROR_WRITING_MAIL_FOLDER: case MK_MSG_SEARCH_FAILED: case MK_MSG_FOLDER_BUSY: msg = XP_STRDUP(XP_GetString(code)); break; case MK_TCP_READ_ERROR: case MK_TCP_WRITE_ERROR: case MK_UNABLE_TO_CREATE_SOCKET: case MK_UNABLE_TO_CONNECT: case MK_HTTP_TYPE_CONFLICT: case MK_TCP_ERROR: sub_error = va_arg(args, int); if (IS_SSL_ERROR(sub_error) || IS_SEC_ERROR(sub_error)) { /* * For SSL/SEC errors, use the message without a wrapper. */ msg = XP_STRDUP(XP_GetString(sub_error)); } else if (code == MK_UNABLE_TO_CONNECT && (sub_error == XP_ERRNO_EINVAL || sub_error == XP_ERRNO_EADDRINUSE)) { /* * With unable-to-connect errors, some errno values/strings * are not more helpful, so just use a plain message for these. */ msg = XP_STRDUP(XP_GetString(MK_UNABLE_TO_CONNECT2)); } else { msg = PR_smprintf(XP_GetString(code), XP_GetString(sub_error)); } break; case MK_MALFORMED_URL_ERROR: case MK_COULD_NOT_PUT_FILE: case MK_UNABLE_TO_LOCATE_FILE: case MK_NNTP_AUTH_FAILED: case MK_UNABLE_TO_LOCATE_HOST: case MK_UNABLE_TO_LOCATE_SOCKS_HOST: case MK_UNABLE_TO_OPEN_FILE: case MK_UNABLE_TO_OPEN_TMP_FILE: case MK_CONNECTION_REFUSED: case MK_NNTP_ERROR_MESSAGE: case MK_MSG_COULDNT_OPEN_FCC_FILE: case MK_TIMEBOMB_WARNING_MESSAGE: case MK_RELATIVE_TIMEBOMB_WARNING_MESSAGE: case MK_ERROR_SENDING_FROM_COMMAND: case MK_ERROR_SENDING_RCPT_COMMAND: case MK_ERROR_SENDING_MESSAGE: case MK_SMTP_SERVER_ERROR: msg = PR_vsmprintf(XP_GetString(code), args); break; case -1: default: msg = PR_smprintf(XP_GetString(MK_COMMUNICATIONS_ERROR), code); break; } va_end (args); TRACEMSG(("NET_ExplainErrorDetails generated: %s", msg ? msg : "(none)")); return(msg); }
PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...) { va_list ap; char line[LINE_BUF_SIZE]; char *line_long = NULL; PRUint32 nb_tid = 0, nb; PRThread *me; PRExplodedTime now; if (!_pr_initialized) _PR_ImplicitInitialization(); if (!logFile) { return; } if (outputTimeStamp) { PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); nb_tid = PR_snprintf(line, sizeof(line)-1, "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ", now.tm_year, now.tm_month, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec); } me = PR_GetCurrentThread(); nb_tid += PR_snprintf(line+nb_tid, sizeof(line)-nb_tid-1, "%ld[%p]: ", #if defined(_PR_BTHREADS) me, me); #else me ? me->id : 0L, me); #endif va_start(ap, fmt); nb = nb_tid + PR_vsnprintf(line+nb_tid, sizeof(line)-nb_tid-1, fmt, ap); va_end(ap); /* * Check if we might have run out of buffer space (in case we have a * long line), and malloc a buffer just this once. */ if (nb == sizeof(line)-2) { va_start(ap, fmt); line_long = PR_vsmprintf(fmt, ap); va_end(ap); /* If this failed, we'll fall back to writing the truncated line. */ } if (line_long) { nb = strlen(line_long); _PR_LOCK_LOG(); if (logBuf != 0) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* * Write out the thread id (with an optional timestamp) and the * malloc'ed buffer. */ _PUT_LOG(logFile, line, nb_tid); _PUT_LOG(logFile, line_long, nb); /* Ensure there is a trailing newline. */ if (!nb || (line_long[nb-1] != '\n')) { char eol[2]; eol[0] = '\n'; eol[1] = '\0'; _PUT_LOG(logFile, eol, 1); } _PR_UNLOCK_LOG(); PR_smprintf_free(line_long); } else { /* Ensure there is a trailing newline. */ if (nb && (line[nb-1] != '\n')) { line[nb++] = '\n'; line[nb] = '\0'; } _PR_LOCK_LOG(); if (logBuf == 0) { _PUT_LOG(logFile, line, nb); } else { /* If nb can't fit into logBuf, write out logBuf first. */ if (logp + nb > logEndp) { _PUT_LOG(logFile, logBuf, logp - logBuf); logp = logBuf; } /* nb is guaranteed to fit into logBuf. */ memcpy(logp, line, nb); logp += nb; } _PR_UNLOCK_LOG(); } PR_LogFlush(); }
void Print(const char* aName, LogLevel aLevel, const char* aFmt, va_list aArgs) { const size_t kBuffSize = 1024; char buff[kBuffSize]; char* buffToWrite = buff; // For backwards compat we need to use the NSPR format string versions // of sprintf and friends and then hand off to printf. va_list argsCopy; va_copy(argsCopy, aArgs); size_t charsWritten = PR_vsnprintf(buff, kBuffSize, aFmt, argsCopy); va_end(argsCopy); if (charsWritten == kBuffSize - 1) { // We may have maxed out, allocate a buffer instead. buffToWrite = PR_vsmprintf(aFmt, aArgs); charsWritten = strlen(buffToWrite); } // Determine if a newline needs to be appended to the message. const char* newline = ""; if (charsWritten == 0 || buffToWrite[charsWritten - 1] != '\n') { newline = "\n"; } FILE* out = stderr; // In case we use rotate, this ensures the FILE is kept alive during // its use. Increased before we load mOutFile. ++mPrintEntryCount; detail::LogFile* outFile = mOutFile; if (outFile) { out = outFile->File(); } // This differs from the NSPR format in that we do not output the // opaque system specific thread pointer (ie pthread_t) cast // to a long. The address of the current PR_Thread continues to be // prefixed. // // Additionally we prefix the output with the abbreviated log level // and the module name. PRThread *currentThread = PR_GetCurrentThread(); const char *currentThreadName = (mMainThread == currentThread) ? "Main Thread" : PR_GetThreadName(currentThread); char noNameThread[40]; if (!currentThreadName) { SprintfLiteral(noNameThread, "Unnamed thread %p", currentThread); currentThreadName = noNameThread; } if (!mAddTimestamp) { fprintf_stderr(out, "[%s]: %s/%s %s%s", currentThreadName, ToLogStr(aLevel), aName, buffToWrite, newline); } else { PRExplodedTime now; PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now); fprintf_stderr( out, "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - [%s]: %s/%s %s%s", now.tm_year, now.tm_month + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec, currentThreadName, ToLogStr(aLevel), aName, buffToWrite, newline); } if (mIsSync) { fflush(out); } if (buffToWrite != buff) { PR_smprintf_free(buffToWrite); } if (mRotate > 0 && outFile) { int32_t fileSize = ftell(out); if (fileSize > mRotate) { uint32_t fileNum = outFile->Num(); uint32_t nextFileNum = fileNum + 1; if (nextFileNum >= kRotateFilesNumber) { nextFileNum = 0; } // And here is the trick. The current out-file remembers its order // number. When no other thread shifted the global file number yet, // we are the thread to open the next file. if (mOutFileNum.compareExchange(fileNum, nextFileNum)) { // We can work with mToReleaseFile because we are sure the // mPrintEntryCount can't drop to zero now - the condition // to actually delete what's stored in that member. // And also, no other thread can enter this piece of code // because mOutFile is still holding the current file with // the non-shifted number. The compareExchange() above is // a no-op for other threads. outFile->mNextToRelease = mToReleaseFile; mToReleaseFile = outFile; mOutFile = OpenFile(false, nextFileNum); } } } if (--mPrintEntryCount == 0 && mToReleaseFile) { // We were the last Print() entered, if there is a file to release // do it now. exchange() is atomic and makes sure we release the file // only once on one thread. detail::LogFile* release = mToReleaseFile.exchange(nullptr); delete release; } }
// this should not throw exception since it is called often in a // catch block to log an error resulting from an exception. void Log::vlog(ModuleId module, Level level, const char *format, std::va_list args) throw() { if (initialized) { if (module >= moduleList->size()) { module = ALL_MODULES; } char *logMsg = PR_vsmprintf(format, args); // call user defined logger if any. if (loggerFunc != NULL) { loggerFunc((*moduleList)[module].name.c_str(), static_cast<am_log_level_t>(static_cast<int>(level)), logMsg); } // do default log. if ((*moduleList)[module].level >= level) { // format: // year-month-day hour:min:sec.usec level pid:thread module: msg // get level string std::size_t levelLabelIndex = getLevelString(level); char levelStr[50]; PRUint32 llen; if (levelLabelIndex < numLabels) { llen = PR_snprintf(levelStr, sizeof(levelStr), "%s", levelLabels[levelLabelIndex]); } else { llen = PR_snprintf(levelStr, sizeof(levelStr), "%d", level); } if (llen > 0) { // get time. PRExplodedTime now; PR_ExplodeTime(PR_Now(), PR_LocalTimeParameters, &now); // format header and msg. PRUint32 len; char hdr[100]; len = PR_snprintf(hdr, sizeof(hdr), "%d-%02d-%02d %02d:%02d:%02d.%03d" "%8s %u:%p %s: %%s\n", now.tm_year, now.tm_month+1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, now.tm_usec / 1000, levelStr, getpid(), PR_GetCurrentThread(), (*moduleList)[module].name.c_str()); if (len > 0) { if (logRotation) { if ((currentLogFileSize + 1000) < maxLogFileSize) { std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } else { ScopeLock scopeLock(*lockPtr); currentLogFileSize = ftell(logFile); if ((currentLogFileSize + 1000) > maxLogFileSize) { // Open a new log file if (!pSetLogFile(logFileName)) { log(ALL_MODULES, LOG_ERROR, "Unable to open log file: '%s', errno = %d", logFileName.c_str(), errno); } } std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } currentLogFileSize = ftell(logFile); } else { std::fprintf(logFile, hdr, logMsg); std::fflush(logFile); } } } } // Remote Logging starts here. if (module == remoteModule) { if (remoteInitialized) { bool doLogRemotely = ((*moduleList)[module].level >= Log::LOG_AUTH_REMOTE) && ((*moduleList)[module].level & level); if (doLogRemotely) { am_status_t status; status = rmtLogSvc->logMessage(logMsg); if(status != AM_SUCCESS) { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::vlog(): Error logging message [%s] " "to remote server. Error: %s.", logMsg, am_status_to_string(status)); } } } else { Log::log(Log::ALL_MODULES, Log::LOG_ERROR, "Log::vlog(): Remote logging service not initialized. " "Cannot log message to remote server."); } } PR_smprintf_free(logMsg); } return; }