00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <unistd.h>
00018 #include <stdlib.h>
00019 #include <errno.h>
00020 #include <stdarg.h>
00021 #include <syslog.h>
00022 #include <string.h>
00023 #include <time.h>
00024
00025 #include "log.h"
00026 #include "mem.h"
00027 #include "printf.h"
00028 #include "str.h"
00029
00030 extern log_options_t *_log_options;
00031
00032 static int errno_orig = 0;
00033
00034 static
00035 void log_fd(int fd, int prio, const char *msg)
00036 {
00037 char timebuf[17];
00038 time_t curtime = time(0);
00039
00040 if (!(_log_options->log_mask & (1 << prio)))
00041 return;
00042
00043 if (_log_options->log_opts & LOGO_PRIO) {
00044 switch (prio) {
00045 case LOGP_ALERT: _lucid_dprintf(fd, "[alert]"); break;
00046 case LOGP_ERROR: _lucid_dprintf(fd, "[error]"); break;
00047 case LOGP_WARN: _lucid_dprintf(fd, "[warn ]"); break;
00048 case LOGP_NOTE: _lucid_dprintf(fd, "[note ]"); break;
00049 case LOGP_INFO: _lucid_dprintf(fd, "[info ]"); break;
00050 case LOGP_DEBUG: _lucid_dprintf(fd, "[debug]"); break;
00051 case LOGP_TRACE: _lucid_dprintf(fd, "[trace]"); break;
00052 default: _lucid_dprintf(fd, "[none ]"); break;
00053 }
00054 }
00055
00056 if (_log_options->log_opts & LOGO_TIME) {
00057 mem_set(timebuf, 0, 17);
00058 strftime(timebuf, 17, "%b %d %T", localtime(&curtime));
00059 _lucid_dprintf(fd, " %s", timebuf);
00060 }
00061
00062 if (_log_options->log_opts & LOGO_IDENT)
00063 _lucid_dprintf(fd, " %s", _log_options->log_ident);
00064
00065 if (_log_options->log_opts & LOGO_PID)
00066 _lucid_dprintf(fd, "[%d]", getpid());
00067
00068 _lucid_dprintf(fd, "%s%s\n",
00069 _log_options->log_opts ? ": " : "", msg);
00070 }
00071
00072 static
00073 int prio_to_syslog(int prio)
00074 {
00075 switch (prio) {
00076 case LOGP_ALERT: return LOG_ALERT;
00077 case LOGP_ERROR: return LOG_ERR;
00078 case LOGP_WARN: return LOG_WARNING;
00079 case LOGP_NOTE: return LOG_NOTICE;
00080 case LOGP_INFO: return LOG_INFO;
00081 case LOGP_DEBUG: return LOG_DEBUG;
00082 }
00083
00084 return -1;
00085 }
00086
00087 static
00088 void log_internal(int prio, int strerr, const char *fmt, va_list ap)
00089 {
00090 char *buf, *msg;
00091
00092 if (!_log_options)
00093 return;
00094
00095 _lucid_vasprintf(&msg, fmt, ap);
00096
00097 if (strerr) {
00098 buf = msg;
00099 _lucid_asprintf(&msg, "%s: %s", buf, strerror(errno_orig));
00100 mem_free(buf);
00101 }
00102
00103 if (_log_options->log_dest & LOGD_STDERR)
00104 log_fd(STDERR_FILENO, prio, msg);
00105
00106 if (_log_options->log_dest & LOGD_FILE)
00107 log_fd(_log_options->log_fd, prio, msg);
00108
00109 if (_log_options->log_dest & LOGD_SYSLOG) {
00110 if ((prio = prio_to_syslog(prio)) >= 0)
00111 syslog(_log_options->log_facility|prio, "%s", msg);
00112 }
00113
00114 mem_free(msg);
00115 }
00116
00117 int log_traceme(const char *file, const char *func, int line)
00118 {
00119 char *base = str_path_basename(file);
00120
00121 int rc = log_trace("@%s() in %s:%d", func, base, line);
00122
00123 mem_free(base);
00124
00125 return rc;
00126 }
00127
00128 #define LOGFUNC(name, level, rc) \
00129 int log_ ## name (const char *fmt, ...) { \
00130 va_list ap; va_start(ap, fmt); \
00131 log_internal(level, 0, fmt, ap); \
00132 va_end(ap); \
00133 return rc; \
00134 }
00135
00136 LOGFUNC(alert, LOGP_ALERT, EXIT_FAILURE)
00137 LOGFUNC(error, LOGP_ERROR, EXIT_FAILURE)
00138 LOGFUNC(warn, LOGP_WARN, EXIT_SUCCESS)
00139 LOGFUNC(notice, LOGP_NOTE, EXIT_SUCCESS)
00140 LOGFUNC(info, LOGP_INFO, EXIT_SUCCESS)
00141 LOGFUNC(debug, LOGP_DEBUG, EXIT_SUCCESS)
00142 LOGFUNC(trace, LOGP_TRACE, EXIT_SUCCESS)
00143
00144 #define LOGFUNCDIE(name, level) \
00145 void log_ ## name ## _and_die(const char *fmt, ...) { \
00146 va_list ap; va_start(ap, fmt); \
00147 log_internal(level, 0, fmt, ap); \
00148 va_end(ap); \
00149 exit(EXIT_FAILURE); \
00150 }
00151
00152 LOGFUNCDIE(alert, LOGP_ALERT)
00153 LOGFUNCDIE(error, LOGP_ERROR)
00154
00155 #define LOGPFUNC(name, level, rc) \
00156 int log_p ## name (const char *fmt, ...) { \
00157 errno_orig = errno; \
00158 va_list ap; va_start(ap, fmt); \
00159 log_internal(level, 1, fmt, ap); \
00160 va_end(ap); \
00161 return rc; \
00162 }
00163
00164 LOGPFUNC(alert, LOGP_ALERT, EXIT_FAILURE)
00165 LOGPFUNC(error, LOGP_ERROR, EXIT_FAILURE)
00166 LOGPFUNC(warn, LOGP_WARN, EXIT_SUCCESS)
00167 LOGPFUNC(notice, LOGP_NOTE, EXIT_SUCCESS)
00168 LOGPFUNC(info, LOGP_INFO, EXIT_SUCCESS)
00169 LOGPFUNC(debug, LOGP_DEBUG, EXIT_SUCCESS)
00170 LOGPFUNC(trace, LOGP_TRACE, EXIT_SUCCESS)
00171
00172 #define LOGPFUNCDIE(name, level) \
00173 void log_p ## name ## _and_die(const char *fmt, ...) { \
00174 errno_orig = errno; \
00175 va_list ap; va_start(ap, fmt); \
00176 log_internal(level, 1, fmt, ap); \
00177 va_end(ap); \
00178 exit(EXIT_FAILURE); \
00179 }
00180
00181 LOGPFUNCDIE(alert, LOGP_ALERT)
00182 LOGPFUNCDIE(error, LOGP_ERROR)