make xfunctions optionally longjump instead of exit.
use it for making NOFORK more practical.
touch: make it a NOFORK applet
diff --git a/applets/applets.c b/applets/applets.c
index db4ee48..9218b40 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -462,7 +462,7 @@
applet_name, usage_string);
}
- exit(xfunc_error_retval);
+ sleep_and_die();
}
diff --git a/coreutils/cmp.c b/coreutils/cmp.c
index cff1182..c70f882 100644
--- a/coreutils/cmp.c
+++ b/coreutils/cmp.c
@@ -30,7 +30,7 @@
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 ae4e689..5f81b23 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 <stdio.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <utime.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdlib.h>
#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 @@
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 0139038..ecce321 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -319,7 +319,7 @@
#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 cec31a7..8e3f402 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -620,6 +620,7 @@
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 0d0ec22..805b801 100644
--- a/libbb/copyfd.c
+++ b/libbb/copyfd.c
@@ -77,7 +77,7 @@
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 @@
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 7c5a4eb..39178a3 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 <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
#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 dec97d7..28b4797 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -457,6 +457,7 @@
/* 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 d256939..286ee26 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -115,11 +115,27 @@
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 @@
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 0cf2005..fa4a152 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -476,7 +476,7 @@
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);
}