nsprpub/pr/src/io/prlog.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial