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