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