1 /* $OpenBSD: log.c,v 1.3 2019/03/31 03:53:42 yasuoka Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <errno.h> 20 #include <stdarg.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <syslog.h> 25 #include <time.h> 26 27 #include "log.h" 28 29 int log_debug_use_syslog = 0; 30 static int log_initialized = 0; 31 static int debug = 0; 32 33 void logit(int, const char *, ...); 34 35 void 36 log_init(int n_debug) 37 { 38 extern char *__progname; 39 40 debug = n_debug; 41 42 if (!debug) 43 openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON); 44 45 tzset(); 46 log_initialized++; 47 } 48 49 void 50 logit(int pri, const char *fmt, ...) 51 { 52 va_list ap; 53 54 va_start(ap, fmt); 55 vlog(pri, fmt, ap); 56 va_end(ap); 57 } 58 59 void 60 vlog(int pri, const char *fmt, va_list ap) 61 { 62 char fmtbuf[1024]; 63 time_t curr; 64 struct tm tm; 65 u_int i = 0, j; 66 int saved_errno = errno; 67 static struct { 68 int v; 69 const char *l; 70 } syslog_prionames[] = { 71 #define NV(_l) { _l, #_l } 72 NV(LOG_DEBUG), 73 NV(LOG_INFO), 74 NV(LOG_NOTICE), 75 NV(LOG_WARNING), 76 NV(LOG_ERR), 77 NV(LOG_ALERT), 78 NV(LOG_CRIT), 79 #undef NV 80 { -1, NULL } 81 }; 82 83 if (log_initialized && !debug) { 84 vsyslog(pri, fmt, ap); 85 return; 86 } 87 if (log_initialized) { 88 time(&curr); 89 localtime_r(&curr, &tm); 90 strftime(fmtbuf, sizeof(fmtbuf), "%Y-%m-%d %H:%M:%S:", &tm); 91 for (i = 0; syslog_prionames[i].v != -1; i++) { 92 if (syslog_prionames[i].v == LOG_PRI(pri)) { 93 strlcat(fmtbuf, syslog_prionames[i].l + 4, 94 sizeof(fmtbuf)); 95 strlcat(fmtbuf, ": ", sizeof(fmtbuf)); 96 break; 97 } 98 } 99 i = strlen(fmtbuf); 100 } 101 for (j = 0; i < sizeof(fmtbuf) - 2 && fmt[j] != '\0'; j++) { 102 if (fmt[j] == '%' && fmt[j + 1] == 'm') { 103 ++j; 104 fmtbuf[i] = '\0'; 105 strlcat(fmtbuf, strerror(saved_errno), 106 sizeof(fmtbuf) - 1); 107 i = strlen(fmtbuf); 108 } else 109 fmtbuf[i++] = fmt[j]; 110 } 111 fmtbuf[i++] = '\n'; 112 fmtbuf[i++] = '\0'; 113 114 vfprintf(stderr, fmtbuf, ap); 115 } 116 117 118 void 119 log_warn(const char *emsg, ...) 120 { 121 char *nfmt; 122 va_list ap; 123 int saved_errno = errno; 124 125 /* best effort to even work in out of memory situations */ 126 if (emsg == NULL) 127 logit(LOG_WARNING, "%s", strerror(saved_errno)); 128 else { 129 va_start(ap, emsg); 130 131 if (asprintf(&nfmt, "%s: %s", emsg, strerror(saved_errno)) 132 == -1) { 133 /* we tried it... */ 134 vlog(LOG_WARNING, emsg, ap); 135 logit(LOG_WARNING, "%s", strerror(saved_errno)); 136 } else { 137 vlog(LOG_WARNING, nfmt, ap); 138 free(nfmt); 139 } 140 va_end(ap); 141 } 142 } 143 144 void 145 log_warnx(const char *emsg, ...) 146 { 147 va_list ap; 148 149 va_start(ap, emsg); 150 vlog(LOG_WARNING, emsg, ap); 151 va_end(ap); 152 } 153 154 void 155 log_info(const char *emsg, ...) 156 { 157 va_list ap; 158 159 va_start(ap, emsg); 160 vlog(LOG_INFO, emsg, ap); 161 va_end(ap); 162 } 163 164 void 165 log_debug(const char *emsg, ...) 166 { 167 va_list ap; 168 169 if (debug || log_debug_use_syslog) { 170 va_start(ap, emsg); 171 vlog(LOG_DEBUG, emsg, ap); 172 va_end(ap); 173 } 174 } 175 176 void 177 fatal(const char *emsg) 178 { 179 if (emsg == NULL) 180 logit(LOG_CRIT, "fatal: %s", strerror(errno)); 181 else 182 if (errno) 183 logit(LOG_CRIT, "fatal: %s: %s", 184 emsg, strerror(errno)); 185 else 186 logit(LOG_CRIT, "fatal: %s", emsg); 187 188 exit(1); 189 } 190 191 void 192 fatalx(const char *emsg) 193 { 194 errno = 0; 195 fatal(emsg); 196 } 197