1204076Spjd/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4217964Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 5217964Spjd * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org> 6204076Spjd * All rights reserved. 7204076Spjd * 8204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 9204076Spjd * the FreeBSD Foundation. 10204076Spjd * 11204076Spjd * Redistribution and use in source and binary forms, with or without 12204076Spjd * modification, are permitted provided that the following conditions 13204076Spjd * are met: 14204076Spjd * 1. Redistributions of source code must retain the above copyright 15204076Spjd * notice, this list of conditions and the following disclaimer. 16204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 17204076Spjd * notice, this list of conditions and the following disclaimer in the 18204076Spjd * documentation and/or other materials provided with the distribution. 19204076Spjd * 20204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 21204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 24204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30204076Spjd * SUCH DAMAGE. 31204076Spjd */ 32204076Spjd 33204076Spjd#include <sys/cdefs.h> 34204076Spjd__FBSDID("$FreeBSD: stable/11/sbin/hastd/pjdlog.c 330449 2018-03-05 07:26:05Z eadler $"); 35204076Spjd 36222087Spjd#include <sys/types.h> 37219370Spjd#include <sys/socket.h> 38219370Spjd#include <netinet/in.h> 39222087Spjd#include <arpa/inet.h> 40219370Spjd 41204076Spjd#include <assert.h> 42204076Spjd#include <errno.h> 43219370Spjd#include <libutil.h> 44219370Spjd#include <printf.h> 45204076Spjd#include <stdarg.h> 46219370Spjd#include <stdint.h> 47204076Spjd#include <stdio.h> 48204076Spjd#include <stdlib.h> 49204076Spjd#include <string.h> 50204076Spjd#include <syslog.h> 51204076Spjd 52204076Spjd#include "pjdlog.h" 53204076Spjd 54219369Spjd#define PJDLOG_NEVER_INITIALIZED 0 55219369Spjd#define PJDLOG_NOT_INITIALIZED 1 56219369Spjd#define PJDLOG_INITIALIZED 2 57219369Spjd 58219369Spjdstatic int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; 59218040Spjdstatic int pjdlog_mode, pjdlog_debug_level; 60204076Spjdstatic char pjdlog_prefix[128]; 61204076Spjd 62219370Spjdstatic int 63219370Spjdpjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, 64219370Spjd size_t n, int *argt) 65219370Spjd{ 66219370Spjd 67219370Spjd assert(n >= 1); 68219370Spjd argt[0] = PA_INT | PA_FLAG_INTMAX; 69219370Spjd return (1); 70219370Spjd} 71219370Spjd 72219370Spjdstatic int 73219370Spjdpjdlog_printf_render_humanized_number(struct __printf_io *io, 74219370Spjd const struct printf_info *pi, const void * const *arg) 75219370Spjd{ 76219370Spjd char buf[5]; 77219370Spjd intmax_t num; 78219370Spjd int ret; 79219370Spjd 80219370Spjd num = *(const intmax_t *)arg[0]; 81219370Spjd humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, 82219370Spjd HN_NOSPACE | HN_DECIMAL); 83219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 84219370Spjd __printf_flush(io); 85219370Spjd return (ret); 86219370Spjd} 87219370Spjd 88219370Spjdstatic int 89219370Spjdpjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, 90219370Spjd size_t n, int *argt) 91219370Spjd{ 92219370Spjd 93219370Spjd assert(n >= 1); 94219370Spjd argt[0] = PA_POINTER; 95219370Spjd return (1); 96219370Spjd} 97219370Spjd 98219370Spjdstatic int 99219370Spjdpjdlog_printf_render_sockaddr(struct __printf_io *io, 100219370Spjd const struct printf_info *pi, const void * const *arg) 101219370Spjd{ 102219385Spjd const struct sockaddr_storage *ss; 103219370Spjd char buf[64]; 104219370Spjd int ret; 105219370Spjd 106219385Spjd ss = *(const struct sockaddr_storage * const *)arg[0]; 107219385Spjd switch (ss->ss_family) { 108219370Spjd case AF_INET: 109219370Spjd { 110222087Spjd char addr[INET_ADDRSTRLEN]; 111219370Spjd const struct sockaddr_in *sin; 112219370Spjd unsigned int port; 113219370Spjd 114219385Spjd sin = (const struct sockaddr_in *)ss; 115219370Spjd port = ntohs(sin->sin_port); 116222087Spjd if (inet_ntop(ss->ss_family, &sin->sin_addr, addr, 117222087Spjd sizeof(addr)) == NULL) { 118222087Spjd PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.", 119222087Spjd strerror(errno)); 120222087Spjd } 121222087Spjd snprintf(buf, sizeof(buf), "%s:%u", addr, port); 122222087Spjd break; 123222087Spjd } 124222087Spjd case AF_INET6: 125222087Spjd { 126222087Spjd char addr[INET6_ADDRSTRLEN]; 127222087Spjd const struct sockaddr_in6 *sin; 128222087Spjd unsigned int port; 129219370Spjd 130222087Spjd sin = (const struct sockaddr_in6 *)ss; 131222087Spjd port = ntohs(sin->sin6_port); 132222087Spjd if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr, 133222087Spjd sizeof(addr)) == NULL) { 134222087Spjd PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.", 135222087Spjd strerror(errno)); 136222087Spjd } 137222087Spjd snprintf(buf, sizeof(buf), "[%s]:%u", addr, port); 138219370Spjd break; 139219370Spjd } 140219370Spjd default: 141222087Spjd snprintf(buf, sizeof(buf), "[unsupported family %hhu]", 142222087Spjd ss->ss_family); 143219370Spjd break; 144219370Spjd } 145219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 146219370Spjd __printf_flush(io); 147219370Spjd return (ret); 148219370Spjd} 149219370Spjd 150217965Spjdvoid 151217965Spjdpjdlog_init(int mode) 152217965Spjd{ 153225773Spjd int saved_errno; 154217965Spjd 155219369Spjd assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || 156219369Spjd pjdlog_initialized == PJDLOG_NOT_INITIALIZED); 157217965Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 158217965Spjd 159225773Spjd saved_errno = errno; 160225773Spjd 161219370Spjd if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { 162219370Spjd __use_xprintf = 1; 163219370Spjd register_printf_render_std("T"); 164219370Spjd register_printf_render('N', 165219370Spjd pjdlog_printf_render_humanized_number, 166219370Spjd pjdlog_printf_arginfo_humanized_number); 167219370Spjd register_printf_render('S', 168219370Spjd pjdlog_printf_render_sockaddr, 169219370Spjd pjdlog_printf_arginfo_sockaddr); 170219370Spjd } 171219370Spjd 172217965Spjd if (mode == PJDLOG_MODE_SYSLOG) 173217965Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 174217965Spjd pjdlog_mode = mode; 175218040Spjd pjdlog_debug_level = 0; 176218040Spjd bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); 177217965Spjd 178219369Spjd pjdlog_initialized = PJDLOG_INITIALIZED; 179225773Spjd 180225773Spjd errno = saved_errno; 181217965Spjd} 182217965Spjd 183217965Spjdvoid 184217965Spjdpjdlog_fini(void) 185217965Spjd{ 186225773Spjd int saved_errno; 187217965Spjd 188219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 189217965Spjd 190225773Spjd saved_errno = errno; 191225773Spjd 192217965Spjd if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 193217965Spjd closelog(); 194217965Spjd 195219369Spjd pjdlog_initialized = PJDLOG_NOT_INITIALIZED; 196225773Spjd 197225773Spjd errno = saved_errno; 198217965Spjd} 199217965Spjd 200204076Spjd/* 201204076Spjd * Configure where the logs should go. 202204076Spjd * By default they are send to stdout/stderr, but after going into background 203204076Spjd * (eg. by calling daemon(3)) application is responsible for changing mode to 204204076Spjd * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 205204076Spjd */ 206204076Spjdvoid 207204076Spjdpjdlog_mode_set(int mode) 208204076Spjd{ 209225773Spjd int saved_errno; 210204076Spjd 211219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 212204076Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 213204076Spjd 214217965Spjd if (pjdlog_mode == mode) 215217965Spjd return; 216212052Spjd 217225773Spjd saved_errno = errno; 218225773Spjd 219212052Spjd if (mode == PJDLOG_MODE_SYSLOG) 220217962Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 221217965Spjd else /* if (mode == PJDLOG_MODE_STD) */ 222217965Spjd closelog(); 223217965Spjd 224217965Spjd pjdlog_mode = mode; 225225773Spjd 226225773Spjd errno = saved_errno; 227204076Spjd} 228204076Spjd 229204076Spjd/* 230204076Spjd * Return current mode. 231204076Spjd */ 232204076Spjdint 233204076Spjdpjdlog_mode_get(void) 234204076Spjd{ 235204076Spjd 236219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 237217965Spjd 238204076Spjd return (pjdlog_mode); 239204076Spjd} 240204076Spjd 241204076Spjd/* 242204076Spjd * Set debug level. All the logs above the level specified here will be 243204076Spjd * ignored. 244204076Spjd */ 245204076Spjdvoid 246204076Spjdpjdlog_debug_set(int level) 247204076Spjd{ 248204076Spjd 249219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 250204076Spjd assert(level >= 0); 251204076Spjd 252204076Spjd pjdlog_debug_level = level; 253204076Spjd} 254204076Spjd 255204076Spjd/* 256204076Spjd * Return current debug level. 257204076Spjd */ 258204076Spjdint 259204076Spjdpjdlog_debug_get(void) 260204076Spjd{ 261204076Spjd 262219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 263217965Spjd 264204076Spjd return (pjdlog_debug_level); 265204076Spjd} 266204076Spjd 267204076Spjd/* 268204076Spjd * Set prefix that will be used before each log. 269204076Spjd * Setting prefix to NULL will remove it. 270204076Spjd */ 271204076Spjdvoid 272204076Spjdpjdlog_prefix_set(const char *fmt, ...) 273204076Spjd{ 274204076Spjd va_list ap; 275204076Spjd 276219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 277217965Spjd 278204076Spjd va_start(ap, fmt); 279217731Spjd pjdlogv_prefix_set(fmt, ap); 280204076Spjd va_end(ap); 281204076Spjd} 282204076Spjd 283204076Spjd/* 284204076Spjd * Set prefix that will be used before each log. 285204076Spjd * Setting prefix to NULL will remove it. 286204076Spjd */ 287204076Spjdvoid 288217731Spjdpjdlogv_prefix_set(const char *fmt, va_list ap) 289204076Spjd{ 290225773Spjd int saved_errno; 291204076Spjd 292219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 293204076Spjd assert(fmt != NULL); 294204076Spjd 295225773Spjd saved_errno = errno; 296225773Spjd 297204076Spjd vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 298225773Spjd 299225773Spjd errno = saved_errno; 300204076Spjd} 301204076Spjd 302204076Spjd/* 303204076Spjd * Convert log level into string. 304204076Spjd */ 305204076Spjdstatic const char * 306204076Spjdpjdlog_level_string(int loglevel) 307204076Spjd{ 308204076Spjd 309204076Spjd switch (loglevel) { 310204076Spjd case LOG_EMERG: 311204076Spjd return ("EMERG"); 312204076Spjd case LOG_ALERT: 313204076Spjd return ("ALERT"); 314204076Spjd case LOG_CRIT: 315204076Spjd return ("CRIT"); 316204076Spjd case LOG_ERR: 317204076Spjd return ("ERROR"); 318204076Spjd case LOG_WARNING: 319204076Spjd return ("WARNING"); 320204076Spjd case LOG_NOTICE: 321204076Spjd return ("NOTICE"); 322204076Spjd case LOG_INFO: 323204076Spjd return ("INFO"); 324204076Spjd case LOG_DEBUG: 325204076Spjd return ("DEBUG"); 326204076Spjd } 327204076Spjd assert(!"Invalid log level."); 328204076Spjd abort(); /* XXX: gcc */ 329204076Spjd} 330204076Spjd 331204076Spjd/* 332204076Spjd * Common log routine. 333204076Spjd */ 334204076Spjdvoid 335204076Spjdpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 336204076Spjd{ 337204076Spjd va_list ap; 338204076Spjd 339219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 340217965Spjd 341204076Spjd va_start(ap, fmt); 342204076Spjd pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 343204076Spjd va_end(ap); 344204076Spjd} 345204076Spjd 346204076Spjd/* 347204076Spjd * Common log routine, which can handle regular log level as well as debug 348204076Spjd * level. We decide here where to send the logs (stdout/stderr or syslog). 349204076Spjd */ 350204076Spjdvoid 351204076Spjdpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 352204076Spjd va_list ap) 353204076Spjd{ 354225773Spjd int saved_errno; 355204076Spjd 356219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 357204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 358204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 359204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 360204076Spjd loglevel == LOG_INFO || loglevel == LOG_DEBUG); 361204076Spjd assert(loglevel != LOG_DEBUG || debuglevel > 0); 362204076Spjd assert(error >= -1); 363204076Spjd 364204076Spjd /* Ignore debug above configured level. */ 365204076Spjd if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 366204076Spjd return; 367204076Spjd 368225773Spjd saved_errno = errno; 369225773Spjd 370204076Spjd switch (pjdlog_mode) { 371204076Spjd case PJDLOG_MODE_STD: 372204076Spjd { 373204076Spjd FILE *out; 374204076Spjd 375204076Spjd /* 376204076Spjd * We send errors and warning to stderr and the rest to stdout. 377204076Spjd */ 378204076Spjd switch (loglevel) { 379204076Spjd case LOG_EMERG: 380204076Spjd case LOG_ALERT: 381204076Spjd case LOG_CRIT: 382204076Spjd case LOG_ERR: 383204076Spjd case LOG_WARNING: 384204076Spjd out = stderr; 385204076Spjd break; 386204076Spjd case LOG_NOTICE: 387204076Spjd case LOG_INFO: 388204076Spjd case LOG_DEBUG: 389204076Spjd out = stdout; 390204076Spjd break; 391204076Spjd default: 392204076Spjd assert(!"Invalid loglevel."); 393204076Spjd abort(); /* XXX: gcc */ 394204076Spjd } 395204076Spjd 396204076Spjd fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 397204076Spjd /* Attach debuglevel if this is debug log. */ 398204076Spjd if (loglevel == LOG_DEBUG) 399204076Spjd fprintf(out, "[%d]", debuglevel); 400213939Spjd fprintf(out, " %s", pjdlog_prefix); 401204076Spjd vfprintf(out, fmt, ap); 402204076Spjd if (error != -1) 403204076Spjd fprintf(out, ": %s.", strerror(error)); 404204076Spjd fprintf(out, "\n"); 405211898Spjd fflush(out); 406204076Spjd break; 407204076Spjd } 408204076Spjd case PJDLOG_MODE_SYSLOG: 409204076Spjd { 410204076Spjd char log[1024]; 411204076Spjd int len; 412204076Spjd 413204076Spjd len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 414204076Spjd if ((size_t)len < sizeof(log)) 415206697Spjd len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 416204076Spjd if (error != -1 && (size_t)len < sizeof(log)) { 417204076Spjd (void)snprintf(log + len, sizeof(log) - len, ": %s.", 418204076Spjd strerror(error)); 419204076Spjd } 420204076Spjd syslog(loglevel, "%s", log); 421204076Spjd break; 422204076Spjd } 423204076Spjd default: 424204076Spjd assert(!"Invalid mode."); 425204076Spjd } 426225773Spjd 427225773Spjd errno = saved_errno; 428204076Spjd} 429204076Spjd 430204076Spjd/* 431204076Spjd * Regular logs. 432204076Spjd */ 433204076Spjdvoid 434204076Spjdpjdlogv(int loglevel, const char *fmt, va_list ap) 435204076Spjd{ 436204076Spjd 437219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 438217965Spjd 439204076Spjd /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 440204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 441204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 442204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 443204076Spjd loglevel == LOG_INFO); 444204076Spjd 445204076Spjd pjdlogv_common(loglevel, 0, -1, fmt, ap); 446204076Spjd} 447204076Spjd 448204076Spjd/* 449204076Spjd * Regular logs. 450204076Spjd */ 451204076Spjdvoid 452204076Spjdpjdlog(int loglevel, const char *fmt, ...) 453204076Spjd{ 454204076Spjd va_list ap; 455204076Spjd 456219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 457217965Spjd 458204076Spjd va_start(ap, fmt); 459204076Spjd pjdlogv(loglevel, fmt, ap); 460204076Spjd va_end(ap); 461204076Spjd} 462204076Spjd 463204076Spjd/* 464204076Spjd * Debug logs. 465204076Spjd */ 466204076Spjdvoid 467204076Spjdpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 468204076Spjd{ 469204076Spjd 470219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 471217965Spjd 472204076Spjd pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 473204076Spjd} 474204076Spjd 475204076Spjd/* 476204076Spjd * Debug logs. 477204076Spjd */ 478204076Spjdvoid 479204076Spjdpjdlog_debug(int debuglevel, const char *fmt, ...) 480204076Spjd{ 481204076Spjd va_list ap; 482204076Spjd 483219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 484217965Spjd 485204076Spjd va_start(ap, fmt); 486204076Spjd pjdlogv_debug(debuglevel, fmt, ap); 487204076Spjd va_end(ap); 488204076Spjd} 489204076Spjd 490204076Spjd/* 491204076Spjd * Error logs with errno logging. 492204076Spjd */ 493204076Spjdvoid 494204076Spjdpjdlogv_errno(int loglevel, const char *fmt, va_list ap) 495204076Spjd{ 496204076Spjd 497219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 498217965Spjd 499204076Spjd pjdlogv_common(loglevel, 0, errno, fmt, ap); 500204076Spjd} 501204076Spjd 502204076Spjd/* 503204076Spjd * Error logs with errno logging. 504204076Spjd */ 505204076Spjdvoid 506204076Spjdpjdlog_errno(int loglevel, const char *fmt, ...) 507204076Spjd{ 508204076Spjd va_list ap; 509204076Spjd 510219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 511217965Spjd 512204076Spjd va_start(ap, fmt); 513204076Spjd pjdlogv_errno(loglevel, fmt, ap); 514204076Spjd va_end(ap); 515204076Spjd} 516204076Spjd 517204076Spjd/* 518204076Spjd * Log error, errno and exit. 519204076Spjd */ 520204076Spjdvoid 521204076Spjdpjdlogv_exit(int exitcode, const char *fmt, va_list ap) 522204076Spjd{ 523204076Spjd 524219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 525217965Spjd 526204076Spjd pjdlogv_errno(LOG_ERR, fmt, ap); 527204076Spjd exit(exitcode); 528210872Spjd /* NOTREACHED */ 529204076Spjd} 530204076Spjd 531204076Spjd/* 532204076Spjd * Log error, errno and exit. 533204076Spjd */ 534204076Spjdvoid 535204076Spjdpjdlog_exit(int exitcode, const char *fmt, ...) 536204076Spjd{ 537204076Spjd va_list ap; 538204076Spjd 539219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 540217965Spjd 541204076Spjd va_start(ap, fmt); 542204076Spjd pjdlogv_exit(exitcode, fmt, ap); 543204076Spjd /* NOTREACHED */ 544204076Spjd va_end(ap); 545204076Spjd} 546204076Spjd 547204076Spjd/* 548204076Spjd * Log error and exit. 549204076Spjd */ 550204076Spjdvoid 551204076Spjdpjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 552204076Spjd{ 553204076Spjd 554219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 555217965Spjd 556204076Spjd pjdlogv(LOG_ERR, fmt, ap); 557204076Spjd exit(exitcode); 558210872Spjd /* NOTREACHED */ 559204076Spjd} 560204076Spjd 561204076Spjd/* 562204076Spjd * Log error and exit. 563204076Spjd */ 564204076Spjdvoid 565204076Spjdpjdlog_exitx(int exitcode, const char *fmt, ...) 566204076Spjd{ 567204076Spjd va_list ap; 568204076Spjd 569219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 570217965Spjd 571204076Spjd va_start(ap, fmt); 572204076Spjd pjdlogv_exitx(exitcode, fmt, ap); 573204076Spjd /* NOTREACHED */ 574204076Spjd va_end(ap); 575204076Spjd} 576210875Spjd 577210875Spjd/* 578218132Spjd * Log failure message and exit. 579210875Spjd */ 580210875Spjdvoid 581218132Spjdpjdlog_abort(const char *func, const char *file, int line, 582217966Spjd const char *failedexpr, const char *fmt, ...) 583210875Spjd{ 584217966Spjd va_list ap; 585210875Spjd 586219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 587217966Spjd 588217966Spjd /* 589217966Spjd * When there is no message we pass __func__ as 'fmt'. 590217966Spjd * It would be cleaner to pass NULL or "", but gcc generates a warning 591217966Spjd * for both of those. 592217966Spjd */ 593217966Spjd if (fmt != func) { 594217966Spjd va_start(ap, fmt); 595217966Spjd pjdlogv_critical(fmt, ap); 596217966Spjd va_end(ap); 597217966Spjd } 598217966Spjd if (failedexpr == NULL) { 599217966Spjd if (func == NULL) { 600217966Spjd pjdlog_critical("Aborted at file %s, line %d.", file, 601217966Spjd line); 602217966Spjd } else { 603217966Spjd pjdlog_critical("Aborted at function %s, file %s, line %d.", 604217966Spjd func, file, line); 605217966Spjd } 606210875Spjd } else { 607217966Spjd if (func == NULL) { 608217966Spjd pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 609217966Spjd failedexpr, file, line); 610217966Spjd } else { 611217966Spjd pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 612217966Spjd failedexpr, func, file, line); 613217966Spjd } 614210875Spjd } 615210875Spjd abort(); 616210875Spjd} 617