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