00001
00002
00003
00004
00005 static const char rcsid[] =
00006 "$Id: log.c,v 1.3 2007/05/10 14:17:58 tat 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
00022 extern int facility;
00023
00024
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;
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
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;
00121
00122
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;
00130 }
00131
00132
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
00156 file = NULL;
00157 line = 0;
00158 func = NULL;
00159
00160 save_errno(savederr);
00161
00162
00163 va_start(ap, fmt);
00164
00165
00166 rc = vfprintf(stderr, fmt, ap);
00167
00168 va_end(ap);
00169
00170 if(rc < 0)
00171 goto err;
00172
00173
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;
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
00200
00201
00202 long long rc;
00203
00204
00205 rc = (long long)strerror_r(en, buf, BUFSZ);
00206
00207 if(rc == 0)
00208 {
00209 strlcpy(msg, buf, sz);
00210 } else if(rc == -1 || (rc > 0 && rc < 1024)) {
00211
00212 goto err;
00213 } else {
00214
00215 strlcpy(msg, (char*)rc, sz);
00216 }
00217 #else
00218
00219 char *p;
00220
00221 dbg_err_if((p = strerror(en)) == NULL);
00222
00223 strlcpy(msg, p, sz);
00224 #endif
00225
00226 return 0;
00227 err:
00228 return ~0;
00229 }
00230