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