17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5fee9b58dSjrutt * Common Development and Distribution License (the "License"). 6fee9b58dSjrutt * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*f6e214c7SGavin Maltby * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 257c478bd9Sstevel@tonic-gate #include <sys/types.h> 267c478bd9Sstevel@tonic-gate #include <sys/stat.h> 277c478bd9Sstevel@tonic-gate #include <sys/wait.h> 287c478bd9Sstevel@tonic-gate #include <sys/corectl.h> 297c478bd9Sstevel@tonic-gate #include <sys/resource.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <priv_utils.h> 327c478bd9Sstevel@tonic-gate #include <signal.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <limits.h> 357c478bd9Sstevel@tonic-gate #include <fcntl.h> 367c478bd9Sstevel@tonic-gate #include <strings.h> 377c478bd9Sstevel@tonic-gate #include <stdlib.h> 387c478bd9Sstevel@tonic-gate #include <stdio.h> 39*f6e214c7SGavin Maltby #include <zone.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #include <fmd_error.h> 427c478bd9Sstevel@tonic-gate #include <fmd_string.h> 437c478bd9Sstevel@tonic-gate #include <fmd_conf.h> 447c478bd9Sstevel@tonic-gate #include <fmd_dispq.h> 457c478bd9Sstevel@tonic-gate #include <fmd_subr.h> 467c478bd9Sstevel@tonic-gate #include <fmd.h> 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate fmd_t fmd; 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 517c478bd9Sstevel@tonic-gate * For DEBUG builds, we define a set of hooks for libumem that provide useful 527c478bd9Sstevel@tonic-gate * default settings for the allocator's debugging facilities. 537c478bd9Sstevel@tonic-gate */ 547c478bd9Sstevel@tonic-gate #ifdef DEBUG 557c478bd9Sstevel@tonic-gate const char * 567c478bd9Sstevel@tonic-gate _umem_debug_init() 577c478bd9Sstevel@tonic-gate { 587c478bd9Sstevel@tonic-gate return ("default,verbose"); /* $UMEM_DEBUG setting */ 597c478bd9Sstevel@tonic-gate } 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate const char * 627c478bd9Sstevel@tonic-gate _umem_logging_init(void) 637c478bd9Sstevel@tonic-gate { 647c478bd9Sstevel@tonic-gate return ("fail,contents"); /* $UMEM_LOGGING setting */ 657c478bd9Sstevel@tonic-gate } 667c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * We use a two-phase algorithm for becoming a daemon because we want the 707c478bd9Sstevel@tonic-gate * daemon process (the child) to do the work of becoming MT-hot and opening our 717c478bd9Sstevel@tonic-gate * event transport. Since these operations can fail and need to result in the 727c478bd9Sstevel@tonic-gate * daemon failing to start, the parent must wait until fmd_run() completes to 737c478bd9Sstevel@tonic-gate * know whether it can return zero or non-zero status to the invoking command. 747c478bd9Sstevel@tonic-gate * The parent waits on a pipe inside this function to read the exit status. 757c478bd9Sstevel@tonic-gate * The child gets the write-end of the pipe returned by daemonize_init() and 767c478bd9Sstevel@tonic-gate * then fmd_run() uses the pipe to set the exit status and detach the parent. 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate static int 797c478bd9Sstevel@tonic-gate daemonize_init(void) 807c478bd9Sstevel@tonic-gate { 81*f6e214c7SGavin Maltby const char *gzp1, *gzp2, *gzp3, *gzp4, *gzp5; 827c478bd9Sstevel@tonic-gate int status, pfds[2]; 837c478bd9Sstevel@tonic-gate sigset_t set, oset; 847c478bd9Sstevel@tonic-gate struct rlimit rlim; 857c478bd9Sstevel@tonic-gate char path[PATH_MAX]; 867c478bd9Sstevel@tonic-gate pid_t pid; 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Set our per-process core file path to leave core files in our 907c478bd9Sstevel@tonic-gate * var/fm/fmd directory, named after the PID to aid in debugging, 917c478bd9Sstevel@tonic-gate * and make sure that there is no restriction on core file size. 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate (void) snprintf(path, sizeof (path), 947c478bd9Sstevel@tonic-gate "%s/var/fm/fmd/core.%s.%%p", fmd.d_rootdir, fmd.d_pname); 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate (void) core_set_process_path(path, strlen(path) + 1, fmd.d_pid); 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate rlim.rlim_cur = RLIM_INFINITY; 997c478bd9Sstevel@tonic-gate rlim.rlim_max = RLIM_INFINITY; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate (void) setrlimit(RLIMIT_CORE, &rlim); 1027c478bd9Sstevel@tonic-gate 1037c478bd9Sstevel@tonic-gate /* 1040166a357SEric Schrock * Claim all the file descriptors we can. 1050166a357SEric Schrock */ 1060166a357SEric Schrock if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) { 1070166a357SEric Schrock rlim.rlim_cur = rlim.rlim_max; 1080166a357SEric Schrock (void) setrlimit(RLIMIT_NOFILE, &rlim); 1090166a357SEric Schrock } 1100166a357SEric Schrock 1110166a357SEric Schrock /* 1127c478bd9Sstevel@tonic-gate * Reset all of our privilege sets to the minimum set of required 1137c478bd9Sstevel@tonic-gate * privileges. We continue to run as root so that files we create 1147c478bd9Sstevel@tonic-gate * such as logs and checkpoints are secured in the /var filesystem. 115*f6e214c7SGavin Maltby * 116*f6e214c7SGavin Maltby * In a non-global zone some of the privileges we retain in a 117*f6e214c7SGavin Maltby * global zone are only optionally assigned to the zone, while others 118*f6e214c7SGavin Maltby * are prohibited: 119*f6e214c7SGavin Maltby * 120*f6e214c7SGavin Maltby * PRIV_PROC_PRIOCNTL (optional in a non-global zone): 121*f6e214c7SGavin Maltby * There are no calls to priocntl(2) in fmd or plugins. 122*f6e214c7SGavin Maltby * 123*f6e214c7SGavin Maltby * PRIV_SYS_CONFIG (prohibited in a non-global zone): 124*f6e214c7SGavin Maltby * Required, I think, for sysevent_post_event and/or 125*f6e214c7SGavin Maltby * other legacy sysevent activity. Legacy sysevent is not 126*f6e214c7SGavin Maltby * supported in a non-global zone. 127*f6e214c7SGavin Maltby * 128*f6e214c7SGavin Maltby * PRIV_SYS_DEVICES (prohibited in a non-global zone): 129*f6e214c7SGavin Maltby * Needed in the global zone for ioctls on various drivers 130*f6e214c7SGavin Maltby * such as memory-controller drivers. 131*f6e214c7SGavin Maltby * 132*f6e214c7SGavin Maltby * PRIV_SYS_RES_CONFIG (prohibited in a non-global zone): 133*f6e214c7SGavin Maltby * Require for p_online(2) calls to offline cpus. 134*f6e214c7SGavin Maltby * 135*f6e214c7SGavin Maltby * PRIV_SYS_NET_CONFIG (prohibited in a non-global zone): 136*f6e214c7SGavin Maltby * Required for ipsec in etm (which also requires 137*f6e214c7SGavin Maltby * PRIV_NET_PRIVADDR). 138*f6e214c7SGavin Maltby * 139*f6e214c7SGavin Maltby * We do without those privileges in a non-global zone. It's 140*f6e214c7SGavin Maltby * possible that there are other privs we could drop since 141*f6e214c7SGavin Maltby * hardware-related plugins are not present. 1427c478bd9Sstevel@tonic-gate */ 143*f6e214c7SGavin Maltby if (getzoneid() == GLOBAL_ZONEID) { 144*f6e214c7SGavin Maltby gzp1 = PRIV_PROC_PRIOCNTL; 145*f6e214c7SGavin Maltby gzp2 = PRIV_SYS_CONFIG; 146*f6e214c7SGavin Maltby gzp3 = PRIV_SYS_DEVICES; 147*f6e214c7SGavin Maltby gzp4 = PRIV_SYS_RES_CONFIG; 148*f6e214c7SGavin Maltby gzp5 = PRIV_SYS_NET_CONFIG; 149*f6e214c7SGavin Maltby } else { 150*f6e214c7SGavin Maltby gzp1 = gzp2 = gzp3 = gzp4 = gzp5 = NULL; 151*f6e214c7SGavin Maltby } 152*f6e214c7SGavin Maltby 1537c478bd9Sstevel@tonic-gate if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS, 1547c478bd9Sstevel@tonic-gate 0, 0, /* run as uid 0 and gid 0 */ 1557c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_EXECUTE, PRIV_FILE_DAC_READ, PRIV_FILE_DAC_SEARCH, 1567c478bd9Sstevel@tonic-gate PRIV_FILE_DAC_WRITE, PRIV_FILE_OWNER, PRIV_PROC_OWNER, 157*f6e214c7SGavin Maltby PRIV_SYS_ADMIN, PRIV_NET_PRIVADDR, 158*f6e214c7SGavin Maltby gzp1, gzp2, gzp3, gzp4, gzp5, NULL) != 0) 1597c478bd9Sstevel@tonic-gate fmd_error(EFMD_EXIT, "additional privileges required to run\n"); 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Block all signals prior to the fork and leave them blocked in the 1637c478bd9Sstevel@tonic-gate * parent so we don't get in a situation where the parent gets SIGINT 1647c478bd9Sstevel@tonic-gate * and returns non-zero exit status and the child is actually running. 1657c478bd9Sstevel@tonic-gate * In the child, restore the signal mask once we've done our setsid(). 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate (void) sigfillset(&set); 1687c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGABRT); 1697c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_BLOCK, &set, &oset); 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if (pipe(pfds) == -1) 1727c478bd9Sstevel@tonic-gate fmd_error(EFMD_EXIT, "failed to create pipe for daemonize"); 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if ((pid = fork()) == -1) 1757c478bd9Sstevel@tonic-gate fmd_error(EFMD_EXIT, "failed to fork into background"); 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate /* 1787c478bd9Sstevel@tonic-gate * If we're the parent process, wait for either the child to send us 1797c478bd9Sstevel@tonic-gate * the appropriate exit status over the pipe or for the read to fail 1807c478bd9Sstevel@tonic-gate * (presumably with 0 for EOF if our child terminated abnormally). 1817c478bd9Sstevel@tonic-gate * If the read fails, exit with either the child's exit status if it 1827c478bd9Sstevel@tonic-gate * exited or with FMD_EXIT_ERROR if it died from a fatal signal. 1837c478bd9Sstevel@tonic-gate */ 1847c478bd9Sstevel@tonic-gate if (pid != 0) { 1857c478bd9Sstevel@tonic-gate (void) close(pfds[1]); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 1887c478bd9Sstevel@tonic-gate _exit(status); 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 1917c478bd9Sstevel@tonic-gate _exit(WEXITSTATUS(status)); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate _exit(FMD_EXIT_ERROR); 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate fmd.d_pid = getpid(); 1977c478bd9Sstevel@tonic-gate (void) setsid(); 1987c478bd9Sstevel@tonic-gate (void) sigprocmask(SIG_SETMASK, &oset, NULL); 1997c478bd9Sstevel@tonic-gate (void) chdir("/"); 2007c478bd9Sstevel@tonic-gate (void) umask(022); 2017c478bd9Sstevel@tonic-gate (void) close(pfds[0]); 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate return (pfds[1]); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate static void 2077c478bd9Sstevel@tonic-gate daemonize_fini(int fd) 2087c478bd9Sstevel@tonic-gate { 2097c478bd9Sstevel@tonic-gate (void) close(fd); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate if ((fd = open("/dev/null", O_RDWR)) >= 0) { 2127c478bd9Sstevel@tonic-gate (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 2137c478bd9Sstevel@tonic-gate (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 2147c478bd9Sstevel@tonic-gate (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 2157c478bd9Sstevel@tonic-gate (void) close(fd); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate } 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate static void 2207c478bd9Sstevel@tonic-gate handler(int sig) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate if (fmd.d_signal == 0) 2237c478bd9Sstevel@tonic-gate fmd.d_signal = sig; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate static int 2277c478bd9Sstevel@tonic-gate usage(const char *arg0, FILE *fp) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate (void) fprintf(fp, 2307c478bd9Sstevel@tonic-gate "Usage: %s [-V] [-f file] [-o opt=val] [-R dir]\n", arg0); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate return (FMD_EXIT_USAGE); 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate int 2367c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 2377c478bd9Sstevel@tonic-gate { 2387c478bd9Sstevel@tonic-gate const char *opt_f = NULL, *opt_R = NULL; 2397c478bd9Sstevel@tonic-gate const char optstr[] = "f:o:R:V"; 2407c478bd9Sstevel@tonic-gate int c, pfd = -1, opt_V = 0; 2417c478bd9Sstevel@tonic-gate char *p; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate struct sigaction act; 2447c478bd9Sstevel@tonic-gate sigset_t set; 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * Parse the command-line once to validate all options and retrieve 2487c478bd9Sstevel@tonic-gate * any overrides for our configuration file and root directory. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, optstr)) != EOF) { 2517c478bd9Sstevel@tonic-gate switch (c) { 2527c478bd9Sstevel@tonic-gate case 'f': 2537c478bd9Sstevel@tonic-gate opt_f = optarg; 2547c478bd9Sstevel@tonic-gate break; 2557c478bd9Sstevel@tonic-gate case 'o': 2567c478bd9Sstevel@tonic-gate break; /* handle -o below */ 2577c478bd9Sstevel@tonic-gate case 'R': 2587c478bd9Sstevel@tonic-gate opt_R = optarg; 2597c478bd9Sstevel@tonic-gate break; 2607c478bd9Sstevel@tonic-gate case 'V': 2617c478bd9Sstevel@tonic-gate opt_V++; 2627c478bd9Sstevel@tonic-gate break; 2637c478bd9Sstevel@tonic-gate default: 2647c478bd9Sstevel@tonic-gate return (usage(argv[0], stderr)); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate } 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate if (optind < argc) 2697c478bd9Sstevel@tonic-gate return (usage(argv[0], stderr)); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate if (opt_V) { 2727c478bd9Sstevel@tonic-gate #ifdef DEBUG 2730166a357SEric Schrock const char *debug = " (DEBUG)"; 2747c478bd9Sstevel@tonic-gate #else 2750166a357SEric Schrock const char *debug = ""; 2767c478bd9Sstevel@tonic-gate #endif 2770166a357SEric Schrock (void) printf("%s: version %s%s\n", 2780166a357SEric Schrock argv[0], _fmd_version, debug); 2797c478bd9Sstevel@tonic-gate return (FMD_EXIT_SUCCESS); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate closefrom(STDERR_FILENO + 1); 2837c478bd9Sstevel@tonic-gate fmd_create(&fmd, argv[0], opt_R, opt_f); 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * Now that we've initialized our global state, parse the command-line 2877c478bd9Sstevel@tonic-gate * again for any configuration options specified using -o and set them. 2887c478bd9Sstevel@tonic-gate */ 2897c478bd9Sstevel@tonic-gate for (optind = 1; (c = getopt(argc, argv, optstr)) != EOF; ) { 2907c478bd9Sstevel@tonic-gate if (c == 'o') { 2917c478bd9Sstevel@tonic-gate if ((p = strchr(optarg, '=')) == NULL) { 2927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: failed to set " 2937c478bd9Sstevel@tonic-gate "option -o %s: option requires value\n", 2947c478bd9Sstevel@tonic-gate fmd.d_pname, optarg); 2957c478bd9Sstevel@tonic-gate return (FMD_EXIT_USAGE); 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate *p++ = '\0'; /* strike out the delimiter */ 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate if (p[0] == '"' && p[strlen(p) - 1] == '"') { 3017c478bd9Sstevel@tonic-gate p[strlen(p) - 1] = '\0'; 3027c478bd9Sstevel@tonic-gate (void) fmd_stresc2chr(++p); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate if (fmd_conf_setprop(fmd.d_conf, optarg, p) != 0) { 3067c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3077c478bd9Sstevel@tonic-gate "%s: failed to set option -o %s: %s\n", 3087c478bd9Sstevel@tonic-gate fmd.d_pname, optarg, fmd_strerror(errno)); 3097c478bd9Sstevel@tonic-gate return (FMD_EXIT_USAGE); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate } 3127c478bd9Sstevel@tonic-gate } 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gate if (fmd.d_fmd_debug & FMD_DBG_HELP) { 3157c478bd9Sstevel@tonic-gate fmd_help(&fmd); 3167c478bd9Sstevel@tonic-gate fmd_destroy(&fmd); 3177c478bd9Sstevel@tonic-gate return (FMD_EXIT_SUCCESS); 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate 3207c478bd9Sstevel@tonic-gate /* 3217c478bd9Sstevel@tonic-gate * Update the value of fmd.d_fg based on "fg" in case it changed. We 3227c478bd9Sstevel@tonic-gate * use this property to decide whether to daemonize below. 3237c478bd9Sstevel@tonic-gate */ 3247c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(fmd.d_conf, "fg", &fmd.d_fg); 3257c478bd9Sstevel@tonic-gate 3267c478bd9Sstevel@tonic-gate /* 3277c478bd9Sstevel@tonic-gate * Once we're done setting our global state up, set up signal handlers 3287c478bd9Sstevel@tonic-gate * for ensuring orderly termination on SIGTERM. If we are starting in 3297c478bd9Sstevel@tonic-gate * the foreground, we also use the same handler for SIGINT and SIGHUP. 3307c478bd9Sstevel@tonic-gate */ 3317c478bd9Sstevel@tonic-gate (void) sigfillset(&set); 3327c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGABRT); /* always unblocked for ASSERT() */ 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate (void) sigfillset(&act.sa_mask); 3357c478bd9Sstevel@tonic-gate act.sa_handler = handler; 3367c478bd9Sstevel@tonic-gate act.sa_flags = 0; 3377c478bd9Sstevel@tonic-gate 3387c478bd9Sstevel@tonic-gate (void) sigaction(SIGTERM, &act, NULL); 3397c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGTERM); 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate if (fmd.d_fg) { 3427c478bd9Sstevel@tonic-gate (void) sigaction(SIGHUP, &act, NULL); 3437c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGHUP); 3447c478bd9Sstevel@tonic-gate (void) sigaction(SIGINT, &act, NULL); 3457c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGINT); 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGTSTP); 3487c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGTTIN); 3497c478bd9Sstevel@tonic-gate (void) sigdelset(&set, SIGTTOU); 3507c478bd9Sstevel@tonic-gate 3517c478bd9Sstevel@tonic-gate (void) printf("%s: [ loading modules ... ", fmd.d_pname); 3527c478bd9Sstevel@tonic-gate (void) fflush(stdout); 3537c478bd9Sstevel@tonic-gate } else 3547c478bd9Sstevel@tonic-gate pfd = daemonize_init(); 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate /* 3577c478bd9Sstevel@tonic-gate * Prior to this point, we are single-threaded. Once fmd_run() is 3587c478bd9Sstevel@tonic-gate * called, we will be multi-threaded from this point on. The daemon's 3597c478bd9Sstevel@tonic-gate * main thread will wait at the end of this function for signals. 3607c478bd9Sstevel@tonic-gate */ 3617c478bd9Sstevel@tonic-gate fmd_run(&fmd, pfd); 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate if (fmd.d_fg) { 3647c478bd9Sstevel@tonic-gate (void) printf("done ]\n"); 3657c478bd9Sstevel@tonic-gate (void) printf("%s: [ awaiting events ]\n", fmd.d_pname); 3667c478bd9Sstevel@tonic-gate } else 3677c478bd9Sstevel@tonic-gate daemonize_fini(pfd); 3687c478bd9Sstevel@tonic-gate 3697c478bd9Sstevel@tonic-gate while (!fmd.d_signal) 3707c478bd9Sstevel@tonic-gate (void) sigsuspend(&set); 3717c478bd9Sstevel@tonic-gate 3727c478bd9Sstevel@tonic-gate fmd_destroy(&fmd); 3737c478bd9Sstevel@tonic-gate return (FMD_EXIT_SUCCESS); 3747c478bd9Sstevel@tonic-gate } 375