Get vfork_daemon_rexec working under uclinux
[platform/upstream/busybox.git] / libbb / vfork_daemon_rexec.c
1 /*
2  * Rexec program for system have fork() as vfork() with foregound option
3  *
4  * Copyright (C) Vladimir N. Oleynik <dzo@simtreas.ru>
5  * Copyright (C) 2003 Russ Dill <Russ.Dill@asu.edu>
6  *
7  * daemon() portion taken from uclibc:
8  *
9  * Copyright (c) 1991, 1993
10  *      The Regents of the University of California.  All rights reserved.
11  *
12  * Modified for uClibc by Erik Andersen <andersee@debian.org>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27  */
28
29 #include <unistd.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32 #include <paths.h>
33 #include "libbb.h"
34
35
36 #if defined(__uClinux__)
37 void vfork_daemon_rexec(int nochdir, int noclose,
38                 int argc, char **argv, char *foreground_opt)
39 {
40         int fd;
41         char **vfork_args;
42         int a = 0;
43         
44         setsid();
45         
46         if (!nochdir)
47                 chdir("/");
48
49         if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
50                 dup2(fd, STDIN_FILENO);
51                 dup2(fd, STDOUT_FILENO);
52                 dup2(fd, STDERR_FILENO);
53                 if (fd > 2)
54                         close(fd);
55         }
56
57         vfork_args = xcalloc(sizeof(char *), argc + 3);
58         vfork_args[a++] = "/bin/busybox";
59         while(*argv) {
60             vfork_args[a++] = *argv;
61             argv++;
62         }
63         vfork_args[a] = foreground_opt;
64         switch (vfork()) {
65         case 0: /* child */
66                 /* Make certain we are not a session leader, or else we
67                  * might reacquire a controlling terminal */
68                 if (vfork())
69                         _exit(0);
70                 execv(vfork_args[0], vfork_args);
71                 bb_perror_msg_and_die("execv %s", vfork_args[0]);
72         case -1: /* error */
73                 bb_perror_msg_and_die("vfork");
74         default: /* parent */
75                 exit(0);
76         }       
77 }
78 #endif /* uClinux */