LCOV - app.info - nsprpub/pr/src/io/prlog.c

LCOV - code coverage report
| Current view: | directory - nsprpub/pr/src/io - prlog.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 167 | 18 | 10.8 %
| Date: | 2012-04-07 | Functions: | 10 | 3 | 30.0 %

           1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 :
           3                 : /* ***** BEGIN LICENSE BLOCK *****
           4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           5                 :  *
           6                 :  * The contents of this file are subject to the Mozilla Public License Version
           7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           8                 :  * the License. You may obtain a copy of the License at
           9                 :  * http://www.mozilla.org/MPL/
          10                 :  *
          11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          13                 :  * for the specific language governing rights and limitations under the
          14                 :  * License.
          15                 :  *
          16                 :  * The Original Code is the Netscape Portable Runtime (NSPR).
          17                 :  *
          18                 :  * The Initial Developer of the Original Code is
          19                 :  * Netscape Communications Corporation.
          20                 :  * Portions created by the Initial Developer are Copyright (C) 1998-2000
          21                 :  * the Initial Developer. All Rights Reserved.
          22                 :  *
          23                 :  * Contributor(s):
          24                 :  *   IBM Corporation
          25                 :  *
          26                 :  * Alternatively, the contents of this file may be used under the terms of
          27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          30                 :  * of those above. If you wish to allow use of your version of this file only
          31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          32                 :  * use your version of this file under the terms of the MPL, indicate your
          33                 :  * decision by deleting the provisions above and replace them with the notice
          34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          35                 :  * the provisions above, a recipient may use your version of this file under
          36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          37                 :  *
          38                 :  * ***** END LICENSE BLOCK ***** */
          39                 :
          40                 : #include "primpl.h"
          41                 : #include "prenv.h"
          42                 : #include "prprf.h"
          43                 : #include <string.h>
          44                 : #ifdef ANDROID
          45                 : #include <android/log.h>
          46                 : #endif
          47                 :
          48                 : /*
          49                 :  * Lock used to lock the log.
          50                 :  *
          51                 :  * We can't define _PR_LOCK_LOG simply as PR_Lock because PR_Lock may
          52                 :  * contain assertions.  We have to avoid assertions in _PR_LOCK_LOG
          53                 :  * because PR_ASSERT calls PR_LogPrint, which in turn calls _PR_LOCK_LOG.
          54                 :  * This can lead to infinite recursion.
          55                 :  */
          56                 : static PRLock *_pr_logLock;
          57                 : #if defined(_PR_PTHREADS) || defined(_PR_BTHREADS)
          58                 : #define _PR_LOCK_LOG() PR_Lock(_pr_logLock);
          59                 : #define _PR_UNLOCK_LOG() PR_Unlock(_pr_logLock);
          60                 : #elif defined(_PR_GLOBAL_THREADS_ONLY)
          61                 : #define _PR_LOCK_LOG() { _PR_LOCK_LOCK(_pr_logLock)
          62                 : #define _PR_UNLOCK_LOG() _PR_LOCK_UNLOCK(_pr_logLock); }
          63                 : #else
          64                 :
          65                 : #define _PR_LOCK_LOG() \
          66                 : { \
          67                 :     PRIntn _is; \
          68                 :     PRThread *_me = _PR_MD_CURRENT_THREAD(); \
          69                 :     if (!_PR_IS_NATIVE_THREAD(_me)) \
          70                 :         _PR_INTSOFF(_is); \
          71                 :     _PR_LOCK_LOCK(_pr_logLock)
          72                 :
          73                 : #define _PR_UNLOCK_LOG() \
          74                 :     _PR_LOCK_UNLOCK(_pr_logLock); \
          75                 :     PR_ASSERT(_me == _PR_MD_CURRENT_THREAD()); \
          76                 :     if (!_PR_IS_NATIVE_THREAD(_me)) \
          77                 :         _PR_INTSON(_is); \
          78                 : }
          79                 :
          80                 : #endif
          81                 :
          82                 : #if defined(XP_PC)
          83                 : #define strcasecmp stricmp
          84                 : #endif
          85                 :
          86                 : /*
          87                 :  * On NT, we can't define _PUT_LOG as PR_Write or _PR_MD_WRITE,
          88                 :  * because every asynchronous file io operation leads to a fiber context
          89                 :  * switch.  So we define _PUT_LOG as fputs (from stdio.h).  A side
          90                 :  * benefit is that fputs handles the LF->CRLF translation.  This
          91                 :  * code can also be used on other platforms with file stream io.
          92                 :  */
          93                 : #if defined(WIN32) || defined(XP_OS2)
          94                 : #define _PR_USE_STDIO_FOR_LOGGING
          95                 : #endif
          96                 :
          97                 : /*
          98                 : ** Coerce Win32 log output to use OutputDebugString() when
          99                 : ** NSPR_LOG_FILE is set to "WinDebug".
         100                 : */
         101                 : #if defined(XP_PC)
         102                 : #define WIN32_DEBUG_FILE (FILE*)-2
         103                 : #endif
         104                 :
         105                 : #ifdef WINCE
         106                 : static void OutputDebugStringA(const char* msg) {
         107                 :     int len = MultiByteToWideChar(CP_ACP, 0, msg, -1, 0, 0);
         108                 :     WCHAR *wMsg = (WCHAR *)PR_Malloc(len * sizeof(WCHAR));
         109                 :     MultiByteToWideChar(CP_ACP, 0, msg, -1, wMsg, len);
         110                 :     OutputDebugStringW(wMsg);
         111                 :     PR_Free(wMsg);
         112                 : }
         113                 : #endif
         114                 :
         115                 : /* Macros used to reduce #ifdef pollution */
         116                 :
         117                 : #if defined(_PR_USE_STDIO_FOR_LOGGING) && defined(XP_PC)
         118                 : #define _PUT_LOG(fd, buf, nb) \
         119                 :     PR_BEGIN_MACRO \
         120                 :     if (logFile == WIN32_DEBUG_FILE) { \
         121                 :         char savebyte = buf[nb]; \
         122                 :         buf[nb] = '\0'; \
         123                 :         OutputDebugStringA(buf); \
         124                 :         buf[nb] = savebyte; \
         125                 :     } else { \
         126                 :         fwrite(buf, 1, nb, fd); \
         127                 :         fflush(fd); \
         128                 :     } \
         129                 :     PR_END_MACRO
         130                 : #elif defined(_PR_USE_STDIO_FOR_LOGGING)
         131                 : #define _PUT_LOG(fd, buf, nb) {fwrite(buf, 1, nb, fd); fflush(fd);}
         132                 : #elif defined(ANDROID)
         133                 : #define _PUT_LOG(fd, buf, nb)                                \
         134                 :     PR_BEGIN_MACRO                                           \
         135                 :     if (fd == _pr_stderr) {                                  \
         136                 :         char savebyte = buf[nb];                             \
         137                 :         buf[nb] = '\0';                                      \
         138                 :         __android_log_write(ANDROID_LOG_INFO, "PRLog", buf); \
         139                 :         buf[nb] = savebyte;                                  \
         140                 :     } else {                                                 \
         141                 :         PR_Write(fd, buf, nb);                               \
         142                 :     }                                                        \
         143                 :     PR_END_MACRO
         144                 : #elif defined(_PR_PTHREADS)
         145                 : #define _PUT_LOG(fd, buf, nb) PR_Write(fd, buf, nb)
         146                 : #else
         147                 : #define _PUT_LOG(fd, buf, nb) _PR_MD_WRITE(fd, buf, nb)
         148                 : #endif
         149                 :
         150                 : /************************************************************************/
         151                 :
         152                 : static PRLogModuleInfo *logModules;
         153                 :
         154                 : static char *logBuf = NULL;
         155                 : static char *logp;
         156                 : static char *logEndp;
         157                 : #ifdef _PR_USE_STDIO_FOR_LOGGING
         158                 : static FILE *logFile = NULL;
         159                 : #else
         160                 : static PRFileDesc *logFile = 0;
         161                 : #endif
         162                 : static PRBool outputTimeStamp = PR_FALSE;
         163                 : static PRBool appendToLog = PR_FALSE;
         164                 :
         165                 : #define LINE_BUF_SIZE           512
         166                 : #define DEFAULT_BUF_SIZE        16384
         167                 :
         168                 : #ifdef _PR_NEED_STRCASECMP
         169                 :
         170                 : /*
         171                 :  * strcasecmp is defined in /usr/ucblib/libucb.a on some platforms
         172                 :  * such as NCR and Unixware.  Linking with both libc and libucb
         173                 :  * may cause some problem, so I just provide our own implementation
         174                 :  * of strcasecmp here.
         175                 :  */
         176                 :
         177                 : static const unsigned char uc[] =
         178                 : {
         179                 :     '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
         180                 :     '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
         181                 :     '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
         182                 :     '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
         183                 :     ' ',    '!',    '"',    '#',    '$',    '%',    '&',    '\'',
         184                 :     '(',    ')',    '*',    '+',    ',',    '-',    '.',    '/',
         185                 :     '0',    '1',    '2',    '3',    '4',    '5',    '6',    '7',
         186                 :     '8',    '9',    ':',    ';',    '<',    '=',    '>',    '?',
         187                 :     '@',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
         188                 :     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
         189                 :     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
         190                 :     'X',    'Y',    'Z',    '[',    '\\',   ']',    '^',    '_',
         191                 :     '`',    'A',    'B',    'C',    'D',    'E',    'F',    'G',
         192                 :     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
         193                 :     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
         194                 :     'X',    'Y',    'Z',    '{',    '|',    '}',    '~',    '\177'
         195                 : };
         196                 :
         197                 : PRIntn strcasecmp(const char *a, const char *b)
         198                 : {
         199                 :     const unsigned char *ua = (const unsigned char *)a;
         200                 :     const unsigned char *ub = (const unsigned char *)b;
         201                 :
         202                 :     if( ((const char *)0 == a) || (const char *)0 == b )
         203                 :         return (PRIntn)(a-b);
         204                 :
         205                 :     while( (uc[*ua] == uc[*ub]) && ('\0' != *a) )
         206                 :     {
         207                 :         a++;
         208                 :         ua++;
         209                 :         ub++;
         210                 :     }
         211                 :
         212                 :     return (PRIntn)(uc[*ua] - uc[*ub]);
         213                 : }
         214                 :
         215                 : #endif /* _PR_NEED_STRCASECMP */
         216                 :
         217           18667 : void _PR_InitLog(void)
         218                 : {
         219                 :     char *ev;
         220                 :
         221           18667 :     _pr_logLock = PR_NewLock();
         222                 :
         223           18667 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
         224           18667 :     if (ev && ev[0]) {
         225                 :         char module[64];  /* Security-Critical: If you change this
         226                 :                            * size, you must also change the sscanf
         227                 :                            * format string to be size-1.
         228                 :                            */
         229               0 :         PRBool isSync = PR_FALSE;
         230               0 :         PRIntn evlen = strlen(ev), pos = 0;
         231               0 :         PRInt32 bufSize = DEFAULT_BUF_SIZE;
         232               0 :         while (pos < evlen) {
         233               0 :             PRIntn level = 1, count = 0, delta = 0;
         234               0 :             count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n",
         235                 :                            module, &delta, &level, &delta);
         236               0 :             pos += delta;
         237               0 :             if (count == 0) break;
         238                 :
         239                 :             /*
         240                 :             ** If count == 2, then we got module and level. If count
         241                 :             ** == 1, then level defaults to 1 (module enabled).
         242                 :             */
         243               0 :             if (strcasecmp(module, "sync") == 0) {
         244               0 :                 isSync = PR_TRUE;
         245               0 :             } else if (strcasecmp(module, "bufsize") == 0) {
         246               0 :                 if (level >= LINE_BUF_SIZE) {
         247               0 :                     bufSize = level;
         248                 :                 }
         249               0 :             } else if (strcasecmp(module, "timestamp") == 0) {
         250               0 :                 outputTimeStamp = PR_TRUE;
         251               0 :             } else if (strcasecmp(module, "append") == 0) {
         252               0 :                 appendToLog = PR_TRUE;
         253                 :             } else {
         254               0 :                 PRLogModuleInfo *lm = logModules;
         255               0 :                 PRBool skip_modcheck =
         256               0 :                     (0 == strcasecmp (module, "all")) ? PR_TRUE : PR_FALSE;
         257                 :
         258               0 :                 while (lm != NULL) {
         259               0 :                     if (skip_modcheck) lm -> level = (PRLogModuleLevel)level;
         260               0 :                     else if (strcasecmp(module, lm->name) == 0) {
         261               0 :                         lm->level = (PRLogModuleLevel)level;
         262               0 :                         break;
         263                 :                     }
         264               0 :                     lm = lm->next;
         265                 :                 }
         266                 :             }
         267                 :             /*found:*/
         268               0 :             count = sscanf(&ev[pos], " , %n", &delta);
         269               0 :             pos += delta;
         270               0 :             if (count == EOF) break;
         271                 :         }
         272               0 :         PR_SetLogBuffering(isSync ? 0 : bufSize);
         273                 :
         274                 : #ifdef XP_UNIX
         275               0 :         if ((getuid() != geteuid()) || (getgid() != getegid())) {
         276               0 :             return;
         277                 :         }
         278                 : #endif /* XP_UNIX */
         279                 :
         280               0 :         ev = PR_GetEnv("NSPR_LOG_FILE");
         281               0 :         if (ev && ev[0]) {
         282               0 :             if (!PR_SetLogFile(ev)) {
         283                 : #ifdef XP_PC
         284                 :                 char* str = PR_smprintf("Unable to create nspr log file '%s'\n", ev);
         285                 :                 if (str) {
         286                 :                     OutputDebugStringA(str);
         287                 :                     PR_smprintf_free(str);
         288                 :                 }
         289                 : #else
         290               0 :                 fprintf(stderr, "Unable to create nspr log file '%s'\n", ev);
         291                 : #endif
         292                 :             }
         293                 :         } else {
         294                 : #ifdef _PR_USE_STDIO_FOR_LOGGING
         295                 :             logFile = stderr;
         296                 : #else
         297               0 :             logFile = _pr_stderr;
         298                 : #endif
         299                 :         }
         300                 :     }
         301                 : }
         302                 :
         303               0 : void _PR_LogCleanup(void)
         304                 : {
         305               0 :     PRLogModuleInfo *lm = logModules;
         306                 :
         307               0 :     PR_LogFlush();
         308                 :
         309                 : #ifdef _PR_USE_STDIO_FOR_LOGGING
         310                 :     if (logFile
         311                 :         && logFile != stdout
         312                 :         && logFile != stderr
         313                 : #ifdef XP_PC
         314                 :         && logFile != WIN32_DEBUG_FILE
         315                 : #endif
         316                 :         ) {
         317                 :         fclose(logFile);
         318                 :     }
         319                 : #else
         320               0 :     if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
         321               0 :         PR_Close(logFile);
         322                 :     }
         323                 : #endif
         324               0 :     logFile = NULL;
         325                 :
         326               0 :     if (logBuf)
         327               0 :         PR_DELETE(logBuf);
         328                 :
         329               0 :     while (lm != NULL) {
         330               0 :         PRLogModuleInfo *next = lm->next;
         331               0 :         free((/*const*/ char *)lm->name);
         332               0 :         PR_Free(lm);
         333               0 :         lm = next;
         334                 :     }
         335               0 :     logModules = NULL;
         336                 :
         337               0 :     if (_pr_logLock) {
         338               0 :         PR_DestroyLock(_pr_logLock);
         339               0 :         _pr_logLock = NULL;
         340                 :     }
         341               0 : }
         342                 :
         343          205337 : static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
         344                 : {
         345                 :     char *ev;
         346                 :
         347          205337 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
         348          205337 :     if (ev && ev[0]) {
         349                 :         char module[64];  /* Security-Critical: If you change this
         350                 :                            * size, you must also change the sscanf
         351                 :                            * format string to be size-1.
         352                 :                            */
         353               0 :         PRIntn evlen = strlen(ev), pos = 0;
         354               0 :         while (pos < evlen) {
         355               0 :             PRIntn level = 1, count = 0, delta = 0;
         356                 :
         357               0 :             count = sscanf(&ev[pos], "%63[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-]%n:%d%n",
         358                 :                            module, &delta, &level, &delta);
         359               0 :             pos += delta;
         360               0 :             if (count == 0) break;
         361                 :
         362                 :             /*
         363                 :             ** If count == 2, then we got module and level. If count
         364                 :             ** == 1, then level defaults to 1 (module enabled).
         365                 :             */
         366               0 :             if (lm != NULL)
         367                 :             {
         368               0 :                 if ((strcasecmp(module, "all") == 0)
         369               0 :                     || (strcasecmp(module, lm->name) == 0))
         370                 :                 {
         371               0 :                     lm->level = (PRLogModuleLevel)level;
         372                 :                 }
         373                 :             }
         374               0 :             count = sscanf(&ev[pos], " , %n", &delta);
         375               0 :             pos += delta;
         376               0 :             if (count == EOF) break;
         377                 :         }
         378                 :     }
         379          205337 : } /* end _PR_SetLogModuleLevel() */
         380                 :
         381          205337 : PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name)
         382                 : {
         383                 :     PRLogModuleInfo *lm;
         384                 :
         385          205337 :         if (!_pr_initialized) _PR_ImplicitInitialization();
         386                 :
         387          205337 :     lm = PR_NEWZAP(PRLogModuleInfo);
         388          205337 :     if (lm) {
         389          205337 :         lm->name = strdup(name);
         390          205337 :         lm->level = PR_LOG_NONE;
         391          205337 :         lm->next = logModules;
         392          205337 :         logModules = lm;
         393          205337 :         _PR_SetLogModuleLevel(lm);
         394                 :     }
         395          205337 :     return lm;
         396                 : }
         397                 :
         398               0 : PR_IMPLEMENT(PRBool) PR_SetLogFile(const char *file)
         399                 : {
         400                 : #ifdef _PR_USE_STDIO_FOR_LOGGING
         401                 :     FILE *newLogFile;
         402                 :
         403                 : #ifdef XP_PC
         404                 :     if ( strcmp( file, "WinDebug") == 0)
         405                 :     {
         406                 :         newLogFile = WIN32_DEBUG_FILE;
         407                 :     }
         408                 :     else
         409                 : #endif
         410                 :     {
         411                 :         const char *mode = appendToLog ? "a" : "w";
         412                 :         newLogFile = fopen(file, mode);
         413                 :         if (!newLogFile)
         414                 :             return PR_FALSE;
         415                 :
         416                 : #ifndef WINCE  /* _IONBF does not exist in the Windows Mobile 6 SDK. */
         417                 :         /* We do buffering ourselves. */
         418                 :         setvbuf(newLogFile, NULL, _IONBF, 0);
         419                 : #endif
         420                 :     }
         421                 :     if (logFile
         422                 :         && logFile != stdout
         423                 :         && logFile != stderr
         424                 : #ifdef XP_PC
         425                 :         && logFile != WIN32_DEBUG_FILE
         426                 : #endif
         427                 :         ) {
         428                 :         fclose(logFile);
         429                 :     }
         430                 :     logFile = newLogFile;
         431                 :     return PR_TRUE;
         432                 : #else
         433                 :     PRFileDesc *newLogFile;
         434               0 :     PRIntn flags = PR_WRONLY|PR_CREATE_FILE;
         435               0 :     if (appendToLog) {
         436               0 :         flags |= PR_APPEND;
         437                 :     } else {
         438               0 :         flags |= PR_TRUNCATE;
         439                 :     }
         440                 :
         441               0 :     newLogFile = PR_Open(file, flags, 0666);
         442               0 :     if (newLogFile) {
         443               0 :         if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
         444               0 :             PR_Close(logFile);
         445                 :         }
         446               0 :         logFile = newLogFile;
         447                 :     }
         448               0 :     return (PRBool) (newLogFile != 0);
         449                 : #endif /* _PR_USE_STDIO_FOR_LOGGING */
         450                 : }
         451                 :
         452               0 : PR_IMPLEMENT(void) PR_SetLogBuffering(PRIntn buffer_size)
         453                 : {
         454               0 :     PR_LogFlush();
         455                 :
         456               0 :     if (logBuf)
         457               0 :         PR_DELETE(logBuf);
         458                 :
         459               0 :     if (buffer_size >= LINE_BUF_SIZE) {
         460               0 :         logp = logBuf = (char*) PR_MALLOC(buffer_size);
         461               0 :         logEndp = logp + buffer_size;
         462                 :     }
         463               0 : }
         464                 :
         465               0 : PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
         466                 : {
         467                 :     va_list ap;
         468                 :     char line[LINE_BUF_SIZE];
         469               0 :     char *line_long = NULL;
         470               0 :     PRUint32 nb_tid = 0, nb;
         471                 :     PRThread *me;
         472                 :     PRExplodedTime now;
         473                 :
         474               0 :     if (!_pr_initialized) _PR_ImplicitInitialization();
         475                 :
         476               0 :     if (!logFile) {
         477               0 :         return;
         478                 :     }
         479                 :
         480               0 :     if (outputTimeStamp) {
         481               0 :         PR_ExplodeTime(PR_Now(), PR_GMTParameters, &now);
         482               0 :         nb_tid = PR_snprintf(line, sizeof(line)-1,
         483                 :                              "%04d-%02d-%02d %02d:%02d:%02d.%06d UTC - ",
         484               0 :                              now.tm_year, now.tm_month + 1, now.tm_mday,
         485                 :                              now.tm_hour, now.tm_min, now.tm_sec,
         486                 :                              now.tm_usec);
         487                 :     }
         488                 :
         489               0 :     me = PR_GetCurrentThread();
         490               0 :     nb_tid += PR_snprintf(line+nb_tid, sizeof(line)-nb_tid-1, "%ld[%p]: ",
         491                 : #if defined(_PR_BTHREADS)
         492                 :                           me, me);
         493                 : #else
         494                 :                           me ? me->id : 0L, me);
         495                 : #endif
         496                 :
         497               0 :     va_start(ap, fmt);
         498               0 :     nb = nb_tid + PR_vsnprintf(line+nb_tid, sizeof(line)-nb_tid-1, fmt, ap);
         499               0 :     va_end(ap);
         500                 :
         501                 :     /*
         502                 :      * Check if we might have run out of buffer space (in case we have a
         503                 :      * long line), and malloc a buffer just this once.
         504                 :      */
         505               0 :     if (nb == sizeof(line)-2) {
         506               0 :         va_start(ap, fmt);
         507               0 :         line_long = PR_vsmprintf(fmt, ap);
         508               0 :         va_end(ap);
         509                 :         /* If this failed, we'll fall back to writing the truncated line. */
         510                 :     }
         511                 :
         512               0 :     if (line_long) {
         513               0 :         nb = strlen(line_long);
         514               0 :         _PR_LOCK_LOG();
         515               0 :         if (logBuf != 0) {
         516               0 :             _PUT_LOG(logFile, logBuf, logp - logBuf);
         517               0 :             logp = logBuf;
         518                 :         }
         519                 :         /*
         520                 :          * Write out the thread id (with an optional timestamp) and the
         521                 :          * malloc'ed buffer.
         522                 :          */
         523               0 :         _PUT_LOG(logFile, line, nb_tid);
         524               0 :         _PUT_LOG(logFile, line_long, nb);
         525                 :         /* Ensure there is a trailing newline. */
         526               0 :         if (!nb || (line_long[nb-1] != '\n')) {
         527                 :             char eol[2];
         528               0 :             eol[0] = '\n';
         529               0 :             eol[1] = '\0';
         530               0 :             _PUT_LOG(logFile, eol, 1);
         531                 :         }
         532               0 :         _PR_UNLOCK_LOG();
         533               0 :         PR_smprintf_free(line_long);
         534                 :     } else {
         535                 :         /* Ensure there is a trailing newline. */
         536               0 :         if (nb && (line[nb-1] != '\n')) {
         537               0 :             line[nb++] = '\n';
         538               0 :             line[nb] = '\0';
         539                 :         }
         540               0 :         _PR_LOCK_LOG();
         541               0 :         if (logBuf == 0) {
         542               0 :             _PUT_LOG(logFile, line, nb);
         543                 :         } else {
         544                 :             /* If nb can't fit into logBuf, write out logBuf first. */
         545               0 :             if (logp + nb > logEndp) {
         546               0 :                 _PUT_LOG(logFile, logBuf, logp - logBuf);
         547               0 :                 logp = logBuf;
         548                 :             }
         549                 :             /* nb is guaranteed to fit into logBuf. */
         550               0 :             memcpy(logp, line, nb);
         551               0 :             logp += nb;
         552                 :         }
         553               0 :         _PR_UNLOCK_LOG();
         554                 :     }
         555               0 :     PR_LogFlush();
         556                 : }
         557                 :
         558               0 : PR_IMPLEMENT(void) PR_LogFlush(void)
         559                 : {
         560               0 :     if (logBuf && logFile) {
         561               0 :         _PR_LOCK_LOG();
         562               0 :             if (logp > logBuf) {
         563               0 :                 _PUT_LOG(logFile, logBuf, logp - logBuf);
         564               0 :                 logp = logBuf;
         565                 :             }
         566               0 :         _PR_UNLOCK_LOG();
         567                 :     }
         568               0 : }
         569                 :
         570               0 : PR_IMPLEMENT(void) PR_Abort(void)
         571                 : {
         572               0 :     PR_LogPrint("Aborting");
         573               0 :     abort();
         574                 : }
         575                 :
         576               0 : PR_IMPLEMENT(void) PR_Assert(const char *s, const char *file, PRIntn ln)
         577                 : {
         578               0 :     PR_LogPrint("Assertion failure: %s, at %s:%d\n", s, file, ln);
         579               0 :     fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
         580               0 :     fflush(stderr);
         581                 : #ifdef WIN32
         582                 :     DebugBreak();
         583                 : #endif
         584                 : #ifdef XP_OS2
         585                 :     asm("int $3");
         586                 : #endif
         587               0 :     abort();
         588                 : }

Generated by: LCOV version 1.7