1*250a0733Sth199096 /* 2*250a0733Sth199096 * CDDL HEADER START 3*250a0733Sth199096 * 4*250a0733Sth199096 * The contents of this file are subject to the terms of the 5*250a0733Sth199096 * Common Development and Distribution License (the "License"). 6*250a0733Sth199096 * You may not use this file except in compliance with the License. 7*250a0733Sth199096 * 8*250a0733Sth199096 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*250a0733Sth199096 * or http://www.opensolaris.org/os/licensing. 10*250a0733Sth199096 * See the License for the specific language governing permissions 11*250a0733Sth199096 * and limitations under the License. 12*250a0733Sth199096 * 13*250a0733Sth199096 * When distributing Covered Code, include this CDDL HEADER in each 14*250a0733Sth199096 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*250a0733Sth199096 * If applicable, add the following below this CDDL HEADER, with the 16*250a0733Sth199096 * fields enclosed by brackets "[]" replaced with your own identifying 17*250a0733Sth199096 * information: Portions Copyright [yyyy] [name of copyright owner] 18*250a0733Sth199096 * 19*250a0733Sth199096 * CDDL HEADER END 20*250a0733Sth199096 */ 21*250a0733Sth199096 /* 22*250a0733Sth199096 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23*250a0733Sth199096 * Use is subject to license terms. 24*250a0733Sth199096 */ 25*250a0733Sth199096 26*250a0733Sth199096 /* LINTLIBRARY */ 27*250a0733Sth199096 /* PROTOLIB1 */ 28*250a0733Sth199096 29*250a0733Sth199096 #pragma ident "%Z%%M% %I% %E% SMI" 30*250a0733Sth199096 31*250a0733Sth199096 /* NFS server */ 32*250a0733Sth199096 33*250a0733Sth199096 #include <sys/param.h> 34*250a0733Sth199096 #include <sys/types.h> 35*250a0733Sth199096 #include <errno.h> 36*250a0733Sth199096 #include <stdio.h> 37*250a0733Sth199096 #include <stdio_ext.h> 38*250a0733Sth199096 #include <stdlib.h> 39*250a0733Sth199096 #include <signal.h> 40*250a0733Sth199096 #include <unistd.h> 41*250a0733Sth199096 #include <sys/wait.h> 42*250a0733Sth199096 #include <sys/stat.h> 43*250a0733Sth199096 #include <fcntl.h> 44*250a0733Sth199096 #include <libscf.h> 45*250a0733Sth199096 46*250a0733Sth199096 /* 47*250a0733Sth199096 * The parent never returns from this function. It sits 48*250a0733Sth199096 * and waits for the child to send status on whether it 49*250a0733Sth199096 * loaded or not. 50*250a0733Sth199096 * 51*250a0733Sth199096 * We do not close down the standard file descriptors until 52*250a0733Sth199096 * we know the child is going to run. 53*250a0733Sth199096 */ 54*250a0733Sth199096 int 55*250a0733Sth199096 daemonize_init(void) 56*250a0733Sth199096 { 57*250a0733Sth199096 int status, pfds[2]; 58*250a0733Sth199096 sigset_t set, oset; 59*250a0733Sth199096 pid_t pid; 60*250a0733Sth199096 61*250a0733Sth199096 /* 62*250a0733Sth199096 * Block all signals prior to the fork and leave them blocked in the 63*250a0733Sth199096 * parent so we don't get in a situation where the parent gets SIGINT 64*250a0733Sth199096 * and returns non-zero exit status and the child is actually running. 65*250a0733Sth199096 * In the child, restore the signal mask once we've done our setsid(). 66*250a0733Sth199096 */ 67*250a0733Sth199096 (void) sigfillset(&set); 68*250a0733Sth199096 (void) sigdelset(&set, SIGABRT); 69*250a0733Sth199096 (void) sigprocmask(SIG_BLOCK, &set, &oset); 70*250a0733Sth199096 71*250a0733Sth199096 /* 72*250a0733Sth199096 * We need to do this before we open the pipe - it makes things 73*250a0733Sth199096 * easier in the long run. 74*250a0733Sth199096 */ 75*250a0733Sth199096 closefrom(STDERR_FILENO + 1); 76*250a0733Sth199096 77*250a0733Sth199096 if (pipe(pfds) == -1) { 78*250a0733Sth199096 fprintf(stderr, "failed to create pipe for daemonize"); 79*250a0733Sth199096 exit(SMF_EXIT_ERR_FATAL); 80*250a0733Sth199096 } 81*250a0733Sth199096 82*250a0733Sth199096 if ((pid = fork()) == -1) { 83*250a0733Sth199096 fprintf(stderr, "failed to fork into background"); 84*250a0733Sth199096 exit(SMF_EXIT_ERR_FATAL); 85*250a0733Sth199096 } 86*250a0733Sth199096 87*250a0733Sth199096 if (pid != 0) { 88*250a0733Sth199096 (void) close(pfds[1]); 89*250a0733Sth199096 90*250a0733Sth199096 if (read(pfds[0], &status, sizeof (status)) == sizeof (status)) 91*250a0733Sth199096 exit(status); 92*250a0733Sth199096 93*250a0733Sth199096 if (waitpid(pid, &status, 0) == pid && WIFEXITED(status)) 94*250a0733Sth199096 exit(WEXITSTATUS(status)); 95*250a0733Sth199096 96*250a0733Sth199096 exit(SMF_EXIT_ERR_FATAL); 97*250a0733Sth199096 } 98*250a0733Sth199096 99*250a0733Sth199096 /* 100*250a0733Sth199096 * All child from here on... 101*250a0733Sth199096 */ 102*250a0733Sth199096 (void) setsid(); 103*250a0733Sth199096 (void) sigprocmask(SIG_SETMASK, &oset, NULL); 104*250a0733Sth199096 (void) close(pfds[0]); 105*250a0733Sth199096 106*250a0733Sth199096 return (pfds[1]); 107*250a0733Sth199096 } 108*250a0733Sth199096 109*250a0733Sth199096 /* 110*250a0733Sth199096 * We are only a daemon if the file descriptor is valid. 111*250a0733Sth199096 */ 112*250a0733Sth199096 void 113*250a0733Sth199096 daemonize_fini(int fd) 114*250a0733Sth199096 { 115*250a0733Sth199096 int status = 0; 116*250a0733Sth199096 117*250a0733Sth199096 if (fd != -1) { 118*250a0733Sth199096 (void) write(fd, &status, sizeof (status)); 119*250a0733Sth199096 120*250a0733Sth199096 (void) close(fd); 121*250a0733Sth199096 122*250a0733Sth199096 if ((fd = open("/dev/null", O_RDWR)) >= 0) { 123*250a0733Sth199096 (void) fcntl(fd, F_DUP2FD, STDIN_FILENO); 124*250a0733Sth199096 (void) fcntl(fd, F_DUP2FD, STDOUT_FILENO); 125*250a0733Sth199096 (void) fcntl(fd, F_DUP2FD, STDERR_FILENO); 126*250a0733Sth199096 (void) close(fd); 127*250a0733Sth199096 } 128*250a0733Sth199096 } 129*250a0733Sth199096 } 130