blob: 05c9c0dabf7d8c41315987f975fbc561631faaad [file] [log] [blame]
Bernhard Reutner-Fischer0a8812b2006-05-19 13:12:21 +00001/* vi: set sw=4 ts=4: */
Eric Andersen35e643b2003-07-28 07:40:39 +00002/*
Eric Andersenaff114c2004-04-14 17:51:38 +00003 * Rexec program for system have fork() as vfork() with foreground option
Russ Dilla1fece22003-12-15 21:57:44 +00004 *
5 * Copyright (C) Vladimir N. Oleynik <dzo@simtreas.ru>
6 * Copyright (C) 2003 Russ Dill <Russ.Dill@asu.edu>
7 *
Eric Andersenaff114c2004-04-14 17:51:38 +00008 * daemon() portion taken from uClibc:
Russ Dilla1fece22003-12-15 21:57:44 +00009 *
10 * Copyright (c) 1991, 1993
11 * The Regents of the University of California. All rights reserved.
12 *
13 * Modified for uClibc by Erik Andersen <andersee@debian.org>
14 *
Bernhard Reutner-Fischer0a8812b2006-05-19 13:12:21 +000015 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersen35e643b2003-07-28 07:40:39 +000016 */
17
18#include <unistd.h>
Russ Dilla1fece22003-12-15 21:57:44 +000019#include <stdio.h>
20#include <fcntl.h>
21#include <paths.h>
Eric Andersen35e643b2003-07-28 07:40:39 +000022#include "libbb.h"
23
24
Bernhard Reutner-Fischerc418d482006-05-31 10:19:51 +000025#ifdef BB_NOMMU
Mike Frysinger6fb58472006-06-07 21:48:30 +000026static void vfork_daemon_common(int nochdir, int noclose)
Eric Andersen35e643b2003-07-28 07:40:39 +000027{
Russ Dilla1fece22003-12-15 21:57:44 +000028 int fd;
Eric Andersenc7bda1c2004-03-15 08:29:22 +000029
Russ Dilla1fece22003-12-15 21:57:44 +000030 setsid();
Eric Andersenc7bda1c2004-03-15 08:29:22 +000031
Russ Dilla1fece22003-12-15 21:57:44 +000032 if (!nochdir)
33 chdir("/");
34
Bernhard Reutner-Fischer0a8812b2006-05-19 13:12:21 +000035 if (!noclose && (fd = open(bb_dev_null, O_RDWR, 0)) != -1) {
Russ Dilla1fece22003-12-15 21:57:44 +000036 dup2(fd, STDIN_FILENO);
37 dup2(fd, STDOUT_FILENO);
38 dup2(fd, STDERR_FILENO);
39 if (fd > 2)
40 close(fd);
Mike Frysinger6fb58472006-06-07 21:48:30 +000041 }
42}
43
44void vfork_daemon(int nochdir, int noclose)
45{
46 vfork_daemon_common(nochdir, noclose);
47
48 if (vfork())
49 exit(0);
50}
51
52void vfork_daemon_rexec(int nochdir, int noclose,
53 int argc, char **argv, char *foreground_opt)
54{
55 char **vfork_args;
56 int a = 0;
57
58 vfork_daemon_common(nochdir, noclose);
Eric Andersen35e643b2003-07-28 07:40:39 +000059
60 vfork_args = xcalloc(sizeof(char *), argc + 3);
Russ Dilla1fece22003-12-15 21:57:44 +000061 vfork_args[a++] = "/bin/busybox";
Eric Andersen35e643b2003-07-28 07:40:39 +000062 while(*argv) {
63 vfork_args[a++] = *argv;
64 argv++;
65 }
66 vfork_args[a] = foreground_opt;
Russ Dilla1fece22003-12-15 21:57:44 +000067 switch (vfork()) {
68 case 0: /* child */
69 /* Make certain we are not a session leader, or else we
70 * might reacquire a controlling terminal */
71 if (vfork())
72 _exit(0);
73 execv(vfork_args[0], vfork_args);
74 bb_perror_msg_and_die("execv %s", vfork_args[0]);
75 case -1: /* error */
76 bb_perror_msg_and_die("vfork");
77 default: /* parent */
78 exit(0);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000079 }
Eric Andersen35e643b2003-07-28 07:40:39 +000080}
Bernhard Reutner-Fischerc418d482006-05-31 10:19:51 +000081#endif /* BB_NOMMU */