1255570Strasz/*-
2255570Strasz * Copyright (c) 2012 The FreeBSD Foundation
3255570Strasz * All rights reserved.
4255570Strasz *
5255570Strasz * This software was developed by Edward Tomasz Napierala under sponsorship
6255570Strasz * from the FreeBSD Foundation.
7255570Strasz *
8255570Strasz * Redistribution and use in source and binary forms, with or without
9255570Strasz * modification, are permitted provided that the following conditions
10255570Strasz * are met:
11255570Strasz * 1. Redistributions of source code must retain the above copyright
12255570Strasz *    notice, this list of conditions and the following disclaimer.
13255570Strasz * 2. Redistributions in binary form must reproduce the above copyright
14255570Strasz *    notice, this list of conditions and the following disclaimer in the
15255570Strasz *    documentation and/or other materials provided with the distribution.
16255570Strasz *
17255570Strasz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18255570Strasz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19255570Strasz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20255570Strasz * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21255570Strasz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22255570Strasz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23255570Strasz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24255570Strasz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25255570Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26255570Strasz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27255570Strasz * SUCH DAMAGE.
28255570Strasz *
29255570Strasz */
30255570Strasz
31270888Strasz#include <sys/cdefs.h>
32270888Strasz__FBSDID("$FreeBSD$");
33270888Strasz
34255570Strasz#include <errno.h>
35255570Strasz#include <stdarg.h>
36255570Strasz#include <stdio.h>
37255570Strasz#include <stdlib.h>
38255570Strasz#include <string.h>
39255570Strasz#include <syslog.h>
40255570Strasz#include <vis.h>
41255570Strasz
42255570Strasz#include "ctld.h"
43255570Strasz
44255570Straszstatic int log_level = 0;
45255570Straszstatic char *peer_name = NULL;
46255570Straszstatic char *peer_addr = NULL;
47255570Strasz
48255570Strasz#define	MSGBUF_LEN	1024
49255570Strasz
50255570Straszvoid
51255570Straszlog_init(int level)
52255570Strasz{
53255570Strasz
54255570Strasz	log_level = level;
55255570Strasz	openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
56255570Strasz}
57255570Strasz
58255570Straszvoid
59255570Straszlog_set_peer_name(const char *name)
60255570Strasz{
61255570Strasz
62255570Strasz	/*
63255570Strasz	 * XXX: Turn it into assertion?
64255570Strasz	 */
65255570Strasz	if (peer_name != NULL)
66255570Strasz		log_errx(1, "%s called twice", __func__);
67255570Strasz	if (peer_addr == NULL)
68255570Strasz		log_errx(1, "%s called before log_set_peer_addr", __func__);
69255570Strasz
70255570Strasz	peer_name = checked_strdup(name);
71255570Strasz}
72255570Strasz
73255570Straszvoid
74255570Straszlog_set_peer_addr(const char *addr)
75255570Strasz{
76255570Strasz
77255570Strasz	/*
78255570Strasz	 * XXX: Turn it into assertion?
79255570Strasz	 */
80255570Strasz	if (peer_addr != NULL)
81255570Strasz		log_errx(1, "%s called twice", __func__);
82255570Strasz
83255570Strasz	peer_addr = checked_strdup(addr);
84255570Strasz}
85255570Strasz
86255570Straszstatic void
87255570Straszlog_common(int priority, int log_errno, const char *fmt, va_list ap)
88255570Strasz{
89255570Strasz	static char msgbuf[MSGBUF_LEN];
90255570Strasz	static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
91255570Strasz	int ret;
92255570Strasz
93255570Strasz	ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
94255570Strasz	if (ret < 0) {
95255570Strasz		fprintf(stderr, "%s: snprintf failed", getprogname());
96255570Strasz		syslog(LOG_CRIT, "snprintf failed");
97255570Strasz		exit(1);
98255570Strasz	}
99255570Strasz
100255570Strasz	ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL);
101255570Strasz	if (ret < 0) {
102255570Strasz		fprintf(stderr, "%s: strnvis failed", getprogname());
103255570Strasz		syslog(LOG_CRIT, "strnvis failed");
104255570Strasz		exit(1);
105255570Strasz	}
106255570Strasz
107255570Strasz	if (log_errno == -1) {
108255570Strasz		if (peer_name != NULL) {
109255570Strasz			fprintf(stderr, "%s: %s (%s): %s\n", getprogname(),
110255570Strasz			    peer_addr, peer_name, msgbuf_strvised);
111255570Strasz			syslog(priority, "%s (%s): %s",
112255570Strasz			    peer_addr, peer_name, msgbuf_strvised);
113255570Strasz		} else if (peer_addr != NULL) {
114255570Strasz			fprintf(stderr, "%s: %s: %s\n", getprogname(),
115255570Strasz			    peer_addr, msgbuf_strvised);
116255570Strasz			syslog(priority, "%s: %s",
117255570Strasz			    peer_addr, msgbuf_strvised);
118255570Strasz		} else {
119255570Strasz			fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised);
120255570Strasz			syslog(priority, "%s", msgbuf_strvised);
121255570Strasz		}
122255570Strasz
123255570Strasz	} else {
124255570Strasz		if (peer_name != NULL) {
125255570Strasz			fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
126255570Strasz			    peer_addr, peer_name, msgbuf_strvised, strerror(errno));
127255570Strasz			syslog(priority, "%s (%s): %s: %s",
128255570Strasz			    peer_addr, peer_name, msgbuf_strvised, strerror(errno));
129255570Strasz		} else if (peer_addr != NULL) {
130255570Strasz			fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
131255570Strasz			    peer_addr, msgbuf_strvised, strerror(errno));
132255570Strasz			syslog(priority, "%s: %s: %s",
133255570Strasz			    peer_addr, msgbuf_strvised, strerror(errno));
134255570Strasz		} else {
135255570Strasz			fprintf(stderr, "%s: %s: %s\n", getprogname(),
136255570Strasz			    msgbuf_strvised, strerror(errno));
137255570Strasz			syslog(priority, "%s: %s",
138255570Strasz			    msgbuf_strvised, strerror(errno));
139255570Strasz		}
140255570Strasz	}
141255570Strasz}
142255570Strasz
143255570Straszvoid
144255570Straszlog_err(int eval, const char *fmt, ...)
145255570Strasz{
146255570Strasz	va_list ap;
147255570Strasz
148255570Strasz	va_start(ap, fmt);
149255570Strasz	log_common(LOG_CRIT, errno, fmt, ap);
150255570Strasz	va_end(ap);
151255570Strasz
152255570Strasz	exit(eval);
153255570Strasz}
154255570Strasz
155255570Straszvoid
156255570Straszlog_errx(int eval, const char *fmt, ...)
157255570Strasz{
158255570Strasz	va_list ap;
159255570Strasz
160255570Strasz	va_start(ap, fmt);
161255570Strasz	log_common(LOG_CRIT, -1, fmt, ap);
162255570Strasz	va_end(ap);
163255570Strasz
164255570Strasz	exit(eval);
165255570Strasz}
166255570Strasz
167255570Straszvoid
168255570Straszlog_warn(const char *fmt, ...)
169255570Strasz{
170255570Strasz	va_list ap;
171255570Strasz
172255570Strasz	va_start(ap, fmt);
173255570Strasz	log_common(LOG_WARNING, errno, fmt, ap);
174255570Strasz	va_end(ap);
175255570Strasz}
176255570Strasz
177255570Straszvoid
178255570Straszlog_warnx(const char *fmt, ...)
179255570Strasz{
180255570Strasz	va_list ap;
181255570Strasz
182255570Strasz	va_start(ap, fmt);
183255570Strasz	log_common(LOG_WARNING, -1, fmt, ap);
184255570Strasz	va_end(ap);
185255570Strasz}
186255570Strasz
187255570Straszvoid
188255570Straszlog_debugx(const char *fmt, ...)
189255570Strasz{
190255570Strasz	va_list ap;
191255570Strasz
192255570Strasz	if (log_level == 0)
193255570Strasz		return;
194255570Strasz
195255570Strasz	va_start(ap, fmt);
196255570Strasz	log_common(LOG_DEBUG, -1, fmt, ap);
197255570Strasz	va_end(ap);
198255570Strasz}
199