netsnmp_daemonize.c revision 290001
1/*
2 * system.c
3 */
4/* Portions of this file are subject to the following copyright(s).  See
5 * the Net-SNMP's COPYING file for more details and other copyrights
6 * that may apply:
7 */
8/***********************************************************
9        Copyright 1992 by Carnegie Mellon University
10
11                      All Rights Reserved
12
13Permission to use, copy, modify, and distribute this software and its
14documentation for any purpose and without fee is hereby granted,
15provided that the above copyright notice appear in all copies and that
16both that copyright notice and this permission notice appear in
17supporting documentation, and that the name of CMU not be
18used in advertising or publicity pertaining to distribution of the
19software without specific, written prior permission.
20
21CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27SOFTWARE.
28******************************************************************/
29/*
30 * Portions of this file are copyrighted by:
31 * Copyright � 2003 Sun Microsystems, Inc. All rights reserved.
32 * Use is subject to license terms specified in the COPYING file
33 * distributed with the Net-SNMP package.
34 */
35/*
36 * System dependent routines go here
37 */
38#include <net-snmp/net-snmp-config.h>
39#undef PACKAGE_BUGREPORT
40#undef PACKAGE_NAME
41#undef PACKAGE_STRING
42#undef PACKAGE_TARNAME
43#undef PACKAGE_URL
44#undef PACKAGE_VERSION
45#include <config.h>
46
47#ifdef NEED_NETSNMP_DAEMONIZE
48
49#include <stdio.h>
50#include <ctype.h>
51#include <errno.h>
52
53#if HAVE_UNISTD_H
54#include <unistd.h>
55#endif
56#if HAVE_STDLIB_H
57#include <stdlib.h>
58#endif
59
60#if TIME_WITH_SYS_TIME
61# ifdef WIN32
62#  include <sys/timeb.h>
63# else
64#  include <sys/time.h>
65# endif
66# include <time.h>
67#else
68# if HAVE_SYS_TIME_H
69#  include <sys/time.h>
70# else
71#  include <time.h>
72# endif
73#endif
74
75#include <sys/types.h>
76
77#if HAVE_NETINET_IN_H
78#include <netinet/in.h>
79#endif
80
81#if HAVE_WINSOCK_H
82#include <winsock.h>
83#endif
84#if HAVE_SYS_SOCKET_H
85#include <sys/socket.h>
86#endif
87#if HAVE_NET_IF_H
88#include <net/if.h>
89#endif
90
91#if HAVE_SYS_SOCKIO_H
92#include <sys/sockio.h>
93#endif
94
95#if HAVE_SYS_IOCTL_H
96#include <sys/ioctl.h>
97#endif
98
99#ifdef HAVE_NLIST_H
100#include <nlist.h>
101#endif
102
103#if HAVE_SYS_FILE_H
104#include <sys/file.h>
105#endif
106
107#if HAVE_KSTAT_H
108#include <kstat.h>
109#endif
110
111#if HAVE_SYS_PARAM_H
112#include <sys/param.h>
113#endif
114#if HAVE_SYS_SYSCTL_H
115#include <sys/sysctl.h>
116#endif
117
118#if HAVE_STRING_H
119#include <string.h>
120#else
121#include <strings.h>
122#endif
123
124#if HAVE_DMALLOC_H
125#include <dmalloc.h>
126#endif
127
128#ifdef HAVE_SYS_STAT_H
129#include <sys/stat.h>
130#endif
131#if HAVE_FCNTL_H
132#include <fcntl.h>
133#endif
134
135#if defined(hpux10) || defined(hpux11)
136#include <sys/pstat.h>
137#endif
138
139#if HAVE_SYS_UTSNAME_H
140#include <sys/utsname.h>
141#endif
142
143#if HAVE_SYS_SYSTEMCFG_H
144#include <sys/systemcfg.h>
145#endif
146
147#if HAVE_SYS_SYSTEMINFO_H
148#include <sys/systeminfo.h>
149#endif
150
151#include <net-snmp/types.h>
152#include <net-snmp/output_api.h>
153#include <net-snmp/utilities.h>
154#include <net-snmp/library/system.h>    /* for "internal" definitions */
155
156#include <net-snmp/library/snmp_api.h>
157#include <net-snmp/library/read_config.h> /* for get_temp_file_pattern() */
158
159#ifndef IFF_LOOPBACK
160#	define IFF_LOOPBACK 0
161#endif
162
163#ifdef  INADDR_LOOPBACK
164# define LOOPBACK    INADDR_LOOPBACK
165#else
166# define LOOPBACK    0x7f000001
167#endif
168
169/**
170 * fork current process into the background.
171 *
172 * This function forks a process into the background, in order to
173 * become a daemon process. It does a few things along the way:
174 *
175 * - becoming a process/session group leader, and  forking a second time so
176 *   that process/session group leader can exit.
177 *
178 * - changing the working directory to /
179 *
180 * - closing stdin, stdout and stderr (unless stderr_log is set) and
181 *   redirecting them to /dev/null
182 *
183 * @param quit_immediately : indicates if the parent process should
184 *                           exit after a successful fork.
185 * @param stderr_log       : indicates if stderr is being used for
186 *                           logging and shouldn't be closed
187 * @returns -1 : fork error
188 *           0 : child process returning
189 *          >0 : parent process returning. returned value is the child PID.
190 */
191int
192netsnmp_daemonize(int quit_immediately, int stderr_log)
193{
194    int i = 0;
195    int saved_errno;
196
197    DEBUGMSGT(("daemonize","deamonizing...\n"));
198#ifdef HAVE_WORKING_FORK
199    /*
200     * Fork to return control to the invoking process and to
201     * guarantee that we aren't a process group leader.
202     */
203    i = fork();
204    if (i != 0) {
205        /* Parent. */
206	saved_errno = errno;
207        DEBUGMSGT(("daemonize","first fork returned %d.\n", i));
208        if(i == -1) {
209            snmp_log(LOG_ERR,"first fork failed (errno %d) in "
210                     "netsnmp_daemonize()\n", saved_errno);
211            return -1;
212        }
213        if (quit_immediately) {
214            DEBUGMSGT(("daemonize","parent exiting\n"));
215            exit(0);
216        }
217    } else {
218        /* Child. */
219#ifdef HAVE_SETSID
220        /* Become a process/session group leader. */
221        setsid();
222#endif
223        /*
224         * Fork to let the process/session group leader exit.
225         */
226        if ((i = fork()) != 0) {
227	    saved_errno = errno;
228            DEBUGMSGT(("daemonize","second fork returned %d.\n", i));
229            if(i == -1) {
230                snmp_log(LOG_ERR,"second fork failed (errno %d) in "
231                         "netsnmp_daemonize()\n", saved_errno);
232            }
233            /* Parent. */
234            exit(0);
235        }
236#ifndef WIN32
237        else {
238            /* Child. */
239
240            DEBUGMSGT(("daemonize","child continuing\n"));
241
242            /* Avoid keeping any directory in use. */
243            chdir("/");
244
245            if (!stderr_log) {
246                /*
247                 * Close inherited file descriptors to avoid
248                 * keeping unnecessary references.
249                 */
250                close(0);
251                close(1);
252                close(2);
253
254                /*
255                 * Redirect std{in,out,err} to /dev/null, just in
256                 * case.
257                 */
258                open("/dev/null", O_RDWR);
259                dup(0);
260                dup(0);
261            }
262        }
263#endif /* !WIN32 */
264    }
265#endif /* HAVE_WORKING_FORK */
266    return i;
267}
268
269#else /* !NEED_NETSNMP_DAEMONIZE */
270int netsnp_daemonize_bs;
271#endif
272