00001
00002
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
00020 extern int facility;
00021
00022
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;
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
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;
00162
00163
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;
00171 }
00172
00173
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
00197 file = NULL, line = 0, func = NULL;
00198
00199 save_errno(savederr);
00200
00201
00202 va_start(ap, fmt);
00203
00204
00205 rc = vfprintf(stderr, fmt, ap);
00206
00207 va_end(ap);
00208
00209 if(rc < 0)
00210 goto err;
00211
00212
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;
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
00241 rc = (intptr_t)strerror_r(en, buf, BUFSZ);
00242
00243 if(rc == 0)
00244 {
00245 (void) strlcpy(msg, buf, sz);
00246 } else if(rc == -1 || (rc > 0 && rc < 1024)) {
00247
00248 goto err;
00249 } else {
00250
00251 (void) strlcpy(msg, (char*)rc, sz);
00252 }
00253 #else
00254
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