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$"); 33204076Spjd 34222087Spjd#include <sys/types.h> 35219370Spjd#include <sys/socket.h> 36219370Spjd#include <netinet/in.h> 37222087Spjd#include <arpa/inet.h> 38219370Spjd 39204076Spjd#include <assert.h> 40204076Spjd#include <errno.h> 41219370Spjd#include <libutil.h> 42219370Spjd#include <printf.h> 43204076Spjd#include <stdarg.h> 44219370Spjd#include <stdint.h> 45204076Spjd#include <stdio.h> 46204076Spjd#include <stdlib.h> 47204076Spjd#include <string.h> 48204076Spjd#include <syslog.h> 49204076Spjd 50204076Spjd#include "pjdlog.h" 51204076Spjd 52219369Spjd#define PJDLOG_NEVER_INITIALIZED 0 53219369Spjd#define PJDLOG_NOT_INITIALIZED 1 54219369Spjd#define PJDLOG_INITIALIZED 2 55219369Spjd 56219369Spjdstatic int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; 57218040Spjdstatic int pjdlog_mode, pjdlog_debug_level; 58204076Spjdstatic char pjdlog_prefix[128]; 59204076Spjd 60219370Spjdstatic int 61219370Spjdpjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, 62219370Spjd size_t n, int *argt) 63219370Spjd{ 64219370Spjd 65219370Spjd assert(n >= 1); 66219370Spjd argt[0] = PA_INT | PA_FLAG_INTMAX; 67219370Spjd return (1); 68219370Spjd} 69219370Spjd 70219370Spjdstatic int 71219370Spjdpjdlog_printf_render_humanized_number(struct __printf_io *io, 72219370Spjd const struct printf_info *pi, const void * const *arg) 73219370Spjd{ 74219370Spjd char buf[5]; 75219370Spjd intmax_t num; 76219370Spjd int ret; 77219370Spjd 78219370Spjd num = *(const intmax_t *)arg[0]; 79219370Spjd humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, 80219370Spjd HN_NOSPACE | HN_DECIMAL); 81219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 82219370Spjd __printf_flush(io); 83219370Spjd return (ret); 84219370Spjd} 85219370Spjd 86219370Spjdstatic int 87219370Spjdpjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, 88219370Spjd size_t n, int *argt) 89219370Spjd{ 90219370Spjd 91219370Spjd assert(n >= 1); 92219370Spjd argt[0] = PA_POINTER; 93219370Spjd return (1); 94219370Spjd} 95219370Spjd 96219370Spjdstatic int 97219370Spjdpjdlog_printf_render_sockaddr(struct __printf_io *io, 98219370Spjd const struct printf_info *pi, const void * const *arg) 99219370Spjd{ 100219385Spjd const struct sockaddr_storage *ss; 101219370Spjd char buf[64]; 102219370Spjd int ret; 103219370Spjd 104219385Spjd ss = *(const struct sockaddr_storage * const *)arg[0]; 105219385Spjd switch (ss->ss_family) { 106219370Spjd case AF_INET: 107219370Spjd { 108222087Spjd char addr[INET_ADDRSTRLEN]; 109219370Spjd const struct sockaddr_in *sin; 110219370Spjd unsigned int port; 111219370Spjd 112219385Spjd sin = (const struct sockaddr_in *)ss; 113219370Spjd port = ntohs(sin->sin_port); 114222087Spjd if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, 115222087Spjd sizeof(addr)) == NULL) { 116222087Spjd PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", 117222087Spjd strerror(errno)); 118222087Spjd } 119222087Spjd snprintf(buf, sizeof(buf), "%s:%u", addr, port); 120222087Spjd break; 121222087Spjd } 122222087Spjd case AF_INET6: 123222087Spjd { 124222087Spjd char addr[INET6_ADDRSTRLEN]; 125222087Spjd const struct sockaddr_in6 *sin; 126222087Spjd unsigned int port; 127219370Spjd 128222087Spjd sin = (const struct sockaddr_in6 *)ss; 129222087Spjd port = ntohs(sin->sin6_port); 130222087Spjd if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, 131222087Spjd sizeof(addr)) == NULL) { 132222087Spjd PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", 133222087Spjd strerror(errno)); 134222087Spjd } 135222087Spjd snprintf(buf, sizeof(buf), "[%s]:%u", addr, port); 136219370Spjd break; 137219370Spjd } 138219370Spjd default: 139222087Spjd snprintf(buf, sizeof(buf), "[unsupported family %hhu]", 140222087Spjd ss->ss_family); 141219370Spjd break; 142219370Spjd } 143219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 144219370Spjd __printf_flush(io); 145219370Spjd return (ret); 146219370Spjd} 147219370Spjd 148217965Spjdvoid 149217965Spjdpjdlog_init(int mode) 150217965Spjd{ 151225773Spjd int saved_errno; 152217965Spjd 153219369Spjd assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || 154219369Spjd pjdlog_initialized == PJDLOG_NOT_INITIALIZED); 155217965Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 156217965Spjd 157225773Spjd saved_errno = errno; 158225773Spjd 159219370Spjd if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { 160219370Spjd __use_xprintf = 1; 161219370Spjd register_printf_render_std("T"); 162219370Spjd register_printf_render('N', 163219370Spjd pjdlog_printf_render_humanized_number, 164219370Spjd pjdlog_printf_arginfo_humanized_number); 165219370Spjd register_printf_render('S', 166219370Spjd pjdlog_printf_render_sockaddr, 167219370Spjd pjdlog_printf_arginfo_sockaddr); 168219370Spjd } 169219370Spjd 170217965Spjd if (mode == PJDLOG_MODE_SYSLOG) 171217965Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 172217965Spjd pjdlog_mode = mode; 173218040Spjd pjdlog_debug_level = 0; 174218040Spjd bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); 175217965Spjd 176219369Spjd pjdlog_initialized = PJDLOG_INITIALIZED; 177225773Spjd 178225773Spjd errno = saved_errno; 179217965Spjd} 180217965Spjd 181217965Spjdvoid 182217965Spjdpjdlog_fini(void) 183217965Spjd{ 184225773Spjd int saved_errno; 185217965Spjd 186219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 187217965Spjd 188225773Spjd saved_errno = errno; 189225773Spjd 190217965Spjd if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 191217965Spjd closelog(); 192217965Spjd 193219369Spjd pjdlog_initialized = PJDLOG_NOT_INITIALIZED; 194225773Spjd 195225773Spjd errno = saved_errno; 196217965Spjd} 197217965Spjd 198204076Spjd/* 199204076Spjd * Configure where the logs should go. 200204076Spjd * By default they are send to stdout/stderr, but after going into background 201204076Spjd * (eg. by calling daemon(3)) application is responsible for changing mode to 202204076Spjd * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 203204076Spjd */ 204204076Spjdvoid 205204076Spjdpjdlog_mode_set(int mode) 206204076Spjd{ 207225773Spjd int saved_errno; 208204076Spjd 209219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 210204076Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 211204076Spjd 212217965Spjd if (pjdlog_mode == mode) 213217965Spjd return; 214212052Spjd 215225773Spjd saved_errno = errno; 216225773Spjd 217212052Spjd if (mode == PJDLOG_MODE_SYSLOG) 218217962Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 219217965Spjd else /* if (mode == PJDLOG_MODE_STD) */ 220217965Spjd closelog(); 221217965Spjd 222217965Spjd pjdlog_mode = mode; 223225773Spjd 224225773Spjd errno = saved_errno; 225204076Spjd} 226204076Spjd 227204076Spjd/* 228204076Spjd * Return current mode. 229204076Spjd */ 230204076Spjdint 231204076Spjdpjdlog_mode_get(void) 232204076Spjd{ 233204076Spjd 234219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 235217965Spjd 236204076Spjd return (pjdlog_mode); 237204076Spjd} 238204076Spjd 239204076Spjd/* 240204076Spjd * Set debug level. All the logs above the level specified here will be 241204076Spjd * ignored. 242204076Spjd */ 243204076Spjdvoid 244204076Spjdpjdlog_debug_set(int level) 245204076Spjd{ 246204076Spjd 247219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 248204076Spjd assert(level >= 0); 249204076Spjd 250204076Spjd pjdlog_debug_level = level; 251204076Spjd} 252204076Spjd 253204076Spjd/* 254204076Spjd * Return current debug level. 255204076Spjd */ 256204076Spjdint 257204076Spjdpjdlog_debug_get(void) 258204076Spjd{ 259204076Spjd 260219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 261217965Spjd 262204076Spjd return (pjdlog_debug_level); 263204076Spjd} 264204076Spjd 265204076Spjd/* 266204076Spjd * Set prefix that will be used before each log. 267204076Spjd * Setting prefix to NULL will remove it. 268204076Spjd */ 269204076Spjdvoid 270204076Spjdpjdlog_prefix_set(const char *fmt, ...) 271204076Spjd{ 272204076Spjd va_list ap; 273204076Spjd 274219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 275217965Spjd 276204076Spjd va_start(ap, fmt); 277217731Spjd pjdlogv_prefix_set(fmt, ap); 278204076Spjd va_end(ap); 279204076Spjd} 280204076Spjd 281204076Spjd/* 282204076Spjd * Set prefix that will be used before each log. 283204076Spjd * Setting prefix to NULL will remove it. 284204076Spjd */ 285204076Spjdvoid 286217731Spjdpjdlogv_prefix_set(const char *fmt, va_list ap) 287204076Spjd{ 288225773Spjd int saved_errno; 289204076Spjd 290219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 291204076Spjd assert(fmt != NULL); 292204076Spjd 293225773Spjd saved_errno = errno; 294225773Spjd 295204076Spjd vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 296225773Spjd 297225773Spjd errno = saved_errno; 298204076Spjd} 299204076Spjd 300204076Spjd/* 301204076Spjd * Convert log level into string. 302204076Spjd */ 303204076Spjdstatic const char * 304204076Spjdpjdlog_level_string(int loglevel) 305204076Spjd{ 306204076Spjd 307204076Spjd switch (loglevel) { 308204076Spjd case LOG_EMERG: 309204076Spjd return ("EMERG"); 310204076Spjd case LOG_ALERT: 311204076Spjd return ("ALERT"); 312204076Spjd case LOG_CRIT: 313204076Spjd return ("CRIT"); 314204076Spjd case LOG_ERR: 315204076Spjd return ("ERROR"); 316204076Spjd case LOG_WARNING: 317204076Spjd return ("WARNING"); 318204076Spjd case LOG_NOTICE: 319204076Spjd return ("NOTICE"); 320204076Spjd case LOG_INFO: 321204076Spjd return ("INFO"); 322204076Spjd case LOG_DEBUG: 323204076Spjd return ("DEBUG"); 324204076Spjd } 325204076Spjd assert(!"Invalid log level."); 326204076Spjd abort(); /* XXX: gcc */ 327204076Spjd} 328204076Spjd 329204076Spjd/* 330204076Spjd * Common log routine. 331204076Spjd */ 332204076Spjdvoid 333204076Spjdpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 334204076Spjd{ 335204076Spjd va_list ap; 336204076Spjd 337219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 338217965Spjd 339204076Spjd va_start(ap, fmt); 340204076Spjd pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 341204076Spjd va_end(ap); 342204076Spjd} 343204076Spjd 344204076Spjd/* 345204076Spjd * Common log routine, which can handle regular log level as well as debug 346204076Spjd * level. We decide here where to send the logs (stdout/stderr or syslog). 347204076Spjd */ 348204076Spjdvoid 349204076Spjdpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 350204076Spjd va_list ap) 351204076Spjd{ 352225773Spjd int saved_errno; 353204076Spjd 354219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 355204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 356204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 357204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 358204076Spjd loglevel == LOG_INFO || loglevel == LOG_DEBUG); 359204076Spjd assert(loglevel != LOG_DEBUG || debuglevel > 0); 360204076Spjd assert(error >= -1); 361204076Spjd 362204076Spjd /* Ignore debug above configured level. */ 363204076Spjd if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 364204076Spjd return; 365204076Spjd 366225773Spjd saved_errno = errno; 367225773Spjd 368204076Spjd switch (pjdlog_mode) { 369204076Spjd case PJDLOG_MODE_STD: 370204076Spjd { 371204076Spjd FILE *out; 372204076Spjd 373204076Spjd /* 374204076Spjd * We send errors and warning to stderr and the rest to stdout. 375204076Spjd */ 376204076Spjd switch (loglevel) { 377204076Spjd case LOG_EMERG: 378204076Spjd case LOG_ALERT: 379204076Spjd case LOG_CRIT: 380204076Spjd case LOG_ERR: 381204076Spjd case LOG_WARNING: 382204076Spjd out = stderr; 383204076Spjd break; 384204076Spjd case LOG_NOTICE: 385204076Spjd case LOG_INFO: 386204076Spjd case LOG_DEBUG: 387204076Spjd out = stdout; 388204076Spjd break; 389204076Spjd default: 390204076Spjd assert(!"Invalid loglevel."); 391204076Spjd abort(); /* XXX: gcc */ 392204076Spjd } 393204076Spjd 394204076Spjd fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 395204076Spjd /* Attach debuglevel if this is debug log. */ 396204076Spjd if (loglevel == LOG_DEBUG) 397204076Spjd fprintf(out, "[%d]", debuglevel); 398213939Spjd fprintf(out, " %s", pjdlog_prefix); 399204076Spjd vfprintf(out, fmt, ap); 400204076Spjd if (error != -1) 401204076Spjd fprintf(out, ": %s.", strerror(error)); 402204076Spjd fprintf(out, "\n"); 403211898Spjd fflush(out); 404204076Spjd break; 405204076Spjd } 406204076Spjd case PJDLOG_MODE_SYSLOG: 407204076Spjd { 408204076Spjd char log[1024]; 409204076Spjd int len; 410204076Spjd 411204076Spjd len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 412204076Spjd if ((size_t)len < sizeof(log)) 413206697Spjd len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 414204076Spjd if (error != -1 && (size_t)len < sizeof(log)) { 415204076Spjd (void)snprintf(log + len, sizeof(log) - len, ": %s.", 416204076Spjd strerror(error)); 417204076Spjd } 418204076Spjd syslog(loglevel, "%s", log); 419204076Spjd break; 420204076Spjd } 421204076Spjd default: 422204076Spjd assert(!"Invalid mode."); 423204076Spjd } 424225773Spjd 425225773Spjd errno = saved_errno; 426204076Spjd} 427204076Spjd 428204076Spjd/* 429204076Spjd * Regular logs. 430204076Spjd */ 431204076Spjdvoid 432204076Spjdpjdlogv(int loglevel, const char *fmt, va_list ap) 433204076Spjd{ 434204076Spjd 435219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 436217965Spjd 437204076Spjd /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 438204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 439204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 440204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 441204076Spjd loglevel == LOG_INFO); 442204076Spjd 443204076Spjd pjdlogv_common(loglevel, 0, -1, fmt, ap); 444204076Spjd} 445204076Spjd 446204076Spjd/* 447204076Spjd * Regular logs. 448204076Spjd */ 449204076Spjdvoid 450204076Spjdpjdlog(int loglevel, const char *fmt, ...) 451204076Spjd{ 452204076Spjd va_list ap; 453204076Spjd 454219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 455217965Spjd 456204076Spjd va_start(ap, fmt); 457204076Spjd pjdlogv(loglevel, fmt, ap); 458204076Spjd va_end(ap); 459204076Spjd} 460204076Spjd 461204076Spjd/* 462204076Spjd * Debug logs. 463204076Spjd */ 464204076Spjdvoid 465204076Spjdpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 466204076Spjd{ 467204076Spjd 468219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 469217965Spjd 470204076Spjd pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 471204076Spjd} 472204076Spjd 473204076Spjd/* 474204076Spjd * Debug logs. 475204076Spjd */ 476204076Spjdvoid 477204076Spjdpjdlog_debug(int debuglevel, const char *fmt, ...) 478204076Spjd{ 479204076Spjd va_list ap; 480204076Spjd 481219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 482217965Spjd 483204076Spjd va_start(ap, fmt); 484204076Spjd pjdlogv_debug(debuglevel, fmt, ap); 485204076Spjd va_end(ap); 486204076Spjd} 487204076Spjd 488204076Spjd/* 489204076Spjd * Error logs with errno logging. 490204076Spjd */ 491204076Spjdvoid 492204076Spjdpjdlogv_errno(int loglevel, const char *fmt, va_list ap) 493204076Spjd{ 494204076Spjd 495219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 496217965Spjd 497204076Spjd pjdlogv_common(loglevel, 0, errno, fmt, ap); 498204076Spjd} 499204076Spjd 500204076Spjd/* 501204076Spjd * Error logs with errno logging. 502204076Spjd */ 503204076Spjdvoid 504204076Spjdpjdlog_errno(int loglevel, const char *fmt, ...) 505204076Spjd{ 506204076Spjd va_list ap; 507204076Spjd 508219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 509217965Spjd 510204076Spjd va_start(ap, fmt); 511204076Spjd pjdlogv_errno(loglevel, fmt, ap); 512204076Spjd va_end(ap); 513204076Spjd} 514204076Spjd 515204076Spjd/* 516204076Spjd * Log error, errno and exit. 517204076Spjd */ 518204076Spjdvoid 519204076Spjdpjdlogv_exit(int exitcode, const char *fmt, va_list ap) 520204076Spjd{ 521204076Spjd 522219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 523217965Spjd 524204076Spjd pjdlogv_errno(LOG_ERR, fmt, ap); 525204076Spjd exit(exitcode); 526210872Spjd /* NOTREACHED */ 527204076Spjd} 528204076Spjd 529204076Spjd/* 530204076Spjd * Log error, errno and exit. 531204076Spjd */ 532204076Spjdvoid 533204076Spjdpjdlog_exit(int exitcode, const char *fmt, ...) 534204076Spjd{ 535204076Spjd va_list ap; 536204076Spjd 537219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 538217965Spjd 539204076Spjd va_start(ap, fmt); 540204076Spjd pjdlogv_exit(exitcode, fmt, ap); 541204076Spjd /* NOTREACHED */ 542204076Spjd va_end(ap); 543204076Spjd} 544204076Spjd 545204076Spjd/* 546204076Spjd * Log error and exit. 547204076Spjd */ 548204076Spjdvoid 549204076Spjdpjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 550204076Spjd{ 551204076Spjd 552219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 553217965Spjd 554204076Spjd pjdlogv(LOG_ERR, fmt, ap); 555204076Spjd exit(exitcode); 556210872Spjd /* NOTREACHED */ 557204076Spjd} 558204076Spjd 559204076Spjd/* 560204076Spjd * Log error and exit. 561204076Spjd */ 562204076Spjdvoid 563204076Spjdpjdlog_exitx(int exitcode, const char *fmt, ...) 564204076Spjd{ 565204076Spjd va_list ap; 566204076Spjd 567219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 568217965Spjd 569204076Spjd va_start(ap, fmt); 570204076Spjd pjdlogv_exitx(exitcode, fmt, ap); 571204076Spjd /* NOTREACHED */ 572204076Spjd va_end(ap); 573204076Spjd} 574210875Spjd 575210875Spjd/* 576218132Spjd * Log failure message and exit. 577210875Spjd */ 578210875Spjdvoid 579218132Spjdpjdlog_abort(const char *func, const char *file, int line, 580217966Spjd const char *failedexpr, const char *fmt, ...) 581210875Spjd{ 582217966Spjd va_list ap; 583210875Spjd 584219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 585217966Spjd 586217966Spjd /* 587217966Spjd * When there is no message we pass __func__ as 'fmt'. 588217966Spjd * It would be cleaner to pass NULL or "", but gcc generates a warning 589217966Spjd * for both of those. 590217966Spjd */ 591217966Spjd if (fmt != func) { 592217966Spjd va_start(ap, fmt); 593217966Spjd pjdlogv_critical(fmt, ap); 594217966Spjd va_end(ap); 595217966Spjd } 596217966Spjd if (failedexpr == NULL) { 597217966Spjd if (func == NULL) { 598217966Spjd pjdlog_critical("Aborted at file %s, line %d.", file, 599217966Spjd line); 600217966Spjd } else { 601217966Spjd pjdlog_critical("Aborted at function %s, file %s, line %d.", 602217966Spjd func, file, line); 603217966Spjd } 604210875Spjd } else { 605217966Spjd if (func == NULL) { 606217966Spjd pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 607217966Spjd failedexpr, file, line); 608217966Spjd } else { 609217966Spjd pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 610217966Spjd failedexpr, func, file, line); 611217966Spjd } 612210875Spjd } 613210875Spjd abort(); 614210875Spjd} 615