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
netsnmp_daemonize(int quit_immediately,int stderr_log)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