Main Page | Modules | Data Structures | File List | Data Fields

log.c

00001 /*
00002  * Copyright (c) 2005, 2006 by KoanLogic s.r.l. - All rights reserved.  
00003  */
00004 
00005 static const char rcsid[] =
00006     "$Id: log.c,v 1.1 2006/11/20 13:38:01 tho Exp $";
00007 
00008 #include <sys/types.h>
00009 #include <errno.h>
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <stdarg.h>
00013 #include <signal.h>
00014 #include <unistd.h>
00015 #include <toolbox/log.h>
00016 #include <toolbox/carpal.h>
00017 #include <toolbox/misc.h>
00018 #include <u/missing.h>
00019 #include <missing/syslog.h>
00020 
00021 /* applications that use libu will defined their own "int facility" variable */
00022 extern int facility;
00023 
00024 /* log hook. if not-zero use this function to write log messages */
00025 static u_log_hook_t hook = NULL;
00026 static void *hook_arg = NULL;
00027 
00028 enum { STRERR_BUFSZ = 128, ERRMSG_BUFSZ = 256 };
00029 
00030 #ifdef OS_WIN
00031 #define err_type DWORD
00032 #define save_errno(var) var = GetLastError();
00033 #define restore_errno(var) SetLastError(var);
00034 #else
00035 #define err_type int
00036 #define save_errno(var) var = errno;
00037 #define restore_errno(var) errno = var;
00038 #endif
00039 
00040 static inline const char* u_log_label(int lev)
00041 {
00042     switch(lev)
00043     {
00044     case LOG_DEBUG:  
00045         return "dbg"; 
00046     case LOG_INFO:   
00047         return "inf"; 
00048     case LOG_NOTICE: 
00049         return "ntc"; 
00050     case LOG_WARNING:
00051         return "wrn";
00052     case LOG_ERR:    
00053         return "err";
00054     case LOG_CRIT:   
00055         return "crt";
00056     case LOG_ALERT:   
00057         return "alr";
00058     case LOG_EMERG:   
00059         return "emg";
00060     default: 
00061         syslog(LOG_WARNING, 
00062                "[wrn][%d:::] unknown log level: %d", getpid(), lev);
00063         return "unk";
00064     }
00065 }
00066 
00067 static int u_log(int fac, int level, const char *fmt, ...)
00068 {
00069     va_list ap;
00070     char buf[U_MAX_LOG_LENGTH];
00071 
00072     va_start(ap, fmt); 
00073 
00074     if(hook)
00075     {
00076         if(vsnprintf(buf, U_MAX_LOG_LENGTH, fmt, ap) > U_MAX_LOG_LENGTH)
00077         {
00078             va_end(ap);
00079             return ~0; /* buffer too small */
00080         }
00081         buf[U_MAX_LOG_LENGTH - 1] = 0; 
00082         hook(hook_arg, level, buf);
00083     } else 
00084         vsyslog(fac | level, fmt, ap);
00085 
00086     va_end(ap);
00087 
00088     return 0;
00089 }
00090 
00091 int u_log_set_hook(u_log_hook_t func, void *arg, u_log_hook_t *old, void **parg)
00092 {
00093     if(old)
00094         *old = hook;
00095     if(parg)
00096         *parg = hook_arg;
00097 
00098     hook = func;
00099     hook_arg = arg;
00100 
00101     return 0;
00102 }
00103 
00104 int u_log_write_ex(int fac, int lev, int flags, int err, const char* file, 
00105     int line, const char *func, const char* fmt, ...)
00106 {
00107     va_list ap;
00108     err_type savederr;
00109     int rc;
00110     char msg[U_MAX_LOG_LENGTH], strerr[STRERR_BUFSZ], errmsg[STRERR_BUFSZ];
00111 
00112     save_errno(savederr);
00113 
00114     /* build the message to send to the log system */
00115     va_start(ap, fmt); 
00116     rc = vsnprintf(msg, U_MAX_LOG_LENGTH, fmt, ap);
00117     va_end(ap);
00118 
00119     if(rc >= U_MAX_LOG_LENGTH)
00120         goto err; /* message too long */
00121 
00122     /* init empty strings */
00123     errmsg[0] = strerr[0] = 0;
00124 
00125     if(err)
00126     {
00127         u_strerror_r(err, strerr, sizeof(strerr));
00128         snprintf(errmsg, sizeof(errmsg), "[errno: %d, %s]", err, strerr);
00129         errmsg[sizeof(errmsg) - 1] = 0; /* paranoid set */
00130     } 
00131 
00132     /* ok, send the msg to the logger */
00133     if(flags & LOG_WRITE_FLAG_CTX)
00134         u_log(fac, lev, "[%s][%d:%s:%d:%s] %s %s", 
00135                u_log_label(lev), getpid(), file, line, func, msg, errmsg);
00136     else
00137         u_log(fac, lev, "[%s][%d:::] %s %s", 
00138                u_log_label(lev), getpid(), msg, errmsg);
00139 
00140     restore_errno(savederr);
00141     return 0;
00142 err:
00143     restore_errno(savederr);
00144     return ~0;
00145 }
00146 
00147 int u_console_write_ex(int err, const char* file, int line, 
00148     const char *func, const char* fmt, ...)
00149 {
00150     err_type savederr;
00151     va_list ap;
00152     int rc;
00153     char strerr[STRERR_BUFSZ], errmsg[STRERR_BUFSZ];
00154 
00155     /* when writing to console the following parameters are not used */
00156     file = NULL;
00157     line = 0;
00158     func = NULL;
00159 
00160     save_errno(savederr);
00161 
00162     /* build the message to send to the log system */
00163     va_start(ap, fmt); 
00164 
00165     /* write the message to the standard error */
00166     rc = vfprintf(stderr, fmt, ap);
00167 
00168     va_end(ap);
00169 
00170     if(rc < 0)
00171         goto err;
00172 
00173     /* init empty strings */
00174     errmsg[0] = strerr[0] = 0;
00175 
00176     if(err)
00177     {
00178         u_strerror_r(err, strerr, sizeof(strerr));
00179         snprintf(errmsg, sizeof(errmsg), "[errno: %d, %s]", err, strerr);
00180         errmsg[sizeof(errmsg) - 1] = 0; /* paranoid set */
00181         fprintf(stderr, " %s\n", errmsg);
00182     } else
00183         fprintf(stderr, "\n");
00184 
00185 
00186     restore_errno(savederr);
00187     return 0;
00188 err:
00189     restore_errno(savederr);
00190     return ~0;
00191 }
00192 
00193 int u_strerror_r(int en, char *msg, size_t sz)
00194 {
00195 
00196 #ifdef HAVE_STRERROR_R
00197     enum { BUFSZ = 256 };
00198     char buf[BUFSZ] = { 0 };
00199     int rc;
00200 
00201     /* assume POSIX prototype */
00202     rc = (int)strerror_r(en, buf, BUFSZ);
00203 
00204     if(rc == 0)
00205     {    /* posix version, success */
00206         strlcpy(msg, buf, sz);
00207     } else if(rc == -1 || (rc > 0 && rc < 1024)) {
00208          /* posix version, failed (returns -1 or an error number) */
00209          goto err;
00210     } else {
00211         /* glibc char*-returning version, always succeeds */
00212         strlcpy(msg, (char*)rc, sz);
00213     }
00214 #else
00215     /* there's not strerror_r, use strerror() instead */
00216     char *p;
00217 
00218     dbg_err_if((p = strerror(en)) == NULL);
00219 
00220     strlcpy(msg, p, sz);
00221 #endif
00222 
00223     return 0;
00224 err:
00225     return ~0;
00226 }
00227 

←Products
© 2005-2006 - KoanLogic S.r.l. - All rights reserved