1258945Sroberto/*
2258945Sroberto * system.c
3258945Sroberto */
4258945Sroberto/* Portions of this file are subject to the following copyright(s).  See
5258945Sroberto * the Net-SNMP's COPYING file for more details and other copyrights
6258945Sroberto * that may apply:
7258945Sroberto */
8258945Sroberto/***********************************************************
9258945Sroberto        Copyright 1992 by Carnegie Mellon University
10258945Sroberto
11258945Sroberto                      All Rights Reserved
12258945Sroberto
13258945SrobertoPermission to use, copy, modify, and distribute this software and its
14258945Srobertodocumentation for any purpose and without fee is hereby granted,
15258945Srobertoprovided that the above copyright notice appear in all copies and that
16258945Srobertoboth that copyright notice and this permission notice appear in
17258945Srobertosupporting documentation, and that the name of CMU not be
18258945Srobertoused in advertising or publicity pertaining to distribution of the
19258945Srobertosoftware without specific, written prior permission.
20258945Sroberto
21258945SrobertoCMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22258945SrobertoALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23258945SrobertoCMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24258945SrobertoANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25258945SrobertoWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26258945SrobertoARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27258945SrobertoSOFTWARE.
28258945Sroberto******************************************************************/
29258945Sroberto/*
30258945Sroberto * Portions of this file are copyrighted by:
31258945Sroberto * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
32258945Sroberto * Use is subject to license terms specified in the COPYING file
33258945Sroberto * distributed with the Net-SNMP package.
34258945Sroberto */
35258945Sroberto/*
36258945Sroberto * System dependent routines go here
37258945Sroberto */
38258945Sroberto#include <net-snmp/net-snmp-config.h>
39258945Sroberto#undef PACKAGE_BUGREPORT
40258945Sroberto#undef PACKAGE_NAME
41258945Sroberto#undef PACKAGE_STRING
42258945Sroberto#undef PACKAGE_TARNAME
43280849Scy#undef PACKAGE_URL
44258945Sroberto#undef PACKAGE_VERSION
45258945Sroberto#include <config.h>
46258945Sroberto
47258945Sroberto#ifdef NEED_NETSNMP_DAEMONIZE
48258945Sroberto
49258945Sroberto#include <stdio.h>
50258945Sroberto#include <ctype.h>
51258945Sroberto#include <errno.h>
52258945Sroberto
53258945Sroberto#if HAVE_UNISTD_H
54258945Sroberto#include <unistd.h>
55258945Sroberto#endif
56258945Sroberto#if HAVE_STDLIB_H
57258945Sroberto#include <stdlib.h>
58258945Sroberto#endif
59258945Sroberto
60258945Sroberto#if TIME_WITH_SYS_TIME
61258945Sroberto# ifdef WIN32
62258945Sroberto#  include <sys/timeb.h>
63258945Sroberto# else
64258945Sroberto#  include <sys/time.h>
65258945Sroberto# endif
66258945Sroberto# include <time.h>
67258945Sroberto#else
68258945Sroberto# if HAVE_SYS_TIME_H
69258945Sroberto#  include <sys/time.h>
70258945Sroberto# else
71258945Sroberto#  include <time.h>
72258945Sroberto# endif
73258945Sroberto#endif
74258945Sroberto
75258945Sroberto#include <sys/types.h>
76258945Sroberto
77258945Sroberto#if HAVE_NETINET_IN_H
78258945Sroberto#include <netinet/in.h>
79258945Sroberto#endif
80258945Sroberto
81258945Sroberto#if HAVE_WINSOCK_H
82258945Sroberto#include <winsock.h>
83258945Sroberto#endif
84258945Sroberto#if HAVE_SYS_SOCKET_H
85258945Sroberto#include <sys/socket.h>
86258945Sroberto#endif
87258945Sroberto#if HAVE_NET_IF_H
88258945Sroberto#include <net/if.h>
89258945Sroberto#endif
90258945Sroberto
91258945Sroberto#if HAVE_SYS_SOCKIO_H
92258945Sroberto#include <sys/sockio.h>
93258945Sroberto#endif
94258945Sroberto
95258945Sroberto#if HAVE_SYS_IOCTL_H
96258945Sroberto#include <sys/ioctl.h>
97258945Sroberto#endif
98258945Sroberto
99258945Sroberto#ifdef HAVE_NLIST_H
100258945Sroberto#include <nlist.h>
101258945Sroberto#endif
102258945Sroberto
103258945Sroberto#if HAVE_SYS_FILE_H
104258945Sroberto#include <sys/file.h>
105258945Sroberto#endif
106258945Sroberto
107258945Sroberto#if HAVE_KSTAT_H
108258945Sroberto#include <kstat.h>
109258945Sroberto#endif
110258945Sroberto
111258945Sroberto#if HAVE_SYS_PARAM_H
112258945Sroberto#include <sys/param.h>
113258945Sroberto#endif
114258945Sroberto#if HAVE_SYS_SYSCTL_H
115258945Sroberto#include <sys/sysctl.h>
116258945Sroberto#endif
117258945Sroberto
118258945Sroberto#if HAVE_STRING_H
119258945Sroberto#include <string.h>
120258945Sroberto#else
121258945Sroberto#include <strings.h>
122258945Sroberto#endif
123258945Sroberto
124258945Sroberto#if HAVE_DMALLOC_H
125258945Sroberto#include <dmalloc.h>
126258945Sroberto#endif
127258945Sroberto
128258945Sroberto#ifdef HAVE_SYS_STAT_H
129258945Sroberto#include <sys/stat.h>
130258945Sroberto#endif
131258945Sroberto#if HAVE_FCNTL_H
132258945Sroberto#include <fcntl.h>
133258945Sroberto#endif
134258945Sroberto
135258945Sroberto#if defined(hpux10) || defined(hpux11)
136258945Sroberto#include <sys/pstat.h>
137258945Sroberto#endif
138258945Sroberto
139258945Sroberto#if HAVE_SYS_UTSNAME_H
140258945Sroberto#include <sys/utsname.h>
141258945Sroberto#endif
142258945Sroberto
143258945Sroberto#if HAVE_SYS_SYSTEMCFG_H
144258945Sroberto#include <sys/systemcfg.h>
145258945Sroberto#endif
146258945Sroberto
147258945Sroberto#if HAVE_SYS_SYSTEMINFO_H
148258945Sroberto#include <sys/systeminfo.h>
149258945Sroberto#endif
150258945Sroberto
151258945Sroberto#include <net-snmp/types.h>
152258945Sroberto#include <net-snmp/output_api.h>
153258945Sroberto#include <net-snmp/utilities.h>
154258945Sroberto#include <net-snmp/library/system.h>    /* for "internal" definitions */
155258945Sroberto
156258945Sroberto#include <net-snmp/library/snmp_api.h>
157258945Sroberto#include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */
158258945Sroberto
159258945Sroberto#ifndef IFF_LOOPBACK
160258945Sroberto#	define IFF_LOOPBACK 0
161258945Sroberto#endif
162258945Sroberto
163258945Sroberto#ifdef  INADDR_LOOPBACK
164258945Sroberto# define LOOPBACK    INADDR_LOOPBACK
165258945Sroberto#else
166258945Sroberto# define LOOPBACK    0x7f000001
167258945Sroberto#endif
168258945Sroberto
169258945Sroberto/**
170258945Sroberto * fork current process into the background.
171258945Sroberto *
172258945Sroberto * This function forks a process into the background, in order to
173258945Sroberto * become a daemon process. It does a few things along the way:
174258945Sroberto *
175258945Sroberto * - becoming a process/session group leader, and  forking a second time so
176258945Sroberto *   that process/session group leader can exit.
177258945Sroberto *
178258945Sroberto * - changing the working directory to /
179258945Sroberto *
180258945Sroberto * - closing stdin, stdout and stderr (unless stderr_log is set) and
181258945Sroberto *   redirecting them to /dev/null
182258945Sroberto *
183258945Sroberto * @param quit_immediately : indicates if the parent process should
184258945Sroberto *                           exit after a successful fork.
185258945Sroberto * @param stderr_log       : indicates if stderr is being used for
186258945Sroberto *                           logging and shouldn't be closed
187258945Sroberto * @returns -1 : fork error
188258945Sroberto *           0 : child process returning
189258945Sroberto *          >0 : parent process returning. returned value is the child PID.
190258945Sroberto */
191258945Srobertoint
192258945Srobertonetsnmp_daemonize(int quit_immediately, int stderr_log)
193258945Sroberto{
194258945Sroberto    int i = 0;
195280849Scy    int saved_errno;
196280849Scy
197330106Sdelphij    DEBUGMSGT(("daemonize","daemonizing...\n"));
198280849Scy#ifdef HAVE_WORKING_FORK
199258945Sroberto    /*
200258945Sroberto     * Fork to return control to the invoking process and to
201258945Sroberto     * guarantee that we aren't a process group leader.
202258945Sroberto     */
203258945Sroberto    i = fork();
204258945Sroberto    if (i != 0) {
205258945Sroberto        /* Parent. */
206280849Scy	saved_errno = errno;
207258945Sroberto        DEBUGMSGT(("daemonize","first fork returned %d.\n", i));
208258945Sroberto        if(i == -1) {
209258945Sroberto            snmp_log(LOG_ERR,"first fork failed (errno %d) in "
210280849Scy                     "netsnmp_daemonize()\n", saved_errno);
211258945Sroberto            return -1;
212258945Sroberto        }
213258945Sroberto        if (quit_immediately) {
214258945Sroberto            DEBUGMSGT(("daemonize","parent exiting\n"));
215258945Sroberto            exit(0);
216258945Sroberto        }
217258945Sroberto    } else {
218258945Sroberto        /* Child. */
219258945Sroberto#ifdef HAVE_SETSID
220258945Sroberto        /* Become a process/session group leader. */
221258945Sroberto        setsid();
222258945Sroberto#endif
223258945Sroberto        /*
224258945Sroberto         * Fork to let the process/session group leader exit.
225258945Sroberto         */
226258945Sroberto        if ((i = fork()) != 0) {
227280849Scy	    saved_errno = errno;
228258945Sroberto            DEBUGMSGT(("daemonize","second fork returned %d.\n", i));
229258945Sroberto            if(i == -1) {
230258945Sroberto                snmp_log(LOG_ERR,"second fork failed (errno %d) in "
231280849Scy                         "netsnmp_daemonize()\n", saved_errno);
232258945Sroberto            }
233258945Sroberto            /* Parent. */
234258945Sroberto            exit(0);
235258945Sroberto        }
236258945Sroberto#ifndef WIN32
237258945Sroberto        else {
238258945Sroberto            /* Child. */
239258945Sroberto
240258945Sroberto            DEBUGMSGT(("daemonize","child continuing\n"));
241258945Sroberto
242258945Sroberto            /* Avoid keeping any directory in use. */
243258945Sroberto            chdir("/");
244258945Sroberto
245258945Sroberto            if (!stderr_log) {
246258945Sroberto                /*
247258945Sroberto                 * Close inherited file descriptors to avoid
248258945Sroberto                 * keeping unnecessary references.
249258945Sroberto                 */
250258945Sroberto                close(0);
251258945Sroberto                close(1);
252258945Sroberto                close(2);
253258945Sroberto
254258945Sroberto                /*
255258945Sroberto                 * Redirect std{in,out,err} to /dev/null, just in
256258945Sroberto                 * case.
257258945Sroberto                 */
258258945Sroberto                open("/dev/null", O_RDWR);
259258945Sroberto                dup(0);
260258945Sroberto                dup(0);
261258945Sroberto            }
262258945Sroberto        }
263258945Sroberto#endif /* !WIN32 */
264258945Sroberto    }
265258945Sroberto#endif /* HAVE_WORKING_FORK */
266258945Sroberto    return i;
267258945Sroberto}
268258945Sroberto
269258945Sroberto#else /* !NEED_NETSNMP_DAEMONIZE */
270258945Srobertoint netsnp_daemonize_bs;
271258945Sroberto#endif
272