269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER START
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The contents of this file are subject to the terms of the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Common Development and Distribution License (the "License").
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You may not use this file except in compliance with the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
269473047d747f7815af570197e4ef7322d3632cEvan Yan * or http://www.opensolaris.org/os/licensing.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * See the License for the specific language governing permissions
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and limitations under the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If applicable, add the following below this CDDL HEADER, with the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
269473047d747f7815af570197e4ef7322d3632cEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER END
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Use is subject to license terms.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <stdio.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <stdlib.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <unistd.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <errno.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <fcntl.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <signal.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <stdarg.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <strings.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <syslog.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <priv.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <wait.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <getopt.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <synch.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/param.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/stat.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <sys/types.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <libhotplug.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include <libhotplug_impl.h>
269473047d747f7815af570197e4ef7322d3632cEvan Yan#include "hotplugd_impl.h"
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Define long options for command line.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic const struct option lopts[] = {
269473047d747f7815af570197e4ef7322d3632cEvan Yan { "help", no_argument, 0, '?' },
269473047d747f7815af570197e4ef7322d3632cEvan Yan { "version", no_argument, 0, 'V' },
269473047d747f7815af570197e4ef7322d3632cEvan Yan { "debug", no_argument, 0, 'd' },
269473047d747f7815af570197e4ef7322d3632cEvan Yan { 0, 0, 0, 0 }
269473047d747f7815af570197e4ef7322d3632cEvan Yan};
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Local functions.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void usage(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t check_privileges(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int daemonize(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void init_signals(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void signal_handler(int signum);
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void shutdown_daemon(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Global variables.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic char *prog;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic char version[] = "1.0";
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t log_flag = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t debug_flag = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t exit_flag = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic sema_t signal_sem;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * main()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The hotplug daemon is designed to be a background daemon
269473047d747f7815af570197e4ef7322d3632cEvan Yan * controlled by SMF. So by default it will daemonize and
269473047d747f7815af570197e4ef7322d3632cEvan Yan * do some coordination with its parent process in order to
269473047d747f7815af570197e4ef7322d3632cEvan Yan * indicate proper success or failure back to SMF. And all
269473047d747f7815af570197e4ef7322d3632cEvan Yan * output will be sent to syslog.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * But if given the '-d' command line option, it will instead
269473047d747f7815af570197e4ef7322d3632cEvan Yan * run in the foreground in a standalone, debug mode. Errors
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and additional debug messages will be printed to the controlling
269473047d747f7815af570197e4ef7322d3632cEvan Yan * terminal instead of to syslog.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanint
269473047d747f7815af570197e4ef7322d3632cEvan Yanmain(int argc, char *argv[])
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int opt;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int pfd;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int status;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((prog = strrchr(argv[0], '/')) == NULL)
269473047d747f7815af570197e4ef7322d3632cEvan Yan prog = argv[0];
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan prog++;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Check privileges */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!check_privileges()) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) fprintf(stderr, "Insufficient privileges. "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "(All privileges are required.)\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (-1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Process options */
269473047d747f7815af570197e4ef7322d3632cEvan Yan while ((opt = getopt_clip(argc, argv, "dV?", lopts, NULL)) != -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (opt) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case 'd':
269473047d747f7815af570197e4ef7322d3632cEvan Yan debug_flag = B_TRUE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan case 'V':
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) printf("%s: Version %s\n", prog, version);
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (optopt == '?') {
269473047d747f7815af570197e4ef7322d3632cEvan Yan usage();
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) fprintf(stderr, "Unrecognized option '%c'.\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan optopt);
269473047d747f7815af570197e4ef7322d3632cEvan Yan usage();
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (-1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Initialize semaphore for daemon shutdown */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (sema_init(&signal_sem, 1, USYNC_THREAD, NULL) != 0)
269473047d747f7815af570197e4ef7322d3632cEvan Yan exit(EXIT_FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Initialize signal handling */
269473047d747f7815af570197e4ef7322d3632cEvan Yan init_signals();
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Daemonize, if not in DEBUG mode */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!debug_flag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan pfd = daemonize();
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Initialize door service */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!door_server_init()) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!debug_flag) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan status = EXIT_FAILURE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) write(pfd, &status, sizeof (status));
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(pfd);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan exit(EXIT_FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Daemon initialized */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!debug_flag) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan status = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) write(pfd, &status, sizeof (status));
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(pfd);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Note that daemon is running */
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_info("hotplug daemon started.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Wait for shutdown signal */
269473047d747f7815af570197e4ef7322d3632cEvan Yan while (!exit_flag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sema_wait(&signal_sem);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan shutdown_daemon();
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * usage()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Print a brief usage synopsis for the command line options.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanusage(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) printf("Usage: %s [-d]\n", prog);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * check_privileges()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Check if the current process has enough privileges
269473047d747f7815af570197e4ef7322d3632cEvan Yan * to run the daemon. Note that all privileges are
269473047d747f7815af570197e4ef7322d3632cEvan Yan * required in order for RCM interactions to work.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic boolean_t
269473047d747f7815af570197e4ef7322d3632cEvan Yancheck_privileges(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan priv_set_t *privset;
269473047d747f7815af570197e4ef7322d3632cEvan Yan boolean_t rv = B_FALSE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((privset = priv_allocset()) != NULL) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (getppriv(PRIV_EFFECTIVE, privset) == 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan rv = priv_isfullset(privset);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan priv_freeset(privset);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (rv);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * daemonize()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Fork the daemon process into the background, and detach from
269473047d747f7815af570197e4ef7322d3632cEvan Yan * the controlling terminal. Setup a shared pipe that will later
269473047d747f7815af570197e4ef7322d3632cEvan Yan * be used to report startup status to the parent process.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int
269473047d747f7815af570197e4ef7322d3632cEvan Yandaemonize(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan int status;
269473047d747f7815af570197e4ef7322d3632cEvan Yan int pfds[2];
269473047d747f7815af570197e4ef7322d3632cEvan Yan pid_t pid;
269473047d747f7815af570197e4ef7322d3632cEvan Yan sigset_t set;
269473047d747f7815af570197e4ef7322d3632cEvan Yan sigset_t oset;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Temporarily block all signals. They will remain blocked in
269473047d747f7815af570197e4ef7322d3632cEvan Yan * the parent, but will be unblocked in the child once it has
269473047d747f7815af570197e4ef7322d3632cEvan Yan * notified the parent of its startup status.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigfillset(&set);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGABRT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigprocmask(SIG_BLOCK, &set, &oset);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Create the shared pipe */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (pipe(pfds) == -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot create pipe (%s)\n", strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan exit(EXIT_FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Fork the daemon process */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((pid = fork()) == -1) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Cannot fork daemon process (%s)\n", strerror(errno));
269473047d747f7815af570197e4ef7322d3632cEvan Yan exit(EXIT_FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Parent: waits for exit status from child. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (pid > 0) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(pfds[1]);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
269473047d747f7815af570197e4ef7322d3632cEvan Yan _exit(status);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if ((waitpid(pid, &status, 0) == pid) && WIFEXITED(status))
269473047d747f7815af570197e4ef7322d3632cEvan Yan _exit(WEXITSTATUS(status));
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_err("Failed to spawn daemon process.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan _exit(EXIT_FAILURE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Child continues... */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) setsid();
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) chdir("/");
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) umask(CMASK);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigprocmask(SIG_SETMASK, &oset, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(pfds[0]);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Detach from controlling terminal */
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(0);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) close(2);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) open("/dev/null", O_RDONLY);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) open("/dev/null", O_WRONLY);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) open("/dev/null", O_WRONLY);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Use syslog for future messages */
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_flag = B_TRUE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan openlog(prog, LOG_PID, LOG_DAEMON);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return (pfds[1]);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * init_signals()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Initialize signal handling.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yaninit_signals(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan struct sigaction act;
269473047d747f7815af570197e4ef7322d3632cEvan Yan sigset_t set;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigfillset(&set);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGABRT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigfillset(&act.sa_mask);
269473047d747f7815af570197e4ef7322d3632cEvan Yan act.sa_handler = signal_handler;
269473047d747f7815af570197e4ef7322d3632cEvan Yan act.sa_flags = 0;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigaction(SIGTERM, &act, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigaction(SIGHUP, &act, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigaction(SIGINT, &act, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigaction(SIGPIPE, &act, NULL);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGTERM);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGHUP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGINT);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sigdelset(&set, SIGPIPE);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * signal_handler()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Most signals cause the hotplug daemon to shut down.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Shutdown is triggered using a semaphore to wake up
269473047d747f7815af570197e4ef7322d3632cEvan Yan * the main thread for a clean exit.
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Except SIGPIPE is used to coordinate between the parent
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and child processes when the daemon first starts.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yansignal_handler(int signum)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_info("Received signal %d.\n", signum);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan switch (signum) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan case 0:
269473047d747f7815af570197e4ef7322d3632cEvan Yan case SIGPIPE:
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan default:
269473047d747f7815af570197e4ef7322d3632cEvan Yan exit_flag = B_TRUE;
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sema_post(&signal_sem);
269473047d747f7815af570197e4ef7322d3632cEvan Yan break;
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * shutdown_daemon()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Perform a clean shutdown of the daemon.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic void
269473047d747f7815af570197e4ef7322d3632cEvan Yanshutdown_daemon(void)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan log_info("Hotplug daemon shutting down.\n");
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan door_server_fini();
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (log_flag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan closelog();
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) sema_destroy(&signal_sem);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * log_err()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Display an error message. Use syslog if in daemon
269473047d747f7815af570197e4ef7322d3632cEvan Yan * mode, otherwise print to stderr when in debug mode.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*PRINTFLIKE1*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanvoid
269473047d747f7815af570197e4ef7322d3632cEvan Yanlog_err(char *fmt, ...)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_list ap;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_start(ap, fmt);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (debug_flag || !log_flag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) vfprintf(stderr, fmt, ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan vsyslog(LOG_ERR, fmt, ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_end(ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * log_info()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Display an information message. Use syslog if in daemon
269473047d747f7815af570197e4ef7322d3632cEvan Yan * mode, otherwise print to stdout when in debug mode.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*PRINTFLIKE1*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanvoid
269473047d747f7815af570197e4ef7322d3632cEvan Yanlog_info(char *fmt, ...)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_list ap;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_start(ap, fmt);
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (debug_flag || !log_flag)
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) vfprintf(stdout, fmt, ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan else
269473047d747f7815af570197e4ef7322d3632cEvan Yan vsyslog(LOG_INFO, fmt, ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_end(ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*
269473047d747f7815af570197e4ef7322d3632cEvan Yan * dprintf()
269473047d747f7815af570197e4ef7322d3632cEvan Yan *
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Print a debug tracing statement. Only works in debug
269473047d747f7815af570197e4ef7322d3632cEvan Yan * mode, and always prints to stdout.
269473047d747f7815af570197e4ef7322d3632cEvan Yan */
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*PRINTFLIKE1*/
269473047d747f7815af570197e4ef7322d3632cEvan Yanvoid
269473047d747f7815af570197e4ef7322d3632cEvan Yandprintf(char *fmt, ...)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_list ap;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (debug_flag) {
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_start(ap, fmt);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) vprintf(fmt, ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan va_end(ap);
269473047d747f7815af570197e4ef7322d3632cEvan Yan }
269473047d747f7815af570197e4ef7322d3632cEvan Yan}