Fix typo
[rfmod.git] / daemon.c
blobba1d13577caabfbc0d38d8a7e63a12b6e25db546
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <fcntl.h>
8 #include <syslog.h>
9 #include <errno.h>
10 #include <pwd.h>
11 #include <signal.h>
13 #define EXIT_SUCCESS 0
14 #define EXIT_FAILURE 1
17 static void child_handler(int signum)
19 switch (signum) {
20 case SIGALRM:
21 exit(EXIT_FAILURE);
22 break;
23 case SIGUSR1:
24 exit(EXIT_SUCCESS);
25 break;
26 case SIGCHLD:
27 exit(EXIT_FAILURE);
28 break;
32 void daemonize(const char *lockfile, const char *username)
34 pid_t pid, sid, parent;
35 int lfp = -1;
37 /* already a daemon */
38 if (getppid() == 1) {
39 return;
42 /* Create the lock file as the current user */
43 if (lockfile && lockfile[0]) {
44 lfp = open(lockfile, O_RDWR|O_CREAT, 0640);
45 if (lfp < 0) {
46 syslog(LOG_ERR, "unable to create lock file %s, code=%d (%s)",
47 lockfile, errno, strerror(errno));
48 exit(EXIT_FAILURE);
52 /* Drop user if there is one, and we were run as root */
53 if (username != NULL && (getuid() == 0 || geteuid() == 0)) {
54 struct passwd *pw = getpwnam(username);
55 if (pw) {
56 syslog(LOG_NOTICE, "setting user to %s", username);
57 setuid(pw->pw_uid);
61 /* Trap signals that we expect to recieve */
62 signal(SIGCHLD, child_handler);
63 signal(SIGUSR1, child_handler);
64 signal(SIGALRM, child_handler);
66 /* Fork off the parent process */
67 pid = fork();
68 if (pid < 0) {
69 syslog(LOG_ERR, "unable to fork daemon, code=%d (%s)",
70 errno, strerror(errno));
71 exit(EXIT_FAILURE);
73 /* If we got a good PID, then we can exit the parent process. */
74 if (pid > 0) {
76 /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
77 for two seconds to elapse (SIGALRM). pause() should not return. */
78 alarm(2);
79 pause();
81 exit(EXIT_FAILURE);
84 /* At this point we are executing as the child process */
85 parent = getppid();
87 /* Cancel certain signals */
88 signal(SIGCHLD, SIG_DFL); /* A child process dies */
89 signal(SIGTSTP, SIG_IGN); /* Various TTY signals */
90 signal(SIGTTOU, SIG_IGN);
91 signal(SIGTTIN, SIG_IGN);
92 signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */
93 signal(SIGTERM, SIG_DFL); /* Die on SIGTERM */
95 /* Change the file mode mask */
96 umask(0);
98 /* Create a new SID for the child process */
99 sid = setsid();
100 if (sid < 0) {
101 syslog(LOG_ERR, "unable to create a new session, code %d (%s)",
102 errno, strerror(errno));
103 exit(EXIT_FAILURE);
106 /* Change the current working directory. This prevents the current
107 directory from being locked; hence not being able to remove it. */
108 if ((chdir("/")) < 0) {
109 syslog(LOG_ERR, "unable to change directory to %s, code %d (%s)",
110 "/", errno, strerror(errno));
111 exit(EXIT_FAILURE);
114 /* Redirect standard files to /dev/null */
115 freopen("/dev/null", "r", stdin);
116 freopen("/dev/null", "w", stdout);
117 freopen("/dev/null", "w", stderr);
119 /* Tell the parent process that we are A-okay */
120 kill(parent, SIGUSR1);