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