pjdlog.c revision 217965
1204076Spjd/*- 2217964Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 3217964Spjd * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> 4204076Spjd * All rights reserved. 5204076Spjd * 6204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 7204076Spjd * the FreeBSD Foundation. 8204076Spjd * 9204076Spjd * Redistribution and use in source and binary forms, with or without 10204076Spjd * modification, are permitted provided that the following conditions 11204076Spjd * are met: 12204076Spjd * 1. Redistributions of source code must retain the above copyright 13204076Spjd * notice, this list of conditions and the following disclaimer. 14204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 15204076Spjd * notice, this list of conditions and the following disclaimer in the 16204076Spjd * documentation and/or other materials provided with the distribution. 17204076Spjd * 18204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28204076Spjd * SUCH DAMAGE. 29204076Spjd */ 30204076Spjd 31204076Spjd#include <sys/cdefs.h> 32204076Spjd__FBSDID("$FreeBSD: head/sbin/hastd/pjdlog.c 217965 2011-01-27 19:24:07Z pjd $"); 33204076Spjd 34204076Spjd#include <assert.h> 35204076Spjd#include <errno.h> 36204076Spjd#include <stdarg.h> 37217965Spjd#include <stdbool.h> 38204076Spjd#include <stdio.h> 39204076Spjd#include <stdlib.h> 40204076Spjd#include <string.h> 41204076Spjd#include <syslog.h> 42204076Spjd 43204076Spjd#include "pjdlog.h" 44204076Spjd 45217965Spjdstatic bool pjdlog_initialized = false; 46204076Spjdstatic int pjdlog_mode = PJDLOG_MODE_STD; 47204076Spjdstatic int pjdlog_debug_level = 0; 48204076Spjdstatic char pjdlog_prefix[128]; 49204076Spjd 50217965Spjdvoid 51217965Spjdpjdlog_init(int mode) 52217965Spjd{ 53217965Spjd 54217965Spjd assert(!pjdlog_initialized); 55217965Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 56217965Spjd 57217965Spjd if (mode == PJDLOG_MODE_SYSLOG) 58217965Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 59217965Spjd pjdlog_mode = mode; 60217965Spjd 61217965Spjd pjdlog_initialized = true; 62217965Spjd} 63217965Spjd 64217965Spjdvoid 65217965Spjdpjdlog_fini(void) 66217965Spjd{ 67217965Spjd 68217965Spjd assert(pjdlog_initialized); 69217965Spjd 70217965Spjd if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 71217965Spjd closelog(); 72217965Spjd 73217965Spjd pjdlog_initialized = false; 74217965Spjd} 75217965Spjd 76204076Spjd/* 77204076Spjd * Configure where the logs should go. 78204076Spjd * By default they are send to stdout/stderr, but after going into background 79204076Spjd * (eg. by calling daemon(3)) application is responsible for changing mode to 80204076Spjd * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 81204076Spjd */ 82204076Spjdvoid 83204076Spjdpjdlog_mode_set(int mode) 84204076Spjd{ 85204076Spjd 86217965Spjd assert(pjdlog_initialized); 87204076Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 88204076Spjd 89217965Spjd if (pjdlog_mode == mode) 90217965Spjd return; 91212052Spjd 92212052Spjd if (mode == PJDLOG_MODE_SYSLOG) 93217962Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 94217965Spjd else /* if (mode == PJDLOG_MODE_STD) */ 95217965Spjd closelog(); 96217965Spjd 97217965Spjd pjdlog_mode = mode; 98204076Spjd} 99204076Spjd 100204076Spjd/* 101204076Spjd * Return current mode. 102204076Spjd */ 103204076Spjdint 104204076Spjdpjdlog_mode_get(void) 105204076Spjd{ 106204076Spjd 107217965Spjd assert(pjdlog_initialized); 108217965Spjd 109204076Spjd return (pjdlog_mode); 110204076Spjd} 111204076Spjd 112204076Spjd/* 113204076Spjd * Set debug level. All the logs above the level specified here will be 114204076Spjd * ignored. 115204076Spjd */ 116204076Spjdvoid 117204076Spjdpjdlog_debug_set(int level) 118204076Spjd{ 119204076Spjd 120217965Spjd assert(pjdlog_initialized); 121204076Spjd assert(level >= 0); 122204076Spjd 123204076Spjd pjdlog_debug_level = level; 124204076Spjd} 125204076Spjd 126204076Spjd/* 127204076Spjd * Return current debug level. 128204076Spjd */ 129204076Spjdint 130204076Spjdpjdlog_debug_get(void) 131204076Spjd{ 132204076Spjd 133217965Spjd assert(pjdlog_initialized); 134217965Spjd 135204076Spjd return (pjdlog_debug_level); 136204076Spjd} 137204076Spjd 138204076Spjd/* 139204076Spjd * Set prefix that will be used before each log. 140204076Spjd * Setting prefix to NULL will remove it. 141204076Spjd */ 142204076Spjdvoid 143204076Spjdpjdlog_prefix_set(const char *fmt, ...) 144204076Spjd{ 145204076Spjd va_list ap; 146204076Spjd 147217965Spjd assert(pjdlog_initialized); 148217965Spjd 149204076Spjd va_start(ap, fmt); 150217731Spjd pjdlogv_prefix_set(fmt, ap); 151204076Spjd va_end(ap); 152204076Spjd} 153204076Spjd 154204076Spjd/* 155204076Spjd * Set prefix that will be used before each log. 156204076Spjd * Setting prefix to NULL will remove it. 157204076Spjd */ 158204076Spjdvoid 159217731Spjdpjdlogv_prefix_set(const char *fmt, va_list ap) 160204076Spjd{ 161204076Spjd 162217965Spjd assert(pjdlog_initialized); 163204076Spjd assert(fmt != NULL); 164204076Spjd 165204076Spjd vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 166204076Spjd} 167204076Spjd 168204076Spjd/* 169204076Spjd * Convert log level into string. 170204076Spjd */ 171204076Spjdstatic const char * 172204076Spjdpjdlog_level_string(int loglevel) 173204076Spjd{ 174204076Spjd 175204076Spjd switch (loglevel) { 176204076Spjd case LOG_EMERG: 177204076Spjd return ("EMERG"); 178204076Spjd case LOG_ALERT: 179204076Spjd return ("ALERT"); 180204076Spjd case LOG_CRIT: 181204076Spjd return ("CRIT"); 182204076Spjd case LOG_ERR: 183204076Spjd return ("ERROR"); 184204076Spjd case LOG_WARNING: 185204076Spjd return ("WARNING"); 186204076Spjd case LOG_NOTICE: 187204076Spjd return ("NOTICE"); 188204076Spjd case LOG_INFO: 189204076Spjd return ("INFO"); 190204076Spjd case LOG_DEBUG: 191204076Spjd return ("DEBUG"); 192204076Spjd } 193204076Spjd assert(!"Invalid log level."); 194204076Spjd abort(); /* XXX: gcc */ 195204076Spjd} 196204076Spjd 197204076Spjd/* 198204076Spjd * Common log routine. 199204076Spjd */ 200204076Spjdvoid 201204076Spjdpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 202204076Spjd{ 203204076Spjd va_list ap; 204204076Spjd 205217965Spjd assert(pjdlog_initialized); 206217965Spjd 207204076Spjd va_start(ap, fmt); 208204076Spjd pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 209204076Spjd va_end(ap); 210204076Spjd} 211204076Spjd 212204076Spjd/* 213204076Spjd * Common log routine, which can handle regular log level as well as debug 214204076Spjd * level. We decide here where to send the logs (stdout/stderr or syslog). 215204076Spjd */ 216204076Spjdvoid 217204076Spjdpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 218204076Spjd va_list ap) 219204076Spjd{ 220204076Spjd 221217965Spjd assert(pjdlog_initialized); 222204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 223204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 224204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 225204076Spjd loglevel == LOG_INFO || loglevel == LOG_DEBUG); 226204076Spjd assert(loglevel != LOG_DEBUG || debuglevel > 0); 227204076Spjd assert(error >= -1); 228204076Spjd 229204076Spjd /* Ignore debug above configured level. */ 230204076Spjd if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 231204076Spjd return; 232204076Spjd 233204076Spjd switch (pjdlog_mode) { 234204076Spjd case PJDLOG_MODE_STD: 235204076Spjd { 236204076Spjd FILE *out; 237204076Spjd 238204076Spjd /* 239204076Spjd * We send errors and warning to stderr and the rest to stdout. 240204076Spjd */ 241204076Spjd switch (loglevel) { 242204076Spjd case LOG_EMERG: 243204076Spjd case LOG_ALERT: 244204076Spjd case LOG_CRIT: 245204076Spjd case LOG_ERR: 246204076Spjd case LOG_WARNING: 247204076Spjd out = stderr; 248204076Spjd break; 249204076Spjd case LOG_NOTICE: 250204076Spjd case LOG_INFO: 251204076Spjd case LOG_DEBUG: 252204076Spjd out = stdout; 253204076Spjd break; 254204076Spjd default: 255204076Spjd assert(!"Invalid loglevel."); 256204076Spjd abort(); /* XXX: gcc */ 257204076Spjd } 258204076Spjd 259204076Spjd fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 260204076Spjd /* Attach debuglevel if this is debug log. */ 261204076Spjd if (loglevel == LOG_DEBUG) 262204076Spjd fprintf(out, "[%d]", debuglevel); 263213939Spjd fprintf(out, " %s", pjdlog_prefix); 264204076Spjd vfprintf(out, fmt, ap); 265204076Spjd if (error != -1) 266204076Spjd fprintf(out, ": %s.", strerror(error)); 267204076Spjd fprintf(out, "\n"); 268211898Spjd fflush(out); 269204076Spjd break; 270204076Spjd } 271204076Spjd case PJDLOG_MODE_SYSLOG: 272204076Spjd { 273204076Spjd char log[1024]; 274204076Spjd int len; 275204076Spjd 276204076Spjd len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 277204076Spjd if ((size_t)len < sizeof(log)) 278206697Spjd len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 279204076Spjd if (error != -1 && (size_t)len < sizeof(log)) { 280204076Spjd (void)snprintf(log + len, sizeof(log) - len, ": %s.", 281204076Spjd strerror(error)); 282204076Spjd } 283204076Spjd syslog(loglevel, "%s", log); 284204076Spjd break; 285204076Spjd } 286204076Spjd default: 287204076Spjd assert(!"Invalid mode."); 288204076Spjd } 289204076Spjd} 290204076Spjd 291204076Spjd/* 292204076Spjd * Regular logs. 293204076Spjd */ 294204076Spjdvoid 295204076Spjdpjdlogv(int loglevel, const char *fmt, va_list ap) 296204076Spjd{ 297204076Spjd 298217965Spjd assert(pjdlog_initialized); 299217965Spjd 300204076Spjd /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 301204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 302204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 303204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 304204076Spjd loglevel == LOG_INFO); 305204076Spjd 306204076Spjd pjdlogv_common(loglevel, 0, -1, fmt, ap); 307204076Spjd} 308204076Spjd 309204076Spjd/* 310204076Spjd * Regular logs. 311204076Spjd */ 312204076Spjdvoid 313204076Spjdpjdlog(int loglevel, const char *fmt, ...) 314204076Spjd{ 315204076Spjd va_list ap; 316204076Spjd 317217965Spjd assert(pjdlog_initialized); 318217965Spjd 319204076Spjd va_start(ap, fmt); 320204076Spjd pjdlogv(loglevel, fmt, ap); 321204076Spjd va_end(ap); 322204076Spjd} 323204076Spjd 324204076Spjd/* 325204076Spjd * Debug logs. 326204076Spjd */ 327204076Spjdvoid 328204076Spjdpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 329204076Spjd{ 330204076Spjd 331217965Spjd assert(pjdlog_initialized); 332217965Spjd 333204076Spjd pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 334204076Spjd} 335204076Spjd 336204076Spjd/* 337204076Spjd * Debug logs. 338204076Spjd */ 339204076Spjdvoid 340204076Spjdpjdlog_debug(int debuglevel, const char *fmt, ...) 341204076Spjd{ 342204076Spjd va_list ap; 343204076Spjd 344217965Spjd assert(pjdlog_initialized); 345217965Spjd 346204076Spjd va_start(ap, fmt); 347204076Spjd pjdlogv_debug(debuglevel, fmt, ap); 348204076Spjd va_end(ap); 349204076Spjd} 350204076Spjd 351204076Spjd/* 352204076Spjd * Error logs with errno logging. 353204076Spjd */ 354204076Spjdvoid 355204076Spjdpjdlogv_errno(int loglevel, const char *fmt, va_list ap) 356204076Spjd{ 357204076Spjd 358217965Spjd assert(pjdlog_initialized); 359217965Spjd 360204076Spjd pjdlogv_common(loglevel, 0, errno, fmt, ap); 361204076Spjd} 362204076Spjd 363204076Spjd/* 364204076Spjd * Error logs with errno logging. 365204076Spjd */ 366204076Spjdvoid 367204076Spjdpjdlog_errno(int loglevel, const char *fmt, ...) 368204076Spjd{ 369204076Spjd va_list ap; 370204076Spjd 371217965Spjd assert(pjdlog_initialized); 372217965Spjd 373204076Spjd va_start(ap, fmt); 374204076Spjd pjdlogv_errno(loglevel, fmt, ap); 375204076Spjd va_end(ap); 376204076Spjd} 377204076Spjd 378204076Spjd/* 379204076Spjd * Log error, errno and exit. 380204076Spjd */ 381204076Spjdvoid 382204076Spjdpjdlogv_exit(int exitcode, const char *fmt, va_list ap) 383204076Spjd{ 384204076Spjd 385217965Spjd assert(pjdlog_initialized); 386217965Spjd 387204076Spjd pjdlogv_errno(LOG_ERR, fmt, ap); 388204076Spjd exit(exitcode); 389210872Spjd /* NOTREACHED */ 390204076Spjd} 391204076Spjd 392204076Spjd/* 393204076Spjd * Log error, errno and exit. 394204076Spjd */ 395204076Spjdvoid 396204076Spjdpjdlog_exit(int exitcode, const char *fmt, ...) 397204076Spjd{ 398204076Spjd va_list ap; 399204076Spjd 400217965Spjd assert(pjdlog_initialized); 401217965Spjd 402204076Spjd va_start(ap, fmt); 403204076Spjd pjdlogv_exit(exitcode, fmt, ap); 404204076Spjd /* NOTREACHED */ 405204076Spjd va_end(ap); 406204076Spjd} 407204076Spjd 408204076Spjd/* 409204076Spjd * Log error and exit. 410204076Spjd */ 411204076Spjdvoid 412204076Spjdpjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 413204076Spjd{ 414204076Spjd 415217965Spjd assert(pjdlog_initialized); 416217965Spjd 417204076Spjd pjdlogv(LOG_ERR, fmt, ap); 418204076Spjd exit(exitcode); 419210872Spjd /* NOTREACHED */ 420204076Spjd} 421204076Spjd 422204076Spjd/* 423204076Spjd * Log error and exit. 424204076Spjd */ 425204076Spjdvoid 426204076Spjdpjdlog_exitx(int exitcode, const char *fmt, ...) 427204076Spjd{ 428204076Spjd va_list ap; 429204076Spjd 430217965Spjd assert(pjdlog_initialized); 431217965Spjd 432204076Spjd va_start(ap, fmt); 433204076Spjd pjdlogv_exitx(exitcode, fmt, ap); 434204076Spjd /* NOTREACHED */ 435204076Spjd va_end(ap); 436204076Spjd} 437210875Spjd 438210875Spjd/* 439210875Spjd * Log assertion and exit. 440210875Spjd */ 441210875Spjdvoid 442210875Spjdpjdlog_verify(const char *func, const char *file, int line, 443210875Spjd const char *failedexpr) 444210875Spjd{ 445210875Spjd 446210875Spjd if (func == NULL) { 447210875Spjd pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 448210875Spjd failedexpr, file, line); 449210875Spjd } else { 450210875Spjd pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 451210875Spjd failedexpr, func, file, line); 452210875Spjd } 453210875Spjd abort(); 454210875Spjd} 455