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