1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28#include <stdarg.h>
29#include <errno.h>
30#include <stdio.h>
31#include <syslog.h>
32#include <libintl.h>
33#include <string.h>
34#include <limits.h>
35
36#include "dhcpmsg.h"
37
38static boolean_t	is_daemon  = B_FALSE;
39static boolean_t	is_verbose = B_FALSE;
40static char		program[PATH_MAX] = "<unknown>";
41static int		debug_level;
42
43static const char	*err_to_string(int);
44static int		err_to_syslog(int);
45
46/*
47 * dhcpmsg(): logs a message to the console or to syslog
48 *
49 *   input: int: the level to log the message at
50 *	    const char *: a printf-like format string
51 *	    ...: arguments to the format string
52 *  output: void
53 */
54
55void
56dhcpmsg(int errlevel, const char *fmt, ...)
57{
58	va_list		ap;
59	char		buf[512];
60	char		*errmsg;
61
62	if ((errlevel == MSG_DEBUG2 && (debug_level < 2)) ||
63	    (errlevel == MSG_DEBUG && (debug_level < 1)) ||
64	    (errlevel == MSG_VERBOSE && !is_verbose))
65		return;
66
67	va_start(ap, fmt);
68
69	/*
70	 * either log to stderr, or log to syslog.  print out unix
71	 * error message if errlevel is MSG_ERR and errno is set
72	 */
73
74	if (is_daemon) {
75		(void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR &&
76		    errno != 0) ? "%s: %%m\n" : "%s\n", gettext(fmt));
77		(void) vsyslog(err_to_syslog(errlevel), buf, ap);
78	} else {
79		errmsg = strerror(errno);
80		if (errmsg == NULL)
81			errmsg = dgettext(TEXT_DOMAIN, "<unknown error>");
82
83		(void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR &&
84		    errno != 0) ? "%s: %s: %s: %s\n" : "%s: %s: %s\n", program,
85		    dgettext(TEXT_DOMAIN, err_to_string(errlevel)),
86		    gettext(fmt), errmsg);
87
88		(void) vfprintf(stderr, buf, ap);
89	}
90
91	va_end(ap);
92}
93
94/*
95 * dhcpmsg_init(): opens and initializes the DHCP messaging facility
96 *
97 *   input: const char *: the name of the executable
98 *	    boolean_t: whether the executable is a daemon
99 *	    boolean_t: whether the executable is running "verbosely"
100 *	    int: the debugging level the executable is being run at
101 *  output: void
102 */
103
104void
105dhcpmsg_init(const char *program_name, boolean_t daemon, boolean_t verbose,
106    int level)
107{
108	(void) strlcpy(program, program_name, sizeof (program));
109
110	debug_level = level;
111	is_verbose = verbose;
112
113	if (daemon) {
114		is_daemon = B_TRUE;
115		(void) openlog(program, LOG_PID, LOG_DAEMON);
116		if (is_verbose) {
117			syslog(err_to_syslog(MSG_VERBOSE), "%s",
118			    dgettext(TEXT_DOMAIN, "Daemon started"));
119		}
120	}
121}
122
123/*
124 * dhcpmsg_fini(): closes the DHCP messaging facility.
125 *
126 *   input: void
127 *  output: void
128 */
129
130void
131dhcpmsg_fini(void)
132{
133	if (is_daemon) {
134		if (is_verbose) {
135			syslog(err_to_syslog(MSG_VERBOSE), "%s",
136			    dgettext(TEXT_DOMAIN, "Daemon terminated"));
137		}
138		closelog();
139	}
140}
141
142/*
143 * err_to_syslog(): converts a dhcpmsg log level into a syslog log level
144 *
145 *   input: int: the dhcpmsg log level
146 *  output: int: the syslog log level
147 */
148
149static int
150err_to_syslog(int errlevel)
151{
152	switch (errlevel) {
153
154	case MSG_DEBUG:
155	case MSG_DEBUG2:
156		return (LOG_DEBUG);
157
158	case MSG_ERROR:
159	case MSG_ERR:
160		return (LOG_ERR);
161
162	case MSG_WARNING:
163		return (LOG_WARNING);
164
165	case MSG_NOTICE:
166		return (LOG_NOTICE);
167
168	case MSG_CRIT:
169		return (LOG_CRIT);
170
171	case MSG_VERBOSE:
172	case MSG_INFO:
173		return (LOG_INFO);
174	}
175
176	return (LOG_INFO);
177}
178
179/*
180 * err_to_string(): converts a log level into a string
181 *
182 *   input: int: the log level
183 *  output: const char *: the stringified log level
184 */
185
186static const char *
187err_to_string(int errlevel)
188{
189	switch (errlevel) {
190
191	case MSG_DEBUG:
192	case MSG_DEBUG2:
193		return ("debug");
194
195	case MSG_ERR:
196	case MSG_ERROR:
197		return ("error");
198
199	case MSG_WARNING:
200		return ("warning");
201
202	case MSG_NOTICE:
203		return ("notice");
204
205	case MSG_CRIT:
206		return ("CRITICAL");
207
208	case MSG_VERBOSE:
209	case MSG_INFO:
210		return ("info");
211	}
212
213	return ("<unknown>");
214}
215