1*9b2c1562Sbluhm /* $OpenBSD: log.c,v 1.14 2017/03/21 12:06:55 bluhm Exp $ */
2b7b6a941Sreyk
3b7b6a941Sreyk /*
4b7b6a941Sreyk * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5b7b6a941Sreyk *
6b7b6a941Sreyk * Permission to use, copy, modify, and distribute this software for any
7b7b6a941Sreyk * purpose with or without fee is hereby granted, provided that the above
8b7b6a941Sreyk * copyright notice and this permission notice appear in all copies.
9b7b6a941Sreyk *
10b7b6a941Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11b7b6a941Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12b7b6a941Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13b7b6a941Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14d4fdf7edSreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15d4fdf7edSreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16d4fdf7edSreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17b7b6a941Sreyk */
18b7b6a941Sreyk
19b7b6a941Sreyk #include <stdio.h>
20b7b6a941Sreyk #include <stdlib.h>
2108141198Sreyk #include <stdarg.h>
22b7b6a941Sreyk #include <string.h>
23b7b6a941Sreyk #include <syslog.h>
2408141198Sreyk #include <errno.h>
2586f952e4Sreyk #include <time.h>
26b7b6a941Sreyk
27871fc12cSreyk static int debug;
28871fc12cSreyk static int verbose;
290f12961aSreyk const char *log_procname;
30b7b6a941Sreyk
310f12961aSreyk void log_init(int, int);
320f12961aSreyk void log_procinit(const char *);
33871fc12cSreyk void log_setverbose(int);
34871fc12cSreyk int log_getverbose(void);
3508141198Sreyk void log_warn(const char *, ...)
3608141198Sreyk __attribute__((__format__ (printf, 1, 2)));
3708141198Sreyk void log_warnx(const char *, ...)
3808141198Sreyk __attribute__((__format__ (printf, 1, 2)));
3908141198Sreyk void log_info(const char *, ...)
4008141198Sreyk __attribute__((__format__ (printf, 1, 2)));
4108141198Sreyk void log_debug(const char *, ...)
4208141198Sreyk __attribute__((__format__ (printf, 1, 2)));
43b7b6a941Sreyk void logit(int, const char *, ...)
44b7b6a941Sreyk __attribute__((__format__ (printf, 2, 3)));
4508141198Sreyk void vlog(int, const char *, va_list)
4608141198Sreyk __attribute__((__format__ (printf, 2, 0)));
470f12961aSreyk __dead void fatal(const char *, ...)
480f12961aSreyk __attribute__((__format__ (printf, 1, 2)));
490f12961aSreyk __dead void fatalx(const char *, ...)
500f12961aSreyk __attribute__((__format__ (printf, 1, 2)));
51b7b6a941Sreyk
52b7b6a941Sreyk void
log_init(int n_debug,int facility)530f12961aSreyk log_init(int n_debug, int facility)
54b7b6a941Sreyk {
55b7b6a941Sreyk extern char *__progname;
56b7b6a941Sreyk
57b7b6a941Sreyk debug = n_debug;
58b7b6a941Sreyk verbose = n_debug;
590f12961aSreyk log_procinit(__progname);
60b7b6a941Sreyk
61b7b6a941Sreyk if (!debug)
620f12961aSreyk openlog(__progname, LOG_PID | LOG_NDELAY, facility);
63b7b6a941Sreyk
64b7b6a941Sreyk tzset();
65b7b6a941Sreyk }
66b7b6a941Sreyk
67b7b6a941Sreyk void
log_procinit(const char * procname)680f12961aSreyk log_procinit(const char *procname)
690f12961aSreyk {
700f12961aSreyk if (procname != NULL)
710f12961aSreyk log_procname = procname;
720f12961aSreyk }
730f12961aSreyk
740f12961aSreyk void
log_setverbose(int v)75871fc12cSreyk log_setverbose(int v)
76b7b6a941Sreyk {
77b7b6a941Sreyk verbose = v;
78b7b6a941Sreyk }
79b7b6a941Sreyk
80871fc12cSreyk int
log_getverbose(void)81871fc12cSreyk log_getverbose(void)
82871fc12cSreyk {
83871fc12cSreyk return (verbose);
84871fc12cSreyk }
85871fc12cSreyk
86b7b6a941Sreyk void
logit(int pri,const char * fmt,...)87b7b6a941Sreyk logit(int pri, const char *fmt, ...)
88b7b6a941Sreyk {
89b7b6a941Sreyk va_list ap;
90b7b6a941Sreyk
91b7b6a941Sreyk va_start(ap, fmt);
92b7b6a941Sreyk vlog(pri, fmt, ap);
93b7b6a941Sreyk va_end(ap);
94b7b6a941Sreyk }
95b7b6a941Sreyk
96b7b6a941Sreyk void
vlog(int pri,const char * fmt,va_list ap)97b7b6a941Sreyk vlog(int pri, const char *fmt, va_list ap)
98b7b6a941Sreyk {
99b7b6a941Sreyk char *nfmt;
1009f5ef5a9Sreyk int saved_errno = errno;
101b7b6a941Sreyk
102b7b6a941Sreyk if (debug) {
103b7b6a941Sreyk /* best effort in out of mem situations */
104b7b6a941Sreyk if (asprintf(&nfmt, "%s\n", fmt) == -1) {
105b7b6a941Sreyk vfprintf(stderr, fmt, ap);
106b7b6a941Sreyk fprintf(stderr, "\n");
107b7b6a941Sreyk } else {
108b7b6a941Sreyk vfprintf(stderr, nfmt, ap);
109b7b6a941Sreyk free(nfmt);
110b7b6a941Sreyk }
111b7b6a941Sreyk fflush(stderr);
112b7b6a941Sreyk } else
113b7b6a941Sreyk vsyslog(pri, fmt, ap);
114b7b6a941Sreyk
1159f5ef5a9Sreyk errno = saved_errno;
1169f5ef5a9Sreyk }
117b7b6a941Sreyk
118b7b6a941Sreyk void
log_warn(const char * emsg,...)119b7b6a941Sreyk log_warn(const char *emsg, ...)
120b7b6a941Sreyk {
121b7b6a941Sreyk char *nfmt;
122b7b6a941Sreyk va_list ap;
123a6bfe157Sreyk int saved_errno = errno;
124b7b6a941Sreyk
125b7b6a941Sreyk /* best effort to even work in out of memory situations */
126b7b6a941Sreyk if (emsg == NULL)
127*9b2c1562Sbluhm logit(LOG_ERR, "%s", strerror(saved_errno));
128b7b6a941Sreyk else {
129b7b6a941Sreyk va_start(ap, emsg);
130b7b6a941Sreyk
131a6bfe157Sreyk if (asprintf(&nfmt, "%s: %s", emsg,
132a6bfe157Sreyk strerror(saved_errno)) == -1) {
133b7b6a941Sreyk /* we tried it... */
134*9b2c1562Sbluhm vlog(LOG_ERR, emsg, ap);
135*9b2c1562Sbluhm logit(LOG_ERR, "%s", strerror(saved_errno));
136b7b6a941Sreyk } else {
137*9b2c1562Sbluhm vlog(LOG_ERR, nfmt, ap);
138b7b6a941Sreyk free(nfmt);
139b7b6a941Sreyk }
140b7b6a941Sreyk va_end(ap);
141b7b6a941Sreyk }
1429f5ef5a9Sreyk
1439f5ef5a9Sreyk errno = saved_errno;
144b7b6a941Sreyk }
145b7b6a941Sreyk
146b7b6a941Sreyk void
log_warnx(const char * emsg,...)147b7b6a941Sreyk log_warnx(const char *emsg, ...)
148b7b6a941Sreyk {
149b7b6a941Sreyk va_list ap;
150b7b6a941Sreyk
151b7b6a941Sreyk va_start(ap, emsg);
152*9b2c1562Sbluhm vlog(LOG_ERR, emsg, ap);
153b7b6a941Sreyk va_end(ap);
154b7b6a941Sreyk }
155b7b6a941Sreyk
156b7b6a941Sreyk void
log_info(const char * emsg,...)157b7b6a941Sreyk log_info(const char *emsg, ...)
158b7b6a941Sreyk {
159b7b6a941Sreyk va_list ap;
160b7b6a941Sreyk
161b7b6a941Sreyk va_start(ap, emsg);
162b7b6a941Sreyk vlog(LOG_INFO, emsg, ap);
163b7b6a941Sreyk va_end(ap);
164b7b6a941Sreyk }
165b7b6a941Sreyk
166b7b6a941Sreyk void
log_debug(const char * emsg,...)167b7b6a941Sreyk log_debug(const char *emsg, ...)
168b7b6a941Sreyk {
169b7b6a941Sreyk va_list ap;
170b7b6a941Sreyk
171b7b6a941Sreyk if (verbose > 1) {
172b7b6a941Sreyk va_start(ap, emsg);
173b7b6a941Sreyk vlog(LOG_DEBUG, emsg, ap);
174b7b6a941Sreyk va_end(ap);
175b7b6a941Sreyk }
176b7b6a941Sreyk }
177b7b6a941Sreyk
1780f12961aSreyk static void
vfatalc(int code,const char * emsg,va_list ap)1799f5ef5a9Sreyk vfatalc(int code, const char *emsg, va_list ap)
180b7b6a941Sreyk {
1810f12961aSreyk static char s[BUFSIZ];
1820f12961aSreyk const char *sep;
183b7b6a941Sreyk
1840f12961aSreyk if (emsg != NULL) {
1850f12961aSreyk (void)vsnprintf(s, sizeof(s), emsg, ap);
1860f12961aSreyk sep = ": ";
1870f12961aSreyk } else {
1880f12961aSreyk s[0] = '\0';
1890f12961aSreyk sep = "";
1900f12961aSreyk }
1919f5ef5a9Sreyk if (code)
192cd7658e8Sreyk logit(LOG_CRIT, "%s: %s%s%s",
1939f5ef5a9Sreyk log_procname, s, sep, strerror(code));
1940f12961aSreyk else
195cd7658e8Sreyk logit(LOG_CRIT, "%s%s%s", log_procname, sep, s);
1960f12961aSreyk }
1970f12961aSreyk
1980f12961aSreyk void
fatal(const char * emsg,...)1990f12961aSreyk fatal(const char *emsg, ...)
2000f12961aSreyk {
2010f12961aSreyk va_list ap;
2020f12961aSreyk
2030f12961aSreyk va_start(ap, emsg);
2049f5ef5a9Sreyk vfatalc(errno, emsg, ap);
2050f12961aSreyk va_end(ap);
206b7b6a941Sreyk exit(1);
207b7b6a941Sreyk }
208b7b6a941Sreyk
209b7b6a941Sreyk void
fatalx(const char * emsg,...)2100f12961aSreyk fatalx(const char *emsg, ...)
211b7b6a941Sreyk {
2120f12961aSreyk va_list ap;
2130f12961aSreyk
2140f12961aSreyk va_start(ap, emsg);
2159f5ef5a9Sreyk vfatalc(0, emsg, ap);
2160f12961aSreyk va_end(ap);
2170f12961aSreyk exit(1);
218b7b6a941Sreyk }
219