pjdlog.c revision 219370
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: head/sbin/hastd/pjdlog.c 219370 2011-03-07 10:38:18Z pjd $"); 33204076Spjd 34219370Spjd#include <sys/socket.h> 35219370Spjd#include <netinet/in.h> 36219370Spjd 37204076Spjd#include <assert.h> 38204076Spjd#include <errno.h> 39219370Spjd#include <libutil.h> 40219370Spjd#include <printf.h> 41204076Spjd#include <stdarg.h> 42219370Spjd#include <stdint.h> 43204076Spjd#include <stdio.h> 44204076Spjd#include <stdlib.h> 45204076Spjd#include <string.h> 46204076Spjd#include <syslog.h> 47204076Spjd 48204076Spjd#include "pjdlog.h" 49204076Spjd 50219369Spjd#define PJDLOG_NEVER_INITIALIZED 0 51219369Spjd#define PJDLOG_NOT_INITIALIZED 1 52219369Spjd#define PJDLOG_INITIALIZED 2 53219369Spjd 54219369Spjdstatic int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED; 55218040Spjdstatic int pjdlog_mode, pjdlog_debug_level; 56204076Spjdstatic char pjdlog_prefix[128]; 57204076Spjd 58219370Spjdstatic int 59219370Spjdpjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused, 60219370Spjd size_t n, int *argt) 61219370Spjd{ 62219370Spjd 63219370Spjd assert(n >= 1); 64219370Spjd argt[0] = PA_INT | PA_FLAG_INTMAX; 65219370Spjd return (1); 66219370Spjd} 67219370Spjd 68219370Spjdstatic int 69219370Spjdpjdlog_printf_render_humanized_number(struct __printf_io *io, 70219370Spjd const struct printf_info *pi, const void * const *arg) 71219370Spjd{ 72219370Spjd char buf[5]; 73219370Spjd intmax_t num; 74219370Spjd int ret; 75219370Spjd 76219370Spjd num = *(const intmax_t *)arg[0]; 77219370Spjd humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE, 78219370Spjd HN_NOSPACE | HN_DECIMAL); 79219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 80219370Spjd __printf_flush(io); 81219370Spjd return (ret); 82219370Spjd} 83219370Spjd 84219370Spjdstatic int 85219370Spjdpjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused, 86219370Spjd size_t n, int *argt) 87219370Spjd{ 88219370Spjd 89219370Spjd assert(n >= 1); 90219370Spjd argt[0] = PA_POINTER; 91219370Spjd return (1); 92219370Spjd} 93219370Spjd 94219370Spjdstatic int 95219370Spjdpjdlog_printf_render_sockaddr(struct __printf_io *io, 96219370Spjd const struct printf_info *pi, const void * const *arg) 97219370Spjd{ 98219370Spjd const struct sockaddr *sa; 99219370Spjd char buf[64]; 100219370Spjd int ret; 101219370Spjd 102219370Spjd sa = *(const struct sockaddr * const *)arg[0]; 103219370Spjd switch (sa->sa_family) { 104219370Spjd case AF_INET: 105219370Spjd { 106219370Spjd const struct sockaddr_in *sin; 107219370Spjd in_addr_t ip; 108219370Spjd unsigned int port; 109219370Spjd 110219370Spjd sin = (const struct sockaddr_in *)sa; 111219370Spjd ip = ntohl(sin->sin_addr.s_addr); 112219370Spjd port = ntohs(sin->sin_port); 113219370Spjd 114219370Spjd snprintf(buf, sizeof(buf), "%u.%u.%u.%u:%u", 115219370Spjd ((ip >> 24) & 0xff), ((ip >> 16) & 0xff), 116219370Spjd ((ip >> 8) & 0xff), (ip & 0xff), port); 117219370Spjd break; 118219370Spjd } 119219370Spjd default: 120219370Spjd snprintf(buf, sizeof(buf), "[unsupported family %u]", 121219370Spjd (unsigned int)sa->sa_family); 122219370Spjd break; 123219370Spjd } 124219370Spjd ret = __printf_out(io, pi, buf, strlen(buf)); 125219370Spjd __printf_flush(io); 126219370Spjd return (ret); 127219370Spjd} 128219370Spjd 129217965Spjdvoid 130217965Spjdpjdlog_init(int mode) 131217965Spjd{ 132217965Spjd 133219369Spjd assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED || 134219369Spjd pjdlog_initialized == PJDLOG_NOT_INITIALIZED); 135217965Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 136217965Spjd 137219370Spjd if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) { 138219370Spjd __use_xprintf = 1; 139219370Spjd register_printf_render_std("T"); 140219370Spjd register_printf_render('N', 141219370Spjd pjdlog_printf_render_humanized_number, 142219370Spjd pjdlog_printf_arginfo_humanized_number); 143219370Spjd register_printf_render('S', 144219370Spjd pjdlog_printf_render_sockaddr, 145219370Spjd pjdlog_printf_arginfo_sockaddr); 146219370Spjd } 147219370Spjd 148217965Spjd if (mode == PJDLOG_MODE_SYSLOG) 149217965Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 150217965Spjd pjdlog_mode = mode; 151218040Spjd pjdlog_debug_level = 0; 152218040Spjd bzero(pjdlog_prefix, sizeof(pjdlog_prefix)); 153217965Spjd 154219369Spjd pjdlog_initialized = PJDLOG_INITIALIZED; 155217965Spjd} 156217965Spjd 157217965Spjdvoid 158217965Spjdpjdlog_fini(void) 159217965Spjd{ 160217965Spjd 161219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 162217965Spjd 163217965Spjd if (pjdlog_mode == PJDLOG_MODE_SYSLOG) 164217965Spjd closelog(); 165217965Spjd 166219369Spjd pjdlog_initialized = PJDLOG_NOT_INITIALIZED; 167217965Spjd} 168217965Spjd 169204076Spjd/* 170204076Spjd * Configure where the logs should go. 171204076Spjd * By default they are send to stdout/stderr, but after going into background 172204076Spjd * (eg. by calling daemon(3)) application is responsible for changing mode to 173204076Spjd * PJDLOG_MODE_SYSLOG, so logs will be send to syslog. 174204076Spjd */ 175204076Spjdvoid 176204076Spjdpjdlog_mode_set(int mode) 177204076Spjd{ 178204076Spjd 179219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 180204076Spjd assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG); 181204076Spjd 182217965Spjd if (pjdlog_mode == mode) 183217965Spjd return; 184212052Spjd 185212052Spjd if (mode == PJDLOG_MODE_SYSLOG) 186217962Spjd openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON); 187217965Spjd else /* if (mode == PJDLOG_MODE_STD) */ 188217965Spjd closelog(); 189217965Spjd 190217965Spjd pjdlog_mode = mode; 191204076Spjd} 192204076Spjd 193204076Spjd/* 194204076Spjd * Return current mode. 195204076Spjd */ 196204076Spjdint 197204076Spjdpjdlog_mode_get(void) 198204076Spjd{ 199204076Spjd 200219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 201217965Spjd 202204076Spjd return (pjdlog_mode); 203204076Spjd} 204204076Spjd 205204076Spjd/* 206204076Spjd * Set debug level. All the logs above the level specified here will be 207204076Spjd * ignored. 208204076Spjd */ 209204076Spjdvoid 210204076Spjdpjdlog_debug_set(int level) 211204076Spjd{ 212204076Spjd 213219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 214204076Spjd assert(level >= 0); 215204076Spjd 216204076Spjd pjdlog_debug_level = level; 217204076Spjd} 218204076Spjd 219204076Spjd/* 220204076Spjd * Return current debug level. 221204076Spjd */ 222204076Spjdint 223204076Spjdpjdlog_debug_get(void) 224204076Spjd{ 225204076Spjd 226219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 227217965Spjd 228204076Spjd return (pjdlog_debug_level); 229204076Spjd} 230204076Spjd 231204076Spjd/* 232204076Spjd * Set prefix that will be used before each log. 233204076Spjd * Setting prefix to NULL will remove it. 234204076Spjd */ 235204076Spjdvoid 236204076Spjdpjdlog_prefix_set(const char *fmt, ...) 237204076Spjd{ 238204076Spjd va_list ap; 239204076Spjd 240219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 241217965Spjd 242204076Spjd va_start(ap, fmt); 243217731Spjd pjdlogv_prefix_set(fmt, ap); 244204076Spjd va_end(ap); 245204076Spjd} 246204076Spjd 247204076Spjd/* 248204076Spjd * Set prefix that will be used before each log. 249204076Spjd * Setting prefix to NULL will remove it. 250204076Spjd */ 251204076Spjdvoid 252217731Spjdpjdlogv_prefix_set(const char *fmt, va_list ap) 253204076Spjd{ 254204076Spjd 255219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 256204076Spjd assert(fmt != NULL); 257204076Spjd 258204076Spjd vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap); 259204076Spjd} 260204076Spjd 261204076Spjd/* 262204076Spjd * Convert log level into string. 263204076Spjd */ 264204076Spjdstatic const char * 265204076Spjdpjdlog_level_string(int loglevel) 266204076Spjd{ 267204076Spjd 268204076Spjd switch (loglevel) { 269204076Spjd case LOG_EMERG: 270204076Spjd return ("EMERG"); 271204076Spjd case LOG_ALERT: 272204076Spjd return ("ALERT"); 273204076Spjd case LOG_CRIT: 274204076Spjd return ("CRIT"); 275204076Spjd case LOG_ERR: 276204076Spjd return ("ERROR"); 277204076Spjd case LOG_WARNING: 278204076Spjd return ("WARNING"); 279204076Spjd case LOG_NOTICE: 280204076Spjd return ("NOTICE"); 281204076Spjd case LOG_INFO: 282204076Spjd return ("INFO"); 283204076Spjd case LOG_DEBUG: 284204076Spjd return ("DEBUG"); 285204076Spjd } 286204076Spjd assert(!"Invalid log level."); 287204076Spjd abort(); /* XXX: gcc */ 288204076Spjd} 289204076Spjd 290204076Spjd/* 291204076Spjd * Common log routine. 292204076Spjd */ 293204076Spjdvoid 294204076Spjdpjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...) 295204076Spjd{ 296204076Spjd va_list ap; 297204076Spjd 298219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 299217965Spjd 300204076Spjd va_start(ap, fmt); 301204076Spjd pjdlogv_common(loglevel, debuglevel, error, fmt, ap); 302204076Spjd va_end(ap); 303204076Spjd} 304204076Spjd 305204076Spjd/* 306204076Spjd * Common log routine, which can handle regular log level as well as debug 307204076Spjd * level. We decide here where to send the logs (stdout/stderr or syslog). 308204076Spjd */ 309204076Spjdvoid 310204076Spjdpjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt, 311204076Spjd va_list ap) 312204076Spjd{ 313204076Spjd 314219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 315204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 316204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 317204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 318204076Spjd loglevel == LOG_INFO || loglevel == LOG_DEBUG); 319204076Spjd assert(loglevel != LOG_DEBUG || debuglevel > 0); 320204076Spjd assert(error >= -1); 321204076Spjd 322204076Spjd /* Ignore debug above configured level. */ 323204076Spjd if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level) 324204076Spjd return; 325204076Spjd 326204076Spjd switch (pjdlog_mode) { 327204076Spjd case PJDLOG_MODE_STD: 328204076Spjd { 329204076Spjd FILE *out; 330204076Spjd 331204076Spjd /* 332204076Spjd * We send errors and warning to stderr and the rest to stdout. 333204076Spjd */ 334204076Spjd switch (loglevel) { 335204076Spjd case LOG_EMERG: 336204076Spjd case LOG_ALERT: 337204076Spjd case LOG_CRIT: 338204076Spjd case LOG_ERR: 339204076Spjd case LOG_WARNING: 340204076Spjd out = stderr; 341204076Spjd break; 342204076Spjd case LOG_NOTICE: 343204076Spjd case LOG_INFO: 344204076Spjd case LOG_DEBUG: 345204076Spjd out = stdout; 346204076Spjd break; 347204076Spjd default: 348204076Spjd assert(!"Invalid loglevel."); 349204076Spjd abort(); /* XXX: gcc */ 350204076Spjd } 351204076Spjd 352204076Spjd fprintf(out, "[%s]", pjdlog_level_string(loglevel)); 353204076Spjd /* Attach debuglevel if this is debug log. */ 354204076Spjd if (loglevel == LOG_DEBUG) 355204076Spjd fprintf(out, "[%d]", debuglevel); 356213939Spjd fprintf(out, " %s", pjdlog_prefix); 357204076Spjd vfprintf(out, fmt, ap); 358204076Spjd if (error != -1) 359204076Spjd fprintf(out, ": %s.", strerror(error)); 360204076Spjd fprintf(out, "\n"); 361211898Spjd fflush(out); 362204076Spjd break; 363204076Spjd } 364204076Spjd case PJDLOG_MODE_SYSLOG: 365204076Spjd { 366204076Spjd char log[1024]; 367204076Spjd int len; 368204076Spjd 369204076Spjd len = snprintf(log, sizeof(log), "%s", pjdlog_prefix); 370204076Spjd if ((size_t)len < sizeof(log)) 371206697Spjd len += vsnprintf(log + len, sizeof(log) - len, fmt, ap); 372204076Spjd if (error != -1 && (size_t)len < sizeof(log)) { 373204076Spjd (void)snprintf(log + len, sizeof(log) - len, ": %s.", 374204076Spjd strerror(error)); 375204076Spjd } 376204076Spjd syslog(loglevel, "%s", log); 377204076Spjd break; 378204076Spjd } 379204076Spjd default: 380204076Spjd assert(!"Invalid mode."); 381204076Spjd } 382204076Spjd} 383204076Spjd 384204076Spjd/* 385204076Spjd * Regular logs. 386204076Spjd */ 387204076Spjdvoid 388204076Spjdpjdlogv(int loglevel, const char *fmt, va_list ap) 389204076Spjd{ 390204076Spjd 391219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 392217965Spjd 393204076Spjd /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */ 394204076Spjd assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT || 395204076Spjd loglevel == LOG_CRIT || loglevel == LOG_ERR || 396204076Spjd loglevel == LOG_WARNING || loglevel == LOG_NOTICE || 397204076Spjd loglevel == LOG_INFO); 398204076Spjd 399204076Spjd pjdlogv_common(loglevel, 0, -1, fmt, ap); 400204076Spjd} 401204076Spjd 402204076Spjd/* 403204076Spjd * Regular logs. 404204076Spjd */ 405204076Spjdvoid 406204076Spjdpjdlog(int loglevel, const char *fmt, ...) 407204076Spjd{ 408204076Spjd va_list ap; 409204076Spjd 410219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 411217965Spjd 412204076Spjd va_start(ap, fmt); 413204076Spjd pjdlogv(loglevel, fmt, ap); 414204076Spjd va_end(ap); 415204076Spjd} 416204076Spjd 417204076Spjd/* 418204076Spjd * Debug logs. 419204076Spjd */ 420204076Spjdvoid 421204076Spjdpjdlogv_debug(int debuglevel, const char *fmt, va_list ap) 422204076Spjd{ 423204076Spjd 424219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 425217965Spjd 426204076Spjd pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap); 427204076Spjd} 428204076Spjd 429204076Spjd/* 430204076Spjd * Debug logs. 431204076Spjd */ 432204076Spjdvoid 433204076Spjdpjdlog_debug(int debuglevel, const char *fmt, ...) 434204076Spjd{ 435204076Spjd va_list ap; 436204076Spjd 437219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 438217965Spjd 439204076Spjd va_start(ap, fmt); 440204076Spjd pjdlogv_debug(debuglevel, fmt, ap); 441204076Spjd va_end(ap); 442204076Spjd} 443204076Spjd 444204076Spjd/* 445204076Spjd * Error logs with errno logging. 446204076Spjd */ 447204076Spjdvoid 448204076Spjdpjdlogv_errno(int loglevel, const char *fmt, va_list ap) 449204076Spjd{ 450204076Spjd 451219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 452217965Spjd 453204076Spjd pjdlogv_common(loglevel, 0, errno, fmt, ap); 454204076Spjd} 455204076Spjd 456204076Spjd/* 457204076Spjd * Error logs with errno logging. 458204076Spjd */ 459204076Spjdvoid 460204076Spjdpjdlog_errno(int loglevel, const char *fmt, ...) 461204076Spjd{ 462204076Spjd va_list ap; 463204076Spjd 464219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 465217965Spjd 466204076Spjd va_start(ap, fmt); 467204076Spjd pjdlogv_errno(loglevel, fmt, ap); 468204076Spjd va_end(ap); 469204076Spjd} 470204076Spjd 471204076Spjd/* 472204076Spjd * Log error, errno and exit. 473204076Spjd */ 474204076Spjdvoid 475204076Spjdpjdlogv_exit(int exitcode, const char *fmt, va_list ap) 476204076Spjd{ 477204076Spjd 478219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 479217965Spjd 480204076Spjd pjdlogv_errno(LOG_ERR, fmt, ap); 481204076Spjd exit(exitcode); 482210872Spjd /* NOTREACHED */ 483204076Spjd} 484204076Spjd 485204076Spjd/* 486204076Spjd * Log error, errno and exit. 487204076Spjd */ 488204076Spjdvoid 489204076Spjdpjdlog_exit(int exitcode, const char *fmt, ...) 490204076Spjd{ 491204076Spjd va_list ap; 492204076Spjd 493219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 494217965Spjd 495204076Spjd va_start(ap, fmt); 496204076Spjd pjdlogv_exit(exitcode, fmt, ap); 497204076Spjd /* NOTREACHED */ 498204076Spjd va_end(ap); 499204076Spjd} 500204076Spjd 501204076Spjd/* 502204076Spjd * Log error and exit. 503204076Spjd */ 504204076Spjdvoid 505204076Spjdpjdlogv_exitx(int exitcode, const char *fmt, va_list ap) 506204076Spjd{ 507204076Spjd 508219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 509217965Spjd 510204076Spjd pjdlogv(LOG_ERR, fmt, ap); 511204076Spjd exit(exitcode); 512210872Spjd /* NOTREACHED */ 513204076Spjd} 514204076Spjd 515204076Spjd/* 516204076Spjd * Log error and exit. 517204076Spjd */ 518204076Spjdvoid 519204076Spjdpjdlog_exitx(int exitcode, const char *fmt, ...) 520204076Spjd{ 521204076Spjd va_list ap; 522204076Spjd 523219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 524217965Spjd 525204076Spjd va_start(ap, fmt); 526204076Spjd pjdlogv_exitx(exitcode, fmt, ap); 527204076Spjd /* NOTREACHED */ 528204076Spjd va_end(ap); 529204076Spjd} 530210875Spjd 531210875Spjd/* 532218132Spjd * Log failure message and exit. 533210875Spjd */ 534210875Spjdvoid 535218132Spjdpjdlog_abort(const char *func, const char *file, int line, 536217966Spjd const char *failedexpr, const char *fmt, ...) 537210875Spjd{ 538217966Spjd va_list ap; 539210875Spjd 540219369Spjd assert(pjdlog_initialized == PJDLOG_INITIALIZED); 541217966Spjd 542217966Spjd /* 543217966Spjd * When there is no message we pass __func__ as 'fmt'. 544217966Spjd * It would be cleaner to pass NULL or "", but gcc generates a warning 545217966Spjd * for both of those. 546217966Spjd */ 547217966Spjd if (fmt != func) { 548217966Spjd va_start(ap, fmt); 549217966Spjd pjdlogv_critical(fmt, ap); 550217966Spjd va_end(ap); 551217966Spjd } 552217966Spjd if (failedexpr == NULL) { 553217966Spjd if (func == NULL) { 554217966Spjd pjdlog_critical("Aborted at file %s, line %d.", file, 555217966Spjd line); 556217966Spjd } else { 557217966Spjd pjdlog_critical("Aborted at function %s, file %s, line %d.", 558217966Spjd func, file, line); 559217966Spjd } 560210875Spjd } else { 561217966Spjd if (func == NULL) { 562217966Spjd pjdlog_critical("Assertion failed: (%s), file %s, line %d.", 563217966Spjd failedexpr, file, line); 564217966Spjd } else { 565217966Spjd pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.", 566217966Spjd failedexpr, func, file, line); 567217966Spjd } 568210875Spjd } 569210875Spjd abort(); 570210875Spjd} 571