1/*	$OpenBSD: err.c,v 1.2 2002/06/25 15:50:15 mickey Exp $	*/
2
3/*
4 * log.c
5 *
6 * Based on err.c, which was adapted from OpenBSD libc *err* *warn* code.
7 *
8 * Copyright (c) 2005 Nick Mathewson <nickm@freehaven.net>
9 *
10 * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
11 *
12 * Copyright (c) 1993
13 *	The Regents of the University of California.  All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 */
39
40#ifdef HAVE_CONFIG_H
41#include "config.h"
42#endif
43
44#ifdef WIN32
45#define WIN32_LEAN_AND_MEAN
46#include <windows.h>
47#undef WIN32_LEAN_AND_MEAN
48#include "misc.h"
49#endif
50#include <sys/types.h>
51#include <sys/tree.h>
52#ifdef HAVE_SYS_TIME_H
53#include <sys/time.h>
54#else
55#include <sys/_time.h>
56#endif
57#include <stdio.h>
58#include <stdlib.h>
59#include <stdarg.h>
60#include <string.h>
61#include <errno.h>
62#include "event.h"
63
64#include "log.h"
65
66static void _warn_helper(int severity, int log_errno, const char *fmt,
67                         va_list ap);
68static void event_log(int severity, const char *msg);
69
70static int
71event_vsnprintf(char *str, size_t size, const char *format, va_list args)
72{
73	int r;
74	if (size == 0)
75		return -1;
76#ifdef WIN32
77	r = _vsnprintf(str, size, format, args);
78#else
79	r = vsnprintf(str, size, format, args);
80#endif
81	str[size-1] = '\0';
82	if (r < 0 || ((size_t)r) >= size) {
83		/* different platforms behave differently on overflow;
84		 * handle both kinds. */
85		return -1;
86	}
87	return r;
88}
89
90static int
91event_snprintf(char *str, size_t size, const char *format, ...)
92{
93    va_list ap;
94    int r;
95    va_start(ap, format);
96    r = event_vsnprintf(str, size, format, ap);
97    va_end(ap);
98    return r;
99}
100
101void
102event_err(int eval, const char *fmt, ...)
103{
104	va_list ap;
105
106	va_start(ap, fmt);
107	_warn_helper(_EVENT_LOG_ERR, errno, fmt, ap);
108	va_end(ap);
109	exit(eval);
110}
111
112void
113event_warn(const char *fmt, ...)
114{
115	va_list ap;
116
117	va_start(ap, fmt);
118	_warn_helper(_EVENT_LOG_WARN, errno, fmt, ap);
119	va_end(ap);
120}
121
122void
123event_errx(int eval, const char *fmt, ...)
124{
125	va_list ap;
126
127	va_start(ap, fmt);
128	_warn_helper(_EVENT_LOG_ERR, -1, fmt, ap);
129	va_end(ap);
130	exit(eval);
131}
132
133void
134event_warnx(const char *fmt, ...)
135{
136	va_list ap;
137
138	va_start(ap, fmt);
139	_warn_helper(_EVENT_LOG_WARN, -1, fmt, ap);
140	va_end(ap);
141}
142
143void
144event_msgx(const char *fmt, ...)
145{
146	va_list ap;
147
148	va_start(ap, fmt);
149	_warn_helper(_EVENT_LOG_MSG, -1, fmt, ap);
150	va_end(ap);
151}
152
153void
154_event_debugx(const char *fmt, ...)
155{
156	va_list ap;
157
158	va_start(ap, fmt);
159	_warn_helper(_EVENT_LOG_DEBUG, -1, fmt, ap);
160	va_end(ap);
161}
162
163static void
164_warn_helper(int severity, int log_errno, const char *fmt, va_list ap)
165{
166	char buf[1024];
167	size_t len;
168
169	if (fmt != NULL)
170		event_vsnprintf(buf, sizeof(buf), fmt, ap);
171	else
172		buf[0] = '\0';
173
174	if (log_errno >= 0) {
175		len = strlen(buf);
176		if (len < sizeof(buf) - 3) {
177			event_snprintf(buf + len, sizeof(buf) - len, ": %s",
178			    strerror(log_errno));
179		}
180	}
181
182	event_log(severity, buf);
183}
184
185static event_log_cb log_fn = NULL;
186
187void
188event_set_log_callback(event_log_cb cb)
189{
190	log_fn = cb;
191}
192
193static void
194event_log(int severity, const char *msg)
195{
196	if (log_fn)
197		log_fn(severity, msg);
198	else {
199		const char *severity_str;
200		switch (severity) {
201		case _EVENT_LOG_DEBUG:
202			severity_str = "debug";
203			break;
204		case _EVENT_LOG_MSG:
205			severity_str = "msg";
206			break;
207		case _EVENT_LOG_WARN:
208			severity_str = "warn";
209			break;
210		case _EVENT_LOG_ERR:
211			severity_str = "err";
212			break;
213		default:
214			severity_str = "???";
215			break;
216		}
217		(void)fprintf(stderr, "[%s] %s\n", severity_str, msg);
218	}
219}
220