pjdlog.c revision 206697
1165023Sgrog/*- 2165023Sgrog * Copyright (c) 2009-2010 The FreeBSD Foundation 3165023Sgrog * All rights reserved. 4165023Sgrog * 5165023Sgrog * This software was developed by Pawel Jakub Dawidek under sponsorship from 6165023Sgrog * the FreeBSD Foundation. 7165023Sgrog * 8165023Sgrog * Redistribution and use in source and binary forms, with or without 9165023Sgrog * modification, are permitted provided that the following conditions 10165023Sgrog * are met: 11165023Sgrog * 1. Redistributions of source code must retain the above copyright 12165023Sgrog * notice, this list of conditions and the following disclaimer. 13165023Sgrog * 2. Redistributions in binary form must reproduce the above copyright 14165025Sgrog * notice, this list of conditions and the following disclaimer in the 15165025Sgrog * documentation and/or other materials provided with the distribution. 16165025Sgrog * 17165025Sgrog * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18165025Sgrog * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19165025Sgrog * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20165025Sgrog * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21165025Sgrog * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22165025Sgrog * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23165025Sgrog * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24165025Sgrog * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25165023Sgrog * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26165023Sgrog * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27165023Sgrog * SUCH DAMAGE. 28165023Sgrog * 29165026Sgrog * $FreeBSD: head/sbin/hastd/pjdlog.c 206697 2010-04-16 06:49:12Z pjd $ 30165023Sgrog */ 31165023Sgrog 32165023Sgrog#include <sys/cdefs.h> 33165023Sgrog__FBSDID("$FreeBSD: head/sbin/hastd/pjdlog.c 206697 2010-04-16 06:49:12Z pjd $"); 34165023Sgrog 35165023Sgrog#include <assert.h> 36165023Sgrog#include <errno.h> 37165023Sgrog#include <stdarg.h> 38165023Sgrog#include <stdio.h> 39165023Sgrog#include <stdlib.h> 40165023Sgrog#include <string.h> 41165023Sgrog#include <syslog.h> 42165023Sgrog 43165023Sgrog#include "pjdlog.h" 44165023Sgrog 45165023Sgrogstatic int pjdlog_mode = PJDLOG_MODE_STD; 46165023Sgrogstatic int pjdlog_debug_level = 0; 47165023Sgrogstatic char pjdlog_prefix[128]; 48165023Sgrog 49165023Sgrog/* 50165023Sgrog * Configure where the logs should go. 51165023Sgrog * By default they are send to stdout/stderr, but after going into background 52165023Sgrog * (eg. by calling daemon(3)) application is responsible for changing mode to 53165026Sgrog * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 54165026Sgrog */ 55165026Sgrogvoid 56165026Sgrogpjdlog_mode_set(int mode) 57166959Sgrog{ 58166959Sgrog 59166959Sgrog assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 60166959Sgrog 61166959Sgrog pjdlog_mode = mode; 62166959Sgrog} 63165026Sgrog 64165026Sgrog/* 65165026Sgrog * Return current mode. 66165026Sgrog */ 67165026Sgrogint 68165026Sgrogpjdlog_mode_get(void) 69165026Sgrog{ 70165026Sgrog 71165026Sgrog return (pjdlog_mode); 72165026Sgrog} 73165026Sgrog 74166959Sgrog/* 75166959Sgrog * Set debug level. All the logs above the level specified here will be 76165026Sgrog * ignored. 77165026Sgrog */ 78165026Sgrogvoid 79165023Sgrogpjdlog_debug_set(int level) 80165023Sgrog{ 81165026Sgrog 82165026Sgrog assert(level >= 0); 83165023Sgrog 84165026Sgrog pjdlog_debug_level = level; 85165026Sgrog} 86165026Sgrog 87165026Sgrog/* 88165026Sgrog * Return current debug level. 89165026Sgrog */ 90165026Sgrogint 91165026Sgrogpjdlog_debug_get(void) 92165026Sgrog{ 93165026Sgrog 94165026Sgrog return (pjdlog_debug_level); 95165026Sgrog} 96165026Sgrog 97165026Sgrog/* 98165026Sgrog * Set prefix that will be used before each log. 99165026Sgrog * Setting prefix to NULL will remove it. 100165023Sgrog */ 101165026Sgrogvoid 102165026Sgrogpjdlog_prefix_set(const char *fmt, ...) 103165026Sgrog{ 104165026Sgrog va_list ap; 105165026Sgrog 106165026Sgrog va_start(ap, fmt); 107165026Sgrog pjdlog_prefix_setv(fmt, ap); 108165026Sgrog va_end(ap); 109165026Sgrog} 110165023Sgrog 111166959Sgrog/* 112165026Sgrog * Set prefix that will be used before each log. 113165026Sgrog * Setting prefix to NULL will remove it. 114165026Sgrog */ 115165026Sgrogvoid 116165026Sgrogpjdlog_prefix_setv(const char *fmt, va_list ap) 117165026Sgrog{ 118165026Sgrog 119165026Sgrog assert(fmt != NULL); 120165026Sgrog 121165026Sgrog vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 122165026Sgrog} 123165023Sgrog 124165026Sgrog/* 125165026Sgrog * Convert log level into string. 126165026Sgrog */ 127165026Sgrogstatic const char * 128165023Sgrogpjdlog_level_string(int loglevel) 129165026Sgrog{ 130165026Sgrog 131165026Sgrog switch (loglevel) { 132165026Sgrog case LOG_EMERG: 133165023Sgrog return ("EMERG"); 134165026Sgrog case LOG_ALERT: 135165026Sgrog return ("ALERT"); 136165026Sgrog case LOG_CRIT: 137165026Sgrog return ("CRIT"); 138165023Sgrog case LOG_ERR: 139165026Sgrog return ("ERROR"); 140165026Sgrog case LOG_WARNING: 141165026Sgrog return ("WARNING"); 142165026Sgrog case LOG_NOTICE: 143165023Sgrog return ("NOTICE"); 144165026Sgrog case LOG_INFO: 145165026Sgrog return ("INFO"); 146165026Sgrog case LOG_DEBUG: 147165026Sgrog return ("DEBUG"); 148165026Sgrog } 149165026Sgrog assert(!"Invalid log level."); 150165026Sgrog abort(); /* XXX: gcc */ 151165023Sgrog} 152165026Sgrog 153165026Sgrog/* 154165026Sgrog * Common log routine. 155165026Sgrog */ 156165026Sgrogvoid 157165026Sgrogpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 158165026Sgrog{ 159165023Sgrog va_list ap; 160165026Sgrog 161165026Sgrog va_start(ap, fmt); 162165026Sgrog pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 163165026Sgrog va_end(ap); 164165023Sgrog} 165165026Sgrog 166165023Sgrog/* 167165026Sgrog * Common log routine, which can handle regular log level as well as debug 168165026Sgrog * level. We decide here where to send the logs (stdout/stderr or syslog). 169165026Sgrog */ 170165023Sgrogvoid 171165026Sgrogpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 172165026Sgrog va_list ap) 173165026Sgrog{ 174165026Sgrog 175165026Sgrog assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 176165026Sgrog loglevel == LOG_CRIT || loglevel == LOG_ERR || 177165023Sgrog loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 178165026Sgrog loglevel == LOG_INFO || loglevel == LOG_DEBUG); 179165023Sgrog assert(loglevel != LOG_DEBUG || debuglevel > 0); 180165026Sgrog assert(error >= -1); 181165026Sgrog 182165026Sgrog /* Ignore debug above configured level. */ 183165026Sgrog if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 184165026Sgrog return; 185165023Sgrog 186165026Sgrog switch (pjdlog_mode) { 187165026Sgrog case PJDLOG_MODE_STD: 188165026Sgrog { 189165026Sgrog FILE *out; 190165023Sgrog 191165026Sgrog /* 192165026Sgrog * We send errors and warning to stderr and the rest to stdout. 193165023Sgrog */ 194165026Sgrog switch (loglevel) { 195165026Sgrog case LOG_EMERG: 196165026Sgrog case LOG_ALERT: 197165026Sgrog case LOG_CRIT: 198165023Sgrog case LOG_ERR: 199165026Sgrog case LOG_WARNING: 200165026Sgrog out = stderr; 201165026Sgrog break; 202165026Sgrog case LOG_NOTICE: 203165026Sgrog case LOG_INFO: 204165023Sgrog case LOG_DEBUG: 205165026Sgrog out = stdout; 206165026Sgrog break; 207165026Sgrog default: 208165026Sgrog assert(!"Invalid loglevel."); 209165026Sgrog abort(); /* XXX: gcc */ 210165023Sgrog } 211165026Sgrog 212165026Sgrog fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 213165026Sgrog /* Attach debuglevel if this is debug log. */ 214165026Sgrog if (loglevel == LOG_DEBUG) 215165026Sgrog fprintf(out, "[%d]", debuglevel); 216165023Sgrog fprintf(out, " "); 217165026Sgrog fprintf(out, "%s", pjdlog_prefix); 218165026Sgrog vfprintf(out, fmt, ap); 219165026Sgrog if (error != -1) 220165026Sgrog fprintf(out, ": %s.", strerror(error)); 221165026Sgrog fprintf(out, "\n"); 222165023Sgrog break; 223165026Sgrog } 224165026Sgrog case PJDLOG_MODE_SYSLOG: 225165026Sgrog { 226165026Sgrog char log[1024]; 227165026Sgrog int len; 228165023Sgrog 229165026Sgrog len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 230165026Sgrog if ((size_t)len < sizeof(log)) 231165026Sgrog len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 232165026Sgrog if (error != -1 && (size_t)len < sizeof(log)) { 233165023Sgrog (void)snprintf(log + len, sizeof(log) - len, ": %s.", 234165026Sgrog strerror(error)); 235165026Sgrog } 236165026Sgrog syslog(loglevel, "%s", log); 237165026Sgrog break; 238165026Sgrog } 239165026Sgrog default: 240165026Sgrog assert(!"Invalid mode."); 241165026Sgrog } 242165026Sgrog} 243165023Sgrog 244165026Sgrog/* 245165026Sgrog * Regular logs. 246165026Sgrog */ 247165026Sgrogvoid 248165026Sgrogpjdlogv(int loglevel, const char *fmt, va_list ap) 249165023Sgrog{ 250165026Sgrog 251165026Sgrog /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 252165026Sgrog assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 253165026Sgrog loglevel == LOG_CRIT || loglevel == LOG_ERR || 254165026Sgrog loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 255165026Sgrog loglevel == LOG_INFO); 256165026Sgrog 257165026Sgrog pjdlogv_common(loglevel, 0, -1, fmt, ap); 258165026Sgrog} 259165023Sgrog 260165026Sgrog/* 261165026Sgrog * Regular logs. 262165026Sgrog */ 263165026Sgrogvoid 264165026Sgrogpjdlog(int loglevel, const char *fmt, ...) 265165026Sgrog{ 266165026Sgrog va_list ap; 267165023Sgrog 268165026Sgrog va_start(ap, fmt); 269165026Sgrog pjdlogv(loglevel, fmt, ap); 270165026Sgrog va_end(ap); 271165026Sgrog} 272165026Sgrog 273165026Sgrog/* 274165023Sgrog * Debug logs. 275165026Sgrog */ 276165026Sgrogvoid 277165023Sgrogpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 278{ 279 280 pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 281} 282 283/* 284 * Debug logs. 285 */ 286void 287pjdlog_debug(int debuglevel, const char *fmt, ...) 288{ 289 va_list ap; 290 291 va_start(ap, fmt); 292 pjdlogv_debug(debuglevel, fmt, ap); 293 va_end(ap); 294} 295 296/* 297 * Error logs with errno logging. 298 */ 299void 300pjdlogv_errno(int loglevel, const char *fmt, va_list ap) 301{ 302 303 pjdlogv_common(loglevel, 0, errno, fmt, ap); 304} 305 306/* 307 * Error logs with errno logging. 308 */ 309void 310pjdlog_errno(int loglevel, const char *fmt, ...) 311{ 312 va_list ap; 313 314 va_start(ap, fmt); 315 pjdlogv_errno(loglevel, fmt, ap); 316 va_end(ap); 317} 318 319/* 320 * Log error, errno and exit. 321 */ 322void 323pjdlogv_exit(int exitcode, const char *fmt, va_list ap) 324{ 325 326 pjdlogv_errno(LOG_ERR, fmt, ap); 327 exit(exitcode); 328} 329 330/* 331 * Log error, errno and exit. 332 */ 333void 334pjdlog_exit(int exitcode, const char *fmt, ...) 335{ 336 va_list ap; 337 338 va_start(ap, fmt); 339 pjdlogv_exit(exitcode, fmt, ap); 340 /* NOTREACHED */ 341 va_end(ap); 342} 343 344/* 345 * Log error and exit. 346 */ 347void 348pjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 349{ 350 351 pjdlogv(LOG_ERR, fmt, ap); 352 exit(exitcode); 353} 354 355/* 356 * Log error and exit. 357 */ 358void 359pjdlog_exitx(int exitcode, const char *fmt, ...) 360{ 361 va_list ap; 362 363 va_start(ap, fmt); 364 pjdlogv_exitx(exitcode, fmt, ap); 365 /* NOTREACHED */ 366 va_end(ap); 367} 368