log.c

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

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