ossp-pkg/lmtp2nntp/daemon.c
/*
** daemon.c -- daemonize current process
** Copyright (c) 1999-2000 Ralf S. Engelschall, All Rights Reserved.
**
** See "Unix Programming Frequently Asked Questions":
** http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC10
*/
#include "config.h"
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#ifdef HAVE_TERMIOS_H
#include <sys/termios.h>
#endif
#include "daemon.h"
int daemonize(void)
{
int fd;
int rc;
/*
* if we are started from init,
* no need to become daemon.
*/
if (getppid() == 1)
return 0;
/*
* Ignore tty related signals
*/
#ifdef SIGTTOU
signal(SIGTTOU, SIG_IGN);
#endif
#ifdef SIGTTIN
signal(SIGTTIN, SIG_IGN);
#endif
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
#endif
/*
* fork so the parent can exit, this returns control to the command line
* or shell invoking your program. This step is required so that the new
* process is guaranteed not to be a process group leader (The next step,
* setsid, would fail if you're a process group leader).
*/
rc = fork();
switch (rc) {
case -1: return -1;
case 0: break;
default: _exit(0); /* exit original process */
}
/*
* setsid to become a process group and session group leader. Since a
* controlling terminal is associated with a session, and this new session
* has not yet acquired a controlling terminal our process now has no
* controlling terminal, which is a Good Thing for daemons.
*/
#ifdef HAVE_SETSID
if (setsid() == -1)
return -1;
#else
if (setpgid(0, getpid()) == -1)
return -1;
#ifndef _PATH_TTY
#define _PATH_TTY "/dev/tty"
#endif
if ((fd = open(_PATH_TTY, O_RDWR)) == -1)
return -1;
ioctl(fd, TIOCNOTTY, NULL);
close(fd);
#endif
/*
* fork again so the parent, (the session group leader), can exit. This
* means that we, as a non-session group leader, can never regain a
* controlling terminal.
*/
rc = fork();
switch (rc) {
case -1: return -1;
case 0: break;
default: _exit(0); /* exit original process */
}
/*
* chdir("/") to ensure that our process doesn't keep any directory in
* use. Failure to do this could make it so that an administrator couldn't
* unmount a filesystem, because it was our current directory.
* [Equivalently, we could change to any directory containing files
* important to the daemon's operation.]
*/
chdir("/");
/*
* give us complete control over the permissions of anything we write. We
* don't know what umask we may have inherited. [This step is optional]
*/
umask(0);
/*
* close fds 0, 1, and 2. This releases the standard in, out, and error we
* inherited from our parent process. We have no way of knowing where
* these fds might have been redirected to.
*/
if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
if (fd > 2)
close(fd);
}
return 0;
}