LCOV - code coverage report
Current view: directory - nsprpub/pr/src/io - prlog.c (source / functions) Found Hit Coverage
Test: app.info Lines: 167 43 25.7 %
Date: 2012-06-02 Functions: 10 6 60.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           20034 : void _PR_InitLog(void)
     218                 : {
     219                 :     char *ev;
     220                 : 
     221           20034 :     _pr_logLock = PR_NewLock();
     222                 : 
     223           20034 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
     224           20034 :     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             140 : void _PR_LogCleanup(void)
     304                 : {
     305             140 :     PRLogModuleInfo *lm = logModules;
     306                 : 
     307             140 :     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             140 :     if (logFile && logFile != _pr_stdout && logFile != _pr_stderr) {
     321               0 :         PR_Close(logFile);
     322                 :     }
     323                 : #endif
     324             140 :     logFile = NULL;
     325                 : 
     326             140 :     if (logBuf)
     327               0 :         PR_DELETE(logBuf);
     328                 : 
     329            1820 :     while (lm != NULL) {
     330            1540 :         PRLogModuleInfo *next = lm->next;
     331            1540 :         free((/*const*/ char *)lm->name);
     332            1540 :         PR_Free(lm);
     333            1540 :         lm = next;
     334                 :     }
     335             140 :     logModules = NULL;
     336                 : 
     337             140 :     if (_pr_logLock) {
     338             140 :         PR_DestroyLock(_pr_logLock);
     339             140 :         _pr_logLock = NULL;
     340                 :     }
     341             140 : }
     342                 : 
     343          306978 : static void _PR_SetLogModuleLevel( PRLogModuleInfo *lm )
     344                 : {
     345                 :     char *ev;
     346                 : 
     347          306978 :     ev = PR_GetEnv("NSPR_LOG_MODULES");
     348          306978 :     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          306978 : } /* end _PR_SetLogModuleLevel() */
     380                 : 
     381          306978 : PR_IMPLEMENT(PRLogModuleInfo*) PR_NewLogModule(const char *name)
     382                 : {
     383                 :     PRLogModuleInfo *lm;
     384                 : 
     385          306978 :         if (!_pr_initialized) _PR_ImplicitInitialization();
     386                 : 
     387          306978 :     lm = PR_NEWZAP(PRLogModuleInfo);
     388          306978 :     if (lm) {
     389          306978 :         lm->name = strdup(name);
     390          306978 :         lm->level = PR_LOG_NONE;
     391          306978 :         lm->next = logModules;
     392          306978 :         logModules = lm;
     393          306978 :         _PR_SetLogModuleLevel(lm);
     394                 :     }
     395          306978 :     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            6012 : PR_IMPLEMENT(void) PR_LogPrint(const char *fmt, ...)
     466                 : {
     467                 :     va_list ap;
     468                 :     char line[LINE_BUF_SIZE];
     469            6012 :     char *line_long = NULL;
     470            6012 :     PRUint32 nb_tid = 0, nb;
     471                 :     PRThread *me;
     472                 :     PRExplodedTime now;
     473                 : 
     474            6012 :     if (!_pr_initialized) _PR_ImplicitInitialization();
     475                 : 
     476            6012 :     if (!logFile) {
     477            6012 :         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            7715 : PR_IMPLEMENT(void) PR_LogFlush(void)
     559                 : {
     560            7715 :     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            7715 : }
     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