From 3f3aa2a57dc648ade9083f3b3ad83cce8206b912 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Mon, 9 Apr 2007 21:35:07 +0000 Subject: make xfunctions optionally longjump instead of exit. use it for making NOFORK more practical. touch: make it a NOFORK applet --- applets/applets.c | 2 +- coreutils/cmp.c | 2 +- coreutils/touch.c | 13 ++++--------- include/applets.h | 2 +- include/libbb.h | 1 + libbb/copyfd.c | 4 ++-- libbb/error_msg_and_die.c | 11 ++++++----- libbb/getopt32.c | 1 + libbb/vfork_daemon_rexec.c | 25 +++++++++++++++++++++---- libbb/xfuncs.c | 2 +- 10 files changed, 39 insertions(+), 24 deletions(-) diff --git a/applets/applets.c b/applets/applets.c index db4ee482e..9218b40e4 100644 --- a/applets/applets.c +++ b/applets/applets.c @@ -462,7 +462,7 @@ void bb_show_usage(void) applet_name, usage_string); } - exit(xfunc_error_retval); + sleep_and_die(); } diff --git a/coreutils/cmp.c b/coreutils/cmp.c index cff118279..c70f8822d 100644 --- a/coreutils/cmp.c +++ b/coreutils/cmp.c @@ -30,7 +30,7 @@ static FILE *cmp_xfopen_input(const char * const filename) fp = fopen_or_warn_stdin(filename); if (fp) return fp; - exit(xfunc_error_retval); /* We already output an error message. */ + sleep_and_die(); /* We already output an error message. */ } static const char fmt_eof[] = "cmp: EOF on %s\n"; diff --git a/coreutils/touch.c b/coreutils/touch.c index ae4e689f1..5f81b2380 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -17,21 +17,16 @@ * Also, exiting on a failure was a bug. All args should be processed. */ -#include -#include -#include -#include -#include -#include -#include #include "busybox.h" +/* This is a NOFORK applet. Be very careful! */ + int touch_main(int argc, char **argv); int touch_main(int argc, char **argv) { int fd; int status = EXIT_SUCCESS; - bool flags = (getopt32(argc, argv, "c") & 1); + int flags = getopt32(argc, argv, "c"); argv += optind; @@ -41,7 +36,7 @@ int touch_main(int argc, char **argv) do { if (utime(*argv, NULL)) { - if (errno == ENOENT) { /* no such file*/ + if (errno == ENOENT) { /* no such file */ if (flags) { /* Creation is disabled, so ignore. */ continue; } diff --git a/include/applets.h b/include/applets.h index 013903851..ecce32169 100644 --- a/include/applets.h +++ b/include/applets.h @@ -319,7 +319,7 @@ USE_TFTP(APPLET(tftp, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) #endif USE_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) -USE_TOUCH(APPLET_NOEXEC(touch, touch, _BB_DIR_BIN, _BB_SUID_NEVER, touch)) +USE_TOUCH(APPLET_NOFORK(touch, touch, _BB_DIR_BIN, _BB_SUID_NEVER, touch)) USE_TR(APPLET(tr, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TRACEROUTE(APPLET(traceroute, _BB_DIR_USR_BIN, _BB_SUID_MAYBE)) USE_TRUE(APPLET(true, _BB_DIR_BIN, _BB_SUID_NEVER)) diff --git a/include/libbb.h b/include/libbb.h index cec31a7f4..8e3f4023c 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -620,6 +620,7 @@ extern const char *msg_eol; extern smallint logmode; extern int die_sleep; extern int xfunc_error_retval; +extern jmp_buf die_jmp; extern void sleep_and_die(void) ATTRIBUTE_NORETURN; extern void bb_show_usage(void) ATTRIBUTE_NORETURN ATTRIBUTE_EXTERNALLY_VISIBLE; extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))); diff --git a/libbb/copyfd.c b/libbb/copyfd.c index 0d0ec2232..805b80187 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -77,7 +77,7 @@ void complain_copyfd_and_die(off_t sz) if (sz != -1) bb_error_msg_and_die("short read"); /* if sz == -1, bb_copyfd_XX already complained */ - exit(xfunc_error_retval); + sleep_and_die(); } #endif @@ -97,7 +97,7 @@ void bb_copyfd_exact_size(int fd1, int fd2, off_t size) if (sz != -1) bb_error_msg_and_die("short read"); /* if sz == -1, bb_copyfd_XX already complained */ - exit(xfunc_error_retval); + sleep_and_die(); } off_t bb_copyfd_eof(int fd1, int fd2) diff --git a/libbb/error_msg_and_die.c b/libbb/error_msg_and_die.c index 7c5a4ebe9..39178a3ce 100644 --- a/libbb/error_msg_and_die.c +++ b/libbb/error_msg_and_die.c @@ -7,18 +7,19 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include -#include -#include -#include #include "libbb.h" int die_sleep; +jmp_buf die_jmp; void sleep_and_die(void) { - if (die_sleep) + if (die_sleep) { + /* Special case: don't die, but jump */ + if (die_sleep < 0) + longjmp(die_jmp, xfunc_error_retval); sleep(die_sleep); + } exit(xfunc_error_retval); } diff --git a/libbb/getopt32.c b/libbb/getopt32.c index dec97d743..28b47974e 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c @@ -457,6 +457,7 @@ getopt32(int argc, char **argv, const char *applet_opts, ...) /* In case getopt32 was already called, reinit some state */ optind = 1; + /* optarg = NULL; opterr = 0; optopt = 0; ?? */ /* Note: just "getopt() <= 0" will not work good for * "fake" short options, like this one: diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index d25693917..286ee2678 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -115,11 +115,27 @@ int spawn_and_wait(char **argv) char **pp = argv; while (*++pp) argc++; -#ifdef BB_NOMMU - return a->main(argc, argv); -#else +#ifndef BB_NOMMU if (a->nofork) - return a->main(argc, argv); +#endif + { + int old_sleep = die_sleep; + die_sleep = -1; /* special flag */ + /* sleep_and_die() checks for it */ + rc = setjmp(die_jmp); + if (!rc) { + const struct BB_applet *old_a = current_applet; + current_applet = a; + applet_name = a->name; +// what else should we save/restore? + rc = a->main(argc, argv); + current_applet = old_a; + applet_name = old_a->name; + } + die_sleep = old_sleep; + return rc; + } +#ifndef BB_NOMMU /* MMU only */ /* a->noexec is true */ rc = fork(); if (rc) @@ -135,6 +151,7 @@ int spawn_and_wait(char **argv) return wait4pid(rc); } + #if 0 //ndef BB_NOMMU // Die with an error message if we can't daemonize. void xdaemon(int nochdir, int noclose) diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 0cf2005ac..fa4a15236 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -476,7 +476,7 @@ void xprint_and_close_file(FILE *file) fflush(stdout); // copyfd outputs error messages for us. if (bb_copyfd_eof(fileno(file), 1) == -1) - exit(xfunc_error_retval); + sleep_and_die(); fclose(file); } -- cgit v1.2.3