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