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 #include <stdarg.h>
27 #include <errno.h>
28 #include <stdio.h>
29 #include <syslog.h>
30 #include <libintl.h>
31 #include <string.h>
32 #include <limits.h>
33 
34 #include "dhcpmsg.h"
35 
36 static boolean_t	is_daemon  = B_FALSE;
37 static boolean_t	is_verbose = B_FALSE;
38 static char		program[PATH_MAX] = "<unknown>";
39 static int		debug_level;
40 
41 static const char	*err_to_string(int);
42 static int		err_to_syslog(int);
43 
44 /*
45  * dhcpmsg(): logs a message to the console or to syslog
46  *
47  *   input: int: the level to log the message at
48  *	    const char *: a printf-like format string
49  *	    ...: arguments to the format string
50  *  output: void
51  */
52 
53 void
dhcpmsg(int errlevel,const char * fmt,...)54 dhcpmsg(int errlevel, const char *fmt, ...)
55 {
56 	va_list		ap;
57 	char		buf[512];
58 	char		*errmsg;
59 
60 	if ((errlevel == MSG_DEBUG2 && (debug_level < 2)) ||
61 	    (errlevel == MSG_DEBUG && (debug_level < 1)) ||
62 	    (errlevel == MSG_VERBOSE && !is_verbose))
63 		return;
64 
65 	va_start(ap, fmt);
66 
67 	/*
68 	 * either log to stderr, or log to syslog.  print out unix
69 	 * error message if errlevel is MSG_ERR and errno is set
70 	 */
71 
72 	if (is_daemon) {
73 		(void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR &&
74 		    errno != 0) ? "%s: %%m\n" : "%s\n", gettext(fmt));
75 		(void) vsyslog(err_to_syslog(errlevel), buf, ap);
76 	} else {
77 		errmsg = strerror(errno);
78 		if (errmsg == NULL)
79 			errmsg = dgettext(TEXT_DOMAIN, "<unknown error>");
80 
81 		(void) snprintf(buf, sizeof (buf), (errlevel == MSG_ERR &&
82 		    errno != 0) ? "%s: %s: %s: %s\n" : "%s: %s: %s\n", program,
83 		    dgettext(TEXT_DOMAIN, err_to_string(errlevel)),
84 		    gettext(fmt), errmsg);
85 
86 		(void) vfprintf(stderr, buf, ap);
87 	}
88 
89 	va_end(ap);
90 }
91 
92 /*
93  * dhcpmsg_init(): opens and initializes the DHCP messaging facility
94  *
95  *   input: const char *: the name of the executable
96  *	    boolean_t: whether the executable is a daemon
97  *	    boolean_t: whether the executable is running "verbosely"
98  *	    int: the debugging level the executable is being run at
99  *  output: void
100  */
101 
102 void
dhcpmsg_init(const char * program_name,boolean_t daemon,boolean_t verbose,int level)103 dhcpmsg_init(const char *program_name, boolean_t daemon, boolean_t verbose,
104     int level)
105 {
106 	(void) strlcpy(program, program_name, sizeof (program));
107 
108 	debug_level = level;
109 	is_verbose = verbose;
110 
111 	if (daemon) {
112 		is_daemon = B_TRUE;
113 		(void) openlog(program, LOG_PID, LOG_DAEMON);
114 		if (is_verbose) {
115 			syslog(err_to_syslog(MSG_VERBOSE), "%s",
116 			    dgettext(TEXT_DOMAIN, "Daemon started"));
117 		}
118 	}
119 }
120 
121 /*
122  * dhcpmsg_fini(): closes the DHCP messaging facility.
123  *
124  *   input: void
125  *  output: void
126  */
127 
128 void
dhcpmsg_fini(void)129 dhcpmsg_fini(void)
130 {
131 	if (is_daemon) {
132 		if (is_verbose) {
133 			syslog(err_to_syslog(MSG_VERBOSE), "%s",
134 			    dgettext(TEXT_DOMAIN, "Daemon terminated"));
135 		}
136 		closelog();
137 	}
138 }
139 
140 /*
141  * err_to_syslog(): converts a dhcpmsg log level into a syslog log level
142  *
143  *   input: int: the dhcpmsg log level
144  *  output: int: the syslog log level
145  */
146 
147 static int
err_to_syslog(int errlevel)148 err_to_syslog(int errlevel)
149 {
150 	switch (errlevel) {
151 
152 	case MSG_DEBUG:
153 	case MSG_DEBUG2:
154 		return (LOG_DEBUG);
155 
156 	case MSG_ERROR:
157 	case MSG_ERR:
158 		return (LOG_ERR);
159 
160 	case MSG_WARNING:
161 		return (LOG_WARNING);
162 
163 	case MSG_NOTICE:
164 		return (LOG_NOTICE);
165 
166 	case MSG_CRIT:
167 		return (LOG_CRIT);
168 
169 	case MSG_VERBOSE:
170 	case MSG_INFO:
171 		return (LOG_INFO);
172 	}
173 
174 	return (LOG_INFO);
175 }
176 
177 /*
178  * err_to_string(): converts a log level into a string
179  *
180  *   input: int: the log level
181  *  output: const char *: the stringified log level
182  */
183 
184 static const char *
err_to_string(int errlevel)185 err_to_string(int errlevel)
186 {
187 	switch (errlevel) {
188 
189 	case MSG_DEBUG:
190 	case MSG_DEBUG2:
191 		return ("debug");
192 
193 	case MSG_ERR:
194 	case MSG_ERROR:
195 		return ("error");
196 
197 	case MSG_WARNING:
198 		return ("warning");
199 
200 	case MSG_NOTICE:
201 		return ("notice");
202 
203 	case MSG_CRIT:
204 		return ("CRITICAL");
205 
206 	case MSG_VERBOSE:
207 	case MSG_INFO:
208 		return ("info");
209 	}
210 
211 	return ("<unknown>");
212 }
213