-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathdaemonize.c
105 lines (92 loc) · 2.15 KB
/
daemonize.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/resource.h>
/*
* ref:
* http://0pointer.de/public/systemd-man/daemon.html
*/
int
daemonize(int nochdir, int noclose)
{
int sig;
pid_t pid;
sigset_t set;
struct rlimit limit;
if (!noclose) {
/*
* Close all open file descriptors except STDIN, STDOUT, STDERR
* (i.e. the first three file descriptors 0, 1, 2).
* This ensures that no accidentally passed file descriptor stays around
* in the daemon process.
*/
if (getrlimit(RLIMIT_NOFILE, &limit) == -1) {
return -1;
}
for(; limit.rlim_cur > 3; limit.rlim_cur--) {
close(limit.rlim_cur - 1);
}
}
/* Reset all signal handlers to their default. */
for (sig = 1; sig <= NSIG; sig++) {
signal(sig, SIG_DFL);
}
/* Reset the signal mask using sigprocmask(). */
sigemptyset(&set);
sigprocmask(SIG_SETMASK, &set, NULL);
/* Call fork(), to create a background process. */
pid = fork();
if (pid == -1) {
return -1;
} else if (pid != 0) {
_exit(0);
}
/* Call setsid() to detach from any terminal and create an independent session. */
if (setsid() == -1) {
return -1;
}
/* Call fork() again, to ensure that the daemon can never re-acquire a terminal again. */
signal(SIGHUP, SIG_IGN);
pid = fork();
if (pid == -1) {
return -1;
} else if (pid != 0) {
_exit(0);
}
/* connect /dev/null to STDIN, STDOUT, STDERR. */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
if (open("/dev/null", O_RDONLY) == -1) {
return -1;
}
if (open("/dev/null", O_WRONLY) == -1) {
return -1;
}
if (open("/dev/null", O_RDWR) == -1) {
return -1;
}
/*
* reset the umask to 0, so that the file modes passed to
* open(), mkdir() and suchlike directly control the access mode
* of the created files and directories.
*/
umask(0);
if (!nochdir) {
/*
* change the current directory to the root directory (/),
* in order to avoid that the daemon involuntarily blocks
* mount points from being unmounted.
*/
if (chdir("/") == -1) {
return -1;
}
}
return 0;
}