1243730Srwatson/*- 2243730Srwatson * Copyright (c) 2009-2010 The FreeBSD Foundation 3243730Srwatson * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> 4243730Srwatson * All rights reserved. 5243730Srwatson * 6243730Srwatson * This software was developed by Pawel Jakub Dawidek under sponsorship from 7243730Srwatson * the FreeBSD Foundation. 8243730Srwatson * 9243730Srwatson * Redistribution and use in source and binary forms, with or without 10243730Srwatson * modification, are permitted provided that the following conditions 11243730Srwatson * are met: 12243730Srwatson * 1. Redistributions of source code must retain the above copyright 13243730Srwatson * notice, this list of conditions and the following disclaimer. 14243730Srwatson * 2. Redistributions in binary form must reproduce the above copyright 15243730Srwatson * notice, this list of conditions and the following disclaimer in the 16243730Srwatson * documentation and/or other materials provided with the distribution. 17243730Srwatson * 18243730Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19243730Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20243730Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21243730Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22243730Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23243730Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24243730Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25243730Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26243730Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27243730Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28243730Srwatson * SUCH DAMAGE. 29243730Srwatson * 30243730Srwatson * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/pjdlog.c#1 $ 31243730Srwatson */ 32243730Srwatson 33243730Srwatson#include <sys/types.h> 34243730Srwatson#include <sys/socket.h> 35243730Srwatson#include <netinet/in.h> 36243730Srwatson#include <arpa/inet.h> 37243730Srwatson 38243730Srwatson#include <assert.h> 39243730Srwatson#include <errno.h> 40243730Srwatson#ifdef __FreeBSD__ 41243730Srwatson#include <libutil.h> 42243730Srwatson#include <printf.h> 43243730Srwatson#endif 44243730Srwatson#include <stdarg.h> 45243730Srwatson#include <stdint.h> 46243730Srwatson#include <stdio.h> 47243730Srwatson#include <stdlib.h> 48243730Srwatson#include <string.h> 49243730Srwatson#include <syslog.h> 50243730Srwatson#include <unistd.h> 51243730Srwatson 52243730Srwatson#include "pjdlog.h" 53243730Srwatson 54243730Srwatson#define PJDLOG_NEVER_INITIALIZED 0 55243730Srwatson#define PJDLOG_NOT_INITIALIZED 1 56243730Srwatson#define PJDLOG_INITIALIZED 2 57243730Srwatson 58243730Srwatsonstatic int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; 59243730Srwatsonstatic int pjdlog_mode, pjdlog_debug_level; 60243730Srwatsonstatic char pjdlog_prefix[128]; 61243730Srwatson 62243730Srwatson#ifdef __FreeBSD__ 63243730Srwatsonstatic int 64243730Srwatsonpjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, 65243730Srwatson size_t n, int *argt) 66243730Srwatson{ 67243730Srwatson 68243730Srwatson assert(n >= 1); 69243730Srwatson argt[0] = PA_INT | PA_FLAG_INTMAX; 70243730Srwatson return (1); 71243730Srwatson} 72243730Srwatson 73243730Srwatsonstatic int 74243730Srwatsonpjdlog_printf_render_humanized_number(struct __printf_io *io, 75243730Srwatson const struct printf_info *pi, const void * const *arg) 76243730Srwatson{ 77243730Srwatson char buf[5]; 78243730Srwatson intmax_t num; 79243730Srwatson int ret; 80243730Srwatson 81243730Srwatson num = *(const intmax_t *)arg[0]; 82243730Srwatson humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, 83243730Srwatson HN_NOSPACE | HN_DECIMAL); 84243730Srwatson ret = __printf_out(io, pi, buf, strlen(buf)); 85243730Srwatson __printf_flush(io); 86243730Srwatson return (ret); 87243730Srwatson} 88243730Srwatson 89243730Srwatsonstatic int 90243730Srwatsonpjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, 91243730Srwatson size_t n, int *argt) 92243730Srwatson{ 93243730Srwatson 94243730Srwatson assert(n >= 1); 95243730Srwatson argt[0] = PA_POINTER; 96243730Srwatson return (1); 97243730Srwatson} 98243730Srwatson 99243730Srwatsonstatic int 100243730Srwatsonpjdlog_printf_render_sockaddr(struct __printf_io *io, 101243730Srwatson const struct printf_info *pi, const void * const *arg) 102243730Srwatson{ 103243730Srwatson const struct sockaddr_storage *ss; 104243730Srwatson char buf[64]; 105243730Srwatson int ret; 106243730Srwatson 107243730Srwatson ss = *(const struct sockaddr_storage * const *)arg[0]; 108243730Srwatson switch (ss->ss_family) { 109243730Srwatson case AF_INET: 110243730Srwatson { 111243730Srwatson char addr[INET_ADDRSTRLEN]; 112243730Srwatson const struct sockaddr_in *sin; 113243730Srwatson unsigned int port; 114243730Srwatson 115243730Srwatson sin = (const struct sockaddr_in *)ss; 116243730Srwatson port = ntohs(sin->sin_port); 117243730Srwatson if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, 118243730Srwatson sizeof(addr)) == NULL) { 119243730Srwatson PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", 120243730Srwatson strerror(errno)); 121243730Srwatson } 122243730Srwatson snprintf(buf, sizeof(buf), "%s:%u", addr, port); 123243730Srwatson break; 124243730Srwatson } 125243730Srwatson case AF_INET6: 126243730Srwatson { 127243730Srwatson char addr[INET6_ADDRSTRLEN]; 128243730Srwatson const struct sockaddr_in6 *sin; 129243730Srwatson unsigned int port; 130243730Srwatson 131243730Srwatson sin = (const struct sockaddr_in6 *)ss; 132243730Srwatson port = ntohs(sin->sin6_port); 133243730Srwatson if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, 134243730Srwatson sizeof(addr)) == NULL) { 135243730Srwatson PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", 136243730Srwatson strerror(errno)); 137243730Srwatson } 138243730Srwatson snprintf(buf, sizeof(buf), "[%s]:%u", addr, port); 139243730Srwatson break; 140243730Srwatson } 141243730Srwatson default: 142243730Srwatson snprintf(buf, sizeof(buf), "[unsupported family %hhu]", 143243730Srwatson ss->ss_family); 144243730Srwatson break; 145243730Srwatson } 146243730Srwatson ret = __printf_out(io, pi, buf, strlen(buf)); 147243730Srwatson __printf_flush(io); 148243730Srwatson return (ret); 149243730Srwatson} 150243730Srwatson#endif /* __FreeBSD__ */ 151243730Srwatson 152243730Srwatsonvoid 153243730Srwatsonpjdlog_init(int mode) 154243730Srwatson{ 155243730Srwatson int saved_errno; 156243730Srwatson 157243730Srwatson assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || 158243730Srwatson pjdlog_initialized == PJDLOG_NOT_INITIALIZED); 159243730Srwatson assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 160243730Srwatson 161243730Srwatson saved_errno = errno; 162243730Srwatson 163243730Srwatson if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { 164243730Srwatson#ifdef __FreeBSD__ 165243730Srwatson __use_xprintf = 1; 166243730Srwatson register_printf_render_std("T"); 167243730Srwatson register_printf_render('N', 168243730Srwatson pjdlog_printf_render_humanized_number, 169243730Srwatson pjdlog_printf_arginfo_humanized_number); 170243730Srwatson register_printf_render('S', 171243730Srwatson pjdlog_printf_render_sockaddr, 172243730Srwatson pjdlog_printf_arginfo_sockaddr); 173243730Srwatson#endif 174243730Srwatson } 175243730Srwatson 176243730Srwatson if (mode == PJDLOG_MODE_SYSLOG) 177243730Srwatson openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 178243730Srwatson pjdlog_mode = mode; 179243730Srwatson pjdlog_debug_level = 0; 180243730Srwatson bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); 181243730Srwatson 182243730Srwatson pjdlog_initialized = PJDLOG_INITIALIZED; 183243730Srwatson 184243730Srwatson errno = saved_errno; 185243730Srwatson} 186243730Srwatson 187243730Srwatsonvoid 188243730Srwatsonpjdlog_fini(void) 189243730Srwatson{ 190243730Srwatson int saved_errno; 191243730Srwatson 192243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 193243730Srwatson 194243730Srwatson saved_errno = errno; 195243730Srwatson 196243730Srwatson if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 197243730Srwatson closelog(); 198243730Srwatson 199243730Srwatson pjdlog_initialized = PJDLOG_NOT_INITIALIZED; 200243730Srwatson 201243730Srwatson errno = saved_errno; 202243730Srwatson} 203243730Srwatson 204243730Srwatson/* 205243730Srwatson * Configure where the logs should go. 206243730Srwatson * By default they are send to stdout/stderr, but after going into background 207243730Srwatson * (eg. by calling daemon(3)) application is responsible for changing mode to 208243730Srwatson * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 209243730Srwatson */ 210243730Srwatsonvoid 211243730Srwatsonpjdlog_mode_set(int mode) 212243730Srwatson{ 213243730Srwatson int saved_errno; 214243730Srwatson 215243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 216243730Srwatson assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 217243730Srwatson 218243730Srwatson if (pjdlog_mode == mode) 219243730Srwatson return; 220243730Srwatson 221243730Srwatson saved_errno = errno; 222243730Srwatson 223243730Srwatson if (mode == PJDLOG_MODE_SYSLOG) 224243730Srwatson openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 225243730Srwatson else /* if (mode == PJDLOG_MODE_STD) */ 226243730Srwatson closelog(); 227243730Srwatson 228243730Srwatson pjdlog_mode = mode; 229243730Srwatson 230243730Srwatson errno = saved_errno; 231243730Srwatson} 232243730Srwatson 233243730Srwatson/* 234243730Srwatson * Return current mode. 235243730Srwatson */ 236243730Srwatsonint 237243730Srwatsonpjdlog_mode_get(void) 238243730Srwatson{ 239243730Srwatson 240243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 241243730Srwatson 242243730Srwatson return (pjdlog_mode); 243243730Srwatson} 244243730Srwatson 245243730Srwatson/* 246243730Srwatson * Set debug level. All the logs above the level specified here will be 247243730Srwatson * ignored. 248243730Srwatson */ 249243730Srwatsonvoid 250243730Srwatsonpjdlog_debug_set(int level) 251243730Srwatson{ 252243730Srwatson 253243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 254243730Srwatson assert(level >= 0); 255243730Srwatson 256243730Srwatson pjdlog_debug_level = level; 257243730Srwatson} 258243730Srwatson 259243730Srwatson/* 260243730Srwatson * Return current debug level. 261243730Srwatson */ 262243730Srwatsonint 263243730Srwatsonpjdlog_debug_get(void) 264243730Srwatson{ 265243730Srwatson 266243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 267243730Srwatson 268243730Srwatson return (pjdlog_debug_level); 269243730Srwatson} 270243730Srwatson 271243730Srwatson/* 272243730Srwatson * Set prefix that will be used before each log. 273243730Srwatson * Setting prefix to NULL will remove it. 274243730Srwatson */ 275243730Srwatsonvoid 276243730Srwatsonpjdlog_prefix_set(const char *fmt, ...) 277243730Srwatson{ 278243730Srwatson va_list ap; 279243730Srwatson 280243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 281243730Srwatson 282243730Srwatson va_start(ap, fmt); 283243730Srwatson pjdlogv_prefix_set(fmt, ap); 284243730Srwatson va_end(ap); 285243730Srwatson} 286243730Srwatson 287243730Srwatson/* 288243730Srwatson * Set prefix that will be used before each log. 289243730Srwatson * Setting prefix to NULL will remove it. 290243730Srwatson */ 291243730Srwatsonvoid 292243730Srwatsonpjdlogv_prefix_set(const char *fmt, va_list ap) 293243730Srwatson{ 294243730Srwatson int saved_errno; 295243730Srwatson 296243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 297243730Srwatson assert(fmt != NULL); 298243730Srwatson 299243730Srwatson saved_errno = errno; 300243730Srwatson 301243730Srwatson vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 302243730Srwatson 303243730Srwatson errno = saved_errno; 304243730Srwatson} 305243730Srwatson 306243730Srwatson/* 307243730Srwatson * Convert log level into string. 308243730Srwatson */ 309243730Srwatsonstatic const char * 310243730Srwatsonpjdlog_level_string(int loglevel) 311243730Srwatson{ 312243730Srwatson 313243730Srwatson switch (loglevel) { 314243730Srwatson case LOG_EMERG: 315243730Srwatson return ("EMERG"); 316243730Srwatson case LOG_ALERT: 317243730Srwatson return ("ALERT"); 318243730Srwatson case LOG_CRIT: 319243730Srwatson return ("CRIT"); 320243730Srwatson case LOG_ERR: 321243730Srwatson return ("ERROR"); 322243730Srwatson case LOG_WARNING: 323243730Srwatson return ("WARNING"); 324243730Srwatson case LOG_NOTICE: 325243730Srwatson return ("NOTICE"); 326243730Srwatson case LOG_INFO: 327243730Srwatson return ("INFO"); 328243730Srwatson case LOG_DEBUG: 329243730Srwatson return ("DEBUG"); 330243730Srwatson } 331243730Srwatson assert(!"Invalid log level."); 332243730Srwatson abort(); /* XXX: gcc */ 333243730Srwatson} 334243730Srwatson 335243730Srwatson/* 336243730Srwatson * Common log routine. 337243730Srwatson */ 338243730Srwatsonvoid 339243730Srwatsonpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 340243730Srwatson{ 341243730Srwatson va_list ap; 342243730Srwatson 343243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 344243730Srwatson 345243730Srwatson va_start(ap, fmt); 346243730Srwatson pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 347243730Srwatson va_end(ap); 348243730Srwatson} 349243730Srwatson 350243730Srwatson/* 351243730Srwatson * Common log routine, which can handle regular log level as well as debug 352243730Srwatson * level. We decide here where to send the logs (stdout/stderr or syslog). 353243730Srwatson */ 354243730Srwatsonvoid 355243730Srwatsonpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 356243730Srwatson va_list ap) 357243730Srwatson{ 358243730Srwatson int saved_errno; 359243730Srwatson 360243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 361243730Srwatson assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 362243730Srwatson loglevel == LOG_CRIT || loglevel == LOG_ERR || 363243730Srwatson loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 364243730Srwatson loglevel == LOG_INFO || loglevel == LOG_DEBUG); 365243730Srwatson assert(loglevel != LOG_DEBUG || debuglevel > 0); 366243730Srwatson assert(error >= -1); 367243730Srwatson 368243730Srwatson /* Ignore debug above configured level. */ 369243730Srwatson if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 370243730Srwatson return; 371243730Srwatson 372243730Srwatson saved_errno = errno; 373243730Srwatson 374243730Srwatson switch (pjdlog_mode) { 375243730Srwatson case PJDLOG_MODE_STD: 376243730Srwatson { 377243730Srwatson FILE *out; 378243730Srwatson 379243730Srwatson /* 380243730Srwatson * We send errors and warning to stderr and the rest to stdout. 381243730Srwatson */ 382243730Srwatson switch (loglevel) { 383243730Srwatson case LOG_EMERG: 384243730Srwatson case LOG_ALERT: 385243730Srwatson case LOG_CRIT: 386243730Srwatson case LOG_ERR: 387243730Srwatson case LOG_WARNING: 388243730Srwatson out = stderr; 389243730Srwatson break; 390243730Srwatson case LOG_NOTICE: 391243730Srwatson case LOG_INFO: 392243730Srwatson case LOG_DEBUG: 393243730Srwatson out = stdout; 394243730Srwatson break; 395243730Srwatson default: 396243730Srwatson assert(!"Invalid loglevel."); 397243730Srwatson abort(); /* XXX: gcc */ 398243730Srwatson } 399243730Srwatson 400243730Srwatson fprintf(out, "(%d) ", getpid()); 401243730Srwatson fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 402243730Srwatson /* Attach debuglevel if this is debug log. */ 403243730Srwatson if (loglevel == LOG_DEBUG) 404243730Srwatson fprintf(out, "[%d]", debuglevel); 405243730Srwatson fprintf(out, " %s", pjdlog_prefix); 406243730Srwatson vfprintf(out, fmt, ap); 407243730Srwatson if (error != -1) 408243730Srwatson fprintf(out, ": %s.", strerror(error)); 409243730Srwatson fprintf(out, "\n"); 410243730Srwatson fflush(out); 411243730Srwatson break; 412243730Srwatson } 413243730Srwatson case PJDLOG_MODE_SYSLOG: 414243730Srwatson { 415243730Srwatson char log[1024]; 416243730Srwatson int len; 417243730Srwatson 418243730Srwatson len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 419243730Srwatson if ((size_t)len < sizeof(log)) 420243730Srwatson len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 421243730Srwatson if (error != -1 && (size_t)len < sizeof(log)) { 422243730Srwatson (void)snprintf(log + len, sizeof(log) - len, ": %s.", 423243730Srwatson strerror(error)); 424243730Srwatson } 425243730Srwatson syslog(loglevel, "%s", log); 426243730Srwatson break; 427243730Srwatson } 428243730Srwatson default: 429243730Srwatson assert(!"Invalid mode."); 430243730Srwatson } 431243730Srwatson 432243730Srwatson errno = saved_errno; 433243730Srwatson} 434243730Srwatson 435243730Srwatson/* 436243730Srwatson * Regular logs. 437243730Srwatson */ 438243730Srwatsonvoid 439243730Srwatsonpjdlogv(int loglevel, const char *fmt, va_list ap) 440243730Srwatson{ 441243730Srwatson 442243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 443243730Srwatson 444243730Srwatson /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 445243730Srwatson assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 446243730Srwatson loglevel == LOG_CRIT || loglevel == LOG_ERR || 447243730Srwatson loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 448243730Srwatson loglevel == LOG_INFO); 449243730Srwatson 450243730Srwatson pjdlogv_common(loglevel, 0, -1, fmt, ap); 451243730Srwatson} 452243730Srwatson 453243730Srwatson/* 454243730Srwatson * Regular logs. 455243730Srwatson */ 456243730Srwatsonvoid 457243730Srwatsonpjdlog(int loglevel, const char *fmt, ...) 458243730Srwatson{ 459243730Srwatson va_list ap; 460243730Srwatson 461243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 462243730Srwatson 463243730Srwatson va_start(ap, fmt); 464243730Srwatson pjdlogv(loglevel, fmt, ap); 465243730Srwatson va_end(ap); 466243730Srwatson} 467243730Srwatson 468243730Srwatson/* 469243730Srwatson * Debug logs. 470243730Srwatson */ 471243730Srwatsonvoid 472243730Srwatsonpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 473243730Srwatson{ 474243730Srwatson 475243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 476243730Srwatson 477243730Srwatson pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 478243730Srwatson} 479243730Srwatson 480243730Srwatson/* 481243730Srwatson * Debug logs. 482243730Srwatson */ 483243730Srwatsonvoid 484243730Srwatsonpjdlog_debug(int debuglevel, const char *fmt, ...) 485243730Srwatson{ 486243730Srwatson va_list ap; 487243730Srwatson 488243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 489243730Srwatson 490243730Srwatson va_start(ap, fmt); 491243730Srwatson pjdlogv_debug(debuglevel, fmt, ap); 492243730Srwatson va_end(ap); 493243730Srwatson} 494243730Srwatson 495243730Srwatson/* 496243730Srwatson * Error logs with errno logging. 497243730Srwatson */ 498243730Srwatsonvoid 499243730Srwatsonpjdlogv_errno(int loglevel, const char *fmt, va_list ap) 500243730Srwatson{ 501243730Srwatson 502243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 503243730Srwatson 504243730Srwatson pjdlogv_common(loglevel, 0, errno, fmt, ap); 505243730Srwatson} 506243730Srwatson 507243730Srwatson/* 508243730Srwatson * Error logs with errno logging. 509243730Srwatson */ 510243730Srwatsonvoid 511243730Srwatsonpjdlog_errno(int loglevel, const char *fmt, ...) 512243730Srwatson{ 513243730Srwatson va_list ap; 514243730Srwatson 515243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 516243730Srwatson 517243730Srwatson va_start(ap, fmt); 518243730Srwatson pjdlogv_errno(loglevel, fmt, ap); 519243730Srwatson va_end(ap); 520243730Srwatson} 521243730Srwatson 522243730Srwatson/* 523243730Srwatson * Log error, errno and exit. 524243730Srwatson */ 525243730Srwatsonvoid 526243730Srwatsonpjdlogv_exit(int exitcode, const char *fmt, va_list ap) 527243730Srwatson{ 528243730Srwatson 529243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 530243730Srwatson 531243730Srwatson pjdlogv_errno(LOG_ERR, fmt, ap); 532243730Srwatson exit(exitcode); 533243730Srwatson /* NOTREACHED */ 534243730Srwatson} 535243730Srwatson 536243730Srwatson/* 537243730Srwatson * Log error, errno and exit. 538243730Srwatson */ 539243730Srwatsonvoid 540243730Srwatsonpjdlog_exit(int exitcode, const char *fmt, ...) 541243730Srwatson{ 542243730Srwatson va_list ap; 543243730Srwatson 544243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 545243730Srwatson 546243730Srwatson va_start(ap, fmt); 547243730Srwatson pjdlogv_exit(exitcode, fmt, ap); 548243730Srwatson /* NOTREACHED */ 549243730Srwatson va_end(ap); 550243730Srwatson} 551243730Srwatson 552243730Srwatson/* 553243730Srwatson * Log error and exit. 554243730Srwatson */ 555243730Srwatsonvoid 556243730Srwatsonpjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 557243730Srwatson{ 558243730Srwatson 559243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 560243730Srwatson 561243730Srwatson pjdlogv(LOG_ERR, fmt, ap); 562243730Srwatson exit(exitcode); 563243730Srwatson /* NOTREACHED */ 564243730Srwatson} 565243730Srwatson 566243730Srwatson/* 567243730Srwatson * Log error and exit. 568243730Srwatson */ 569243730Srwatsonvoid 570243730Srwatsonpjdlog_exitx(int exitcode, const char *fmt, ...) 571243730Srwatson{ 572243730Srwatson va_list ap; 573243730Srwatson 574243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 575243730Srwatson 576243730Srwatson va_start(ap, fmt); 577243730Srwatson pjdlogv_exitx(exitcode, fmt, ap); 578243730Srwatson /* NOTREACHED */ 579243730Srwatson va_end(ap); 580243730Srwatson} 581243730Srwatson 582243730Srwatson/* 583243730Srwatson * Log failure message and exit. 584243730Srwatson */ 585243730Srwatsonvoid 586243730Srwatsonpjdlog_abort(const char *func, const char *file, int line, 587243730Srwatson const char *failedexpr, const char *fmt, ...) 588243730Srwatson{ 589243730Srwatson va_list ap; 590243730Srwatson 591243730Srwatson assert(pjdlog_initialized == PJDLOG_INITIALIZED); 592243730Srwatson 593243730Srwatson /* 594243730Srwatson * When there is no message we pass __func__ as 'fmt'. 595243730Srwatson * It would be cleaner to pass NULL or "", but gcc generates a warning 596243730Srwatson * for both of those. 597243730Srwatson */ 598243730Srwatson if (fmt != func) { 599243730Srwatson va_start(ap, fmt); 600243730Srwatson pjdlogv_critical(fmt, ap); 601243730Srwatson va_end(ap); 602243730Srwatson } 603243730Srwatson if (failedexpr == NULL) { 604243730Srwatson if (func == NULL) { 605243730Srwatson pjdlog_critical("Aborted at file %s, line %d.", file, 606243730Srwatson line); 607243730Srwatson } else { 608243730Srwatson pjdlog_critical("Aborted at function %s, file %s, line %d.", 609243730Srwatson func, file, line); 610243730Srwatson } 611243730Srwatson } else { 612243730Srwatson if (func == NULL) { 613243730Srwatson pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 614243730Srwatson failedexpr, file, line); 615243730Srwatson } else { 616243730Srwatson pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 617243730Srwatson failedexpr, func, file, line); 618243730Srwatson } 619243730Srwatson } 620243730Srwatson abort(); 621243730Srwatson} 622