1 /* $OpenBSD: log.c,v 1.3 2017/04/06 14:55:43 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 2017 Alexander Bluhm <bluhm@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <err.h> 21 #include <errno.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <syslog.h> 26 #include <time.h> 27 28 #include "log.h" 29 #include "syslogd.h" 30 31 static int debug; 32 static int verbose; 33 static int facility; 34 static const char *log_procname; 35 static char *debug_ebuf; 36 static size_t debug_length; 37 38 void 39 log_init(int n_debug, int fac) 40 { 41 extern char *__progname; 42 43 debug = n_debug; 44 verbose = n_debug; 45 facility = fac; 46 log_procinit(__progname); 47 48 if (debug_ebuf == NULL) 49 if ((debug_ebuf = malloc(ERRBUFSIZE)) == NULL) 50 err(1, "allocate debug buffer"); 51 debug_ebuf[0] = '\0'; 52 debug_length = 0; 53 54 tzset(); 55 } 56 57 void 58 log_procinit(const char *procname) 59 { 60 if (procname != NULL) 61 log_procname = procname; 62 } 63 64 void 65 log_setdebug(int d) 66 { 67 debug = d; 68 } 69 70 int 71 log_getdebug(void) 72 { 73 return (debug); 74 } 75 76 void 77 log_setverbose(int v) 78 { 79 verbose = v; 80 } 81 82 int 83 log_getverbose(void) 84 { 85 return (verbose); 86 } 87 88 void 89 logit(int pri, const char *fmt, ...) 90 { 91 va_list ap; 92 93 va_start(ap, fmt); 94 vlog(pri, fmt, ap); 95 va_end(ap); 96 } 97 98 void 99 vlog(int pri, const char *fmt, va_list ap) 100 { 101 char ebuf[ERRBUFSIZE]; 102 size_t l; 103 int saved_errno = errno; 104 105 if (debug) { 106 l = snprintf(ebuf, sizeof(ebuf), "%s: ", log_procname); 107 if (l < sizeof(ebuf)) 108 vsnprintf(ebuf+l, sizeof(ebuf)-l, fmt, ap); 109 fprintf(stderr, "%s\n", ebuf); 110 fflush(stderr); 111 } else 112 vlogmsg(facility|pri, log_procname, fmt, ap); 113 114 errno = saved_errno; 115 } 116 117 void 118 log_warn(const char *emsg, ...) 119 { 120 char ebuf[ERRBUFSIZE]; 121 size_t l; 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_ERR, "%s", strerror(saved_errno)); 128 else { 129 va_start(ap, emsg); 130 l = vsnprintf(ebuf, sizeof(ebuf), emsg, ap); 131 if (l < sizeof(ebuf)) 132 snprintf(ebuf+l, sizeof(ebuf)-l, ": %s", 133 strerror(saved_errno)); 134 logit(LOG_ERR, "%s", ebuf); 135 va_end(ap); 136 } 137 errno = saved_errno; 138 } 139 140 void 141 log_warnx(const char *emsg, ...) 142 { 143 va_list ap; 144 145 va_start(ap, emsg); 146 vlog(LOG_ERR, emsg, ap); 147 va_end(ap); 148 } 149 150 void 151 log_info(int pri, const char *emsg, ...) 152 { 153 va_list ap; 154 155 va_start(ap, emsg); 156 vlog(pri, emsg, ap); 157 va_end(ap); 158 } 159 160 void 161 log_debug(const char *emsg, ...) 162 { 163 va_list ap; 164 int saved_errno; 165 166 if (verbose) { 167 saved_errno = errno; 168 va_start(ap, emsg); 169 if (debug_length < ERRBUFSIZE - 1) 170 vsnprintf(debug_ebuf + debug_length, 171 ERRBUFSIZE - debug_length, emsg, ap); 172 fprintf(stderr, "%s\n", debug_ebuf); 173 fflush(stderr); 174 va_end(ap); 175 errno = saved_errno; 176 } 177 debug_ebuf[0] = '\0'; 178 debug_length = 0; 179 } 180 181 void 182 log_debugadd(const char *emsg, ...) 183 { 184 size_t l; 185 va_list ap; 186 int saved_errno; 187 188 if (verbose) { 189 saved_errno = errno; 190 va_start(ap, emsg); 191 if (debug_length < ERRBUFSIZE - 1) { 192 l = vsnprintf(debug_ebuf + debug_length, 193 ERRBUFSIZE - debug_length, emsg, ap); 194 if (l < ERRBUFSIZE - debug_length) 195 debug_length += l; 196 else 197 debug_length = ERRBUFSIZE - 1; 198 } 199 va_end(ap); 200 errno = saved_errno; 201 } 202 } 203 204 static void 205 vfatalc(int error, const char *emsg, va_list ap) 206 { 207 char ebuf[ERRBUFSIZE]; 208 const char *sep; 209 210 if (emsg != NULL) { 211 (void)vsnprintf(ebuf, sizeof(ebuf), emsg, ap); 212 sep = ": "; 213 } else { 214 ebuf[0] = '\0'; 215 sep = ""; 216 } 217 if (error) 218 logit(LOG_CRIT, "fatal in %s: %s%s%s", 219 log_procname, ebuf, sep, strerror(error)); 220 else 221 logit(LOG_CRIT, "fatal in %s%s%s", log_procname, sep, ebuf); 222 } 223 224 void 225 fatal(const char *emsg, ...) 226 { 227 va_list ap; 228 229 va_start(ap, emsg); 230 vfatalc(errno, emsg, ap); 231 va_end(ap); 232 die(0); 233 } 234 235 void 236 fatalx(const char *emsg, ...) 237 { 238 va_list ap; 239 240 va_start(ap, emsg); 241 vfatalc(0, emsg, ap); 242 va_end(ap); 243 die(0); 244 } 245