1/*	$OpenBSD: log.c,v 1.4 2017/04/28 14:52:13 bluhm Exp $	*/
2
3/*
4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2017 Alexander Bluhm <bluhm@openbsd.org>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <err.h>
21#include <errno.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <syslog.h>
26#include <time.h>
27
28#include "log.h"
29#include "syslogd.h"
30
31static int		 verbose;
32static int		 facility;
33static const char	*log_procname;
34static char		*debug_ebuf;
35static size_t		 debug_length;
36
37void
38log_init(int n_debug, int fac)
39{
40	extern char	*__progname;
41
42	verbose = n_debug;
43	facility = fac;
44	log_procinit(__progname);
45
46	if (debug_ebuf == NULL)
47		if ((debug_ebuf = malloc(ERRBUFSIZE)) == NULL)
48			err(1, "allocate debug buffer");
49	debug_ebuf[0] = '\0';
50	debug_length = 0;
51
52	tzset();
53}
54
55void
56log_procinit(const char *procname)
57{
58	if (procname != NULL)
59		log_procname = procname;
60}
61
62void
63log_setverbose(int v)
64{
65	verbose = v;
66}
67
68int
69log_getverbose(void)
70{
71	return (verbose);
72}
73
74void
75logit(int pri, const char *fmt, ...)
76{
77	va_list	ap;
78
79	va_start(ap, fmt);
80	vlog(pri, fmt, ap);
81	va_end(ap);
82}
83
84void
85vlog(int pri, const char *fmt, va_list ap)
86{
87	int	 saved_errno = errno;
88
89	vlogmsg(facility|pri, log_procname, fmt, ap);
90
91	errno = saved_errno;
92}
93
94void
95log_warn(const char *emsg, ...)
96{
97	char	 ebuf[ERRBUFSIZE];
98	size_t	 l;
99	va_list	 ap;
100	int	 saved_errno = errno;
101
102	/* best effort to even work in out of memory situations */
103	if (emsg == NULL)
104		logit(LOG_ERR, "%s", strerror(saved_errno));
105	else {
106		va_start(ap, emsg);
107		l = vsnprintf(ebuf, sizeof(ebuf), emsg, ap);
108		if (l < sizeof(ebuf))
109			snprintf(ebuf+l, sizeof(ebuf)-l, ": %s",
110			    strerror(saved_errno));
111		logit(LOG_ERR, "%s", ebuf);
112		va_end(ap);
113	}
114	errno = saved_errno;
115}
116
117void
118log_warnx(const char *emsg, ...)
119{
120	va_list	 ap;
121
122	va_start(ap, emsg);
123	vlog(LOG_ERR, emsg, ap);
124	va_end(ap);
125}
126
127void
128log_info(int pri, const char *emsg, ...)
129{
130	va_list	 ap;
131
132	va_start(ap, emsg);
133	vlog(pri, emsg, ap);
134	va_end(ap);
135}
136
137void
138log_debug(const char *emsg, ...)
139{
140	va_list	 ap;
141	int	 saved_errno;
142
143	if (verbose) {
144		saved_errno = errno;
145		va_start(ap, emsg);
146		if (debug_length < ERRBUFSIZE - 1)
147			vsnprintf(debug_ebuf + debug_length,
148			    ERRBUFSIZE - debug_length, emsg, ap);
149		fprintf(stderr, "%s\n", debug_ebuf);
150		fflush(stderr);
151		va_end(ap);
152		errno = saved_errno;
153	}
154	debug_ebuf[0] = '\0';
155	debug_length = 0;
156}
157
158void
159log_debugadd(const char *emsg, ...)
160{
161	size_t	 l;
162	va_list	 ap;
163	int	 saved_errno;
164
165	if (verbose) {
166		saved_errno = errno;
167		va_start(ap, emsg);
168		if (debug_length < ERRBUFSIZE - 1) {
169			l = vsnprintf(debug_ebuf + debug_length,
170			    ERRBUFSIZE - debug_length, emsg, ap);
171			if (l < ERRBUFSIZE - debug_length)
172				debug_length += l;
173			else
174				debug_length = ERRBUFSIZE - 1;
175		}
176		va_end(ap);
177		errno = saved_errno;
178	}
179}
180
181static void
182vfatalc(int error, const char *emsg, va_list ap)
183{
184	char		 ebuf[ERRBUFSIZE];
185	const char	*sep;
186
187	if (emsg != NULL) {
188		(void)vsnprintf(ebuf, sizeof(ebuf), emsg, ap);
189		sep = ": ";
190	} else {
191		ebuf[0] = '\0';
192		sep = "";
193	}
194	if (error)
195		logit(LOG_CRIT, "fatal in %s: %s%s%s",
196		    log_procname, ebuf, sep, strerror(error));
197	else
198		logit(LOG_CRIT, "fatal in %s%s%s", log_procname, sep, ebuf);
199}
200
201void
202fatal(const char *emsg, ...)
203{
204	va_list	ap;
205
206	va_start(ap, emsg);
207	vfatalc(errno, emsg, ap);
208	va_end(ap);
209	die(0);
210}
211
212void
213fatalx(const char *emsg, ...)
214{
215	va_list	ap;
216
217	va_start(ap, emsg);
218	vfatalc(0, emsg, ap);
219	va_end(ap);
220	die(0);
221}
222