xref: /freebsd/contrib/ntp/ntpsnmpd/netsnmp_daemonize.c (revision 7937bfbc0ca53fe7cdd0d54414f9296e273a518e)
1 /*
2  * system.c
3  */
4 /* Portions of this file are subject to the following copyright(s).  See
5  * the Net-SNMP's COPYING file for more details and other copyrights
6  * that may apply:
7  */
8 /***********************************************************
9         Copyright 1992 by Carnegie Mellon University
10 
11                       All Rights Reserved
12 
13 Permission to use, copy, modify, and distribute this software and its
14 documentation for any purpose and without fee is hereby granted,
15 provided that the above copyright notice appear in all copies and that
16 both that copyright notice and this permission notice appear in
17 supporting documentation, and that the name of CMU not be
18 used in advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20 
21 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27 SOFTWARE.
28 ******************************************************************/
29 /*
30  * Portions of this file are copyrighted by:
31  * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
32  * Use is subject to license terms specified in the COPYING file
33  * distributed with the Net-SNMP package.
34  */
35 /*
36  * System dependent routines go here
37  */
38 #include <net-snmp/net-snmp-config.h>
39 #undef PACKAGE_BUGREPORT
40 #undef PACKAGE_NAME
41 #undef PACKAGE_STRING
42 #undef PACKAGE_TARNAME
43 #undef PACKAGE_URL
44 #undef PACKAGE_VERSION
45 #include <config.h>
46 
47 #ifdef NEED_NETSNMP_DAEMONIZE
48 
49 #include <stdio.h>
50 #include <ctype.h>
51 #include <errno.h>
52 
53 #if HAVE_UNISTD_H
54 #include <unistd.h>
55 #endif
56 #if HAVE_STDLIB_H
57 #include <stdlib.h>
58 #endif
59 
60 #ifdef WIN32
61 # include <sys/timeb.h>
62 #else
63 # include <sys/time.h>
64 #endif
65 #include <time.h>
66 
67 #include <sys/types.h>
68 
69 #if HAVE_NETINET_IN_H
70 #include <netinet/in.h>
71 #endif
72 
73 #if HAVE_WINSOCK_H
74 #include <winsock.h>
75 #endif
76 #if HAVE_SYS_SOCKET_H
77 #include <sys/socket.h>
78 #endif
79 #if HAVE_NET_IF_H
80 #include <net/if.h>
81 #endif
82 
83 #if HAVE_SYS_SOCKIO_H
84 #include <sys/sockio.h>
85 #endif
86 
87 #if HAVE_SYS_IOCTL_H
88 #include <sys/ioctl.h>
89 #endif
90 
91 #ifdef HAVE_NLIST_H
92 #include <nlist.h>
93 #endif
94 
95 #if HAVE_SYS_FILE_H
96 #include <sys/file.h>
97 #endif
98 
99 #if HAVE_KSTAT_H
100 #include <kstat.h>
101 #endif
102 
103 #if HAVE_SYS_PARAM_H
104 #include <sys/param.h>
105 #endif
106 #if HAVE_SYS_SYSCTL_H
107 #include <sys/sysctl.h>
108 #endif
109 
110 #if HAVE_STRING_H
111 #include <string.h>
112 #else
113 #include <strings.h>
114 #endif
115 
116 #if HAVE_DMALLOC_H
117 #include <dmalloc.h>
118 #endif
119 
120 #ifdef HAVE_SYS_STAT_H
121 #include <sys/stat.h>
122 #endif
123 #if HAVE_FCNTL_H
124 #include <fcntl.h>
125 #endif
126 
127 #if defined(hpux10) || defined(hpux11)
128 #include <sys/pstat.h>
129 #endif
130 
131 #if HAVE_SYS_UTSNAME_H
132 #include <sys/utsname.h>
133 #endif
134 
135 #if HAVE_SYS_SYSTEMCFG_H
136 #include <sys/systemcfg.h>
137 #endif
138 
139 #if HAVE_SYS_SYSTEMINFO_H
140 #include <sys/systeminfo.h>
141 #endif
142 
143 #include <net-snmp/types.h>
144 #include <net-snmp/output_api.h>
145 #include <net-snmp/utilities.h>
146 #include <net-snmp/library/system.h>    /* for "internal" definitions */
147 
148 #include <net-snmp/library/snmp_api.h>
149 #include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */
150 
151 #ifndef IFF_LOOPBACK
152 #	define IFF_LOOPBACK 0
153 #endif
154 
155 #ifdef  INADDR_LOOPBACK
156 # define LOOPBACK    INADDR_LOOPBACK
157 #else
158 # define LOOPBACK    0x7f000001
159 #endif
160 
161 /**
162  * fork current process into the background.
163  *
164  * This function forks a process into the background, in order to
165  * become a daemon process. It does a few things along the way:
166  *
167  * - becoming a process/session group leader, and  forking a second time so
168  *   that process/session group leader can exit.
169  *
170  * - changing the working directory to /
171  *
172  * - closing stdin, stdout and stderr (unless stderr_log is set) and
173  *   redirecting them to /dev/null
174  *
175  * @param quit_immediately : indicates if the parent process should
176  *                           exit after a successful fork.
177  * @param stderr_log       : indicates if stderr is being used for
178  *                           logging and shouldn't be closed
179  * @returns -1 : fork error
180  *           0 : child process returning
181  *          >0 : parent process returning. returned value is the child PID.
182  */
183 int
184 netsnmp_daemonize(int quit_immediately, int stderr_log)
185 {
186     int i = 0;
187     int saved_errno;
188 
189     DEBUGMSGT(("daemonize","daemonizing...\n"));
190 #ifdef HAVE_WORKING_FORK
191     /*
192      * Fork to return control to the invoking process and to
193      * guarantee that we aren't a process group leader.
194      */
195     i = fork();
196     if (i != 0) {
197         /* Parent. */
198 	saved_errno = errno;
199         DEBUGMSGT(("daemonize","first fork returned %d.\n", i));
200         if(i == -1) {
201             snmp_log(LOG_ERR,"first fork failed (errno %d) in "
202                      "netsnmp_daemonize()\n", saved_errno);
203             return -1;
204         }
205         if (quit_immediately) {
206             DEBUGMSGT(("daemonize","parent exiting\n"));
207             exit(0);
208         }
209     } else {
210         /* Child. */
211 #ifdef HAVE_SETSID
212         /* Become a process/session group leader. */
213         setsid();
214 #endif
215         /*
216          * Fork to let the process/session group leader exit.
217          */
218         if ((i = fork()) != 0) {
219 	    saved_errno = errno;
220             DEBUGMSGT(("daemonize","second fork returned %d.\n", i));
221             if(i == -1) {
222                 snmp_log(LOG_ERR,"second fork failed (errno %d) in "
223                          "netsnmp_daemonize()\n", saved_errno);
224             }
225             /* Parent. */
226             exit(0);
227         }
228 #ifndef WIN32
229         else {
230             /* Child. */
231 
232             DEBUGMSGT(("daemonize","child continuing\n"));
233 
234             /* Avoid keeping any directory in use. */
235             chdir("/");
236 
237             if (!stderr_log) {
238                 /*
239                  * Close inherited file descriptors to avoid
240                  * keeping unnecessary references.
241                  */
242                 close(0);
243                 close(1);
244                 close(2);
245 
246                 /*
247                  * Redirect std{in,out,err} to /dev/null, just in
248                  * case.
249                  */
250                 open("/dev/null", O_RDWR);
251                 dup(0);
252                 dup(0);
253             }
254         }
255 #endif /* !WIN32 */
256     }
257 #endif /* HAVE_WORKING_FORK */
258     return i;
259 }
260 
261 #else /* !NEED_NETSNMP_DAEMONIZE */
262 NONEMPTY_TRANSLATION_UNIT
263 #endif
264