suricata
util-daemon.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Gerardo Iglesias Galvan <iglesiasg@gmail.com>
22  *
23  * Daemonization process
24  */
25 
26 #include "suricata.h"
27 #include "suricata-common.h"
28 #include "runmodes.h"
29 #include "util-daemon.h"
30 #include "util-debug.h"
31 #include "conf.h"
32 
33 #ifndef OS_WIN32
34 
35 #include <sys/wait.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 
39 static volatile sig_atomic_t sigflag = 0;
40 
41 /**
42  * \brief Signal handler used to take the parent process out of stand-by
43  */
44 static void SignalHandlerSigusr1 (int signo)
45 {
46  sigflag = 1;
47 }
48 
49 /**
50  * \brief Tell the parent process the child is ready
51  *
52  * \param pid pid of the parent process to signal
53  */
54 static void TellWaitingParent (pid_t pid)
55 {
56  kill(pid, SIGUSR1);
57 }
58 
59 /**
60  * \brief Set the parent on stand-by until the child is ready
61  *
62  * \param pid pid of the child process to wait
63  */
64 static void WaitForChild (pid_t pid)
65 {
66  int status;
67  SCLogDebug("Daemon: Parent waiting for child to be ready...");
68  /* Wait until child signals is ready */
69  while (sigflag == 0) {
70  if (waitpid(pid, &status, WNOHANG)) {
71  /* Check if the child is still there, otherwise the parent should exit */
72  if (WIFEXITED(status) || WIFSIGNALED(status)) {
73  SCLogError(SC_ERR_DAEMON, "Child died unexpectedly");
74  exit(EXIT_FAILURE);
75  }
76  }
77  /* sigsuspend(); */
78  sleep(1);
79  }
80 }
81 
82 /**
83  * \brief Close stdin, stdout, stderr.Redirect logging info to syslog
84  *
85  */
86 static void SetupLogging (void)
87 {
88  /* Redirect stdin, stdout, stderr to /dev/null */
89  int fd = open("/dev/null", O_RDWR);
90  if (fd < 0)
91  return;
92  (void)dup2(fd, 0);
93  (void)dup2(fd, 1);
94  (void)dup2(fd, 2);
95  close(fd);
96 }
97 
98 /**
99  * \brief Daemonize the process
100  *
101  */
102 void Daemonize (void)
103 {
104  pid_t pid, sid;
105 
106  /* Register the signal handler */
107  signal(SIGUSR1, SignalHandlerSigusr1);
108 
109  /** \todo We should check if wie allow more than 1 instance
110  to run simultaneously. Maybe change the behaviour
111  through conf file */
112 
113  /* Creates a new process */
114  pid = fork();
115 
116  if (pid < 0) {
117  /* Fork error */
118  SCLogError(SC_ERR_DAEMON, "Error forking the process");
119  exit(EXIT_FAILURE);
120  } else if (pid == 0) {
121  /* Child continues here */
122  const char *daemondir;
123 
124  sid = setsid();
125  if (sid < 0) {
126  SCLogError(SC_ERR_DAEMON, "Error creating new session");
127  exit(EXIT_FAILURE);
128  }
129 
130  if (ConfGet("daemon-directory", &daemondir) == 1) {
131  if ((chdir(daemondir)) < 0) {
132  SCLogError(SC_ERR_DAEMON, "Error changing to working directory");
133  exit(EXIT_FAILURE);
134  }
135  }
136 #ifndef OS_WIN32
137  else {
138  if (chdir("/") < 0) {
139  SCLogError(SC_ERR_DAEMON, "Error changing to working directory '/'");
140  }
141  }
142 #endif
143 
144  SetupLogging();
145 
146  /* Child is ready, tell its parent */
147  TellWaitingParent(getppid());
148 
149  /* Daemon is up and running */
150  SCLogDebug("Daemon is running");
151  return;
152  }
153  /* Parent continues here, waiting for child to be ready */
154  SCLogDebug("Parent is waiting for child to be ready");
155  WaitForChild(pid);
156 
157  /* Parent exits */
158  SCLogDebug("Child is ready, parent exiting");
159  exit(EXIT_SUCCESS);
160 
161 }
162 
163 #endif /* ifndef OS_WIN32 */
164 
165 /**
166  * \brief Check for a valid combination daemon/mode
167  *
168  * \param daemon daemon on or off
169  * \param mode selected mode
170  *
171  * \retval 1 valid combination
172  * \retval 0 invalid combination
173  */
174 int CheckValidDaemonModes (int daemon, int mode)
175 {
176  if (daemon) {
177  switch (mode) {
178  case RUNMODE_PCAP_FILE:
179  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: pcap offline mode cannot run as daemon");
180  return 0;
181  case RUNMODE_UNITTEST:
182  SCLogError(SC_ERR_INVALID_RUNMODE, "ERROR: unittests cannot run as daemon");
183  return 0;
184  default:
185  SCLogDebug("Allowed mode");
186  break;
187  }
188  }
189  return 1;
190 }
#define SCLogDebug(...)
Definition: util-debug.h:335
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
int CheckValidDaemonModes(int daemon, int mode)
Check for a valid combination daemon/mode.
Definition: util-daemon.c:174
void Daemonize(void)
Daemonize the process.
Definition: util-daemon.c:102