132115b10SPawel Jakub Dawidek /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
46ef7ddd7SPawel Jakub Dawidek * Copyright (c) 2009-2010 The FreeBSD Foundation
56ef7ddd7SPawel Jakub Dawidek * Copyright (c) 2011 Pawel Jakub Dawidek <pjd@FreeBSD.org>
632115b10SPawel Jakub Dawidek * All rights reserved.
732115b10SPawel Jakub Dawidek *
832115b10SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from
932115b10SPawel Jakub Dawidek * the FreeBSD Foundation.
1032115b10SPawel Jakub Dawidek *
1132115b10SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without
1232115b10SPawel Jakub Dawidek * modification, are permitted provided that the following conditions
1332115b10SPawel Jakub Dawidek * are met:
1432115b10SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright
1532115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer.
1632115b10SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright
1732115b10SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the
1832115b10SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution.
1932115b10SPawel Jakub Dawidek *
2032115b10SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
2132115b10SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2232115b10SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2332115b10SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
2432115b10SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2532115b10SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2632115b10SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2732115b10SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2832115b10SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2932115b10SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3032115b10SPawel Jakub Dawidek * SUCH DAMAGE.
3132115b10SPawel Jakub Dawidek */
3232115b10SPawel Jakub Dawidek
330855e423SPawel Jakub Dawidek #include <sys/types.h>
349e5bdc9dSPawel Jakub Dawidek #include <sys/socket.h>
359e5bdc9dSPawel Jakub Dawidek #include <netinet/in.h>
360855e423SPawel Jakub Dawidek #include <arpa/inet.h>
379e5bdc9dSPawel Jakub Dawidek
3832115b10SPawel Jakub Dawidek #include <assert.h>
3932115b10SPawel Jakub Dawidek #include <errno.h>
409e5bdc9dSPawel Jakub Dawidek #include <libutil.h>
41ab40f58cSRuslan Bukin #include <printf.h>
427d729cedSRuslan Bukin #include <stdarg.h>
439e5bdc9dSPawel Jakub Dawidek #include <stdint.h>
4432115b10SPawel Jakub Dawidek #include <stdio.h>
4532115b10SPawel Jakub Dawidek #include <stdlib.h>
4632115b10SPawel Jakub Dawidek #include <string.h>
4732115b10SPawel Jakub Dawidek #include <syslog.h>
4832115b10SPawel Jakub Dawidek
4932115b10SPawel Jakub Dawidek #include "pjdlog.h"
5032115b10SPawel Jakub Dawidek
51a61f5793SPawel Jakub Dawidek #define PJDLOG_NEVER_INITIALIZED 0
52a61f5793SPawel Jakub Dawidek #define PJDLOG_NOT_INITIALIZED 1
53a61f5793SPawel Jakub Dawidek #define PJDLOG_INITIALIZED 2
54a61f5793SPawel Jakub Dawidek
55a61f5793SPawel Jakub Dawidek static int pjdlog_initialized = PJDLOG_NEVER_INITIALIZED;
5670db96bfSPawel Jakub Dawidek static int pjdlog_mode, pjdlog_debug_level;
5732115b10SPawel Jakub Dawidek static char pjdlog_prefix[128];
5832115b10SPawel Jakub Dawidek
599e5bdc9dSPawel Jakub Dawidek static int
pjdlog_printf_arginfo_humanized_number(const struct printf_info * pi __unused,size_t n,int * argt)609e5bdc9dSPawel Jakub Dawidek pjdlog_printf_arginfo_humanized_number(const struct printf_info *pi __unused,
619e5bdc9dSPawel Jakub Dawidek size_t n, int *argt)
629e5bdc9dSPawel Jakub Dawidek {
639e5bdc9dSPawel Jakub Dawidek
649e5bdc9dSPawel Jakub Dawidek assert(n >= 1);
659e5bdc9dSPawel Jakub Dawidek argt[0] = PA_INT | PA_FLAG_INTMAX;
669e5bdc9dSPawel Jakub Dawidek return (1);
679e5bdc9dSPawel Jakub Dawidek }
689e5bdc9dSPawel Jakub Dawidek
699e5bdc9dSPawel Jakub Dawidek static int
pjdlog_printf_render_humanized_number(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)709e5bdc9dSPawel Jakub Dawidek pjdlog_printf_render_humanized_number(struct __printf_io *io,
719e5bdc9dSPawel Jakub Dawidek const struct printf_info *pi, const void * const *arg)
729e5bdc9dSPawel Jakub Dawidek {
739e5bdc9dSPawel Jakub Dawidek char buf[5];
749e5bdc9dSPawel Jakub Dawidek intmax_t num;
759e5bdc9dSPawel Jakub Dawidek int ret;
769e5bdc9dSPawel Jakub Dawidek
779e5bdc9dSPawel Jakub Dawidek num = *(const intmax_t *)arg[0];
789e5bdc9dSPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)num, "", HN_AUTOSCALE,
799e5bdc9dSPawel Jakub Dawidek HN_NOSPACE | HN_DECIMAL);
809e5bdc9dSPawel Jakub Dawidek ret = __printf_out(io, pi, buf, strlen(buf));
819e5bdc9dSPawel Jakub Dawidek __printf_flush(io);
829e5bdc9dSPawel Jakub Dawidek return (ret);
839e5bdc9dSPawel Jakub Dawidek }
849e5bdc9dSPawel Jakub Dawidek
859e5bdc9dSPawel Jakub Dawidek static int
pjdlog_printf_arginfo_sockaddr(const struct printf_info * pi __unused,size_t n,int * argt)869e5bdc9dSPawel Jakub Dawidek pjdlog_printf_arginfo_sockaddr(const struct printf_info *pi __unused,
879e5bdc9dSPawel Jakub Dawidek size_t n, int *argt)
889e5bdc9dSPawel Jakub Dawidek {
899e5bdc9dSPawel Jakub Dawidek
909e5bdc9dSPawel Jakub Dawidek assert(n >= 1);
919e5bdc9dSPawel Jakub Dawidek argt[0] = PA_POINTER;
929e5bdc9dSPawel Jakub Dawidek return (1);
939e5bdc9dSPawel Jakub Dawidek }
949e5bdc9dSPawel Jakub Dawidek
959e5bdc9dSPawel Jakub Dawidek static int
pjdlog_printf_render_sockaddr(struct __printf_io * io,const struct printf_info * pi,const void * const * arg)969e5bdc9dSPawel Jakub Dawidek pjdlog_printf_render_sockaddr(struct __printf_io *io,
979e5bdc9dSPawel Jakub Dawidek const struct printf_info *pi, const void * const *arg)
989e5bdc9dSPawel Jakub Dawidek {
99a98bce29SPawel Jakub Dawidek const struct sockaddr_storage *ss;
1009e5bdc9dSPawel Jakub Dawidek char buf[64];
1019e5bdc9dSPawel Jakub Dawidek int ret;
1029e5bdc9dSPawel Jakub Dawidek
103a98bce29SPawel Jakub Dawidek ss = *(const struct sockaddr_storage * const *)arg[0];
104a98bce29SPawel Jakub Dawidek switch (ss->ss_family) {
1059e5bdc9dSPawel Jakub Dawidek case AF_INET:
1069e5bdc9dSPawel Jakub Dawidek {
1070855e423SPawel Jakub Dawidek char addr[INET_ADDRSTRLEN];
1089e5bdc9dSPawel Jakub Dawidek const struct sockaddr_in *sin;
1099e5bdc9dSPawel Jakub Dawidek unsigned int port;
1109e5bdc9dSPawel Jakub Dawidek
111a98bce29SPawel Jakub Dawidek sin = (const struct sockaddr_in *)ss;
1129e5bdc9dSPawel Jakub Dawidek port = ntohs(sin->sin_port);
1130855e423SPawel Jakub Dawidek if (inet_ntop(ss->ss_family, &sin->sin_addr, addr,
1140855e423SPawel Jakub Dawidek sizeof(addr)) == NULL) {
1150855e423SPawel Jakub Dawidek PJDLOG_ABORT("inet_ntop(AF_INET) failed: %s.",
1160855e423SPawel Jakub Dawidek strerror(errno));
1170855e423SPawel Jakub Dawidek }
1180855e423SPawel Jakub Dawidek snprintf(buf, sizeof(buf), "%s:%u", addr, port);
1190855e423SPawel Jakub Dawidek break;
1200855e423SPawel Jakub Dawidek }
1210855e423SPawel Jakub Dawidek case AF_INET6:
1220855e423SPawel Jakub Dawidek {
1230855e423SPawel Jakub Dawidek char addr[INET6_ADDRSTRLEN];
1240855e423SPawel Jakub Dawidek const struct sockaddr_in6 *sin;
1250855e423SPawel Jakub Dawidek unsigned int port;
1269e5bdc9dSPawel Jakub Dawidek
1270855e423SPawel Jakub Dawidek sin = (const struct sockaddr_in6 *)ss;
1280855e423SPawel Jakub Dawidek port = ntohs(sin->sin6_port);
1290855e423SPawel Jakub Dawidek if (inet_ntop(ss->ss_family, &sin->sin6_addr, addr,
1300855e423SPawel Jakub Dawidek sizeof(addr)) == NULL) {
1310855e423SPawel Jakub Dawidek PJDLOG_ABORT("inet_ntop(AF_INET6) failed: %s.",
1320855e423SPawel Jakub Dawidek strerror(errno));
1330855e423SPawel Jakub Dawidek }
1340855e423SPawel Jakub Dawidek snprintf(buf, sizeof(buf), "[%s]:%u", addr, port);
1359e5bdc9dSPawel Jakub Dawidek break;
1369e5bdc9dSPawel Jakub Dawidek }
1379e5bdc9dSPawel Jakub Dawidek default:
1380855e423SPawel Jakub Dawidek snprintf(buf, sizeof(buf), "[unsupported family %hhu]",
1390855e423SPawel Jakub Dawidek ss->ss_family);
1409e5bdc9dSPawel Jakub Dawidek break;
1419e5bdc9dSPawel Jakub Dawidek }
1429e5bdc9dSPawel Jakub Dawidek ret = __printf_out(io, pi, buf, strlen(buf));
1439e5bdc9dSPawel Jakub Dawidek __printf_flush(io);
1449e5bdc9dSPawel Jakub Dawidek return (ret);
1459e5bdc9dSPawel Jakub Dawidek }
1469e5bdc9dSPawel Jakub Dawidek
147eeb3cd67SPawel Jakub Dawidek void
pjdlog_init(int mode)148eeb3cd67SPawel Jakub Dawidek pjdlog_init(int mode)
149eeb3cd67SPawel Jakub Dawidek {
15080c9ebc2SPawel Jakub Dawidek int saved_errno;
151eeb3cd67SPawel Jakub Dawidek
152a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_NEVER_INITIALIZED ||
153a61f5793SPawel Jakub Dawidek pjdlog_initialized == PJDLOG_NOT_INITIALIZED);
154eeb3cd67SPawel Jakub Dawidek assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
155eeb3cd67SPawel Jakub Dawidek
15680c9ebc2SPawel Jakub Dawidek saved_errno = errno;
15780c9ebc2SPawel Jakub Dawidek
1589e5bdc9dSPawel Jakub Dawidek if (pjdlog_initialized == PJDLOG_NEVER_INITIALIZED) {
1599e5bdc9dSPawel Jakub Dawidek __use_xprintf = 1;
1609e5bdc9dSPawel Jakub Dawidek register_printf_render_std("T");
1619e5bdc9dSPawel Jakub Dawidek register_printf_render('N',
1629e5bdc9dSPawel Jakub Dawidek pjdlog_printf_render_humanized_number,
1639e5bdc9dSPawel Jakub Dawidek pjdlog_printf_arginfo_humanized_number);
1649e5bdc9dSPawel Jakub Dawidek register_printf_render('S',
1659e5bdc9dSPawel Jakub Dawidek pjdlog_printf_render_sockaddr,
1669e5bdc9dSPawel Jakub Dawidek pjdlog_printf_arginfo_sockaddr);
1679e5bdc9dSPawel Jakub Dawidek }
1689e5bdc9dSPawel Jakub Dawidek
169eeb3cd67SPawel Jakub Dawidek if (mode == PJDLOG_MODE_SYSLOG)
170eeb3cd67SPawel Jakub Dawidek openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON);
171eeb3cd67SPawel Jakub Dawidek pjdlog_mode = mode;
17270db96bfSPawel Jakub Dawidek pjdlog_debug_level = 0;
17370db96bfSPawel Jakub Dawidek bzero(pjdlog_prefix, sizeof(pjdlog_prefix));
174eeb3cd67SPawel Jakub Dawidek
175a61f5793SPawel Jakub Dawidek pjdlog_initialized = PJDLOG_INITIALIZED;
17680c9ebc2SPawel Jakub Dawidek
17780c9ebc2SPawel Jakub Dawidek errno = saved_errno;
178eeb3cd67SPawel Jakub Dawidek }
179eeb3cd67SPawel Jakub Dawidek
180eeb3cd67SPawel Jakub Dawidek void
pjdlog_fini(void)181eeb3cd67SPawel Jakub Dawidek pjdlog_fini(void)
182eeb3cd67SPawel Jakub Dawidek {
18380c9ebc2SPawel Jakub Dawidek int saved_errno;
184eeb3cd67SPawel Jakub Dawidek
185a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
186eeb3cd67SPawel Jakub Dawidek
18780c9ebc2SPawel Jakub Dawidek saved_errno = errno;
18880c9ebc2SPawel Jakub Dawidek
189eeb3cd67SPawel Jakub Dawidek if (pjdlog_mode == PJDLOG_MODE_SYSLOG)
190eeb3cd67SPawel Jakub Dawidek closelog();
191eeb3cd67SPawel Jakub Dawidek
192a61f5793SPawel Jakub Dawidek pjdlog_initialized = PJDLOG_NOT_INITIALIZED;
19380c9ebc2SPawel Jakub Dawidek
19480c9ebc2SPawel Jakub Dawidek errno = saved_errno;
195eeb3cd67SPawel Jakub Dawidek }
196eeb3cd67SPawel Jakub Dawidek
19732115b10SPawel Jakub Dawidek /*
19832115b10SPawel Jakub Dawidek * Configure where the logs should go.
19932115b10SPawel Jakub Dawidek * By default they are send to stdout/stderr, but after going into background
20032115b10SPawel Jakub Dawidek * (eg. by calling daemon(3)) application is responsible for changing mode to
20132115b10SPawel Jakub Dawidek * PJDLOG_MODE_SYSLOG, so logs will be send to syslog.
20232115b10SPawel Jakub Dawidek */
20332115b10SPawel Jakub Dawidek void
pjdlog_mode_set(int mode)20432115b10SPawel Jakub Dawidek pjdlog_mode_set(int mode)
20532115b10SPawel Jakub Dawidek {
20680c9ebc2SPawel Jakub Dawidek int saved_errno;
20732115b10SPawel Jakub Dawidek
208a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
20932115b10SPawel Jakub Dawidek assert(mode == PJDLOG_MODE_STD || mode == PJDLOG_MODE_SYSLOG);
21032115b10SPawel Jakub Dawidek
211eeb3cd67SPawel Jakub Dawidek if (pjdlog_mode == mode)
212eeb3cd67SPawel Jakub Dawidek return;
2136d19256bSPawel Jakub Dawidek
21480c9ebc2SPawel Jakub Dawidek saved_errno = errno;
21580c9ebc2SPawel Jakub Dawidek
2166d19256bSPawel Jakub Dawidek if (mode == PJDLOG_MODE_SYSLOG)
217c6245737SPawel Jakub Dawidek openlog(NULL, LOG_PID | LOG_NDELAY, LOG_DAEMON);
218eeb3cd67SPawel Jakub Dawidek else /* if (mode == PJDLOG_MODE_STD) */
219eeb3cd67SPawel Jakub Dawidek closelog();
220eeb3cd67SPawel Jakub Dawidek
221eeb3cd67SPawel Jakub Dawidek pjdlog_mode = mode;
22280c9ebc2SPawel Jakub Dawidek
22380c9ebc2SPawel Jakub Dawidek errno = saved_errno;
22432115b10SPawel Jakub Dawidek }
22532115b10SPawel Jakub Dawidek
22632115b10SPawel Jakub Dawidek /*
22732115b10SPawel Jakub Dawidek * Return current mode.
22832115b10SPawel Jakub Dawidek */
22932115b10SPawel Jakub Dawidek int
pjdlog_mode_get(void)23032115b10SPawel Jakub Dawidek pjdlog_mode_get(void)
23132115b10SPawel Jakub Dawidek {
23232115b10SPawel Jakub Dawidek
233a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
234eeb3cd67SPawel Jakub Dawidek
23532115b10SPawel Jakub Dawidek return (pjdlog_mode);
23632115b10SPawel Jakub Dawidek }
23732115b10SPawel Jakub Dawidek
23832115b10SPawel Jakub Dawidek /*
23932115b10SPawel Jakub Dawidek * Set debug level. All the logs above the level specified here will be
24032115b10SPawel Jakub Dawidek * ignored.
24132115b10SPawel Jakub Dawidek */
24232115b10SPawel Jakub Dawidek void
pjdlog_debug_set(int level)24332115b10SPawel Jakub Dawidek pjdlog_debug_set(int level)
24432115b10SPawel Jakub Dawidek {
24532115b10SPawel Jakub Dawidek
246a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
24732115b10SPawel Jakub Dawidek assert(level >= 0);
24832115b10SPawel Jakub Dawidek
24932115b10SPawel Jakub Dawidek pjdlog_debug_level = level;
25032115b10SPawel Jakub Dawidek }
25132115b10SPawel Jakub Dawidek
25232115b10SPawel Jakub Dawidek /*
25332115b10SPawel Jakub Dawidek * Return current debug level.
25432115b10SPawel Jakub Dawidek */
25532115b10SPawel Jakub Dawidek int
pjdlog_debug_get(void)25632115b10SPawel Jakub Dawidek pjdlog_debug_get(void)
25732115b10SPawel Jakub Dawidek {
25832115b10SPawel Jakub Dawidek
259a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
260eeb3cd67SPawel Jakub Dawidek
26132115b10SPawel Jakub Dawidek return (pjdlog_debug_level);
26232115b10SPawel Jakub Dawidek }
26332115b10SPawel Jakub Dawidek
26432115b10SPawel Jakub Dawidek /*
26532115b10SPawel Jakub Dawidek * Set prefix that will be used before each log.
26632115b10SPawel Jakub Dawidek * Setting prefix to NULL will remove it.
26732115b10SPawel Jakub Dawidek */
26832115b10SPawel Jakub Dawidek void
pjdlog_prefix_set(const char * fmt,...)26932115b10SPawel Jakub Dawidek pjdlog_prefix_set(const char *fmt, ...)
27032115b10SPawel Jakub Dawidek {
27132115b10SPawel Jakub Dawidek va_list ap;
27232115b10SPawel Jakub Dawidek
273a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
274eeb3cd67SPawel Jakub Dawidek
27532115b10SPawel Jakub Dawidek va_start(ap, fmt);
27609d6ae1bSPawel Jakub Dawidek pjdlogv_prefix_set(fmt, ap);
27732115b10SPawel Jakub Dawidek va_end(ap);
27832115b10SPawel Jakub Dawidek }
27932115b10SPawel Jakub Dawidek
28032115b10SPawel Jakub Dawidek /*
28132115b10SPawel Jakub Dawidek * Set prefix that will be used before each log.
28232115b10SPawel Jakub Dawidek * Setting prefix to NULL will remove it.
28332115b10SPawel Jakub Dawidek */
28432115b10SPawel Jakub Dawidek void
pjdlogv_prefix_set(const char * fmt,va_list ap)28509d6ae1bSPawel Jakub Dawidek pjdlogv_prefix_set(const char *fmt, va_list ap)
28632115b10SPawel Jakub Dawidek {
28780c9ebc2SPawel Jakub Dawidek int saved_errno;
28832115b10SPawel Jakub Dawidek
289a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
29032115b10SPawel Jakub Dawidek assert(fmt != NULL);
29132115b10SPawel Jakub Dawidek
29280c9ebc2SPawel Jakub Dawidek saved_errno = errno;
29380c9ebc2SPawel Jakub Dawidek
29432115b10SPawel Jakub Dawidek vsnprintf(pjdlog_prefix, sizeof(pjdlog_prefix), fmt, ap);
29580c9ebc2SPawel Jakub Dawidek
29680c9ebc2SPawel Jakub Dawidek errno = saved_errno;
29732115b10SPawel Jakub Dawidek }
29832115b10SPawel Jakub Dawidek
29932115b10SPawel Jakub Dawidek /*
30032115b10SPawel Jakub Dawidek * Convert log level into string.
30132115b10SPawel Jakub Dawidek */
30232115b10SPawel Jakub Dawidek static const char *
pjdlog_level_string(int loglevel)30332115b10SPawel Jakub Dawidek pjdlog_level_string(int loglevel)
30432115b10SPawel Jakub Dawidek {
30532115b10SPawel Jakub Dawidek
30632115b10SPawel Jakub Dawidek switch (loglevel) {
30732115b10SPawel Jakub Dawidek case LOG_EMERG:
30832115b10SPawel Jakub Dawidek return ("EMERG");
30932115b10SPawel Jakub Dawidek case LOG_ALERT:
31032115b10SPawel Jakub Dawidek return ("ALERT");
31132115b10SPawel Jakub Dawidek case LOG_CRIT:
31232115b10SPawel Jakub Dawidek return ("CRIT");
31332115b10SPawel Jakub Dawidek case LOG_ERR:
31432115b10SPawel Jakub Dawidek return ("ERROR");
31532115b10SPawel Jakub Dawidek case LOG_WARNING:
31632115b10SPawel Jakub Dawidek return ("WARNING");
31732115b10SPawel Jakub Dawidek case LOG_NOTICE:
31832115b10SPawel Jakub Dawidek return ("NOTICE");
31932115b10SPawel Jakub Dawidek case LOG_INFO:
32032115b10SPawel Jakub Dawidek return ("INFO");
32132115b10SPawel Jakub Dawidek case LOG_DEBUG:
32232115b10SPawel Jakub Dawidek return ("DEBUG");
32332115b10SPawel Jakub Dawidek }
32432115b10SPawel Jakub Dawidek assert(!"Invalid log level.");
32532115b10SPawel Jakub Dawidek abort(); /* XXX: gcc */
32632115b10SPawel Jakub Dawidek }
32732115b10SPawel Jakub Dawidek
32832115b10SPawel Jakub Dawidek /*
32932115b10SPawel Jakub Dawidek * Common log routine.
33032115b10SPawel Jakub Dawidek */
33132115b10SPawel Jakub Dawidek void
pjdlog_common(int loglevel,int debuglevel,int error,const char * fmt,...)33232115b10SPawel Jakub Dawidek pjdlog_common(int loglevel, int debuglevel, int error, const char *fmt, ...)
33332115b10SPawel Jakub Dawidek {
33432115b10SPawel Jakub Dawidek va_list ap;
33532115b10SPawel Jakub Dawidek
336a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
337eeb3cd67SPawel Jakub Dawidek
33832115b10SPawel Jakub Dawidek va_start(ap, fmt);
33932115b10SPawel Jakub Dawidek pjdlogv_common(loglevel, debuglevel, error, fmt, ap);
34032115b10SPawel Jakub Dawidek va_end(ap);
34132115b10SPawel Jakub Dawidek }
34232115b10SPawel Jakub Dawidek
34332115b10SPawel Jakub Dawidek /*
34432115b10SPawel Jakub Dawidek * Common log routine, which can handle regular log level as well as debug
34532115b10SPawel Jakub Dawidek * level. We decide here where to send the logs (stdout/stderr or syslog).
34632115b10SPawel Jakub Dawidek */
34732115b10SPawel Jakub Dawidek void
pjdlogv_common(int loglevel,int debuglevel,int error,const char * fmt,va_list ap)34832115b10SPawel Jakub Dawidek pjdlogv_common(int loglevel, int debuglevel, int error, const char *fmt,
34932115b10SPawel Jakub Dawidek va_list ap)
35032115b10SPawel Jakub Dawidek {
35180c9ebc2SPawel Jakub Dawidek int saved_errno;
35232115b10SPawel Jakub Dawidek
353a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
35432115b10SPawel Jakub Dawidek assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
35532115b10SPawel Jakub Dawidek loglevel == LOG_CRIT || loglevel == LOG_ERR ||
35632115b10SPawel Jakub Dawidek loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
35732115b10SPawel Jakub Dawidek loglevel == LOG_INFO || loglevel == LOG_DEBUG);
35832115b10SPawel Jakub Dawidek assert(loglevel != LOG_DEBUG || debuglevel > 0);
35932115b10SPawel Jakub Dawidek assert(error >= -1);
36032115b10SPawel Jakub Dawidek
36132115b10SPawel Jakub Dawidek /* Ignore debug above configured level. */
36232115b10SPawel Jakub Dawidek if (loglevel == LOG_DEBUG && debuglevel > pjdlog_debug_level)
36332115b10SPawel Jakub Dawidek return;
36432115b10SPawel Jakub Dawidek
36580c9ebc2SPawel Jakub Dawidek saved_errno = errno;
36680c9ebc2SPawel Jakub Dawidek
36732115b10SPawel Jakub Dawidek switch (pjdlog_mode) {
36832115b10SPawel Jakub Dawidek case PJDLOG_MODE_STD:
36932115b10SPawel Jakub Dawidek {
37032115b10SPawel Jakub Dawidek FILE *out;
37132115b10SPawel Jakub Dawidek
37232115b10SPawel Jakub Dawidek /*
37332115b10SPawel Jakub Dawidek * We send errors and warning to stderr and the rest to stdout.
37432115b10SPawel Jakub Dawidek */
37532115b10SPawel Jakub Dawidek switch (loglevel) {
37632115b10SPawel Jakub Dawidek case LOG_EMERG:
37732115b10SPawel Jakub Dawidek case LOG_ALERT:
37832115b10SPawel Jakub Dawidek case LOG_CRIT:
37932115b10SPawel Jakub Dawidek case LOG_ERR:
38032115b10SPawel Jakub Dawidek case LOG_WARNING:
38132115b10SPawel Jakub Dawidek out = stderr;
38232115b10SPawel Jakub Dawidek break;
38332115b10SPawel Jakub Dawidek case LOG_NOTICE:
38432115b10SPawel Jakub Dawidek case LOG_INFO:
38532115b10SPawel Jakub Dawidek case LOG_DEBUG:
38632115b10SPawel Jakub Dawidek out = stdout;
38732115b10SPawel Jakub Dawidek break;
38832115b10SPawel Jakub Dawidek default:
38932115b10SPawel Jakub Dawidek assert(!"Invalid loglevel.");
39032115b10SPawel Jakub Dawidek abort(); /* XXX: gcc */
39132115b10SPawel Jakub Dawidek }
39232115b10SPawel Jakub Dawidek
39332115b10SPawel Jakub Dawidek fprintf(out, "[%s]", pjdlog_level_string(loglevel));
39432115b10SPawel Jakub Dawidek /* Attach debuglevel if this is debug log. */
39532115b10SPawel Jakub Dawidek if (loglevel == LOG_DEBUG)
39632115b10SPawel Jakub Dawidek fprintf(out, "[%d]", debuglevel);
39732115b10SPawel Jakub Dawidek fprintf(out, " %s", pjdlog_prefix);
39832115b10SPawel Jakub Dawidek vfprintf(out, fmt, ap);
39932115b10SPawel Jakub Dawidek if (error != -1)
40032115b10SPawel Jakub Dawidek fprintf(out, ": %s.", strerror(error));
40132115b10SPawel Jakub Dawidek fprintf(out, "\n");
4024767ee29SPawel Jakub Dawidek fflush(out);
40332115b10SPawel Jakub Dawidek break;
40432115b10SPawel Jakub Dawidek }
40532115b10SPawel Jakub Dawidek case PJDLOG_MODE_SYSLOG:
40632115b10SPawel Jakub Dawidek {
40732115b10SPawel Jakub Dawidek char log[1024];
40832115b10SPawel Jakub Dawidek int len;
40932115b10SPawel Jakub Dawidek
41032115b10SPawel Jakub Dawidek len = snprintf(log, sizeof(log), "%s", pjdlog_prefix);
41132115b10SPawel Jakub Dawidek if ((size_t)len < sizeof(log))
41220ec52dcSPawel Jakub Dawidek len += vsnprintf(log + len, sizeof(log) - len, fmt, ap);
41332115b10SPawel Jakub Dawidek if (error != -1 && (size_t)len < sizeof(log)) {
41432115b10SPawel Jakub Dawidek (void)snprintf(log + len, sizeof(log) - len, ": %s.",
41532115b10SPawel Jakub Dawidek strerror(error));
41632115b10SPawel Jakub Dawidek }
41732115b10SPawel Jakub Dawidek syslog(loglevel, "%s", log);
41832115b10SPawel Jakub Dawidek break;
41932115b10SPawel Jakub Dawidek }
42032115b10SPawel Jakub Dawidek default:
42132115b10SPawel Jakub Dawidek assert(!"Invalid mode.");
42232115b10SPawel Jakub Dawidek }
42380c9ebc2SPawel Jakub Dawidek
42480c9ebc2SPawel Jakub Dawidek errno = saved_errno;
42532115b10SPawel Jakub Dawidek }
42632115b10SPawel Jakub Dawidek
42732115b10SPawel Jakub Dawidek /*
42832115b10SPawel Jakub Dawidek * Regular logs.
42932115b10SPawel Jakub Dawidek */
43032115b10SPawel Jakub Dawidek void
pjdlogv(int loglevel,const char * fmt,va_list ap)43132115b10SPawel Jakub Dawidek pjdlogv(int loglevel, const char *fmt, va_list ap)
43232115b10SPawel Jakub Dawidek {
43332115b10SPawel Jakub Dawidek
434a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
435eeb3cd67SPawel Jakub Dawidek
43632115b10SPawel Jakub Dawidek /* LOG_DEBUG is invalid here, pjdlogv?_debug() should be used. */
43732115b10SPawel Jakub Dawidek assert(loglevel == LOG_EMERG || loglevel == LOG_ALERT ||
43832115b10SPawel Jakub Dawidek loglevel == LOG_CRIT || loglevel == LOG_ERR ||
43932115b10SPawel Jakub Dawidek loglevel == LOG_WARNING || loglevel == LOG_NOTICE ||
44032115b10SPawel Jakub Dawidek loglevel == LOG_INFO);
44132115b10SPawel Jakub Dawidek
44232115b10SPawel Jakub Dawidek pjdlogv_common(loglevel, 0, -1, fmt, ap);
44332115b10SPawel Jakub Dawidek }
44432115b10SPawel Jakub Dawidek
44532115b10SPawel Jakub Dawidek /*
44632115b10SPawel Jakub Dawidek * Regular logs.
44732115b10SPawel Jakub Dawidek */
44832115b10SPawel Jakub Dawidek void
pjdlog(int loglevel,const char * fmt,...)44932115b10SPawel Jakub Dawidek pjdlog(int loglevel, const char *fmt, ...)
45032115b10SPawel Jakub Dawidek {
45132115b10SPawel Jakub Dawidek va_list ap;
45232115b10SPawel Jakub Dawidek
453a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
454eeb3cd67SPawel Jakub Dawidek
45532115b10SPawel Jakub Dawidek va_start(ap, fmt);
45632115b10SPawel Jakub Dawidek pjdlogv(loglevel, fmt, ap);
45732115b10SPawel Jakub Dawidek va_end(ap);
45832115b10SPawel Jakub Dawidek }
45932115b10SPawel Jakub Dawidek
46032115b10SPawel Jakub Dawidek /*
46132115b10SPawel Jakub Dawidek * Debug logs.
46232115b10SPawel Jakub Dawidek */
46332115b10SPawel Jakub Dawidek void
pjdlogv_debug(int debuglevel,const char * fmt,va_list ap)46432115b10SPawel Jakub Dawidek pjdlogv_debug(int debuglevel, const char *fmt, va_list ap)
46532115b10SPawel Jakub Dawidek {
46632115b10SPawel Jakub Dawidek
467a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
468eeb3cd67SPawel Jakub Dawidek
46932115b10SPawel Jakub Dawidek pjdlogv_common(LOG_DEBUG, debuglevel, -1, fmt, ap);
47032115b10SPawel Jakub Dawidek }
47132115b10SPawel Jakub Dawidek
47232115b10SPawel Jakub Dawidek /*
47332115b10SPawel Jakub Dawidek * Debug logs.
47432115b10SPawel Jakub Dawidek */
47532115b10SPawel Jakub Dawidek void
pjdlog_debug(int debuglevel,const char * fmt,...)47632115b10SPawel Jakub Dawidek pjdlog_debug(int debuglevel, const char *fmt, ...)
47732115b10SPawel Jakub Dawidek {
47832115b10SPawel Jakub Dawidek va_list ap;
47932115b10SPawel Jakub Dawidek
480a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
481eeb3cd67SPawel Jakub Dawidek
48232115b10SPawel Jakub Dawidek va_start(ap, fmt);
48332115b10SPawel Jakub Dawidek pjdlogv_debug(debuglevel, fmt, ap);
48432115b10SPawel Jakub Dawidek va_end(ap);
48532115b10SPawel Jakub Dawidek }
48632115b10SPawel Jakub Dawidek
48732115b10SPawel Jakub Dawidek /*
48832115b10SPawel Jakub Dawidek * Error logs with errno logging.
48932115b10SPawel Jakub Dawidek */
49032115b10SPawel Jakub Dawidek void
pjdlogv_errno(int loglevel,const char * fmt,va_list ap)49132115b10SPawel Jakub Dawidek pjdlogv_errno(int loglevel, const char *fmt, va_list ap)
49232115b10SPawel Jakub Dawidek {
49332115b10SPawel Jakub Dawidek
494a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
495eeb3cd67SPawel Jakub Dawidek
49632115b10SPawel Jakub Dawidek pjdlogv_common(loglevel, 0, errno, fmt, ap);
49732115b10SPawel Jakub Dawidek }
49832115b10SPawel Jakub Dawidek
49932115b10SPawel Jakub Dawidek /*
50032115b10SPawel Jakub Dawidek * Error logs with errno logging.
50132115b10SPawel Jakub Dawidek */
50232115b10SPawel Jakub Dawidek void
pjdlog_errno(int loglevel,const char * fmt,...)50332115b10SPawel Jakub Dawidek pjdlog_errno(int loglevel, const char *fmt, ...)
50432115b10SPawel Jakub Dawidek {
50532115b10SPawel Jakub Dawidek va_list ap;
50632115b10SPawel Jakub Dawidek
507a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
508eeb3cd67SPawel Jakub Dawidek
50932115b10SPawel Jakub Dawidek va_start(ap, fmt);
51032115b10SPawel Jakub Dawidek pjdlogv_errno(loglevel, fmt, ap);
51132115b10SPawel Jakub Dawidek va_end(ap);
51232115b10SPawel Jakub Dawidek }
51332115b10SPawel Jakub Dawidek
51432115b10SPawel Jakub Dawidek /*
51532115b10SPawel Jakub Dawidek * Log error, errno and exit.
51632115b10SPawel Jakub Dawidek */
51732115b10SPawel Jakub Dawidek void
pjdlogv_exit(int exitcode,const char * fmt,va_list ap)51832115b10SPawel Jakub Dawidek pjdlogv_exit(int exitcode, const char *fmt, va_list ap)
51932115b10SPawel Jakub Dawidek {
52032115b10SPawel Jakub Dawidek
521a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
522eeb3cd67SPawel Jakub Dawidek
52332115b10SPawel Jakub Dawidek pjdlogv_errno(LOG_ERR, fmt, ap);
52432115b10SPawel Jakub Dawidek exit(exitcode);
525e3031161SPawel Jakub Dawidek /* NOTREACHED */
52632115b10SPawel Jakub Dawidek }
52732115b10SPawel Jakub Dawidek
52832115b10SPawel Jakub Dawidek /*
52932115b10SPawel Jakub Dawidek * Log error, errno and exit.
53032115b10SPawel Jakub Dawidek */
53132115b10SPawel Jakub Dawidek void
pjdlog_exit(int exitcode,const char * fmt,...)53232115b10SPawel Jakub Dawidek pjdlog_exit(int exitcode, const char *fmt, ...)
53332115b10SPawel Jakub Dawidek {
53432115b10SPawel Jakub Dawidek va_list ap;
53532115b10SPawel Jakub Dawidek
536a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
537eeb3cd67SPawel Jakub Dawidek
53832115b10SPawel Jakub Dawidek va_start(ap, fmt);
53932115b10SPawel Jakub Dawidek pjdlogv_exit(exitcode, fmt, ap);
54032115b10SPawel Jakub Dawidek /* NOTREACHED */
54132115b10SPawel Jakub Dawidek va_end(ap);
54232115b10SPawel Jakub Dawidek }
54332115b10SPawel Jakub Dawidek
54432115b10SPawel Jakub Dawidek /*
54532115b10SPawel Jakub Dawidek * Log error and exit.
54632115b10SPawel Jakub Dawidek */
54732115b10SPawel Jakub Dawidek void
pjdlogv_exitx(int exitcode,const char * fmt,va_list ap)54832115b10SPawel Jakub Dawidek pjdlogv_exitx(int exitcode, const char *fmt, va_list ap)
54932115b10SPawel Jakub Dawidek {
55032115b10SPawel Jakub Dawidek
551a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
552eeb3cd67SPawel Jakub Dawidek
55332115b10SPawel Jakub Dawidek pjdlogv(LOG_ERR, fmt, ap);
55432115b10SPawel Jakub Dawidek exit(exitcode);
555e3031161SPawel Jakub Dawidek /* NOTREACHED */
55632115b10SPawel Jakub Dawidek }
55732115b10SPawel Jakub Dawidek
55832115b10SPawel Jakub Dawidek /*
55932115b10SPawel Jakub Dawidek * Log error and exit.
56032115b10SPawel Jakub Dawidek */
56132115b10SPawel Jakub Dawidek void
pjdlog_exitx(int exitcode,const char * fmt,...)56232115b10SPawel Jakub Dawidek pjdlog_exitx(int exitcode, const char *fmt, ...)
56332115b10SPawel Jakub Dawidek {
56432115b10SPawel Jakub Dawidek va_list ap;
56532115b10SPawel Jakub Dawidek
566a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
567eeb3cd67SPawel Jakub Dawidek
56832115b10SPawel Jakub Dawidek va_start(ap, fmt);
56932115b10SPawel Jakub Dawidek pjdlogv_exitx(exitcode, fmt, ap);
57032115b10SPawel Jakub Dawidek /* NOTREACHED */
57132115b10SPawel Jakub Dawidek va_end(ap);
57232115b10SPawel Jakub Dawidek }
573524840d8SPawel Jakub Dawidek
574524840d8SPawel Jakub Dawidek /*
57505a6b8deSPawel Jakub Dawidek * Log failure message and exit.
576524840d8SPawel Jakub Dawidek */
577524840d8SPawel Jakub Dawidek void
pjdlog_abort(const char * func,const char * file,int line,const char * failedexpr,const char * fmt,...)57805a6b8deSPawel Jakub Dawidek pjdlog_abort(const char *func, const char *file, int line,
57994bf851dSPawel Jakub Dawidek const char *failedexpr, const char *fmt, ...)
580524840d8SPawel Jakub Dawidek {
58194bf851dSPawel Jakub Dawidek va_list ap;
582524840d8SPawel Jakub Dawidek
583a61f5793SPawel Jakub Dawidek assert(pjdlog_initialized == PJDLOG_INITIALIZED);
58494bf851dSPawel Jakub Dawidek
58594bf851dSPawel Jakub Dawidek /*
58694bf851dSPawel Jakub Dawidek * When there is no message we pass __func__ as 'fmt'.
58794bf851dSPawel Jakub Dawidek * It would be cleaner to pass NULL or "", but gcc generates a warning
58894bf851dSPawel Jakub Dawidek * for both of those.
58994bf851dSPawel Jakub Dawidek */
59094bf851dSPawel Jakub Dawidek if (fmt != func) {
59194bf851dSPawel Jakub Dawidek va_start(ap, fmt);
59294bf851dSPawel Jakub Dawidek pjdlogv_critical(fmt, ap);
59394bf851dSPawel Jakub Dawidek va_end(ap);
59494bf851dSPawel Jakub Dawidek }
59594bf851dSPawel Jakub Dawidek if (failedexpr == NULL) {
59694bf851dSPawel Jakub Dawidek if (func == NULL) {
59794bf851dSPawel Jakub Dawidek pjdlog_critical("Aborted at file %s, line %d.", file,
59894bf851dSPawel Jakub Dawidek line);
59994bf851dSPawel Jakub Dawidek } else {
60094bf851dSPawel Jakub Dawidek pjdlog_critical("Aborted at function %s, file %s, line %d.",
60194bf851dSPawel Jakub Dawidek func, file, line);
60294bf851dSPawel Jakub Dawidek }
60394bf851dSPawel Jakub Dawidek } else {
604524840d8SPawel Jakub Dawidek if (func == NULL) {
605524840d8SPawel Jakub Dawidek pjdlog_critical("Assertion failed: (%s), file %s, line %d.",
606524840d8SPawel Jakub Dawidek failedexpr, file, line);
607524840d8SPawel Jakub Dawidek } else {
608524840d8SPawel Jakub Dawidek pjdlog_critical("Assertion failed: (%s), function %s, file %s, line %d.",
609524840d8SPawel Jakub Dawidek failedexpr, func, file, line);
610524840d8SPawel Jakub Dawidek }
61194bf851dSPawel Jakub Dawidek }
612524840d8SPawel Jakub Dawidek abort();
613524840d8SPawel Jakub Dawidek }
614