OSDN Git Service

make xfunctions optionally longjump instead of exit.
authorDenis Vlasenko <vda.linux@googlemail.com>
Mon, 9 Apr 2007 21:35:07 +0000 (21:35 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Mon, 9 Apr 2007 21:35:07 +0000 (21:35 -0000)
use it for making NOFORK more practical.
touch: make it a NOFORK applet

applets/applets.c
coreutils/cmp.c
coreutils/touch.c
include/applets.h
include/libbb.h
libbb/copyfd.c
libbb/error_msg_and_die.c
libbb/getopt32.c
libbb/vfork_daemon_rexec.c
libbb/xfuncs.c

index db4ee48..9218b40 100644 (file)
@@ -462,7 +462,7 @@ void bb_show_usage(void)
                                        applet_name, usage_string);
        }
 
-       exit(xfunc_error_retval);
+       sleep_and_die();
 }
 
 
index cff1182..c70f882 100644 (file)
@@ -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";
index ae4e689..5f81b23 100644 (file)
  * 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;
                                }
index 0139038..ecce321 100644 (file)
@@ -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))
index cec31a7..8e3f402 100644 (file)
@@ -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)));
index 0d0ec22..805b801 100644 (file)
@@ -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)
index 7c5a4eb..39178a3 100644 (file)
@@ -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);
 }
 
index dec97d7..28b4797 100644 (file)
@@ -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:
index d256939..286ee26 100644 (file)
@@ -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)
index 0cf2005..fa4a152 100644 (file)
@@ -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);
 }