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 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