1270096Strasz/*-
2270096Strasz * Copyright (c) 2012 The FreeBSD Foundation
3270096Strasz * All rights reserved.
4270096Strasz *
5270096Strasz * This software was developed by Edward Tomasz Napierala under sponsorship
6270096Strasz * from the FreeBSD Foundation.
7270096Strasz *
8270096Strasz * Redistribution and use in source and binary forms, with or without
9270096Strasz * modification, are permitted provided that the following conditions
10270096Strasz * are met:
11270096Strasz * 1. Redistributions of source code must retain the above copyright
12270096Strasz *    notice, this list of conditions and the following disclaimer.
13270096Strasz * 2. Redistributions in binary form must reproduce the above copyright
14270096Strasz *    notice, this list of conditions and the following disclaimer in the
15270096Strasz *    documentation and/or other materials provided with the distribution.
16270096Strasz *
17270096Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18270096Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19270096Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20270096Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21270096Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22270096Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23270096Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24270096Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25270096Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26270096Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27270096Strasz * SUCH DAMAGE.
28270096Strasz *
29270096Strasz */
30270096Strasz
31270897Strasz#include <sys/cdefs.h>
32270897Strasz__FBSDID("$FreeBSD$");
33270897Strasz
34270096Strasz#include <errno.h>
35270096Strasz#include <stdarg.h>
36270096Strasz#include <stdio.h>
37270096Strasz#include <stdlib.h>
38270096Strasz#include <string.h>
39270096Strasz#include <syslog.h>
40270096Strasz#include <vis.h>
41270096Strasz
42270096Strasz#include "common.h"
43270096Strasz
44270096Straszstatic int log_level = 0;
45270096Straszstatic char *peer_name = NULL;
46270096Straszstatic char *peer_addr = NULL;
47270096Strasz
48270096Strasz#define	MSGBUF_LEN	1024
49270096Strasz
50270096Straszvoid
51270096Straszlog_init(int level)
52270096Strasz{
53270096Strasz
54270096Strasz	log_level = level;
55270096Strasz	openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
56270096Strasz}
57270096Strasz
58270096Straszvoid
59270096Straszlog_set_peer_name(const char *name)
60270096Strasz{
61270096Strasz
62270096Strasz	/*
63270096Strasz	 * XXX: Turn it into assertion?
64270096Strasz	 */
65270096Strasz	if (peer_name != NULL)
66270096Strasz		log_errx(1, "%s called twice", __func__);
67270096Strasz	if (peer_addr == NULL)
68270096Strasz		log_errx(1, "%s called before log_set_peer_addr", __func__);
69270096Strasz
70270096Strasz	peer_name = checked_strdup(name);
71270096Strasz}
72270096Strasz
73270096Straszvoid
74270096Straszlog_set_peer_addr(const char *addr)
75270096Strasz{
76270096Strasz
77270096Strasz	/*
78270096Strasz	 * XXX: Turn it into assertion?
79270096Strasz	 */
80270096Strasz	if (peer_addr != NULL)
81270096Strasz		log_errx(1, "%s called twice", __func__);
82270096Strasz
83270096Strasz	peer_addr = checked_strdup(addr);
84270096Strasz}
85270096Strasz
86270096Straszstatic void
87270096Straszlog_common(int priority, int log_errno, const char *fmt, va_list ap)
88270096Strasz{
89270096Strasz	static char msgbuf[MSGBUF_LEN];
90270096Strasz	static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
91270096Strasz	int ret;
92270096Strasz
93270096Strasz	ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
94270096Strasz	if (ret < 0) {
95270096Strasz		fprintf(stderr, "%s: snprintf failed", getprogname());
96270096Strasz		syslog(LOG_CRIT, "snprintf failed");
97270096Strasz		exit(1);
98270096Strasz	}
99270096Strasz
100270096Strasz	ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL);
101270096Strasz	if (ret < 0) {
102270096Strasz		fprintf(stderr, "%s: strnvis failed", getprogname());
103270096Strasz		syslog(LOG_CRIT, "strnvis failed");
104270096Strasz		exit(1);
105270096Strasz	}
106270096Strasz
107270096Strasz	if (log_errno == -1) {
108270096Strasz		if (peer_name != NULL) {
109270096Strasz			fprintf(stderr, "%s: %s (%s): %s\n", getprogname(),
110270096Strasz			    peer_addr, peer_name, msgbuf_strvised);
111270096Strasz			syslog(priority, "%s (%s): %s",
112270096Strasz			    peer_addr, peer_name, msgbuf_strvised);
113270096Strasz		} else if (peer_addr != NULL) {
114270096Strasz			fprintf(stderr, "%s: %s: %s\n", getprogname(),
115270096Strasz			    peer_addr, msgbuf_strvised);
116270096Strasz			syslog(priority, "%s: %s",
117270096Strasz			    peer_addr, msgbuf_strvised);
118270096Strasz		} else {
119270096Strasz			fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised);
120270096Strasz			syslog(priority, "%s", msgbuf_strvised);
121270096Strasz		}
122270096Strasz
123270096Strasz	} else {
124270096Strasz		if (peer_name != NULL) {
125270096Strasz			fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
126270096Strasz			    peer_addr, peer_name, msgbuf_strvised, strerror(errno));
127270096Strasz			syslog(priority, "%s (%s): %s: %s",
128270096Strasz			    peer_addr, peer_name, msgbuf_strvised, strerror(errno));
129270096Strasz		} else if (peer_addr != NULL) {
130270096Strasz			fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
131270096Strasz			    peer_addr, msgbuf_strvised, strerror(errno));
132270096Strasz			syslog(priority, "%s: %s: %s",
133270096Strasz			    peer_addr, msgbuf_strvised, strerror(errno));
134270096Strasz		} else {
135270096Strasz			fprintf(stderr, "%s: %s: %s\n", getprogname(),
136270096Strasz			    msgbuf_strvised, strerror(errno));
137270096Strasz			syslog(priority, "%s: %s",
138270096Strasz			    msgbuf_strvised, strerror(errno));
139270096Strasz		}
140270096Strasz	}
141270096Strasz}
142270096Strasz
143270096Straszvoid
144270096Straszlog_err(int eval, const char *fmt, ...)
145270096Strasz{
146270096Strasz	va_list ap;
147270096Strasz
148270096Strasz	va_start(ap, fmt);
149270096Strasz	log_common(LOG_CRIT, errno, fmt, ap);
150270096Strasz	va_end(ap);
151270096Strasz
152270096Strasz	exit(eval);
153270096Strasz}
154270096Strasz
155270096Straszvoid
156270096Straszlog_errx(int eval, const char *fmt, ...)
157270096Strasz{
158270096Strasz	va_list ap;
159270096Strasz
160270096Strasz	va_start(ap, fmt);
161270096Strasz	log_common(LOG_CRIT, -1, fmt, ap);
162270096Strasz	va_end(ap);
163270096Strasz
164270096Strasz	exit(eval);
165270096Strasz}
166270096Strasz
167270096Straszvoid
168270096Straszlog_warn(const char *fmt, ...)
169270096Strasz{
170270096Strasz	va_list ap;
171270096Strasz
172270096Strasz	va_start(ap, fmt);
173270096Strasz	log_common(LOG_WARNING, errno, fmt, ap);
174270096Strasz	va_end(ap);
175270096Strasz}
176270096Strasz
177270096Straszvoid
178270096Straszlog_warnx(const char *fmt, ...)
179270096Strasz{
180270096Strasz	va_list ap;
181270096Strasz
182270096Strasz	va_start(ap, fmt);
183270096Strasz	log_common(LOG_WARNING, -1, fmt, ap);
184270096Strasz	va_end(ap);
185270096Strasz}
186270096Strasz
187270096Straszvoid
188270096Straszlog_debugx(const char *fmt, ...)
189270096Strasz{
190270096Strasz	va_list ap;
191270096Strasz
192270096Strasz	if (log_level == 0)
193270096Strasz		return;
194270096Strasz
195270096Strasz	va_start(ap, fmt);
196270096Strasz	log_common(LOG_DEBUG, -1, fmt, ap);
197270096Strasz	va_end(ap);
198270096Strasz}
199