make xfunctions optionally longjump instead of exit. use it for making NOFORK more practical. touch: make it a NOFORK applet
No binary (build failed)
—
(log yok)
| @@ -462,7 +462,7 @@ void bb_show_usage(void) | |
| applet_name, usage_string); | |
| } | |
| - | exit(xfunc_error_retval); |
| + | sleep_and_die(); |
| } | |
| @@ -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"; | |
| @@ -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 @@ 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; | |
| } | |
| @@ -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)) | |
| @@ -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))); | |
| @@ -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) | |
| @@ -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); | |
| } | |
| @@ -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: | |
| @@ -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) | |
| @@ -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); | |
| } | |