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