diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-14 14:09:57 +0400 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-14 14:09:57 +0400 |
commit | f5294e1f4c56afb377ada95a7757b28ad3c89086 (patch) | |
tree | 95a0c3632c8c2b20fa6b60f1e1a33e4fc4b24d4f /libbb | |
parent | 16abcd90aefae8bdb9f7d80a555982dba6ca59b5 (diff) |
hush: use NOFORK applets as appropriate. Net reduction of code size.
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 89 |
1 files changed, 48 insertions, 41 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 7dbc152e2..78f3c4ad4 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -100,6 +100,52 @@ int wait_pid(int *wstat, int pid) return r; } +int run_nofork_applet(const struct bb_applet *a, char **argv) +{ + int rc, argc; + + /* Save some shared globals */ + const struct bb_applet *old_a = current_applet; + int old_x = xfunc_error_retval; + uint32_t old_m = option_mask32; + int old_sleep = die_sleep; + + current_applet = a; + applet_name = a->name; + xfunc_error_retval = EXIT_FAILURE; + /*option_mask32 = 0; - not needed */ + /* special flag for xfunc_die(). If xfunc will "die" + * in NOFORK applet, xfunc_die() sees negative + * die_sleep and longjmp here instead. */ + die_sleep = -1; + + argc = 1; + while (argv[argc]) + argc++; + + rc = setjmp(die_jmp); + if (!rc) { + /* Some callers (xargs) + * need argv untouched because they free argv[i]! */ + char *tmp_argv[argc+1]; + memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); + /* Finally we can call NOFORK applet's main() */ + rc = a->main(argc, tmp_argv); + } else { /* xfunc died in NOFORK applet */ + /* in case they meant to return 0... */ + if (rc == -111) + rc = 0; + } + + /* Restoring globals */ + current_applet = old_a; + applet_name = old_a->name; + xfunc_error_retval = old_x; + option_mask32 = old_m; + die_sleep = old_sleep; + return rc; +} + int spawn_and_wait(char **argv) { int rc; @@ -111,50 +157,11 @@ int spawn_and_wait(char **argv) || a->noexec /* NOEXEC trick needs fork() */ #endif )) { - int argc = 1; - char **pp = argv; - while (*++pp) - argc++; #if BB_MMU if (a->nofork) #endif { - /* Save some shared globals */ - const struct bb_applet *old_a = current_applet; - int old_x = xfunc_error_retval; - uint32_t old_m = option_mask32; - int old_sleep = die_sleep; - - current_applet = a; - applet_name = a->name; - xfunc_error_retval = EXIT_FAILURE; - /*option_mask32 = 0; - not needed */ - /* special flag for xfunc_die(). If xfunc will "die" - * in NOFORK applet, xfunc_die() sees negative - * die_sleep and longjmp here instead. */ - die_sleep = -1; - - rc = setjmp(die_jmp); - if (!rc) { - /* Some callers (xargs) - * need argv untouched because they free argv[i]! */ - char *tmp_argv[argc+1]; - memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); - /* Finally we can call NOFORK applet's main() */ - rc = a->main(argc, tmp_argv); - } else { /* xfunc died in NOFORK applet */ - /* in case they meant to return 0... */ - if (rc == -111) - rc = 0; - } - - /* Restoring globals */ - current_applet = old_a; - applet_name = old_a->name; - xfunc_error_retval = old_x; - option_mask32 = old_m; - die_sleep = old_sleep; - return rc; + return run_nofork_applet(a, argv); } #if BB_MMU /* MMU only */ @@ -165,7 +172,7 @@ int spawn_and_wait(char **argv) /* child */ xfunc_error_retval = EXIT_FAILURE; current_applet = a; - run_current_applet_and_exit(argc, argv); + run_current_applet_and_exit(argv); #endif } #endif /* FEATURE_PREFER_APPLETS */ |