pjdlog.c revision 218040
1139825Simp/*- 242805Skato * Copyright (c) 2009-2010 The FreeBSD Foundation 342805Skato * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> 442805Skato * All rights reserved. 542805Skato * 642805Skato * This software was developed by Pawel Jakub Dawidek under sponsorship from 742805Skato * the FreeBSD Foundation. 842805Skato * 942805Skato * Redistribution and use in source and binary forms, with or without 1042805Skato * modification, are permitted provided that the following conditions 1142805Skato * are met: 1242805Skato * 1. Redistributions of source code must retain the above copyright 1342805Skato * notice, this list of conditions and the following disclaimer. 1442805Skato * 2. Redistributions in binary form must reproduce the above copyright 1542805Skato * notice, this list of conditions and the following disclaimer in the 1642805Skato * documentation and/or other materials provided with the distribution. 1742805Skato * 1842805Skato * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 1942805Skato * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2042805Skato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2142805Skato * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 2242805Skato * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2342805Skato * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2442805Skato * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2542805Skato * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2642805Skato * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2742805Skato * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2850477Speter * SUCH DAMAGE. 2942795Skato */ 3042795Skato 31162711Sru#include <sys/cdefs.h> 3242795Skato__FBSDID("$FreeBSD: head/sbin/hastd/pjdlog.c 218040 2011-01-28 21:36:01Z pjd $"); 3342795Skato 3442795Skato#include <assert.h> 3542795Skato#include <errno.h> 3642795Skato#include <stdarg.h> 3745783Skato#include <stdbool.h> 3842795Skato#include <stdio.h> 3945783Skato#include <stdlib.h> 4045783Skato#include <string.h> 4167370Skato#include <syslog.h> 4242795Skato 4342795Skato#include "pjdlog.h" 4442795Skato 4542795Skatostatic bool pjdlog_initialized = false; 4642795Skatostatic int pjdlog_mode, pjdlog_debug_level; 47146049Snyanstatic char pjdlog_prefix[128]; 4845783Skato 4945783Skatovoid 5042795Skatopjdlog_init(int mode) 5142795Skato{ 5242795Skato 5342795Skato assert(!pjdlog_initialized); 5442795Skato assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 5545783Skato 5642795Skato if (mode == PJDLOG_MODE_SYSLOG) 5745783Skato openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 5845783Skato pjdlog_mode = mode; 5979702Snyan pjdlog_debug_level = 0; 6045783Skato bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); 6142795Skato 6245783Skato pjdlog_initialized = true; 6345783Skato} 6445783Skato 6545783Skatovoid 6679702Snyanpjdlog_fini(void) 6745783Skato{ 6845783Skato 6942795Skato assert(pjdlog_initialized); 7045783Skato 7142795Skato if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 7245783Skato closelog(); 7350236Skato 7442795Skato pjdlog_initialized = false; 7542795Skato} 7645783Skato 7745783Skato/* 7878385Snyan * Configure where the logs should go. 7978385Snyan * By default they are send to stdout/stderr, but after going into background 8044635Skato * (eg. by calling daemon(3)) application is responsible for changing mode to 8144635Skato * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 8250236Skato */ 8344635Skatovoid 8442795Skatopjdlog_mode_set(int mode) 8542795Skato{ 8642795Skato 8742795Skato assert(pjdlog_initialized); 8845783Skato assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 8942795Skato 9078385Snyan if (pjdlog_mode == mode) 9178385Snyan return; 9278385Snyan 9351276Snyan if (mode == PJDLOG_MODE_SYSLOG) 9451276Snyan openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 9551276Snyan else /* if (mode == PJDLOG_MODE_STD) */ 9651276Snyan closelog(); 9745783Skato 9845783Skato pjdlog_mode = mode; 9978385Snyan} 10078385Snyan 10178385Snyan/* 10278385Snyan * Return current mode. 10378385Snyan */ 10478385Snyanint 10578385Snyanpjdlog_mode_get(void) 10678385Snyan{ 10778385Snyan 10878385Snyan assert(pjdlog_initialized); 10978385Snyan 11078385Snyan return (pjdlog_mode); 11178385Snyan} 11278385Snyan 11378385Snyan/* 11442795Skato * Set debug level. All the logs above the level specified here will be 11542795Skato * ignored. 11642795Skato */ 11745783Skatovoid 11842795Skatopjdlog_debug_set(int level) 11950236Skato{ 12045783Skato 12145783Skato assert(pjdlog_initialized); 12278385Snyan assert(level >= 0); 12342795Skato 12478385Snyan pjdlog_debug_level = level; 12578385Snyan} 12678385Snyan 12778385Snyan/* 12878385Snyan * Return current debug level. 12978385Snyan */ 13045783Skatoint 13178385Snyanpjdlog_debug_get(void) 13278385Snyan{ 13378385Snyan 13478385Snyan assert(pjdlog_initialized); 13578385Snyan 13678385Snyan return (pjdlog_debug_level); 137127135Snjl} 13878385Snyan 13978385Snyan/* 140166901Spiso * Set prefix that will be used before each log. 14145783Skato * Setting prefix to NULL will remove it. 14279702Snyan */ 14379702Snyanvoid 14479702Snyanpjdlog_prefix_set(const char *fmt, ...) 14579702Snyan{ 14679702Snyan va_list ap; 14779702Snyan 14879702Snyan assert(pjdlog_initialized); 14979702Snyan 15079702Snyan va_start(ap, fmt); 15179702Snyan pjdlogv_prefix_set(fmt, ap); 15279702Snyan va_end(ap); 153175001Snyan} 15479702Snyan 15545783Skato/* 15642795Skato * Set prefix that will be used before each log. 15742795Skato * Setting prefix to NULL will remove it. 15842795Skato */ 15945783Skatovoid 16042795Skatopjdlogv_prefix_set(const char *fmt, va_list ap) 16150236Skato{ 16242795Skato 163175001Snyan assert(pjdlog_initialized); 16442795Skato assert(fmt != NULL); 16542795Skato 16642795Skato vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 16744635Skato} 16842795Skato 16942795Skato/* 17042795Skato * Convert log level into string. 17144635Skato */ 17242795Skatostatic const char * 17342795Skatopjdlog_level_string(int loglevel) 17442795Skato{ 17542795Skato 17642795Skato switch (loglevel) { 17742795Skato case LOG_EMERG: 17842795Skato return ("EMERG"); 17944635Skato case LOG_ALERT: 18044635Skato return ("ALERT"); 18144635Skato case LOG_CRIT: 18244635Skato return ("CRIT"); 18342795Skato case LOG_ERR: 18442795Skato return ("ERROR"); 18542795Skato case LOG_WARNING: 18650236Skato return ("WARNING"); 18742795Skato case LOG_NOTICE: 18842795Skato return ("NOTICE"); 18944635Skato case LOG_INFO: 19042795Skato return ("INFO"); 19142795Skato case LOG_DEBUG: 19242795Skato return ("DEBUG"); 19342795Skato } 19442795Skato assert(!"Invalid log level."); 19542795Skato abort(); /* XXX: gcc */ 19642795Skato} 19744635Skato 19844635Skato/* 19950236Skato * Common log routine. 20044635Skato */ 20142795Skatovoid 20244635Skatopjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 20350236Skato{ 20444635Skato va_list ap; 20544635Skato 20650236Skato assert(pjdlog_initialized); 20742795Skato 20842795Skato va_start(ap, fmt); 20942795Skato pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 21050236Skato va_end(ap); 21142795Skato} 21242795Skato 21342795Skato/* 21442795Skato * Common log routine, which can handle regular log level as well as debug 21542795Skato * level. We decide here where to send the logs (stdout/stderr or syslog). 21642795Skato */ 21742795Skatovoid 21842795Skatopjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 21950236Skato va_list ap) 22042795Skato{ 22142795Skato 22250236Skato assert(pjdlog_initialized); 22342795Skato assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 22442795Skato loglevel == LOG_CRIT || loglevel == LOG_ERR || 22542795Skato loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 22642795Skato loglevel == LOG_INFO || loglevel == LOG_DEBUG); 22742795Skato assert(loglevel != LOG_DEBUG || debuglevel > 0); 22842795Skato assert(error >= -1); 22942795Skato 23042795Skato /* Ignore debug above configured level. */ 23142795Skato if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 23242795Skato return; 23342795Skato 23442795Skato switch (pjdlog_mode) { 23542795Skato case PJDLOG_MODE_STD: 23642795Skato { 23742795Skato FILE *out; 23842795Skato 23942795Skato /* 24042795Skato * We send errors and warning to stderr and the rest to stdout. 24142795Skato */ 24242795Skato switch (loglevel) { 24342795Skato case LOG_EMERG: 24442795Skato case LOG_ALERT: 24542795Skato case LOG_CRIT: 24642795Skato case LOG_ERR: 24742795Skato case LOG_WARNING: 24842795Skato out = stderr; 249175001Snyan break; 25042795Skato case LOG_NOTICE: 25142795Skato case LOG_INFO: 25242795Skato case LOG_DEBUG: 25342795Skato out = stdout; 25442795Skato break; 255175001Snyan default: 256175001Snyan assert(!"Invalid loglevel."); 257175001Snyan abort(); /* XXX: gcc */ 25842795Skato } 25942795Skato 26042795Skato fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 26142795Skato /* Attach debuglevel if this is debug log. */ 26242795Skato if (loglevel == LOG_DEBUG) 26342795Skato fprintf(out, "[%d]", debuglevel); 26442795Skato fprintf(out, " %s", pjdlog_prefix); 265114216Skan vfprintf(out, fmt, ap); 26642795Skato if (error != -1) 26742795Skato fprintf(out, ": %s.", strerror(error)); 26842795Skato fprintf(out, "\n"); 26942795Skato fflush(out); 27042795Skato break; 27142795Skato } 27242795Skato case PJDLOG_MODE_SYSLOG: 27342795Skato { 27442795Skato char log[1024]; 27542795Skato int len; 27642795Skato 27742795Skato len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 27842795Skato if ((size_t)len < sizeof(log)) 27942795Skato len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 28042795Skato if (error != -1 && (size_t)len < sizeof(log)) { 28142795Skato (void)snprintf(log + len, sizeof(log) - len, ": %s.", 28242795Skato strerror(error)); 28342795Skato } 28442795Skato syslog(loglevel, "%s", log); 28542795Skato break; 28642795Skato } 28742795Skato default: 28842795Skato assert(!"Invalid mode."); 28942795Skato } 29042795Skato} 29142795Skato 29242795Skato/* 29342795Skato * Regular logs. 29442795Skato */ 29542795Skatovoid 29642795Skatopjdlogv(int loglevel, const char *fmt, va_list ap) 29742795Skato{ 29842795Skato 29944635Skato assert(pjdlog_initialized); 30042795Skato 30142795Skato /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 30242795Skato assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 30342795Skato loglevel == LOG_CRIT || loglevel == LOG_ERR || 30442795Skato loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 30542795Skato loglevel == LOG_INFO); 30642795Skato 30742795Skato pjdlogv_common(loglevel, 0, -1, fmt, ap); 30842795Skato} 30942795Skato 31042795Skato/* 31142795Skato * Regular logs. 31242795Skato */ 31342795Skatovoid 31442795Skatopjdlog(int loglevel, const char *fmt, ...) 31542795Skato{ 31642795Skato va_list ap; 31742795Skato 31842795Skato assert(pjdlog_initialized); 31944635Skato 32042795Skato va_start(ap, fmt); 32142795Skato pjdlogv(loglevel, fmt, ap); 32242795Skato va_end(ap); 32342795Skato} 32442795Skato 32542795Skato/* 32642795Skato * Debug logs. 32742795Skato */ 32842795Skatovoid 32942795Skatopjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 33042795Skato{ 33142795Skato 33242795Skato assert(pjdlog_initialized); 33342795Skato 33442795Skato pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 33542795Skato} 33642795Skato 33742795Skato/* 33842795Skato * Debug logs. 33942795Skato */ 34042795Skatovoid 34142795Skatopjdlog_debug(int debuglevel, const char *fmt, ...) 34242795Skato{ 343146138Snyan va_list ap; 34442795Skato 34542795Skato assert(pjdlog_initialized); 34642795Skato 34742795Skato va_start(ap, fmt); 34842795Skato pjdlogv_debug(debuglevel, fmt, ap); 34942795Skato va_end(ap); 35042795Skato} 35142795Skato 35242795Skato/* 35342795Skato * Error logs with errno logging. 35442795Skato */ 35542795Skatovoid 35642795Skatopjdlogv_errno(int loglevel, const char *fmt, va_list ap) 35742795Skato{ 35842795Skato 35942795Skato assert(pjdlog_initialized); 36042795Skato 36142795Skato pjdlogv_common(loglevel, 0, errno, fmt, ap); 36242795Skato} 36342795Skato 36442795Skato/* 36542795Skato * Error logs with errno logging. 36644635Skato */ 36742795Skatovoid 36842795Skatopjdlog_errno(int loglevel, const char *fmt, ...) 36945783Skato{ 37045783Skato va_list ap; 37144635Skato 372117167Sjhb assert(pjdlog_initialized); 37344635Skato 37444635Skato va_start(ap, fmt); 37544635Skato pjdlogv_errno(loglevel, fmt, ap); 37644635Skato va_end(ap); 37744635Skato} 37844635Skato 37944635Skato/* 38044635Skato * Log error, errno and exit. 38144635Skato */ 38242795Skatovoid 38342795Skatopjdlogv_exit(int exitcode, const char *fmt, va_list ap) 38442795Skato{ 38542795Skato 38644635Skato assert(pjdlog_initialized); 38744635Skato 38842795Skato pjdlogv_errno(LOG_ERR, fmt, ap); 38944635Skato exit(exitcode); 39044635Skato /* NOTREACHED */ 39142795Skato} 39244635Skato 39344635Skato/* 39442795Skato * Log error, errno and exit. 39542795Skato */ 39642795Skatovoid 39742795Skatopjdlog_exit(int exitcode, const char *fmt, ...) 39844635Skato{ 39942795Skato va_list ap; 40044635Skato 40142795Skato assert(pjdlog_initialized); 40242795Skato 40342795Skato va_start(ap, fmt); 40442795Skato pjdlogv_exit(exitcode, fmt, ap); 40542795Skato /* NOTREACHED */ 40642795Skato va_end(ap); 40744635Skato} 40842795Skato 40942795Skato/* 41044635Skato * Log error and exit. 41142795Skato */ 41242795Skatovoid 41342795Skatopjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 41442795Skato{ 41542795Skato 41642795Skato assert(pjdlog_initialized); 41742795Skato 41842795Skato pjdlogv(LOG_ERR, fmt, ap); 41942795Skato exit(exitcode); 42042795Skato /* NOTREACHED */ 42142795Skato} 42244635Skato 42342795Skato/* 42444635Skato * Log error and exit. 42544635Skato */ 42644635Skatovoid 42744635Skatopjdlog_exitx(int exitcode, const char *fmt, ...) 42844635Skato{ 42944635Skato va_list ap; 43044635Skato 43142795Skato assert(pjdlog_initialized); 43244635Skato 43344635Skato va_start(ap, fmt); 43442795Skato pjdlogv_exitx(exitcode, fmt, ap); 43544635Skato /* NOTREACHED */ 43644635Skato va_end(ap); 43744635Skato} 43844635Skato 43944635Skato/* 44044635Skato * Log assertion and exit. 44144635Skato */ 44244635Skatovoid 44344635Skatopjdlog_verify(const char *func, const char *file, int line, 44444635Skato const char *failedexpr, const char *fmt, ...) 44544635Skato{ 44644635Skato va_list ap; 44744635Skato 44844635Skato assert(pjdlog_initialized); 44944635Skato 45044635Skato /* 45144635Skato * When there is no message we pass __func__ as 'fmt'. 45244635Skato * It would be cleaner to pass NULL or "", but gcc generates a warning 45344635Skato * for both of those. 45444635Skato */ 45544635Skato if (fmt != func) { 45644635Skato va_start(ap, fmt); 45744635Skato pjdlogv_critical(fmt, ap); 45844635Skato va_end(ap); 45944635Skato } 46044635Skato if (failedexpr == NULL) { 46144635Skato if (func == NULL) { 46244635Skato pjdlog_critical("Aborted at file %s, line %d.", file, 46344635Skato line); 46444635Skato } else { 46544635Skato pjdlog_critical("Aborted at function %s, file %s, line %d.", 46644635Skato func, file, line); 46742795Skato } 46844635Skato } else { 46942795Skato if (func == NULL) { 47042795Skato pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 47144635Skato failedexpr, file, line); 47242795Skato } else { 47342795Skato pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 47442795Skato failedexpr, func, file, line); 47542795Skato } 47642795Skato } 47742795Skato abort(); 47842795Skato} 47942795Skato