xref: /titanic_41/usr/src/cmd/lms/tools/daemonize.cpp (revision 704030f4517ac42005a5e3a4cb2fe578c959bfe2)
1 /*******************************************************************************
2  * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  - Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *
10  *  - Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  *  - Neither the name of Intel Corp. nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *******************************************************************************/
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #ifdef DAEMON
36 
37 #include <cstdio>
38 #include <cstdlib>
39 #include <cstring>
40 #include <cerrno>
41 #include <csignal>
42 #include <unistd.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <syslog.h>
47 #include <pwd.h>
48 
49 #include "daemonize.h"
50 
51 static RETSIGTYPE child_handler(int signum)
52 {
53 	switch (signum) {
54 	case SIGALRM:
55 		exit(EXIT_FAILURE);
56 		break;
57 	case SIGUSR1:
58 		exit(EXIT_SUCCESS);
59 		break;
60 	case SIGCHLD:
61 		exit(EXIT_FAILURE);
62 		break;
63 	}
64 }
65 
66 void daemonize()
67 {
68 	pid_t pid, sid, parent;
69 
70 	/* Drop user if there is one, and we were run as root */
71 	if (getuid() == 0 || geteuid() == 0) {
72 		struct passwd *pw = getpwnam(RUN_AS_USER);
73 		if (pw) {
74 			//syslog(LOG_NOTICE, "setting user to " RUN_AS_USER);
75 			setuid(pw->pw_uid);
76 		}
77 	}
78 
79 	/* Trap signals that we expect to recieve */
80 	signal(SIGCHLD, child_handler);
81 	signal(SIGUSR1, child_handler);
82 	signal(SIGALRM, child_handler);
83 
84 	/* Fork off the parent process */
85 	pid = fork();
86 	if (pid < 0) {
87 		syslog(LOG_ERR, "unable to fork daemon, code=%d (%s)",
88 		       errno, strerror(errno));
89 		exit(EXIT_FAILURE);
90 	}
91 	/* If we got a good PID, then we can exit the parent process. */
92 	if (pid > 0) {
93 
94 		/* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
95 		   for two seconds to elapse (SIGALRM).  pause() should not return. */
96 		alarm(2);
97 		pause();
98 
99 		exit(EXIT_FAILURE);
100 	}
101 
102 	/* At this point we are executing as the child process */
103 	parent = getppid();
104 
105 	signal(SIGCHLD, SIG_DFL);
106 	signal(SIGUSR1, SIG_DFL);
107 	signal(SIGALRM, SIG_DFL);
108 	setTerminationHandler();
109 
110 	/* Create a new SID for the child process */
111 	sid = setsid();
112 	if (sid < 0) {
113 		syslog(LOG_ERR,
114 		       "unable to create a new session, code %d (%s)",
115 		       errno, strerror(errno));
116 		exit(EXIT_FAILURE);
117 	}
118 
119 	/* Change the current working directory.  This prevents the current
120 	   directory from being locked; hence not being able to remove it. */
121 	if ((chdir("/")) < 0) {
122 		syslog(LOG_ERR,
123 		       "unable to change directory to %s, code %d (%s)",
124 		       "/", errno, strerror(errno));
125 		exit(EXIT_FAILURE);
126 	}
127 
128 	/* Redirect standard files to /dev/null */
129 	freopen("/dev/null", "r", stdin);
130 	freopen("/dev/null", "w", stdout);
131 	freopen("/dev/null", "w", stderr);
132 
133 	/* Tell the parent process that we are A-okay */
134 	kill(parent, SIGUSR1);
135 }
136 
137 #endif //DAEMON
138 
139