From 9067f13be067f39f6c8586926b190b7dee0def3d Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Sat, 24 Mar 2007 12:11:17 +0000 Subject: [PATCH] NOMMU re-exec trick shuld not depend on existence of "don't daemonize" option for every affected applet (and dnsd, for example, don't have one). Thus rework re-exec support to not require it. Code got smaller too. --- applets/busybox.c | 7 +++++++ applets/individual.c | 3 +-- include/libbb.h | 5 ++--- libbb/vfork_daemon_rexec.c | 23 +++++++++-------------- miscutils/crond.c | 4 ++-- miscutils/watchdog.c | 8 +++++--- networking/dnsd.c | 4 ++-- networking/inetd.c | 4 ++-- sysklogd/klogd.c | 3 ++- sysklogd/syslogd.c | 3 ++- 10 files changed, 34 insertions(+), 30 deletions(-) diff --git a/applets/busybox.c b/applets/busybox.c index 0387d79b7..5334827ca 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -7,6 +7,7 @@ #include "busybox.h" const char *applet_name ATTRIBUTE_EXTERNALLY_VISIBLE; +smallint re_execed; #ifdef CONFIG_FEATURE_INSTALLER /* @@ -59,6 +60,12 @@ int main(int argc, char **argv) { const char *s; + /* NOMMU re-exec trick sets high-order bit in first byte of name */ + if (argv[0][0] & 0x80) { + re_execed = 1; + argv[0][0] &= 0x7f; + } + applet_name = argv[0]; if (*applet_name == '-') applet_name++; diff --git a/applets/individual.c b/applets/individual.c index 072168352..1667f188b 100644 --- a/applets/individual.c +++ b/applets/individual.c @@ -9,12 +9,11 @@ const char *applet_name; #include #include -//Ok to remove? #include "bb_config.h" #include "usage.h" int main(int argc, char *argv[]) { - applet_name=argv[0]; + applet_name = argv[0]; return APPLET_main(argc,argv); } diff --git a/include/libbb.h b/include/libbb.h index 659bfcaa7..0cfc22018 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -616,9 +616,7 @@ extern int index_in_substr_array(const char * const string_array[], const char * extern void print_login_issue(const char *issue_file, const char *tty); extern void print_login_prompt(void); #ifdef BB_NOMMU -extern void vfork_daemon(int nochdir, int noclose); -extern void vfork_daemon_rexec(int nochdir, int noclose, - int argc, char **argv, char *foreground_opt); +extern void vfork_daemon_rexec(int nochdir, int noclose, char **argv); #endif extern int get_terminal_width_height(const int fd, int *width, int *height); @@ -763,6 +761,7 @@ enum { /* DO NOT CHANGE THESE VALUES! cp.c, mv.c, install.c depend on them. */ }; #define FILEUTILS_CP_OPTSTR "pdRfils" USE_SELINUX("c") +extern smallint re_execed; extern const char *applet_name; extern const char BB_BANNER[]; diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 26d1826e0..3185f2d39 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -19,19 +19,18 @@ #include "libbb.h" #ifdef BB_NOMMU -void vfork_daemon_rexec(int nochdir, int noclose, - int argc, char **argv, char *foreground_opt) +void vfork_daemon_rexec(int nochdir, int noclose, char **argv) { int fd; - char **vfork_args; - int a = 0; setsid(); if (!nochdir) xchdir("/"); - if (!noclose && (fd = open(bb_dev_null, O_RDWR, 0)) != -1) { + if (!noclose) { + /* if "/dev/null" doesn't exist, bail out! */ + fd = xopen(bb_dev_null, O_RDWR); dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); @@ -39,21 +38,17 @@ void vfork_daemon_rexec(int nochdir, int noclose, close(fd--); } - vfork_args = xzalloc(sizeof(char *) * (argc + 3)); - vfork_args[a++] = CONFIG_BUSYBOX_EXEC_PATH; - while (*argv) { - vfork_args[a++] = *argv; - argv++; - } - vfork_args[a] = foreground_opt; switch (vfork()) { case 0: /* child */ /* Make certain we are not a session leader, or else we * might reacquire a controlling terminal */ if (vfork()) _exit(0); - execv(vfork_args[0], vfork_args); - bb_perror_msg_and_die("execv %s", vfork_args[0]); + /* High-order bit of first char in argv[0] is a hidden + * "we have (alrealy) re-execed, don't do it again" flag */ + argv[0][0] |= 0x80; + execv(CONFIG_BUSYBOX_EXEC_PATH, argv); + bb_perror_msg_and_die("exec %s", CONFIG_BUSYBOX_EXEC_PATH); case -1: /* error */ bb_perror_msg_and_die("vfork"); default: /* parent */ diff --git a/miscutils/crond.c b/miscutils/crond.c index d237a677e..1ab0038e0 100644 --- a/miscutils/crond.c +++ b/miscutils/crond.c @@ -191,8 +191,8 @@ int crond_main(int ac, char **av) if (!(opt & 4)) { #ifdef BB_NOMMU - /* reexec for vfork() do continue parent */ - vfork_daemon_rexec(1, 0, ac, av, "-f"); + if (!re_execed) + vfork_daemon_rexec(1, 0, av); #else xdaemon(1, 0); #endif diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index ed9026d9e..e3d77d17e 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -38,12 +38,14 @@ int watchdog_main(int argc, char **argv) if (optind < argc - 1 || argc == 1) bb_show_usage(); + if (!(opts & OPT_FOREGROUND)) { #ifdef BB_NOMMU - if (!(opts & OPT_FOREGROUND)) - vfork_daemon_rexec(0, 1, argc, argv, "-F"); + if (!re_execed) + vfork_daemon_rexec(0, 1, argv); #else - xdaemon(0, 1); + xdaemon(0, 1); #endif + } signal(SIGHUP, watchdog_shutdown); signal(SIGINT, watchdog_shutdown); diff --git a/networking/dnsd.c b/networking/dnsd.c index 78722d6f6..fb0c56cce 100644 --- a/networking/dnsd.c +++ b/networking/dnsd.c @@ -357,8 +357,8 @@ int dnsd_main(int argc, char **argv) if (OPT_daemon) { //FIXME: NOMMU will NOT set LOGMODE_SYSLOG! #ifdef BB_NOMMU - /* reexec for vfork() do continue parent */ - vfork_daemon_rexec(1, 0, argc, argv, "-d"); + if (!re_execed) + vfork_daemon_rexec(1, 0, argv); #else xdaemon(1, 0); #endif diff --git a/networking/inetd.c b/networking/inetd.c index 8016823c0..48e23db2e 100644 --- a/networking/inetd.c +++ b/networking/inetd.c @@ -1289,8 +1289,8 @@ int inetd_main(int argc, char *argv[]) #ifdef BB_NOMMU if (!(opt & 2)) { - /* reexec for vfork() do continue parent */ - vfork_daemon_rexec(0, 0, argc, argv, "-f"); + if (!re_execed) + vfork_daemon_rexec(0, 0, argv); } bb_sanitize_stdio(); #else diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c index cca6f5671..fc0ed3037 100644 --- a/sysklogd/klogd.c +++ b/sysklogd/klogd.c @@ -51,7 +51,8 @@ int klogd_main(int argc, char **argv) if (!(option_mask32 & OPT_FOREGROUND)) { #ifdef BB_NOMMU - vfork_daemon_rexec(0, 1, argc, argv, "-n"); + if (!re_execed) + vfork_daemon_rexec(0, 1, argv); #else bb_daemonize(); #endif diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 2a2b20c8b..437212372 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -643,7 +643,8 @@ int syslogd_main(int argc, char **argv) if (!(option_mask32 & OPT_nofork)) { #ifdef BB_NOMMU - vfork_daemon_rexec(0, 1, argc, argv, "-n"); + if (!re_execed) + vfork_daemon_rexec(0, 1, argv); #else bb_daemonize(); #endif