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 #if TIME_WITH_SYS_TIME
61 # ifdef WIN32
62 #  include <sys/timeb.h>
63 # else
64 #  include <sys/time.h>
65 # endif
66 # include <time.h>
67 #else
68 # if HAVE_SYS_TIME_H
69 #  include <sys/time.h>
70 # else
71 #  include <time.h>
72 # endif
73 #endif
74 
75 #include <sys/types.h>
76 
77 #if HAVE_NETINET_IN_H
78 #include <netinet/in.h>
79 #endif
80 
81 #if HAVE_WINSOCK_H
82 #include <winsock.h>
83 #endif
84 #if HAVE_SYS_SOCKET_H
85 #include <sys/socket.h>
86 #endif
87 #if HAVE_NET_IF_H
88 #include <net/if.h>
89 #endif
90 
91 #if HAVE_SYS_SOCKIO_H
92 #include <sys/sockio.h>
93 #endif
94 
95 #if HAVE_SYS_IOCTL_H
96 #include <sys/ioctl.h>
97 #endif
98 
99 #ifdef HAVE_NLIST_H
100 #include <nlist.h>
101 #endif
102 
103 #if HAVE_SYS_FILE_H
104 #include <sys/file.h>
105 #endif
106 
107 #if HAVE_KSTAT_H
108 #include <kstat.h>
109 #endif
110 
111 #if HAVE_SYS_PARAM_H
112 #include <sys/param.h>
113 #endif
114 #if HAVE_SYS_SYSCTL_H
115 #include <sys/sysctl.h>
116 #endif
117 
118 #if HAVE_STRING_H
119 #include <string.h>
120 #else
121 #include <strings.h>
122 #endif
123 
124 #if HAVE_DMALLOC_H
125 #include <dmalloc.h>
126 #endif
127 
128 #ifdef HAVE_SYS_STAT_H
129 #include <sys/stat.h>
130 #endif
131 #if HAVE_FCNTL_H
132 #include <fcntl.h>
133 #endif
134 
135 #if defined(hpux10) || defined(hpux11)
136 #include <sys/pstat.h>
137 #endif
138 
139 #if HAVE_SYS_UTSNAME_H
140 #include <sys/utsname.h>
141 #endif
142 
143 #if HAVE_SYS_SYSTEMCFG_H
144 #include <sys/systemcfg.h>
145 #endif
146 
147 #if HAVE_SYS_SYSTEMINFO_H
148 #include <sys/systeminfo.h>
149 #endif
150 
151 #include <net-snmp/types.h>
152 #include <net-snmp/output_api.h>
153 #include <net-snmp/utilities.h>
154 #include <net-snmp/library/system.h>    /* for "internal" definitions */
155 
156 #include <net-snmp/library/snmp_api.h>
157 #include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */
158 
159 #ifndef IFF_LOOPBACK
160 #	define IFF_LOOPBACK 0
161 #endif
162 
163 #ifdef  INADDR_LOOPBACK
164 # define LOOPBACK    INADDR_LOOPBACK
165 #else
166 # define LOOPBACK    0x7f000001
167 #endif
168 
169 /**
170  * fork current process into the background.
171  *
172  * This function forks a process into the background, in order to
173  * become a daemon process. It does a few things along the way:
174  *
175  * - becoming a process/session group leader, and  forking a second time so
176  *   that process/session group leader can exit.
177  *
178  * - changing the working directory to /
179  *
180  * - closing stdin, stdout and stderr (unless stderr_log is set) and
181  *   redirecting them to /dev/null
182  *
183  * @param quit_immediately : indicates if the parent process should
184  *                           exit after a successful fork.
185  * @param stderr_log       : indicates if stderr is being used for
186  *                           logging and shouldn't be closed
187  * @returns -1 : fork error
188  *           0 : child process returning
189  *          >0 : parent process returning. returned value is the child PID.
190  */
191 int
netsnmp_daemonize(int quit_immediately,int stderr_log)192 netsnmp_daemonize(int quit_immediately, int stderr_log)
193 {
194     int i = 0;
195     int saved_errno;
196 
197     DEBUGMSGT(("daemonize","daemonizing...\n"));
198 #ifdef HAVE_WORKING_FORK
199     /*
200      * Fork to return control to the invoking process and to
201      * guarantee that we aren't a process group leader.
202      */
203     i = fork();
204     if (i != 0) {
205         /* Parent. */
206 	saved_errno = errno;
207         DEBUGMSGT(("daemonize","first fork returned %d.\n", i));
208         if(i == -1) {
209             snmp_log(LOG_ERR,"first fork failed (errno %d) in "
210                      "netsnmp_daemonize()\n", saved_errno);
211             return -1;
212         }
213         if (quit_immediately) {
214             DEBUGMSGT(("daemonize","parent exiting\n"));
215             exit(0);
216         }
217     } else {
218         /* Child. */
219 #ifdef HAVE_SETSID
220         /* Become a process/session group leader. */
221         setsid();
222 #endif
223         /*
224          * Fork to let the process/session group leader exit.
225          */
226         if ((i = fork()) != 0) {
227 	    saved_errno = errno;
228             DEBUGMSGT(("daemonize","second fork returned %d.\n", i));
229             if(i == -1) {
230                 snmp_log(LOG_ERR,"second fork failed (errno %d) in "
231                          "netsnmp_daemonize()\n", saved_errno);
232             }
233             /* Parent. */
234             exit(0);
235         }
236 #ifndef WIN32
237         else {
238             /* Child. */
239 
240             DEBUGMSGT(("daemonize","child continuing\n"));
241 
242             /* Avoid keeping any directory in use. */
243             chdir("/");
244 
245             if (!stderr_log) {
246                 /*
247                  * Close inherited file descriptors to avoid
248                  * keeping unnecessary references.
249                  */
250                 close(0);
251                 close(1);
252                 close(2);
253 
254                 /*
255                  * Redirect std{in,out,err} to /dev/null, just in
256                  * case.
257                  */
258                 open("/dev/null", O_RDWR);
259                 dup(0);
260                 dup(0);
261             }
262         }
263 #endif /* !WIN32 */
264     }
265 #endif /* HAVE_WORKING_FORK */
266     return i;
267 }
268 
269 #else /* !NEED_NETSNMP_DAEMONIZE */
270 int netsnp_daemonize_bs;
271 #endif
272