Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: nspr/pr/src/io/prlog.c

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

Powered by Google App Engine
This is Rietveld 408576698