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