617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan/*******************************************************************************
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * Redistribution and use in source and binary forms, with or without
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * modification, are permitted provided that the following conditions are met:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * - Redistributions of source code must retain the above copyright notice,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * this list of conditions and the following disclaimer.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * - Redistributions in binary form must reproduce the above copyright notice,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * this list of conditions and the following disclaimer in the documentation
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * and/or other materials provided with the distribution.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * - Neither the name of Intel Corp. nor the names of its
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * contributors may be used to endorse or promote products derived from this
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * software without specific prior written permission.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan * POSSIBILITY OF SUCH DAMAGE.
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan *******************************************************************************/
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#ifdef HAVE_CONFIG_H
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "config.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#endif
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#ifdef DAEMON
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <cstdio>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <cstdlib>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <cstring>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <cerrno>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <csignal>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <unistd.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/types.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <sys/stat.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <fcntl.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <syslog.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include <pwd.h>
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#include "daemonize.h"
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganstatic RETSIGTYPE child_handler(int signum)
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan switch (signum) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case SIGALRM:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case SIGUSR1:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_SUCCESS);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan case SIGCHLD:
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan break;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Loganvoid daemonize()
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan{
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan pid_t pid, sid, parent;
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Drop user if there is one, and we were run as root */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (getuid() == 0 || geteuid() == 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan struct passwd *pw = getpwnam(RUN_AS_USER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (pw) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan //syslog(LOG_NOTICE, "setting user to " RUN_AS_USER);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan setuid(pw->pw_uid);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Trap signals that we expect to recieve */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGCHLD, child_handler);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGUSR1, child_handler);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGALRM, child_handler);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Fork off the parent process */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan pid = fork();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (pid < 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan syslog(LOG_ERR, "unable to fork daemon, code=%d (%s)",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan errno, strerror(errno));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* If we got a good PID, then we can exit the parent process. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (pid > 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan for two seconds to elapse (SIGALRM). pause() should not return. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan alarm(2);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan pause();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* At this point we are executing as the child process */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan parent = getppid();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGCHLD, SIG_DFL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGUSR1, SIG_DFL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan signal(SIGALRM, SIG_DFL);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan setTerminationHandler();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Create a new SID for the child process */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan sid = setsid();
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if (sid < 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan syslog(LOG_ERR,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "unable to create a new session, code %d (%s)",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan errno, strerror(errno));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Change the current working directory. This prevents the current
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan directory from being locked; hence not being able to remove it. */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan if ((chdir("/")) < 0) {
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan syslog(LOG_ERR,
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "unable to change directory to %s, code %d (%s)",
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan "/", errno, strerror(errno));
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan exit(EXIT_FAILURE);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan }
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Redirect standard files to /dev/null */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan freopen("/dev/null", "r", stdin);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan freopen("/dev/null", "w", stdout);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan freopen("/dev/null", "w", stderr);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan /* Tell the parent process that we are A-okay */
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan kill(parent, SIGUSR1);
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan}
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan#endif //DAEMON
617e2443dfc17fe44fd44c0675d6aad2ffc9df42Mark Logan