1/*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2012 The FreeBSD Foundation
5 *
6 * This software was developed by Edward Tomasz Napierala under sponsorship
7 * from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <errno.h>
36#include <stdarg.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <syslog.h>
41#include <vis.h>
42
43#include "iscsid.h"
44
45static int log_level = 0;
46static char *peer_name = NULL;
47static char *peer_addr = NULL;
48
49#define	MSGBUF_LEN	1024
50
51void
52log_init(int level)
53{
54
55	log_level = level;
56	openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
57}
58
59void
60log_set_peer_name(const char *name)
61{
62
63	/*
64	 * XXX: Turn it into assertion?
65	 */
66	if (peer_name != NULL)
67		log_errx(1, "%s called twice", __func__);
68	if (peer_addr == NULL)
69		log_errx(1, "%s called before log_set_peer_addr", __func__);
70
71	peer_name = checked_strdup(name);
72}
73
74void
75log_set_peer_addr(const char *addr)
76{
77
78	/*
79	 * XXX: Turn it into assertion?
80	 */
81	if (peer_addr != NULL)
82		log_errx(1, "%s called twice", __func__);
83
84	peer_addr = checked_strdup(addr);
85}
86
87static void
88log_common(int priority, int log_errno, const char *fmt, va_list ap)
89{
90	static char msgbuf[MSGBUF_LEN];
91	static char msgbuf_strvised[MSGBUF_LEN * 4 + 1];
92	char *errstr;
93	int ret;
94
95	ret = vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
96	if (ret < 0) {
97		fprintf(stderr, "%s: snprintf failed", getprogname());
98		syslog(LOG_CRIT, "snprintf failed");
99		exit(1);
100	}
101
102	ret = strnvis(msgbuf_strvised, sizeof(msgbuf_strvised), msgbuf, VIS_NL);
103	if (ret < 0) {
104		fprintf(stderr, "%s: strnvis failed", getprogname());
105		syslog(LOG_CRIT, "strnvis failed");
106		exit(1);
107	}
108
109	if (log_errno == -1) {
110		if (peer_name != NULL) {
111			fprintf(stderr, "%s: %s (%s): %s\n", getprogname(),
112			    peer_addr, peer_name, msgbuf_strvised);
113			syslog(priority, "%s (%s): %s",
114			    peer_addr, peer_name, msgbuf_strvised);
115		} else if (peer_addr != NULL) {
116			fprintf(stderr, "%s: %s: %s\n", getprogname(),
117			    peer_addr, msgbuf_strvised);
118			syslog(priority, "%s: %s",
119			    peer_addr, msgbuf_strvised);
120		} else {
121			fprintf(stderr, "%s: %s\n", getprogname(), msgbuf_strvised);
122			syslog(priority, "%s", msgbuf_strvised);
123		}
124
125	} else {
126		errstr = strerror(log_errno);
127
128		if (peer_name != NULL) {
129			fprintf(stderr, "%s: %s (%s): %s: %s\n", getprogname(),
130			    peer_addr, peer_name, msgbuf_strvised, errstr);
131			syslog(priority, "%s (%s): %s: %s",
132			    peer_addr, peer_name, msgbuf_strvised, errstr);
133		} else if (peer_addr != NULL) {
134			fprintf(stderr, "%s: %s: %s: %s\n", getprogname(),
135			    peer_addr, msgbuf_strvised, errstr);
136			syslog(priority, "%s: %s: %s",
137			    peer_addr, msgbuf_strvised, errstr);
138		} else {
139			fprintf(stderr, "%s: %s: %s\n", getprogname(),
140			    msgbuf_strvised, errstr);
141			syslog(priority, "%s: %s",
142			    msgbuf_strvised, errstr);
143		}
144	}
145}
146
147void
148log_err(int eval, const char *fmt, ...)
149{
150	va_list ap;
151
152	va_start(ap, fmt);
153	log_common(LOG_CRIT, errno, fmt, ap);
154	va_end(ap);
155
156	exit(eval);
157}
158
159void
160log_errx(int eval, const char *fmt, ...)
161{
162	va_list ap;
163
164	va_start(ap, fmt);
165	log_common(LOG_CRIT, -1, fmt, ap);
166	va_end(ap);
167
168	exit(eval);
169}
170
171void
172log_warn(const char *fmt, ...)
173{
174	va_list ap;
175
176	va_start(ap, fmt);
177	log_common(LOG_WARNING, errno, fmt, ap);
178	va_end(ap);
179}
180
181void
182log_warnx(const char *fmt, ...)
183{
184	va_list ap;
185
186	va_start(ap, fmt);
187	log_common(LOG_WARNING, -1, fmt, ap);
188	va_end(ap);
189}
190
191void
192log_debugx(const char *fmt, ...)
193{
194	va_list ap;
195
196	if (log_level == 0)
197		return;
198
199	va_start(ap, fmt);
200	log_common(LOG_DEBUG, -1, fmt, ap);
201	va_end(ap);
202}
203