aboutsummaryrefslogtreecommitdiff
path: root/libbb/vfork_daemon_rexec.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-03-26 13:20:04 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-03-26 13:20:04 +0000
commitbb7fcb4229fd5ff583039f26ca1c06340e3f09ea (patch)
tree5e4a6cc92e42ff7694ffc8b6a91434640e953726 /libbb/vfork_daemon_rexec.c
parentf62c6fa1cae0f944243c57b0a776c29eb0c61f18 (diff)
downloadbusybox-w32-bb7fcb4229fd5ff583039f26ca1c06340e3f09ea.tar.gz
busybox-w32-bb7fcb4229fd5ff583039f26ca1c06340e3f09ea.tar.bz2
busybox-w32-bb7fcb4229fd5ff583039f26ca1c06340e3f09ea.zip
libbb: rework NOMMU helper API so that it makes more sense
and easier to use. Doesn't compile - need two more commits.
Diffstat (limited to 'libbb/vfork_daemon_rexec.c')
-rw-r--r--libbb/vfork_daemon_rexec.c134
1 files changed, 133 insertions, 1 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 3185f2d39..c59b0b6fd 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -18,11 +18,68 @@
18#include <paths.h> 18#include <paths.h>
19#include "libbb.h" 19#include "libbb.h"
20 20
21#ifdef BB_NOMMU 21/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */
23pid_t spawn(char **argv)
24{
25 /* Compiler should not optimize stores here */
26 volatile int failed;
27 pid_t pid;
28
29 // Be nice to nommu machines.
30 failed = 0;
31 pid = vfork();
32 if (pid < 0) /* error */
33 return pid;
34 if (!pid) { /* child */
35 /* Don't use BB_EXECVP tricks here! */
36 execvp(argv[0], argv);
37
38 /* We are (maybe) sharing a stack with blocked parent,
39 * let parent know we failed and then exit to unblock parent
40 * (but don't run atexit() stuff, which would screw up parent.)
41 */
42 failed = errno;
43 _exit(0);
44 }
45 /* parent */
46 /* Unfortunately, this is not reliable: vfork()
47 * can be equivalent to fork() according to standards */
48 if (failed) {
49 errno = failed;
50 return -1;
51 }
52 return pid;
53}
54
55/* Die with an error message if we can't spawn a child process. */
56pid_t xspawn(char **argv)
57{
58 pid_t pid = spawn(argv);
59 if (pid < 0) bb_perror_msg_and_die("%s", *argv);
60 return pid;
61}
62
63
64
65#if 0 //ndef BB_NOMMU
66// Die with an error message if we can't daemonize.
67void xdaemon(int nochdir, int noclose)
68{
69 if (daemon(nochdir, noclose))
70 bb_perror_msg_and_die("daemon");
71}
72#endif
73
74#if 0 // def BB_NOMMU
22void vfork_daemon_rexec(int nochdir, int noclose, char **argv) 75void vfork_daemon_rexec(int nochdir, int noclose, char **argv)
23{ 76{
24 int fd; 77 int fd;
25 78
79 /* Maybe we are already re-execed and come here again? */
80 if (re_execed)
81 return;
82
26 setsid(); 83 setsid();
27 84
28 if (!nochdir) 85 if (!nochdir)
@@ -56,3 +113,78 @@ void vfork_daemon_rexec(int nochdir, int noclose, char **argv)
56 } 113 }
57} 114}
58#endif /* BB_NOMMU */ 115#endif /* BB_NOMMU */
116
117#ifdef BB_NOMMU
118static void daemon_or_rexec(char **argv)
119{
120 pid_t pid;
121 /* Maybe we are already re-execed and come here again? */
122 if (re_execed)
123 return;
124
125 pid = vfork();
126 if (pid < 0) /* wtf? */
127 bb_perror_msg_and_die("vfork");
128 if (pid) /* parent */
129 exit(0);
130 /* child - re-exec ourself */
131 /* high-order bit of first char in argv[0] is a hidden
132 * "we have (alrealy) re-execed, don't do it again" flag */
133 argv[0][0] |= 0x80;
134 execv(CONFIG_BUSYBOX_EXEC_PATH, argv);
135 bb_perror_msg_and_die("exec %s", CONFIG_BUSYBOX_EXEC_PATH);
136}
137#else
138static void daemon_or_rexec(void)
139{
140 pid_t pid;
141 pid = fork();
142 if (pid < 0) /* wtf? */
143 bb_perror_msg_and_die("fork");
144 if (pid) /* parent */
145 exit(0);
146 /* child */
147}
148#define daemon_or_rexec(argv) daemon_or_rexec()
149#endif
150
151
152/* Due to a #define in libbb.h on MMU systems we actually have 1 argument -
153 * char **argv "vanishes" */
154void bb_daemonize_or_rexec(int flags, char **argv)
155{
156 int fd;
157
158 fd = xopen(bb_dev_null, O_RDWR);
159
160 if (flags & DAEMON_CHDIR_ROOT)
161 xchdir("/");
162
163 if (flags & DAEMON_DEVNULL_STDIO) {
164 close(0);
165 close(1);
166 close(2);
167 }
168
169 while ((unsigned)fd < 2)
170 fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
171
172 if (!(flags & DAEMON_ONLY_SANITIZE)) {
173 daemon_or_rexec(argv);
174 /* if daemonizing, make sure we detach from stdio */
175 setsid();
176 dup2(fd, 0);
177 dup2(fd, 1);
178 dup2(fd, 2);
179 }
180 if (fd > 2)
181 close(fd--);
182 if (flags & DAEMON_CLOSE_EXTRA_FDS)
183 while (fd > 2)
184 close(fd--); /* close everything after fd#2 */
185}
186
187void bb_sanitize_stdio(void)
188{
189 bb_daemonize_or_rexec(DAEMON_ONLY_SANITIZE, NULL);
190}