1 /* $NetBSD: log.c,v 1.7 2011/11/04 11:54:46 joerg Exp $ */ 2 /* $OpenBSD: log.c,v 1.42 2011/06/17 21:44:30 djm Exp $ */ 3 /* 4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 6 * All rights reserved 7 * 8 * As far as I am concerned, the code I have written for this software 9 * can be used freely for any purpose. Any derived versions of this 10 * software must be clearly marked as such, and if the derived work is 11 * incompatible with the protocol description in the RFC file, it must be 12 * called by a name other than "ssh" or "Secure Shell". 13 */ 14 /* 15 * Copyright (c) 2000 Markus Friedl. All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include "includes.h" 39 __RCSID("$NetBSD: log.c,v 1.7 2011/11/04 11:54:46 joerg Exp $"); 40 #include <sys/types.h> 41 #include <sys/uio.h> 42 43 #include <stdarg.h> 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <syslog.h> 48 #include <unistd.h> 49 #include <errno.h> 50 #include <vis.h> 51 52 #include "xmalloc.h" 53 #include "log.h" 54 55 static LogLevel log_level = SYSLOG_LEVEL_INFO; 56 static int log_on_stderr = 1; 57 static int log_facility = LOG_AUTH; 58 static const char *argv0; 59 static log_handler_fn *log_handler; 60 static void *log_handler_ctx; 61 62 extern char *__progname; 63 64 /* textual representation of log-facilities/levels */ 65 66 static struct { 67 const char *name; 68 SyslogFacility val; 69 } log_facilities[] = { 70 { "DAEMON", SYSLOG_FACILITY_DAEMON }, 71 { "USER", SYSLOG_FACILITY_USER }, 72 { "AUTH", SYSLOG_FACILITY_AUTH }, 73 { "LOCAL0", SYSLOG_FACILITY_LOCAL0 }, 74 { "LOCAL1", SYSLOG_FACILITY_LOCAL1 }, 75 { "LOCAL2", SYSLOG_FACILITY_LOCAL2 }, 76 { "LOCAL3", SYSLOG_FACILITY_LOCAL3 }, 77 { "LOCAL4", SYSLOG_FACILITY_LOCAL4 }, 78 { "LOCAL5", SYSLOG_FACILITY_LOCAL5 }, 79 { "LOCAL6", SYSLOG_FACILITY_LOCAL6 }, 80 { "LOCAL7", SYSLOG_FACILITY_LOCAL7 }, 81 { NULL, SYSLOG_FACILITY_NOT_SET } 82 }; 83 84 static struct { 85 const char *name; 86 LogLevel val; 87 } log_levels[] = 88 { 89 { "QUIET", SYSLOG_LEVEL_QUIET }, 90 { "FATAL", SYSLOG_LEVEL_FATAL }, 91 { "ERROR", SYSLOG_LEVEL_ERROR }, 92 { "INFO", SYSLOG_LEVEL_INFO }, 93 { "VERBOSE", SYSLOG_LEVEL_VERBOSE }, 94 { "DEBUG", SYSLOG_LEVEL_DEBUG1 }, 95 { "DEBUG1", SYSLOG_LEVEL_DEBUG1 }, 96 { "DEBUG2", SYSLOG_LEVEL_DEBUG2 }, 97 { "DEBUG3", SYSLOG_LEVEL_DEBUG3 }, 98 { NULL, SYSLOG_LEVEL_NOT_SET } 99 }; 100 101 SyslogFacility 102 log_facility_number(char *name) 103 { 104 int i; 105 106 if (name != NULL) 107 for (i = 0; log_facilities[i].name; i++) 108 if (strcasecmp(log_facilities[i].name, name) == 0) 109 return log_facilities[i].val; 110 return SYSLOG_FACILITY_NOT_SET; 111 } 112 113 const char * 114 log_facility_name(SyslogFacility facility) 115 { 116 u_int i; 117 118 for (i = 0; log_facilities[i].name; i++) 119 if (log_facilities[i].val == facility) 120 return log_facilities[i].name; 121 return NULL; 122 } 123 124 LogLevel 125 log_level_number(char *name) 126 { 127 int i; 128 129 if (name != NULL) 130 for (i = 0; log_levels[i].name; i++) 131 if (strcasecmp(log_levels[i].name, name) == 0) 132 return log_levels[i].val; 133 return SYSLOG_LEVEL_NOT_SET; 134 } 135 136 const char * 137 log_level_name(LogLevel level) 138 { 139 u_int i; 140 141 for (i = 0; log_levels[i].name != NULL; i++) 142 if (log_levels[i].val == level) 143 return log_levels[i].name; 144 return NULL; 145 } 146 147 /* Error messages that should be logged. */ 148 149 void 150 error(const char *fmt,...) 151 { 152 va_list args; 153 154 va_start(args, fmt); 155 do_log(SYSLOG_LEVEL_ERROR, fmt, args); 156 va_end(args); 157 } 158 159 void 160 sigdie(const char *fmt,...) 161 { 162 va_list args; 163 164 va_start(args, fmt); 165 do_log(SYSLOG_LEVEL_FATAL, fmt, args); 166 va_end(args); 167 _exit(1); 168 } 169 170 171 /* Log this message (information that usually should go to the log). */ 172 173 void 174 logit(const char *fmt,...) 175 { 176 va_list args; 177 178 va_start(args, fmt); 179 do_log(SYSLOG_LEVEL_INFO, fmt, args); 180 va_end(args); 181 } 182 183 /* More detailed messages (information that does not need to go to the log). */ 184 185 void 186 verbose(const char *fmt,...) 187 { 188 va_list args; 189 190 va_start(args, fmt); 191 do_log(SYSLOG_LEVEL_VERBOSE, fmt, args); 192 va_end(args); 193 } 194 195 /* Debugging messages that should not be logged during normal operation. */ 196 197 void 198 debug(const char *fmt,...) 199 { 200 va_list args; 201 202 va_start(args, fmt); 203 do_log(SYSLOG_LEVEL_DEBUG1, fmt, args); 204 va_end(args); 205 } 206 207 void 208 debug2(const char *fmt,...) 209 { 210 va_list args; 211 212 va_start(args, fmt); 213 do_log(SYSLOG_LEVEL_DEBUG2, fmt, args); 214 va_end(args); 215 } 216 217 void 218 debug3(const char *fmt,...) 219 { 220 va_list args; 221 222 va_start(args, fmt); 223 do_log(SYSLOG_LEVEL_DEBUG3, fmt, args); 224 va_end(args); 225 } 226 227 /* 228 * Initialize the log. 229 */ 230 231 void 232 log_init(const char *av0, LogLevel level, SyslogFacility facility, 233 int on_stderr) 234 { 235 argv0 = av0; 236 237 switch (level) { 238 case SYSLOG_LEVEL_QUIET: 239 case SYSLOG_LEVEL_FATAL: 240 case SYSLOG_LEVEL_ERROR: 241 case SYSLOG_LEVEL_INFO: 242 case SYSLOG_LEVEL_VERBOSE: 243 case SYSLOG_LEVEL_DEBUG1: 244 case SYSLOG_LEVEL_DEBUG2: 245 case SYSLOG_LEVEL_DEBUG3: 246 log_level = level; 247 break; 248 default: 249 fprintf(stderr, "Unrecognized internal syslog level code %d\n", 250 (int) level); 251 exit(1); 252 } 253 254 log_handler = NULL; 255 log_handler_ctx = NULL; 256 257 log_on_stderr = on_stderr; 258 if (on_stderr) 259 return; 260 261 switch (facility) { 262 case SYSLOG_FACILITY_DAEMON: 263 log_facility = LOG_DAEMON; 264 break; 265 case SYSLOG_FACILITY_USER: 266 log_facility = LOG_USER; 267 break; 268 case SYSLOG_FACILITY_AUTH: 269 log_facility = LOG_AUTH; 270 break; 271 case SYSLOG_FACILITY_LOCAL0: 272 log_facility = LOG_LOCAL0; 273 break; 274 case SYSLOG_FACILITY_LOCAL1: 275 log_facility = LOG_LOCAL1; 276 break; 277 case SYSLOG_FACILITY_LOCAL2: 278 log_facility = LOG_LOCAL2; 279 break; 280 case SYSLOG_FACILITY_LOCAL3: 281 log_facility = LOG_LOCAL3; 282 break; 283 case SYSLOG_FACILITY_LOCAL4: 284 log_facility = LOG_LOCAL4; 285 break; 286 case SYSLOG_FACILITY_LOCAL5: 287 log_facility = LOG_LOCAL5; 288 break; 289 case SYSLOG_FACILITY_LOCAL6: 290 log_facility = LOG_LOCAL6; 291 break; 292 case SYSLOG_FACILITY_LOCAL7: 293 log_facility = LOG_LOCAL7; 294 break; 295 default: 296 fprintf(stderr, 297 "Unrecognized internal syslog facility code %d\n", 298 (int) facility); 299 exit(1); 300 } 301 } 302 303 #define MSGBUFSIZ 1024 304 305 void 306 set_log_handler(log_handler_fn *handler, void *ctx) 307 { 308 log_handler = handler; 309 log_handler_ctx = ctx; 310 } 311 312 void 313 do_log2(LogLevel level, const char *fmt,...) 314 { 315 va_list args; 316 317 va_start(args, fmt); 318 do_log(level, fmt, args); 319 va_end(args); 320 } 321 322 void 323 do_log(LogLevel level, const char *fmt, va_list args) 324 { 325 #ifdef SYSLOG_DATA_INIT 326 struct syslog_data sdata = SYSLOG_DATA_INIT; 327 #endif 328 char msgbuf[MSGBUFSIZ], *msgbufp; 329 char visbuf[MSGBUFSIZ * 4 + 1]; 330 size_t len, len2; 331 int len3; 332 const char *txt = NULL; 333 int pri = LOG_INFO; 334 int saved_errno = errno; 335 log_handler_fn *tmp_handler; 336 337 if (level > log_level) 338 return; 339 340 switch (level) { 341 case SYSLOG_LEVEL_FATAL: 342 if (!log_on_stderr) 343 txt = "fatal"; 344 pri = LOG_CRIT; 345 break; 346 case SYSLOG_LEVEL_ERROR: 347 if (!log_on_stderr) 348 txt = "error"; 349 pri = LOG_ERR; 350 break; 351 case SYSLOG_LEVEL_INFO: 352 pri = LOG_INFO; 353 break; 354 case SYSLOG_LEVEL_VERBOSE: 355 pri = LOG_INFO; 356 break; 357 case SYSLOG_LEVEL_DEBUG1: 358 txt = "debug1"; 359 pri = LOG_DEBUG; 360 break; 361 case SYSLOG_LEVEL_DEBUG2: 362 txt = "debug2"; 363 pri = LOG_DEBUG; 364 break; 365 case SYSLOG_LEVEL_DEBUG3: 366 txt = "debug3"; 367 pri = LOG_DEBUG; 368 break; 369 default: 370 txt = "internal error"; 371 pri = LOG_ERR; 372 break; 373 } 374 len = sizeof(msgbuf); 375 msgbufp = msgbuf; 376 if (txt != NULL && log_handler == NULL) { 377 len2 = strlen(txt); 378 if (len2 > len - 2) 379 len2 = len - 2; 380 memcpy(msgbufp, txt, len2); 381 msgbufp += len2; 382 *msgbufp++ = ':'; 383 *msgbufp++ = ' '; 384 len -= len2 + 2; 385 } 386 vsnprintf(msgbufp, len, fmt, args); 387 len3 = strnvis(visbuf, sizeof(visbuf), msgbuf, VIS_SAFE|VIS_OCTAL); 388 if (log_handler != NULL) { 389 /* Avoid recursion */ 390 tmp_handler = log_handler; 391 log_handler = NULL; 392 tmp_handler(level, visbuf, log_handler_ctx); 393 log_handler = tmp_handler; 394 } else if (log_on_stderr) { 395 struct iovec iov[] = { 396 { visbuf, len3 }, 397 { __UNCONST("\r\n"), 2 }, 398 }; 399 writev(STDERR_FILENO, iov, __arraycount(iov)); 400 } else { 401 #ifdef SYSLOG_DATA_INIT 402 openlog_r(argv0 ? argv0 : __progname, LOG_PID, log_facility, &sdata); 403 syslog_r(pri, &sdata, "%.500s", visbuf); 404 closelog_r(&sdata); 405 #else 406 openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility); 407 syslog(pri, "%.500s", visbuf); 408 closelog(); 409 #endif 410 } 411 errno = saved_errno; 412 } 413