1 | /* |
---|
2 | * Replacement for a missing daemon. |
---|
3 | * |
---|
4 | * Provides the same functionality as the library function daemon for those |
---|
5 | * systems that don't have it. |
---|
6 | * |
---|
7 | * Written by Russ Allbery <rra@stanford.edu> |
---|
8 | * This work is hereby placed in the public domain by its author. |
---|
9 | */ |
---|
10 | |
---|
11 | #include <config.h> |
---|
12 | #include <portable/system.h> |
---|
13 | |
---|
14 | #include <errno.h> |
---|
15 | #include <fcntl.h> |
---|
16 | #include <sys/ioctl.h> |
---|
17 | #include <sys/stat.h> |
---|
18 | |
---|
19 | /* |
---|
20 | * If we're running the test suite, rename daemon to avoid conflicts with the |
---|
21 | * system version. #undef it first because some systems may define it to |
---|
22 | * another name. |
---|
23 | */ |
---|
24 | #if TESTING |
---|
25 | # undef daemon |
---|
26 | # define daemon test_daemon |
---|
27 | int test_daemon(int, int); |
---|
28 | #endif |
---|
29 | |
---|
30 | int |
---|
31 | daemon(int nochdir, int noclose) |
---|
32 | { |
---|
33 | int status, fd; |
---|
34 | |
---|
35 | /* |
---|
36 | * Fork and exit in the parent to disassociate from the current process |
---|
37 | * group and become the leader of a new process group. |
---|
38 | */ |
---|
39 | status = fork(); |
---|
40 | if (status < 0) |
---|
41 | return -1; |
---|
42 | else if (status > 0) |
---|
43 | _exit(0); |
---|
44 | |
---|
45 | /* |
---|
46 | * setsid() should take care of disassociating from the controlling |
---|
47 | * terminal, and FreeBSD at least doesn't like TIOCNOTTY if you don't |
---|
48 | * already have a controlling terminal. So only use the older TIOCNOTTY |
---|
49 | * method if setsid() isn't available. |
---|
50 | */ |
---|
51 | #if HAVE_SETSID |
---|
52 | if (setsid() < 0) |
---|
53 | return -1; |
---|
54 | #elif defined(TIOCNOTTY) |
---|
55 | fd = open("/dev/tty", O_RDWR); |
---|
56 | if (fd >= 0) { |
---|
57 | if (ioctl(fd, TIOCNOTTY, NULL) < 0) { |
---|
58 | status = errno; |
---|
59 | close(fd); |
---|
60 | errno = status; |
---|
61 | return -1; |
---|
62 | } |
---|
63 | close(fd); |
---|
64 | } |
---|
65 | #endif /* defined(TIOCNOTTY) */ |
---|
66 | |
---|
67 | if (!nochdir && chdir("/") < 0) |
---|
68 | return -1; |
---|
69 | |
---|
70 | if (!noclose) { |
---|
71 | fd = open("/dev/null", O_RDWR, 0); |
---|
72 | if (fd < 0) |
---|
73 | return -1; |
---|
74 | else { |
---|
75 | if (dup2(fd, STDIN_FILENO) < 0) |
---|
76 | return -1; |
---|
77 | if (dup2(fd, STDOUT_FILENO) < 0) |
---|
78 | return -1; |
---|
79 | if (dup2(fd, STDERR_FILENO) < 0) |
---|
80 | return -1; |
---|
81 | if (fd > 2) |
---|
82 | close(fd); |
---|
83 | } |
---|
84 | } |
---|
85 | return 0; |
---|
86 | } |
---|