xref: /onnv-gate/usr/src/cmd/hotplugd/hotplugd.c (revision 10923:df470fd79c3c)
1*10923SEvan.Yan@Sun.COM /*
2*10923SEvan.Yan@Sun.COM  * CDDL HEADER START
3*10923SEvan.Yan@Sun.COM  *
4*10923SEvan.Yan@Sun.COM  * The contents of this file are subject to the terms of the
5*10923SEvan.Yan@Sun.COM  * Common Development and Distribution License (the "License").
6*10923SEvan.Yan@Sun.COM  * You may not use this file except in compliance with the License.
7*10923SEvan.Yan@Sun.COM  *
8*10923SEvan.Yan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*10923SEvan.Yan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*10923SEvan.Yan@Sun.COM  * See the License for the specific language governing permissions
11*10923SEvan.Yan@Sun.COM  * and limitations under the License.
12*10923SEvan.Yan@Sun.COM  *
13*10923SEvan.Yan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*10923SEvan.Yan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*10923SEvan.Yan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*10923SEvan.Yan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*10923SEvan.Yan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*10923SEvan.Yan@Sun.COM  *
19*10923SEvan.Yan@Sun.COM  * CDDL HEADER END
20*10923SEvan.Yan@Sun.COM  */
21*10923SEvan.Yan@Sun.COM 
22*10923SEvan.Yan@Sun.COM /*
23*10923SEvan.Yan@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*10923SEvan.Yan@Sun.COM  * Use is subject to license terms.
25*10923SEvan.Yan@Sun.COM  */
26*10923SEvan.Yan@Sun.COM 
27*10923SEvan.Yan@Sun.COM #include <stdio.h>
28*10923SEvan.Yan@Sun.COM #include <stdlib.h>
29*10923SEvan.Yan@Sun.COM #include <unistd.h>
30*10923SEvan.Yan@Sun.COM #include <errno.h>
31*10923SEvan.Yan@Sun.COM #include <fcntl.h>
32*10923SEvan.Yan@Sun.COM #include <signal.h>
33*10923SEvan.Yan@Sun.COM #include <stdarg.h>
34*10923SEvan.Yan@Sun.COM #include <strings.h>
35*10923SEvan.Yan@Sun.COM #include <syslog.h>
36*10923SEvan.Yan@Sun.COM #include <priv.h>
37*10923SEvan.Yan@Sun.COM #include <wait.h>
38*10923SEvan.Yan@Sun.COM #include <getopt.h>
39*10923SEvan.Yan@Sun.COM #include <synch.h>
40*10923SEvan.Yan@Sun.COM #include <sys/param.h>
41*10923SEvan.Yan@Sun.COM #include <sys/stat.h>
42*10923SEvan.Yan@Sun.COM #include <sys/types.h>
43*10923SEvan.Yan@Sun.COM #include <libhotplug.h>
44*10923SEvan.Yan@Sun.COM #include <libhotplug_impl.h>
45*10923SEvan.Yan@Sun.COM #include "hotplugd_impl.h"
46*10923SEvan.Yan@Sun.COM 
47*10923SEvan.Yan@Sun.COM /*
48*10923SEvan.Yan@Sun.COM  * Define long options for command line.
49*10923SEvan.Yan@Sun.COM  */
50*10923SEvan.Yan@Sun.COM static const struct option lopts[] = {
51*10923SEvan.Yan@Sun.COM 	{ "help",	no_argument,	0, '?' },
52*10923SEvan.Yan@Sun.COM 	{ "version",	no_argument,	0, 'V' },
53*10923SEvan.Yan@Sun.COM 	{ "debug",	no_argument,	0, 'd' },
54*10923SEvan.Yan@Sun.COM 	{ 0, 0, 0, 0 }
55*10923SEvan.Yan@Sun.COM };
56*10923SEvan.Yan@Sun.COM 
57*10923SEvan.Yan@Sun.COM /*
58*10923SEvan.Yan@Sun.COM  * Local functions.
59*10923SEvan.Yan@Sun.COM  */
60*10923SEvan.Yan@Sun.COM static void		usage(void);
61*10923SEvan.Yan@Sun.COM static boolean_t	check_privileges(void);
62*10923SEvan.Yan@Sun.COM static int		daemonize(void);
63*10923SEvan.Yan@Sun.COM static void		init_signals(void);
64*10923SEvan.Yan@Sun.COM static void		signal_handler(int signum);
65*10923SEvan.Yan@Sun.COM static void		shutdown_daemon(void);
66*10923SEvan.Yan@Sun.COM 
67*10923SEvan.Yan@Sun.COM /*
68*10923SEvan.Yan@Sun.COM  * Global variables.
69*10923SEvan.Yan@Sun.COM  */
70*10923SEvan.Yan@Sun.COM static char		*prog;
71*10923SEvan.Yan@Sun.COM static char		version[] = "1.0";
72*10923SEvan.Yan@Sun.COM static boolean_t	log_flag = B_FALSE;
73*10923SEvan.Yan@Sun.COM static boolean_t	debug_flag = B_FALSE;
74*10923SEvan.Yan@Sun.COM static boolean_t	exit_flag = B_FALSE;
75*10923SEvan.Yan@Sun.COM static sema_t		signal_sem;
76*10923SEvan.Yan@Sun.COM 
77*10923SEvan.Yan@Sun.COM /*
78*10923SEvan.Yan@Sun.COM  * main()
79*10923SEvan.Yan@Sun.COM  *
80*10923SEvan.Yan@Sun.COM  *	The hotplug daemon is designed to be a background daemon
81*10923SEvan.Yan@Sun.COM  *	controlled by SMF.  So by default it will daemonize and
82*10923SEvan.Yan@Sun.COM  *	do some coordination with its parent process in order to
83*10923SEvan.Yan@Sun.COM  *	indicate proper success or failure back to SMF.  And all
84*10923SEvan.Yan@Sun.COM  *	output will be sent to syslog.
85*10923SEvan.Yan@Sun.COM  *
86*10923SEvan.Yan@Sun.COM  *	But if given the '-d' command line option, it will instead
87*10923SEvan.Yan@Sun.COM  *	run in the foreground in a standalone, debug mode.  Errors
88*10923SEvan.Yan@Sun.COM  *	and additional debug messages will be printed to the controlling
89*10923SEvan.Yan@Sun.COM  *	terminal instead of to syslog.
90*10923SEvan.Yan@Sun.COM  */
91*10923SEvan.Yan@Sun.COM int
main(int argc,char * argv[])92*10923SEvan.Yan@Sun.COM main(int argc, char *argv[])
93*10923SEvan.Yan@Sun.COM {
94*10923SEvan.Yan@Sun.COM 	int	opt;
95*10923SEvan.Yan@Sun.COM 	int	pfd;
96*10923SEvan.Yan@Sun.COM 	int	status;
97*10923SEvan.Yan@Sun.COM 
98*10923SEvan.Yan@Sun.COM 	if ((prog = strrchr(argv[0], '/')) == NULL)
99*10923SEvan.Yan@Sun.COM 		prog = argv[0];
100*10923SEvan.Yan@Sun.COM 	else
101*10923SEvan.Yan@Sun.COM 		prog++;
102*10923SEvan.Yan@Sun.COM 
103*10923SEvan.Yan@Sun.COM 	/* Check privileges */
104*10923SEvan.Yan@Sun.COM 	if (!check_privileges()) {
105*10923SEvan.Yan@Sun.COM 		(void) fprintf(stderr, "Insufficient privileges.  "
106*10923SEvan.Yan@Sun.COM 		    "(All privileges are required.)\n");
107*10923SEvan.Yan@Sun.COM 		return (-1);
108*10923SEvan.Yan@Sun.COM 	}
109*10923SEvan.Yan@Sun.COM 
110*10923SEvan.Yan@Sun.COM 	/* Process options  */
111*10923SEvan.Yan@Sun.COM 	while ((opt = getopt_clip(argc, argv, "dV?", lopts, NULL)) != -1) {
112*10923SEvan.Yan@Sun.COM 		switch (opt) {
113*10923SEvan.Yan@Sun.COM 		case 'd':
114*10923SEvan.Yan@Sun.COM 			debug_flag = B_TRUE;
115*10923SEvan.Yan@Sun.COM 			break;
116*10923SEvan.Yan@Sun.COM 		case 'V':
117*10923SEvan.Yan@Sun.COM 			(void) printf("%s: Version %s\n", prog, version);
118*10923SEvan.Yan@Sun.COM 			return (0);
119*10923SEvan.Yan@Sun.COM 		default:
120*10923SEvan.Yan@Sun.COM 			if (optopt == '?') {
121*10923SEvan.Yan@Sun.COM 				usage();
122*10923SEvan.Yan@Sun.COM 				return (0);
123*10923SEvan.Yan@Sun.COM 			}
124*10923SEvan.Yan@Sun.COM 			(void) fprintf(stderr, "Unrecognized option '%c'.\n",
125*10923SEvan.Yan@Sun.COM 			    optopt);
126*10923SEvan.Yan@Sun.COM 			usage();
127*10923SEvan.Yan@Sun.COM 			return (-1);
128*10923SEvan.Yan@Sun.COM 		}
129*10923SEvan.Yan@Sun.COM 	}
130*10923SEvan.Yan@Sun.COM 
131*10923SEvan.Yan@Sun.COM 	/* Initialize semaphore for daemon shutdown */
132*10923SEvan.Yan@Sun.COM 	if (sema_init(&signal_sem, 1, USYNC_THREAD, NULL) != 0)
133*10923SEvan.Yan@Sun.COM 		exit(EXIT_FAILURE);
134*10923SEvan.Yan@Sun.COM 
135*10923SEvan.Yan@Sun.COM 	/* Initialize signal handling */
136*10923SEvan.Yan@Sun.COM 	init_signals();
137*10923SEvan.Yan@Sun.COM 
138*10923SEvan.Yan@Sun.COM 	/* Daemonize, if not in DEBUG mode */
139*10923SEvan.Yan@Sun.COM 	if (!debug_flag)
140*10923SEvan.Yan@Sun.COM 		pfd = daemonize();
141*10923SEvan.Yan@Sun.COM 
142*10923SEvan.Yan@Sun.COM 	/* Initialize door service */
143*10923SEvan.Yan@Sun.COM 	if (!door_server_init()) {
144*10923SEvan.Yan@Sun.COM 		if (!debug_flag) {
145*10923SEvan.Yan@Sun.COM 			status = EXIT_FAILURE;
146*10923SEvan.Yan@Sun.COM 			(void) write(pfd, &status, sizeof (status));
147*10923SEvan.Yan@Sun.COM 			(void) close(pfd);
148*10923SEvan.Yan@Sun.COM 		}
149*10923SEvan.Yan@Sun.COM 		exit(EXIT_FAILURE);
150*10923SEvan.Yan@Sun.COM 	}
151*10923SEvan.Yan@Sun.COM 
152*10923SEvan.Yan@Sun.COM 	/* Daemon initialized */
153*10923SEvan.Yan@Sun.COM 	if (!debug_flag) {
154*10923SEvan.Yan@Sun.COM 		status = 0;
155*10923SEvan.Yan@Sun.COM 		(void) write(pfd, &status, sizeof (status));
156*10923SEvan.Yan@Sun.COM 		(void) close(pfd);
157*10923SEvan.Yan@Sun.COM 	}
158*10923SEvan.Yan@Sun.COM 
159*10923SEvan.Yan@Sun.COM 	/* Note that daemon is running */
160*10923SEvan.Yan@Sun.COM 	log_info("hotplug daemon started.\n");
161*10923SEvan.Yan@Sun.COM 
162*10923SEvan.Yan@Sun.COM 	/* Wait for shutdown signal */
163*10923SEvan.Yan@Sun.COM 	while (!exit_flag)
164*10923SEvan.Yan@Sun.COM 		(void) sema_wait(&signal_sem);
165*10923SEvan.Yan@Sun.COM 
166*10923SEvan.Yan@Sun.COM 	shutdown_daemon();
167*10923SEvan.Yan@Sun.COM 	return (0);
168*10923SEvan.Yan@Sun.COM }
169*10923SEvan.Yan@Sun.COM 
170*10923SEvan.Yan@Sun.COM /*
171*10923SEvan.Yan@Sun.COM  * usage()
172*10923SEvan.Yan@Sun.COM  *
173*10923SEvan.Yan@Sun.COM  *	Print a brief usage synopsis for the command line options.
174*10923SEvan.Yan@Sun.COM  */
175*10923SEvan.Yan@Sun.COM static void
usage(void)176*10923SEvan.Yan@Sun.COM usage(void)
177*10923SEvan.Yan@Sun.COM {
178*10923SEvan.Yan@Sun.COM 	(void) printf("Usage: %s [-d]\n", prog);
179*10923SEvan.Yan@Sun.COM }
180*10923SEvan.Yan@Sun.COM 
181*10923SEvan.Yan@Sun.COM /*
182*10923SEvan.Yan@Sun.COM  * check_privileges()
183*10923SEvan.Yan@Sun.COM  *
184*10923SEvan.Yan@Sun.COM  *	Check if the current process has enough privileges
185*10923SEvan.Yan@Sun.COM  *	to run the daemon.  Note that all privileges are
186*10923SEvan.Yan@Sun.COM  *	required in order for RCM interactions to work.
187*10923SEvan.Yan@Sun.COM  */
188*10923SEvan.Yan@Sun.COM static boolean_t
check_privileges(void)189*10923SEvan.Yan@Sun.COM check_privileges(void)
190*10923SEvan.Yan@Sun.COM {
191*10923SEvan.Yan@Sun.COM 	priv_set_t	*privset;
192*10923SEvan.Yan@Sun.COM 	boolean_t	rv = B_FALSE;
193*10923SEvan.Yan@Sun.COM 
194*10923SEvan.Yan@Sun.COM 	if ((privset = priv_allocset()) != NULL) {
195*10923SEvan.Yan@Sun.COM 		if (getppriv(PRIV_EFFECTIVE, privset) == 0) {
196*10923SEvan.Yan@Sun.COM 			rv = priv_isfullset(privset);
197*10923SEvan.Yan@Sun.COM 		}
198*10923SEvan.Yan@Sun.COM 		priv_freeset(privset);
199*10923SEvan.Yan@Sun.COM 	}
200*10923SEvan.Yan@Sun.COM 
201*10923SEvan.Yan@Sun.COM 	return (rv);
202*10923SEvan.Yan@Sun.COM }
203*10923SEvan.Yan@Sun.COM 
204*10923SEvan.Yan@Sun.COM /*
205*10923SEvan.Yan@Sun.COM  * daemonize()
206*10923SEvan.Yan@Sun.COM  *
207*10923SEvan.Yan@Sun.COM  *	Fork the daemon process into the background, and detach from
208*10923SEvan.Yan@Sun.COM  *	the controlling terminal.  Setup a shared pipe that will later
209*10923SEvan.Yan@Sun.COM  *	be used to report startup status to the parent process.
210*10923SEvan.Yan@Sun.COM  */
211*10923SEvan.Yan@Sun.COM static int
daemonize(void)212*10923SEvan.Yan@Sun.COM daemonize(void)
213*10923SEvan.Yan@Sun.COM {
214*10923SEvan.Yan@Sun.COM 	int		status;
215*10923SEvan.Yan@Sun.COM 	int		pfds[2];
216*10923SEvan.Yan@Sun.COM 	pid_t		pid;
217*10923SEvan.Yan@Sun.COM 	sigset_t	set;
218*10923SEvan.Yan@Sun.COM 	sigset_t	oset;
219*10923SEvan.Yan@Sun.COM 
220*10923SEvan.Yan@Sun.COM 	/*
221*10923SEvan.Yan@Sun.COM 	 * Temporarily block all signals.  They will remain blocked in
222*10923SEvan.Yan@Sun.COM 	 * the parent, but will be unblocked in the child once it has
223*10923SEvan.Yan@Sun.COM 	 * notified the parent of its startup status.
224*10923SEvan.Yan@Sun.COM 	 */
225*10923SEvan.Yan@Sun.COM 	(void) sigfillset(&set);
226*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGABRT);
227*10923SEvan.Yan@Sun.COM 	(void) sigprocmask(SIG_BLOCK, &set, &oset);
228*10923SEvan.Yan@Sun.COM 
229*10923SEvan.Yan@Sun.COM 	/* Create the shared pipe */
230*10923SEvan.Yan@Sun.COM 	if (pipe(pfds) == -1) {
231*10923SEvan.Yan@Sun.COM 		log_err("Cannot create pipe (%s)\n", strerror(errno));
232*10923SEvan.Yan@Sun.COM 		exit(EXIT_FAILURE);
233*10923SEvan.Yan@Sun.COM 	}
234*10923SEvan.Yan@Sun.COM 
235*10923SEvan.Yan@Sun.COM 	/* Fork the daemon process */
236*10923SEvan.Yan@Sun.COM 	if ((pid = fork()) == -1) {
237*10923SEvan.Yan@Sun.COM 		log_err("Cannot fork daemon process (%s)\n", strerror(errno));
238*10923SEvan.Yan@Sun.COM 		exit(EXIT_FAILURE);
239*10923SEvan.Yan@Sun.COM 	}
240*10923SEvan.Yan@Sun.COM 
241*10923SEvan.Yan@Sun.COM 	/* Parent:  waits for exit status from child. */
242*10923SEvan.Yan@Sun.COM 	if (pid > 0) {
243*10923SEvan.Yan@Sun.COM 		(void) close(pfds[1]);
244*10923SEvan.Yan@Sun.COM 		if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
245*10923SEvan.Yan@Sun.COM 			_exit(status);
246*10923SEvan.Yan@Sun.COM 		if ((waitpid(pid, &status, 0) == pid) && WIFEXITED(status))
247*10923SEvan.Yan@Sun.COM 			_exit(WEXITSTATUS(status));
248*10923SEvan.Yan@Sun.COM 		log_err("Failed to spawn daemon process.\n");
249*10923SEvan.Yan@Sun.COM 		_exit(EXIT_FAILURE);
250*10923SEvan.Yan@Sun.COM 	}
251*10923SEvan.Yan@Sun.COM 
252*10923SEvan.Yan@Sun.COM 	/* Child continues... */
253*10923SEvan.Yan@Sun.COM 
254*10923SEvan.Yan@Sun.COM 	(void) setsid();
255*10923SEvan.Yan@Sun.COM 	(void) chdir("/");
256*10923SEvan.Yan@Sun.COM 	(void) umask(CMASK);
257*10923SEvan.Yan@Sun.COM 	(void) sigprocmask(SIG_SETMASK, &oset, NULL);
258*10923SEvan.Yan@Sun.COM 	(void) close(pfds[0]);
259*10923SEvan.Yan@Sun.COM 
260*10923SEvan.Yan@Sun.COM 	/* Detach from controlling terminal */
261*10923SEvan.Yan@Sun.COM 	(void) close(0);
262*10923SEvan.Yan@Sun.COM 	(void) close(1);
263*10923SEvan.Yan@Sun.COM 	(void) close(2);
264*10923SEvan.Yan@Sun.COM 	(void) open("/dev/null", O_RDONLY);
265*10923SEvan.Yan@Sun.COM 	(void) open("/dev/null", O_WRONLY);
266*10923SEvan.Yan@Sun.COM 	(void) open("/dev/null", O_WRONLY);
267*10923SEvan.Yan@Sun.COM 
268*10923SEvan.Yan@Sun.COM 	/* Use syslog for future messages */
269*10923SEvan.Yan@Sun.COM 	log_flag = B_TRUE;
270*10923SEvan.Yan@Sun.COM 	openlog(prog, LOG_PID, LOG_DAEMON);
271*10923SEvan.Yan@Sun.COM 
272*10923SEvan.Yan@Sun.COM 	return (pfds[1]);
273*10923SEvan.Yan@Sun.COM }
274*10923SEvan.Yan@Sun.COM 
275*10923SEvan.Yan@Sun.COM /*
276*10923SEvan.Yan@Sun.COM  * init_signals()
277*10923SEvan.Yan@Sun.COM  *
278*10923SEvan.Yan@Sun.COM  *	Initialize signal handling.
279*10923SEvan.Yan@Sun.COM  */
280*10923SEvan.Yan@Sun.COM static void
init_signals(void)281*10923SEvan.Yan@Sun.COM init_signals(void)
282*10923SEvan.Yan@Sun.COM {
283*10923SEvan.Yan@Sun.COM 	struct sigaction	act;
284*10923SEvan.Yan@Sun.COM 	sigset_t		set;
285*10923SEvan.Yan@Sun.COM 
286*10923SEvan.Yan@Sun.COM 	(void) sigfillset(&set);
287*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGABRT);
288*10923SEvan.Yan@Sun.COM 
289*10923SEvan.Yan@Sun.COM 	(void) sigfillset(&act.sa_mask);
290*10923SEvan.Yan@Sun.COM 	act.sa_handler = signal_handler;
291*10923SEvan.Yan@Sun.COM 	act.sa_flags = 0;
292*10923SEvan.Yan@Sun.COM 
293*10923SEvan.Yan@Sun.COM 	(void) sigaction(SIGTERM, &act, NULL);
294*10923SEvan.Yan@Sun.COM 	(void) sigaction(SIGHUP, &act, NULL);
295*10923SEvan.Yan@Sun.COM 	(void) sigaction(SIGINT, &act, NULL);
296*10923SEvan.Yan@Sun.COM 	(void) sigaction(SIGPIPE, &act, NULL);
297*10923SEvan.Yan@Sun.COM 
298*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGTERM);
299*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGHUP);
300*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGINT);
301*10923SEvan.Yan@Sun.COM 	(void) sigdelset(&set, SIGPIPE);
302*10923SEvan.Yan@Sun.COM }
303*10923SEvan.Yan@Sun.COM 
304*10923SEvan.Yan@Sun.COM /*
305*10923SEvan.Yan@Sun.COM  * signal_handler()
306*10923SEvan.Yan@Sun.COM  *
307*10923SEvan.Yan@Sun.COM  *	Most signals cause the hotplug daemon to shut down.
308*10923SEvan.Yan@Sun.COM  *	Shutdown is triggered using a semaphore to wake up
309*10923SEvan.Yan@Sun.COM  *	the main thread for a clean exit.
310*10923SEvan.Yan@Sun.COM  *
311*10923SEvan.Yan@Sun.COM  *	Except SIGPIPE is used to coordinate between the parent
312*10923SEvan.Yan@Sun.COM  *	and child processes when the daemon first starts.
313*10923SEvan.Yan@Sun.COM  */
314*10923SEvan.Yan@Sun.COM static void
signal_handler(int signum)315*10923SEvan.Yan@Sun.COM signal_handler(int signum)
316*10923SEvan.Yan@Sun.COM {
317*10923SEvan.Yan@Sun.COM 	log_info("Received signal %d.\n", signum);
318*10923SEvan.Yan@Sun.COM 
319*10923SEvan.Yan@Sun.COM 	switch (signum) {
320*10923SEvan.Yan@Sun.COM 	case 0:
321*10923SEvan.Yan@Sun.COM 	case SIGPIPE:
322*10923SEvan.Yan@Sun.COM 		break;
323*10923SEvan.Yan@Sun.COM 	default:
324*10923SEvan.Yan@Sun.COM 		exit_flag = B_TRUE;
325*10923SEvan.Yan@Sun.COM 		(void) sema_post(&signal_sem);
326*10923SEvan.Yan@Sun.COM 		break;
327*10923SEvan.Yan@Sun.COM 	}
328*10923SEvan.Yan@Sun.COM }
329*10923SEvan.Yan@Sun.COM 
330*10923SEvan.Yan@Sun.COM /*
331*10923SEvan.Yan@Sun.COM  * shutdown_daemon()
332*10923SEvan.Yan@Sun.COM  *
333*10923SEvan.Yan@Sun.COM  *	Perform a clean shutdown of the daemon.
334*10923SEvan.Yan@Sun.COM  */
335*10923SEvan.Yan@Sun.COM static void
shutdown_daemon(void)336*10923SEvan.Yan@Sun.COM shutdown_daemon(void)
337*10923SEvan.Yan@Sun.COM {
338*10923SEvan.Yan@Sun.COM 	log_info("Hotplug daemon shutting down.\n");
339*10923SEvan.Yan@Sun.COM 
340*10923SEvan.Yan@Sun.COM 	door_server_fini();
341*10923SEvan.Yan@Sun.COM 
342*10923SEvan.Yan@Sun.COM 	if (log_flag)
343*10923SEvan.Yan@Sun.COM 		closelog();
344*10923SEvan.Yan@Sun.COM 
345*10923SEvan.Yan@Sun.COM 	(void) sema_destroy(&signal_sem);
346*10923SEvan.Yan@Sun.COM }
347*10923SEvan.Yan@Sun.COM 
348*10923SEvan.Yan@Sun.COM /*
349*10923SEvan.Yan@Sun.COM  * log_err()
350*10923SEvan.Yan@Sun.COM  *
351*10923SEvan.Yan@Sun.COM  *	Display an error message.  Use syslog if in daemon
352*10923SEvan.Yan@Sun.COM  *	mode, otherwise print to stderr when in debug mode.
353*10923SEvan.Yan@Sun.COM  */
354*10923SEvan.Yan@Sun.COM /*PRINTFLIKE1*/
355*10923SEvan.Yan@Sun.COM void
log_err(char * fmt,...)356*10923SEvan.Yan@Sun.COM log_err(char *fmt, ...)
357*10923SEvan.Yan@Sun.COM {
358*10923SEvan.Yan@Sun.COM 	va_list	ap;
359*10923SEvan.Yan@Sun.COM 
360*10923SEvan.Yan@Sun.COM 	va_start(ap, fmt);
361*10923SEvan.Yan@Sun.COM 	if (debug_flag || !log_flag)
362*10923SEvan.Yan@Sun.COM 		(void) vfprintf(stderr, fmt, ap);
363*10923SEvan.Yan@Sun.COM 	else
364*10923SEvan.Yan@Sun.COM 		vsyslog(LOG_ERR, fmt, ap);
365*10923SEvan.Yan@Sun.COM 	va_end(ap);
366*10923SEvan.Yan@Sun.COM }
367*10923SEvan.Yan@Sun.COM 
368*10923SEvan.Yan@Sun.COM /*
369*10923SEvan.Yan@Sun.COM  * log_info()
370*10923SEvan.Yan@Sun.COM  *
371*10923SEvan.Yan@Sun.COM  *	Display an information message.  Use syslog if in daemon
372*10923SEvan.Yan@Sun.COM  *	mode, otherwise print to stdout when in debug mode.
373*10923SEvan.Yan@Sun.COM  */
374*10923SEvan.Yan@Sun.COM /*PRINTFLIKE1*/
375*10923SEvan.Yan@Sun.COM void
log_info(char * fmt,...)376*10923SEvan.Yan@Sun.COM log_info(char *fmt, ...)
377*10923SEvan.Yan@Sun.COM {
378*10923SEvan.Yan@Sun.COM 	va_list ap;
379*10923SEvan.Yan@Sun.COM 
380*10923SEvan.Yan@Sun.COM 	va_start(ap, fmt);
381*10923SEvan.Yan@Sun.COM 	if (debug_flag || !log_flag)
382*10923SEvan.Yan@Sun.COM 		(void) vfprintf(stdout, fmt, ap);
383*10923SEvan.Yan@Sun.COM 	else
384*10923SEvan.Yan@Sun.COM 		vsyslog(LOG_INFO, fmt, ap);
385*10923SEvan.Yan@Sun.COM 	va_end(ap);
386*10923SEvan.Yan@Sun.COM }
387*10923SEvan.Yan@Sun.COM 
388*10923SEvan.Yan@Sun.COM /*
389*10923SEvan.Yan@Sun.COM  * dprintf()
390*10923SEvan.Yan@Sun.COM  *
391*10923SEvan.Yan@Sun.COM  *	Print a debug tracing statement.  Only works in debug
392*10923SEvan.Yan@Sun.COM  *	mode, and always prints to stdout.
393*10923SEvan.Yan@Sun.COM  */
394*10923SEvan.Yan@Sun.COM /*PRINTFLIKE1*/
395*10923SEvan.Yan@Sun.COM void
dprintf(char * fmt,...)396*10923SEvan.Yan@Sun.COM dprintf(char *fmt, ...)
397*10923SEvan.Yan@Sun.COM {
398*10923SEvan.Yan@Sun.COM 	va_list	ap;
399*10923SEvan.Yan@Sun.COM 
400*10923SEvan.Yan@Sun.COM 	if (debug_flag) {
401*10923SEvan.Yan@Sun.COM 		va_start(ap, fmt);
402*10923SEvan.Yan@Sun.COM 		(void) vprintf(fmt, ap);
403*10923SEvan.Yan@Sun.COM 		va_end(ap);
404*10923SEvan.Yan@Sun.COM 	}
405*10923SEvan.Yan@Sun.COM }
406