netsnmp_daemonize.c revision 258945
1219820Sjeff/* 2219820Sjeff * system.c 3219820Sjeff */ 4219820Sjeff/* Portions of this file are subject to the following copyright(s). See 5219820Sjeff * the Net-SNMP's COPYING file for more details and other copyrights 6219820Sjeff * that may apply: 7219820Sjeff */ 8219820Sjeff/*********************************************************** 9219820Sjeff Copyright 1992 by Carnegie Mellon University 10219820Sjeff 11219820Sjeff All Rights Reserved 12219820Sjeff 13219820SjeffPermission to use, copy, modify, and distribute this software and its 14219820Sjeffdocumentation for any purpose and without fee is hereby granted, 15219820Sjeffprovided that the above copyright notice appear in all copies and that 16219820Sjeffboth that copyright notice and this permission notice appear in 17219820Sjeffsupporting documentation, and that the name of CMU not be 18219820Sjeffused in advertising or publicity pertaining to distribution of the 19219820Sjeffsoftware without specific, written prior permission. 20219820Sjeff 21219820SjeffCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 22219820SjeffALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 23219820SjeffCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 24219820SjeffANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 25219820SjeffWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 26219820SjeffARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 27219820SjeffSOFTWARE. 28219820Sjeff******************************************************************/ 29219820Sjeff/* 30219820Sjeff * Portions of this file are copyrighted by: 31219820Sjeff * Copyright � 2003 Sun Microsystems, Inc. All rights reserved. 32219820Sjeff * Use is subject to license terms specified in the COPYING file 33219820Sjeff * distributed with the Net-SNMP package. 34219820Sjeff */ 35219820Sjeff/* 36219820Sjeff * System dependent routines go here 37219820Sjeff */ 38219820Sjeff#include <net-snmp/net-snmp-config.h> 39219820Sjeff#undef PACKAGE_BUGREPORT 40219820Sjeff#undef PACKAGE_NAME 41219820Sjeff#undef PACKAGE_STRING 42219820Sjeff#undef PACKAGE_TARNAME 43219820Sjeff#undef PACKAGE_VERSION 44219820Sjeff#include <config.h> 45219820Sjeff 46219820Sjeff#ifdef NEED_NETSNMP_DAEMONIZE 47219820Sjeff 48219820Sjeff#include <stdio.h> 49219820Sjeff#include <ctype.h> 50219820Sjeff#include <errno.h> 51219820Sjeff 52219820Sjeff#if HAVE_UNISTD_H 53219820Sjeff#include <unistd.h> 54219820Sjeff#endif 55219820Sjeff#if HAVE_STDLIB_H 56219820Sjeff#include <stdlib.h> 57219820Sjeff#endif 58219820Sjeff 59219820Sjeff#if TIME_WITH_SYS_TIME 60219820Sjeff# ifdef WIN32 61219820Sjeff# include <sys/timeb.h> 62219820Sjeff# else 63219820Sjeff# include <sys/time.h> 64219820Sjeff# endif 65219820Sjeff# include <time.h> 66219820Sjeff#else 67219820Sjeff# if HAVE_SYS_TIME_H 68219820Sjeff# include <sys/time.h> 69219820Sjeff# else 70219820Sjeff# include <time.h> 71219820Sjeff# endif 72219820Sjeff#endif 73219820Sjeff 74219820Sjeff#include <sys/types.h> 75219820Sjeff 76219820Sjeff#if HAVE_NETINET_IN_H 77219820Sjeff#include <netinet/in.h> 78219820Sjeff#endif 79219820Sjeff 80219820Sjeff#if HAVE_WINSOCK_H 81219820Sjeff#include <winsock.h> 82219820Sjeff#endif 83219820Sjeff#if HAVE_SYS_SOCKET_H 84219820Sjeff#include <sys/socket.h> 85219820Sjeff#endif 86219820Sjeff#if HAVE_NET_IF_H 87219820Sjeff#include <net/if.h> 88219820Sjeff#endif 89219820Sjeff 90219820Sjeff#if HAVE_SYS_SOCKIO_H 91219820Sjeff#include <sys/sockio.h> 92219820Sjeff#endif 93219820Sjeff 94219820Sjeff#if HAVE_SYS_IOCTL_H 95219820Sjeff#include <sys/ioctl.h> 96219820Sjeff#endif 97219820Sjeff 98219820Sjeff#ifdef HAVE_NLIST_H 99219820Sjeff#include <nlist.h> 100219820Sjeff#endif 101219820Sjeff 102219820Sjeff#if HAVE_SYS_FILE_H 103219820Sjeff#include <sys/file.h> 104219820Sjeff#endif 105219820Sjeff 106219820Sjeff#if HAVE_KSTAT_H 107219820Sjeff#include <kstat.h> 108219820Sjeff#endif 109219820Sjeff 110219820Sjeff#if HAVE_SYS_PARAM_H 111219820Sjeff#include <sys/param.h> 112219820Sjeff#endif 113219820Sjeff#if HAVE_SYS_SYSCTL_H 114219820Sjeff#include <sys/sysctl.h> 115219820Sjeff#endif 116219820Sjeff 117219820Sjeff#if HAVE_STRING_H 118219820Sjeff#include <string.h> 119219820Sjeff#else 120219820Sjeff#include <strings.h> 121219820Sjeff#endif 122219820Sjeff 123219820Sjeff#if HAVE_DMALLOC_H 124219820Sjeff#include <dmalloc.h> 125219820Sjeff#endif 126219820Sjeff 127219820Sjeff#ifdef HAVE_SYS_STAT_H 128219820Sjeff#include <sys/stat.h> 129219820Sjeff#endif 130219820Sjeff#if HAVE_FCNTL_H 131219820Sjeff#include <fcntl.h> 132219820Sjeff#endif 133219820Sjeff 134219820Sjeff#if defined(hpux10) || defined(hpux11) 135219820Sjeff#include <sys/pstat.h> 136219820Sjeff#endif 137219820Sjeff 138219820Sjeff#if HAVE_SYS_UTSNAME_H 139219820Sjeff#include <sys/utsname.h> 140219820Sjeff#endif 141219820Sjeff 142219820Sjeff#if HAVE_SYS_SYSTEMCFG_H 143219820Sjeff#include <sys/systemcfg.h> 144219820Sjeff#endif 145219820Sjeff 146219820Sjeff#if HAVE_SYS_SYSTEMINFO_H 147219820Sjeff#include <sys/systeminfo.h> 148219820Sjeff#endif 149219820Sjeff 150219820Sjeff#include <net-snmp/types.h> 151219820Sjeff#include <net-snmp/output_api.h> 152219820Sjeff#include <net-snmp/utilities.h> 153219820Sjeff#include <net-snmp/library/system.h> /* for "internal" definitions */ 154219820Sjeff 155219820Sjeff#include <net-snmp/library/snmp_api.h> 156219820Sjeff#include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */ 157219820Sjeff 158219820Sjeff#ifndef IFF_LOOPBACK 159219820Sjeff# define IFF_LOOPBACK 0 160219820Sjeff#endif 161219820Sjeff 162219820Sjeff#ifdef INADDR_LOOPBACK 163219820Sjeff# define LOOPBACK INADDR_LOOPBACK 164219820Sjeff#else 165219820Sjeff# define LOOPBACK 0x7f000001 166219820Sjeff#endif 167219820Sjeff 168219820Sjeff/** 169219820Sjeff * fork current process into the background. 170219820Sjeff * 171219820Sjeff * This function forks a process into the background, in order to 172219820Sjeff * become a daemon process. It does a few things along the way: 173219820Sjeff * 174219820Sjeff * - becoming a process/session group leader, and forking a second time so 175219820Sjeff * that process/session group leader can exit. 176219820Sjeff * 177219820Sjeff * - changing the working directory to / 178219820Sjeff * 179219820Sjeff * - closing stdin, stdout and stderr (unless stderr_log is set) and 180219820Sjeff * redirecting them to /dev/null 181219820Sjeff * 182219820Sjeff * @param quit_immediately : indicates if the parent process should 183219820Sjeff * exit after a successful fork. 184219820Sjeff * @param stderr_log : indicates if stderr is being used for 185219820Sjeff * logging and shouldn't be closed 186219820Sjeff * @returns -1 : fork error 187219820Sjeff * 0 : child process returning 188219820Sjeff * >0 : parent process returning. returned value is the child PID. 189219820Sjeff */ 190219820Sjeffint 191219820Sjeffnetsnmp_daemonize(int quit_immediately, int stderr_log) 192219820Sjeff{ 193219820Sjeff int i = 0; 194219820Sjeff DEBUGMSGT(("daemonize","deamonizing...\n")); 195219820Sjeff#if HAVE_WORKING_FORK 196219820Sjeff /* 197219820Sjeff * Fork to return control to the invoking process and to 198219820Sjeff * guarantee that we aren't a process group leader. 199219820Sjeff */ 200219820Sjeff i = fork(); 201219820Sjeff if (i != 0) { 202219820Sjeff /* Parent. */ 203219820Sjeff DEBUGMSGT(("daemonize","first fork returned %d.\n", i)); 204219820Sjeff if(i == -1) { 205219820Sjeff snmp_log(LOG_ERR,"first fork failed (errno %d) in " 206219820Sjeff "netsnmp_daemonize()\n", errno); 207219820Sjeff return -1; 208219820Sjeff } 209219820Sjeff if (quit_immediately) { 210219820Sjeff DEBUGMSGT(("daemonize","parent exiting\n")); 211219820Sjeff exit(0); 212219820Sjeff } 213219820Sjeff } else { 214219820Sjeff /* Child. */ 215219820Sjeff#ifdef HAVE_SETSID 216219820Sjeff /* Become a process/session group leader. */ 217219820Sjeff setsid(); 218219820Sjeff#endif 219219820Sjeff /* 220219820Sjeff * Fork to let the process/session group leader exit. 221219820Sjeff */ 222219820Sjeff if ((i = fork()) != 0) { 223219820Sjeff DEBUGMSGT(("daemonize","second fork returned %d.\n", i)); 224219820Sjeff if(i == -1) { 225219820Sjeff snmp_log(LOG_ERR,"second fork failed (errno %d) in " 226219820Sjeff "netsnmp_daemonize()\n", errno); 227219820Sjeff } 228219820Sjeff /* Parent. */ 229219820Sjeff exit(0); 230219820Sjeff } 231219820Sjeff#ifndef WIN32 232219820Sjeff else { 233219820Sjeff /* Child. */ 234219820Sjeff 235219820Sjeff DEBUGMSGT(("daemonize","child continuing\n")); 236219820Sjeff 237219820Sjeff /* Avoid keeping any directory in use. */ 238219820Sjeff chdir("/"); 239219820Sjeff 240219820Sjeff if (!stderr_log) { 241219820Sjeff /* 242219820Sjeff * Close inherited file descriptors to avoid 243219820Sjeff * keeping unnecessary references. 244219820Sjeff */ 245219820Sjeff close(0); 246219820Sjeff close(1); 247219820Sjeff close(2); 248219820Sjeff 249219820Sjeff /* 250219820Sjeff * Redirect std{in,out,err} to /dev/null, just in 251219820Sjeff * case. 252219820Sjeff */ 253219820Sjeff open("/dev/null", O_RDWR); 254219820Sjeff dup(0); 255219820Sjeff dup(0); 256219820Sjeff } 257219820Sjeff } 258219820Sjeff#endif /* !WIN32 */ 259219820Sjeff } 260219820Sjeff#endif /* HAVE_WORKING_FORK */ 261219820Sjeff return i; 262219820Sjeff} 263219820Sjeff 264219820Sjeff#else /* !NEED_NETSNMP_DAEMONIZE */ 265219820Sjeffint netsnp_daemonize_bs; 266219820Sjeff#endif 267219820Sjeff