aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/lib.c8
-rw-r--r--main.c4
-rw-r--r--toys.h2
-rw-r--r--toys/lsb/killall.c2
-rw-r--r--toys/posix/sh.c9
5 files changed, 18 insertions, 7 deletions
diff --git a/lib/lib.c b/lib/lib.c
index 06828a40..18578815 100644
--- a/lib/lib.c
+++ b/lib/lib.c
@@ -61,7 +61,9 @@ void error_exit(char *msg, ...)
verror_msg(msg, 0, va);
va_end(va);
- exit(!toys.exitval ? 1 : toys.exitval);
+ if (!toys.exitval) toys.exitval++;
+ if (toys.rebound) longjmp(*toys.rebound, 1);
+ else exit(toys.exitval);
}
@@ -74,7 +76,9 @@ void perror_exit(char *msg, ...)
verror_msg(msg, errno, va);
va_end(va);
- exit(!toys.exitval ? 1 : toys.exitval);
+ if (!toys.exitval) toys.exitval++;
+ if (toys.rebound) longjmp(*toys.rebound, 1);
+ else exit(toys.exitval);
}
// Die unless we can allocate memory.
diff --git a/main.c b/main.c
index c705d645..7fb543ab 100644
--- a/main.c
+++ b/main.c
@@ -76,10 +76,10 @@ void toy_init(struct toy_list *which, char *argv[])
if ((which->flags & TOYFLAG_NEEDROOT) && euid) error_exit("Not root");
}
- // Free old toys contents (to be reentrant)
+ // Free old toys contents (to be reentrant), but leave rebound if any
if (toys.optargs != toys.argv+1) free(toys.optargs);
- memset(&toys, 0, sizeof(struct toy_context));
+ memset(&toys, 0, offsetof(struct toy_context, rebound));
toys.which = which;
toys.argv = argv;
diff --git a/toys.h b/toys.h
index 72670cd7..55256efe 100644
--- a/toys.h
+++ b/toys.h
@@ -24,6 +24,7 @@
#include <sched.h>
#include <shadow.h>
#include <stdarg.h>
+#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -103,6 +104,7 @@ extern struct toy_context {
int optc; // Count of optargs
int exithelp; // Should error_exit print a usage message first?
int old_umask; // Old umask preserved by TOYFLAG_UMASK
+ jmp_buf *rebound; // longjmp here instead of exit when do_rebound set
} toys;
// One big temporary buffer, for use by commands (not library functions).
diff --git a/toys/lsb/killall.c b/toys/lsb/killall.c
index 7883c53d..debc3dfc 100644
--- a/toys/lsb/killall.c
+++ b/toys/lsb/killall.c
@@ -48,7 +48,7 @@ void killall_main(void)
toys.exitval++;
if (!*toys.optargs) {
- toys.exithelp = 1;
+ toys.exithelp++;
error_exit("Process name missing!");
}
diff --git a/toys/posix/sh.c b/toys/posix/sh.c
index 30900b30..32d05ec2 100644
--- a/toys/posix/sh.c
+++ b/toys/posix/sh.c
@@ -293,12 +293,17 @@ static void run_pipeline(struct pipeline *line)
// Is this command a builtin that should run in this process?
if (tl && (tl->flags & TOYFLAG_NOFORK)) {
struct toy_context temp;
+ jmp_buf rebound;
// This fakes lots of what toybox_main() does.
memcpy(&temp, &toys, sizeof(struct toy_context));
memset(&toys, 0, sizeof(struct toy_context));
- toy_init(tl, cmd->argv);
- tl->toy_main();
+
+ if (!setjmp(rebound)) {
+ toys.rebound = rebound;
+ toy_init(tl, cmd->argv);
+ tl->toy_main();
+ }
cmd->pid = toys.exitval;
free(toys.optargs);
if (toys.old_umask) umask(toys.old_umask);