3 * @brief Mbedthis Portable Runtime (MPR) Logging and error reporting.
4 * @remarks We always provide these routines.
7 /*********************************** License **********************************/
11 * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved.
13 * This software is distributed under commercial and open source licenses.
14 * You may use the GPL open source license described below or you may acquire
15 * a commercial license from Mbedthis Software. You agree to be fully bound
16 * by the terms of either license. Consult the LICENSE.TXT distributed with
17 * this software for full details.
19 * This software is open source; you can redistribute it and/or modify it
20 * under the terms of the GNU General Public License as published by the
21 * Free Software Foundation; either version 2 of the License, or (at your
22 * option) any later version. See the GNU General Public License for more
23 * details at: http://www.mbedthis.com/downloads/gplLicense.html
25 * This program is distributed WITHOUT ANY WARRANTY; without even the
26 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
28 * This GPL license does NOT permit incorporating this software into
29 * proprietary programs. If you are unable to comply with the GPL, you must
30 * acquire a commercial license to use this software. Commercial licenses
31 * for this software and support services are available from Mbedthis
32 * Software at http://www.mbedthis.com
39 /****************************** Forward Declarations **************************/
41 static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags,
42 int level, const char *msg);
43 static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level,
46 /************************************ Code ************************************/
48 void mprLog(MprCtx ctx, int level, const char *fmt, ...)
53 if (level > mprGetLogLevel(ctx)) {
58 mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
61 logOutput(MPR_LOC_ARGS(ctx), MPR_LOG_SRC, level, buf);
67 /*****************************************************************************/
72 void mprRawLog(MprCtx ctx, const char *fmt, ...)
79 len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
82 logOutput(MPR_LOC_ARGS(ctx), MPR_RAW, 0, buf);
86 /*****************************************************************************/
91 void mprError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
98 len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
101 logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf);
106 /*****************************************************************************/
108 * Handle an error that should be displayed to the user
111 void mprUserError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
118 len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
121 logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_ERROR_SRC, 0, buf);
126 /*****************************************************************************/
128 * Handle a fatal error. Forcibly shutdown the application.
131 void mprFatalError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
138 len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args);
141 logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_FATAL_SRC, 0, buf);
152 /*****************************************************************************/
154 * Handle a program assertion
157 void mprAssertError(MPR_LOC_DEC(ctx, loc), const char *msg)
159 logOutput(MPR_LOC_PASS(ctx, loc), MPR_ASSERT_MSG | MPR_ASSERT_SRC, 0, msg);
162 /*****************************************************************************/
167 void mprStaticError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...)
171 char buf[MPR_MAX_STRING];
174 len = mprVsprintf(buf, sizeof(buf), fmt, args);
177 logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf);
180 /*****************************************************************************/
182 * Direct output to the standard output. Does not hook into the logging
183 * system and does not allocate memory.
186 void mprStaticAssert(const char *loc, const char *msg)
189 char buf[MPR_MAX_STRING];
192 len = mprSprintf(buf, sizeof(buf), "Assertion %s, failed at %s\n",
194 mprBreakpoint(loc, buf);
198 * MOB -- but is stdout always okay to use
203 * Only time we use printf. We can't get an alloc context so we have
206 #if BREW && !BREW_SIMULATOR
207 printf(" MP: %s\n", buf);
216 /*****************************************************************************/
218 int mprGetLogLevel(MprCtx ctx)
220 return mprGetApp(ctx)->logLevel;
223 /******************************************************************************/
225 void mprSetLogLevel(MprCtx ctx, int level)
227 mprGetApp(ctx)->logLevel = level;
230 /*****************************************************************************/
232 * Output a log message to the log handler
235 static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level,
238 MprLogHandler handler;
240 if (flags & (MPR_ERROR_SRC | MPR_FATAL_SRC | MPR_ASSERT_SRC)) {
241 mprBreakpoint(MPR_LOC, 0);
245 handler = mprGetApp(ctx)->logHandler;
247 (handler)(MPR_LOC_PASS(ctx, loc), flags, level, msg);
250 defaultLogHandler(MPR_LOC_PASS(ctx, loc), flags, level, msg);
253 /*****************************************************************************/
255 * Default log output is just to the console
258 static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags,
259 int level, const char *msg)
264 app = mprGetApp(ctx);
267 while (*msg == '\n') {
268 mprPrintf(ctx, "\n");
272 if (flags & MPR_LOG_SRC) {
273 #if BREW && !BREW_SIMULATOR
274 mprPrintf(ctx, "%s\n", msg);
276 mprPrintf(ctx, "%s: %d: %s\n", prefix, level, msg);
279 } else if (flags & MPR_ERROR_SRC) {
281 * Use static printing to avoid malloc when the messages are small.
282 * This is important for memory allocation errors.
284 if (strlen(msg) < (MPR_MAX_STRING - 32)) {
285 mprStaticPrintf(ctx, "%s: Error: %s\n", prefix, msg);
287 mprPrintf(ctx, "%s: Error: %s\n", prefix, msg);
290 } else if (flags & MPR_FATAL_SRC) {
291 mprPrintf(ctx, "%s: Fatal: %s\n", prefix, msg);
293 } else if (flags & MPR_ASSERT_SRC) {
294 #if BLD_FEATURE_ALLOC_LEAK_TRACK
295 mprPrintf(ctx, "%s: Assertion %s, failed at %s\n", prefix, msg, loc);
297 mprPrintf(ctx, "%s: Assertion %s, failed\n", prefix, msg);
300 } else if (flags & MPR_RAW) {
301 mprPrintf(ctx, "%s", msg);
308 /*****************************************************************************/
310 * Map the O/S error code to portable error codes.
320 * Client has closed the pipe
322 if (rc == ERROR_NO_DATA) {
327 #if LINUX || VXWORKS || SOLARIS
332 * No such thing on Brew. Errors are per class
338 /******************************************************************************/
341 const char *mprGetErrorMsg(int err)
344 * MPR error messages. Declare here so we don't have any globals.
346 char *mprErrMessages[] = {
347 /* 0 MPR_ERR_OK */ "Success",
348 /* -201 MPR_ERR_GENERAL */ "General error",
349 /* -202 MPR_ERR_ABORTED */ "Aborted",
350 /* -203 MPR_ERR_ALREADY_EXISTS */ "Already exists",
351 /* -204 MPR_ERR_BAD_ARGS */ "Bad args",
352 /* -205 MPR_ERR_BAD_FORMAT */ "Bad format",
353 /* -206 MPR_ERR_BAD_HANDLE */ "Bad handle",
354 /* -207 MPR_ERR_BAD_STATE */ "Bad state",
355 /* -208 MPR_ERR_BAD_SYNTAX */ "Bad syntax",
356 /* -209 MPR_ERR_BAD_TYPE */ "Bad type",
357 /* -210 MPR_ERR_BAD_VALUE */ "Bad value",
358 /* -211 MPR_ERR_BUSY */ "Busy",
359 /* -212 MPR_ERR_CANT_ACCESS */ "Can't access",
360 /* -213 MPR_ERR_CANT_COMPLETE */ "Can't complete",
361 /* -214 MPR_ERR_CANT_CREATE */ "Can't create",
362 /* -215 MPR_ERR_CANT_INITIALIZE */ "Can't initialize",
363 /* -216 MPR_ERR_CANT_OPEN */ "Can't open",
364 /* -217 MPR_ERR_CANT_READ */ "Can't read",
365 /* -218 MPR_ERR_CANT_WRITE */ "Can't write",
366 /* -219 MPR_ERR_DELETED */ "Already deleted",
367 /* -220 MPR_ERR_NETWORK */ "Network error",
368 /* -221 MPR_ERR_NOT_FOUND */ "Not found",
369 /* -222 MPR_ERR_NOT_INITIALIZED */ "Not initialized",
370 /* -223 MPR_ERR_NOT_READY */ "Not ready",
371 /* -224 MPR_ERR_READ_ONLY */ "Read only",
372 /* -225 MPR_ERR_TIMEOUT */ "Timeout",
373 /* -226 MPR_ERR_TOO_MANY */ "Too many",
374 /* -227 MPR_ERR_WONT_FIT */ "Won't fit",
375 /* -228 MPR_ERR_WOULD_BLOCK */ "Would block",
376 /* -229 MPR_ERR_CANT_ALLOCATE */ "Can't allocate",
378 int mprNumErr = sizeof(mprErrMessages) / sizeof(char*);
381 * Operating system error messages
384 char *osErrMessages[] =
387 /* 1 EPERM */ "Operation not permitted",
388 /* 2 ENOENT */ "No such file or directory",
389 /* 3 ESRCH */ "No such process",
390 /* 4 EINTR */ "Interrupted function call",
391 /* 5 EIO */ "I/O error",
392 /* 6 ENXIO */ "No such device or address",
393 /* 7 E2BIG */ "Arg list too long",
394 /* 8 ENOEXEC */ "Exec format error",
395 /* 9 EBADF */ "Bad file number",
396 /* 10 ECHILD */ "No child processes",
397 /* 11 EAGAIN */ "Try again",
398 /* 12 ENOMEM */ "Out of memory",
399 /* 13 EACCES */ "Permission denied",
400 /* 14 EFAULT */ "Bad address",
401 /* 15 ENOTBLK */ "Unknown error",
402 /* 16 EBUSY */ "Resource busy",
403 /* 17 EEXIST */ "File exists",
404 /* 18 EXDEV */ "Improper link",
405 /* 19 ENODEV */ "No such device",
406 /* 20 ENOTDIR */ "Not a directory",
407 /* 21 EISDIR */ "Is a directory",
408 /* 22 EINVAL */ "Invalid argument",
409 /* 23 ENFILE */ "Too many open files in system",
410 /* 24 EMFILE */ "Too many open files",
411 /* 25 ENOTTY */ "Inappropriate I/O control operation",
412 /* 26 ETXTBSY */ "Unknown error",
413 /* 27 EFBIG */ "File too large",
414 /* 28 ENOSPC */ "No space left on device",
415 /* 29 ESPIPE */ "Invalid seek",
416 /* 30 EROFS */ "Read-only file system",
417 /* 31 EMLINK */ "Too many links",
418 /* 32 EPIPE */ "Broken pipe",
419 /* 33 EDOM */ "Domain error",
420 /* 34 ERANGE */ "Result too large",
421 /* 35 EUCLEAN */ "Unknown error",
422 /* 36 EDEADLK */ "Resource deadlock would occur",
423 /* 37 UNKNOWN */ "Unknown error",
424 /* 38 ENAMETOOLONG */ "Filename too long",
425 /* 39 ENOLCK */ "No locks available",
426 /* 40 ENOSYS */ "Function not implemented",
427 /* 41 ENOTEMPTY */ "Directory not empty",
428 /* 42 EILSEQ */ "Illegal byte sequence",
429 /* 43 ENETDOWN */ "Network is down",
430 /* 44 ECONNRESET */ "Connection reset",
431 /* 45 ECONNREFUSED */ "Connection refused",
432 /* 46 EADDRINUSE */ "Address already in use"
438 char *osErrMessages[] =
441 /* 1 EPERM */ "Operation not permitted"
442 /* 2 ENOENT */ "No such file or directory"
443 /* 3 ESRCH */ "No such process"
444 /* 4 EINTR */ "Interrupted system call"
445 /* 5 EIO */ "I/O error"
446 /* 6 ENXIO */ "No such device or address"
447 /* 7 E2BIG */ "Arg list too long"
448 /* 8 ENOEXEC */ "Exec format error"
449 /* 9 EBADF */ "Bad file number"
450 /* 10 ECHILD */ "No child processes"
451 /* 11 EAGAIN */ "Try again"
452 /* 12 ENOMEM */ "Out of memory"
453 /* 13 EACCES */ "Permission denied"
454 /* 14 EFAULT */ "Bad address"
455 /* 15 ENOTBLK */ "Block device required"
456 /* 16 EBUSY */ "Device or resource busy"
457 /* 17 EEXIST */ "File exists"
458 /* 18 EXDEV */ "Cross-device link"
459 /* 19 ENODEV */ "No such device"
460 /* 20 ENOTDIR */ "Not a directory"
461 /* 21 EISDIR */ "Is a directory"
462 /* 22 EINVAL */ "Invalid argument"
463 /* 23 ENFILE */ "File table overflow"
464 /* 24 EMFILE */ "Too many open files"
465 /* 25 ENOTTY */ "Not a typewriter"
466 /* 26 ETXTBSY */ "Text file busy"
467 /* 27 EFBIG */ "File too large"
468 /* 28 ENOSPC */ "No space left on device"
469 /* 29 ESPIPE */ "Illegal seek"
470 /* 30 EROFS */ "Read-only file system"
471 /* 31 EMLINK */ "Too many links"
472 /* 32 EPIPE */ "Broken pipe"
473 /* 33 EDOM */ "Math argument out of domain of func"
474 /* 34 ERANGE */ "Math result not representable"
475 /* 35 EDEADLK */ "Resource deadlock would occur"
476 /* 36 ENAMETOOLONG */ "File name too long"
477 /* 37 ENOLCK */ "No record locks available"
478 /* 38 ENOSYS */ "Function not implemented"
479 /* 39 ENOTEMPTY */ "Directory not empty"
480 /* 40 ELOOP */ "Too many symbolic links encountered"
481 /* 41 EWOULDBLOCK EAGAIN */"Operation would block"
482 /* 42 ENOMSG */ "No message of desired type"
483 /* 43 EIDRM */ "Identifier removed"
485 #if !BLD_FEATURE_SQUEEZE
486 /* 44 ECHRNG */ "Channel number out of range"
487 /* 45 EL2NSYNC */ "Level 2 not synchronized"
488 /* 46 EL3HLT */ "Level 3 halted"
489 /* 47 EL3RST */ "Level 3 reset"
490 /* 48 ELNRNG */ "Link number out of range"
491 /* 49 EUNATCH */ "Protocol driver not attached"
492 /* 50 ENOCSI */ "No CSI structure available"
493 /* 51 EL2HLT */ "Level 2 halted"
494 /* 52 EBADE */ "Invalid exchange"
495 /* 53 EBADR */ "Invalid request descriptor"
496 /* 54 EXFULL */ "Exchange full"
497 /* 55 ENOANO */ "No anode"
498 /* 56 EBADRQC */ "Invalid request code"
499 /* 57 EBADSLT */ "Invalid slot"
500 /* 59 EBFONT */ "Bad font file format"
501 /* 60 ENOSTR */ "Device not a stream"
502 /* 61 ENODATA */ "No data available"
503 /* 62 ETIME */ "Timer expired"
504 /* 63 ENOSR */ "Out of streams resources"
505 /* 64 ENONET */ "Machine is not on the network"
506 /* 65 ENOPKG */ "Package not installed"
507 /* 66 EREMOTE */ "Object is remote"
508 /* 67 ENOLINK */ "Link has been severed"
509 /* 68 EADV */ "Advertise error"
510 /* 69 ESRMNT */ "Srmount error"
511 /* 70 ECOMM */ "Communication error on send"
512 /* 71 EPROTO */ "Protocol error"
513 /* 72 EMULTIHOP */ "Multihop attempted"
514 /* 73 EDOTDOT */ "RFS specific error"
515 /* 74 EBADMSG */ "Not a data message"
516 /* 75 EOVERFLOW */ "Value too large for defined data type"
517 /* 76 ENOTUNIQ */ "Name not unique on network"
518 /* 77 EBADFD */ "File descriptor in bad state"
519 /* 78 EREMCHG */ "Remote address changed"
520 /* 79 ELIBACC */ "Can not access a needed shared library"
521 /* 80 ELIBBAD */ "Accessing a corrupted shared library"
522 /* 81 ELIBSCN */ ".lib section in a.out corrupted"
523 /* 82 ELIBMAX */ "Linking in too many shared libraries"
524 /* 83 ELIBEXEC */ "Cannot exec a shared library directly"
525 /* 84 EILSEQ */ "Illegal byte sequence"
526 /* 85 ERESTART */ "Interrupted system call should be restarted"
527 /* 86 ESTRPIPE */ "Streams pipe error"
528 /* 87 EUSERS */ "Too many users"
529 /* 88 ENOTSOCK */ "Socket operation on non-socket"
530 /* 89 EDESTADDRREQ */ "Destination address required"
531 /* 90 EMSGSIZE */ "Message too long"
532 /* 91 EPROTOTYPE */ "Protocol wrong type for socket"
533 /* 92 ENOPROTOOPT */ "Protocol not available"
534 /* 93 EPROTONOSUPPORT */ "Protocol not supported"
535 /* 94 ESOCKTNOSUPPORT */ "Socket type not supported"
536 /* 95 EOPNOTSUPP */ "Operation not supported on transport endpoint"
537 /* 96 EPFNOSUPPORT */ "Protocol family not supported"
538 /* 97 EAFNOSUPPORT */ "Address family not supported by protocol"
539 /* 98 EADDRINUSE */ "Address already in use"
540 /* 99 EADDRNOTAVAIL */ "Cannot assign requested address"
541 /* 100 ENETDOWN */ "Network is down"
542 /* 101 ENETUNREACH */ "Network is unreachable"
543 /* 102 ENETRESET */ "Network dropped connection because of reset"
544 /* 103 ECONNABORTED */ "Software caused connection abort"
545 /* 104 ECONNRESET */ "Connection reset by peer"
546 /* 105 ENOBUFS */ "No buffer space available"
547 /* 106 EISCONN */ "Transport endpoint is already connected"
548 /* 107 ENOTCONN */ "Transport endpoint is not connected"
549 /* 108 ESHUTDOWN */ "Cannot send after transport endpoint shutdown"
550 /* 109 ETOOMANYREFS */ "Too many references: cannot splice"
551 /* 110 ETIMEDOUT */ "Connection timed out"
552 /* 111 ECONNREFUSED */ "Connection refused"
553 /* 112 EHOSTDOWN */ "Host is down"
554 /* 113 EHOSTUNREACH */ "No route to host"
555 /* 114 EALREADY */ "Operation already in progress"
556 /* 115 EINPROGRESS */ "Operation now in progress"
557 /* 116 ESTALE */ "Stale NFS file handle"
558 /* 117 EUCLEAN */ "Structure needs cleaning"
559 /* 118 ENOTNAM */ "Not a XENIX named type file"
560 /* 119 ENAVAIL */ "No XENIX semaphores available"
561 /* 120 EISNAM */ "Is a named type file"
562 /* 121 EREMOTEIO */ "Remote I/O error"
563 /* 122 EDQUOT */ "Quota exceeded"
564 /* 123 ENOMEDIUM */ "No medium found"
565 /* 124 EMEDIUMTYPE */ "Wrong medium type"
567 #endif /* BLD_FEATURE_SQUEEZE */
570 int osNumErr = sizeof(osErrMessages) / sizeof(char*);
572 if (err < MPR_ERR_BASE) {
573 err = MPR_ERR_BASE - err;
574 if (err < 0 || err >= mprNumErr) {
575 return "Bad error code";
577 return mprErrMessages[err];
581 * Negative O/S error code. Map to a positive standard Posix error.
584 if (err < 0 || err >= osNumErr) {
585 return "Bad O/S error code";
587 return osErrMessages[err];
592 /*****************************************************************************/
600 * vim600: sw=4 ts=4 fdm=marker