diff options
Diffstat (limited to 'src/util-daemon.c')
-rw-r--r-- | src/util-daemon.c | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/src/util-daemon.c b/src/util-daemon.c new file mode 100644 index 0000000..9092189 --- /dev/null +++ b/src/util-daemon.c @@ -0,0 +1,193 @@ +/* Copyright (C) 2007-2010 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Gerardo Iglesias Galvan <iglesiasg@gmail.com> + * + * Daemonization process + */ + +#include "suricata.h" +#include "suricata-common.h" +#include "runmodes.h" +#include "util-daemon.h" +#include "util-debug.h" +#include "conf.h" + +#ifndef OS_WIN32 + +#include <sys/wait.h> +#include <sys/stat.h> +#include <fcntl.h> + +static volatile sig_atomic_t sigflag = 0; + +/** + * \brief Signal handler used to take the parent process out of stand-by + */ +static void SignalHandlerSigusr1 (int signo) +{ + sigflag = 1; +} + +/** + * \brief Tell the parent process the child is ready + * + * \param pid pid of the parent process to signal + */ +static void TellWaitingParent (pid_t pid) +{ + kill(pid, SIGUSR1); +} + +/** + * \brief Set the parent on stand-by until the child is ready + * + * \param pid pid of the child process to wait + */ +static void WaitForChild (pid_t pid) +{ + int status; + SCLogDebug("Daemon: Parent waiting for child to be ready..."); + /* Wait until child signals is ready */ + while (sigflag == 0) { + if (waitpid(pid, &status, WNOHANG)) { + /* Check if the child is still there, otherwise the parent should exit */ + if (WIFEXITED(status) || WIFSIGNALED(status)) { + FatalError("Child died unexpectedly"); + } + } + /* sigsuspend(); */ + sleep(1); + } +} + +/** + * \brief Close stdin, stdout, stderr.Redirect logging info to syslog + * + */ +static void SetupLogging (void) +{ + /* Redirect stdin, stdout, stderr to /dev/null */ + int fd = open("/dev/null", O_RDWR); + if (fd < 0) + return; + (void)dup2(fd, 0); + (void)dup2(fd, 1); + (void)dup2(fd, 2); + close(fd); +} + +/** + * \brief Daemonize the process + * + */ +void Daemonize (void) +{ + pid_t pid, sid; + + /* Register the signal handler */ + signal(SIGUSR1, SignalHandlerSigusr1); + + /** \todo We should check if we allow more than 1 instance + to run simultaneously. Maybe change the behaviour + through conf file */ + + /* Creates a new process */ +#if defined(OS_DARWIN) && defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + pid = fork(); +#if defined(OS_DARWIN) && defined(__clang__) +#pragma clang diagnostic pop +#endif + + if (pid < 0) { + /* Fork error */ + FatalError("Error forking the process"); + } else if (pid == 0) { + /* Child continues here */ + const char *daemondir; + + sid = setsid(); + if (sid < 0) { + FatalError("Error creating new session"); + } + + if (ConfGet("daemon-directory", &daemondir) == 1) { + if ((chdir(daemondir)) < 0) { + FatalError("Error changing to working directory"); + } + } +#ifndef OS_WIN32 + else { + if (chdir("/") < 0) { + SCLogError("Error changing to working directory '/'"); + } + } +#endif + + SetupLogging(); + + /* Child is ready, tell its parent */ + TellWaitingParent(getppid()); + + /* Daemon is up and running */ + SCLogDebug("Daemon is running"); + return; + } + /* Parent continues here, waiting for child to be ready */ + SCLogDebug("Parent is waiting for child to be ready"); + WaitForChild(pid); + + /* Parent exits */ + SCLogDebug("Child is ready, parent exiting"); + exit(EXIT_SUCCESS); + +} + +#endif /* ifndef OS_WIN32 */ + +/** + * \brief Check for a valid combination daemon/mode + * + * \param daemon daemon on or off + * \param mode selected mode + * + * \retval 1 valid combination + * \retval 0 invalid combination + */ +int CheckValidDaemonModes (int daemon, int mode) +{ + if (daemon) { + switch (mode) { + case RUNMODE_PCAP_FILE: + SCLogError("ERROR: pcap offline mode cannot run as daemon"); + return 0; + case RUNMODE_UNITTEST: + SCLogError("ERROR: unittests cannot run as daemon"); + return 0; + default: + SCLogDebug("Allowed mode"); + break; + } + } + return 1; +} |