diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-09 13:04:50 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-09 13:04:50 +0000 |
commit | 7e754f12d304704d44e10fd4d2fdb8710526656e (patch) | |
tree | 9aa16703d48b9a7a38ccaec3759a19e95e976383 | |
parent | 2dfdd44d9d6c3984501683bbac2e78b18eeae1e7 (diff) | |
download | busybox-7e754f12d304704d44e10fd4d2fdb8710526656e.tar.gz |
Implement first instance of NOFORK applet - echo
find: use NOFORK/NOEXEC; small -exec buglet also eliminated
vfork_daemon_rexec: honor PREFER_APPLETS
echo: small size improvements
find -exec echo {} \; with PREFER_APPLETS=y runs 4 times faster
-rw-r--r-- | Config.in | 3 | ||||
-rw-r--r-- | coreutils/echo.c | 75 | ||||
-rw-r--r-- | findutils/find.c | 25 | ||||
-rw-r--r-- | include/applets.h | 7 | ||||
-rw-r--r-- | libbb/process_escape_sequence.c | 9 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 8 |
6 files changed, 77 insertions, 50 deletions
@@ -244,7 +244,8 @@ config FEATURE_EXEC_PREFER_APPLETS help This is an experimental option which directs applets about to call 'exec' to try and find an applicable busybox applet before - searching the executable path for a binary or symlink to execute. + searching the PATH. This may affect shell, find -exec, xargs and + similar programs. config BUSYBOX_EXEC_PATH string "Path to BusyBox executable" diff --git a/coreutils/echo.c b/coreutils/echo.c index 8270fc006..486245508 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c @@ -20,86 +20,85 @@ * 1) In handling '\c' escape, the previous version only suppressed the * trailing newline. SUSv3 specifies _no_ output after '\c'. * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. - * The previous version version did not allow 4-digit octals. + * The previous version did not allow 4-digit octals. */ - -#include <stdio.h> -#include <string.h> -#include <stdlib.h> #include "busybox.h" int bb_echo(char **argv) { -#ifndef CONFIG_FEATURE_FANCY_ECHO + const char *arg; +#if !ENABLE_FEATURE_FANCY_ECHO #define eflag '\\' ++argv; #else const char *p; - int nflag = 1; - int eflag = 0; + char nflag = 1; + char eflag = 0; + + while (1) { + arg = *++argv; + if (!arg) + goto ret; + if (*arg != '-') + break; - while (*++argv && (**argv == '-')) { /* If it appears that we are handling options, then make sure * that all of the options specified are actually valid. * Otherwise, the string should just be echoed. */ - - if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ + p = arg + 1; + if (!*p) /* A single '-', so echo it. */ goto just_echo; - } do { - if (strrchr("neE", *p) == 0) { + if (!strrchr("neE", *p)) goto just_echo; - } } while (*++p); /* All of the options in this arg are valid, so handle them. */ - p = *argv + 1; + p = arg + 1; do { - if (*p == 'n') { + if (*p == 'n') nflag = 0; - } else if (*p == 'e') { + if (*p == 'e') eflag = '\\'; - } else { - eflag = 0; - } } while (*++p); } - -just_echo: + just_echo: #endif - while (*argv) { + while (1) { + /* arg is already = *argv and isn't NULL */ int c; - while ((c = *(*argv)++)) { + while ((c = *arg++)) { if (c == eflag) { /* Check for escape seq. */ - if (**argv == 'c') { + if (*arg == 'c') { /* '\c' means cancel newline and * ignore all subsequent chars. */ - return 0; + goto ret; } -#ifndef CONFIG_FEATURE_FANCY_ECHO +#if !ENABLE_FEATURE_FANCY_ECHO /* SUSv3 specifies that octal escapes must begin with '0'. */ - if (((unsigned int)(**argv - '1')) >= 7) + if ( (((unsigned char)*arg) - '1') >= 7) #endif { /* Since SUSv3 mandates a first digit of 0, 4-digit octals * of the form \0### are accepted. */ - if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { - (*argv)++; + if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) { + arg++; } /* bb_process_escape_sequence can handle nul correctly */ - c = bb_process_escape_sequence((const char **) argv); + c = bb_process_escape_sequence(&arg); } } putchar(c); } - if (*++argv) { - putchar(' '); - } + arg = *++argv; + if (!arg) + break; + putchar(' '); } #ifdef CONFIG_FEATURE_FANCY_ECHO @@ -109,14 +108,16 @@ just_echo: #else putchar('\n'); #endif - return 0; + ret: + return fflush(stdout); } +/* This is a NOFORK applet. Be very careful! */ + int echo_main(int argc, char** argv); int echo_main(int argc, char** argv) { - (void)bb_echo(argv); - fflush_stdout_and_exit(EXIT_SUCCESS); + return bb_echo(argv); } /*- diff --git a/findutils/find.c b/findutils/find.c index 594eafca4..7b5a09d56 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -242,9 +242,30 @@ ACTF(exec) for (i = 0; i < ap->exec_argc; i++) argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName); argv[i] = NULL; /* terminate the list */ - rc = wait4pid(spawn(argv)); - if (rc) + + if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) { + const struct BB_applet *a = find_applet_by_name(argv[0]); + if (a) { + if (a->nofork) { + rc = a->main(ap->exec_argc, argv); + goto f; + } +#ifndef BB_NOMMU + if (a->noexec) { + rc = fork(); + if (rc) goto w; + current_applet = a; + run_current_applet_and_exit(ap->exec_argc, argv); + } +#endif + } + } + rc = spawn(argv); + w: + rc = wait4pid(rc); + if (rc < 0) bb_perror_msg("%s", argv[0]); + f: for (i = 0; i < ap->exec_argc; i++) free(argv[i]); return rc == 0; /* return 1 if success */ diff --git a/include/applets.h b/include/applets.h index f411aa258..f20b79629 100644 --- a/include/applets.h +++ b/include/applets.h @@ -28,24 +28,28 @@ s - suid type: # define APPLET_NOUSAGE(name,main,l,s) int main##_main(int argc, char **argv); # define APPLET_ODDNAME(name,main,l,s,name2) int main##_main(int argc, char **argv); # define APPLET_NOEXEC(name,main,l,s,name2) int main##_main(int argc, char **argv); +# define APPLET_NOFORK(name,main,l,s,name2) int main##_main(int argc, char **argv); #elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) name##_trivial_usage "\n\n" name##_full_usage "\0" # define APPLET_NOUSAGE(name,main,l,s) "\b\0" # define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0" # define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0" +# define APPLET_NOFORK(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0" #elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE # define APPLET(name,l,s) name##_trivial_usage "\0" # define APPLET_NOUSAGE(name,main,l,s) "\b\0" # define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\0" # define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\0" +# define APPLET_NOFORK(name,main,l,s,name2) name2##_trivial_usage "\0" #elif defined(MAKE_LINKS) # define APPLET(name,l,c) LINK l name # define APPLET_NOUSAGE(name,main,l,s) LINK l name # define APPLET_ODDNAME(name,main,l,s,name2) LINK l name # define APPLET_NOEXEC(name,main,l,s,name2) LINK l name +# define APPLET_NOFORK(name,main,l,s,name2) LINK l name #else const struct BB_applet applets[] = { /* name,main,location,need_suid */ @@ -53,6 +57,7 @@ s - suid type: # define APPLET_NOUSAGE(name,main,l,s) {#name,main##_main,l,s}, # define APPLET_ODDNAME(name,main,l,s,name2) {#name,main##_main,l,s}, # define APPLET_NOEXEC(name,main,l,s,name2) {#name,main##_main,l,s,1}, +# define APPLET_NOFORK(name,main,l,s,name2) {#name,main##_main,l,s,1,1}, #endif #if ENABLE_INSTALL_NO_USR @@ -118,7 +123,7 @@ USE_DUMPKMAP(APPLET(dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_APP_DUMPLEASES(APPLET(dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) //USE_E2FSCK(APPLET(e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) //USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) -USE_ECHO(APPLET_NOEXEC(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER, echo)) +USE_ECHO(APPLET_NOFORK(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER, echo)) USE_ED(APPLET(ed, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_FEATURE_GREP_EGREP_ALIAS(APPLET_NOUSAGE(egrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER)) USE_EJECT(APPLET(eject, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) diff --git a/libbb/process_escape_sequence.c b/libbb/process_escape_sequence.c index 138e751f5..3178ad34a 100644 --- a/libbb/process_escape_sequence.c +++ b/libbb/process_escape_sequence.c @@ -8,9 +8,6 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include <stdio.h> -#include <limits.h> -#include <ctype.h> #include "libbb.h" #define WANT_HEX_ESCAPES 1 @@ -46,10 +43,10 @@ char bb_process_escape_sequence(const char **ptr) #endif do { - d = (unsigned int)(*q - '0'); + d = (unsigned char)(*q) - '0'; #ifdef WANT_HEX_ESCAPES if (d >= 10) { - d = ((unsigned int)(_tolower(*q) - 'a')) + 10; + d = (unsigned char)(_tolower(*q)) - 'a' + 10; } #endif @@ -80,7 +77,7 @@ char bb_process_escape_sequence(const char **ptr) break; } } while (*++p); - n = *(p+(sizeof(charmap)/2)); + n = *(p + (sizeof(charmap)/2)); } *ptr = q; diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index ec8b9b1d7..11dbb24fc 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -26,14 +26,16 @@ pid_t spawn(char **argv) volatile int failed; pid_t pid; - // Be nice to nommu machines. +// Ain't it a good place to fflush(NULL)? + + /* Be nice to nommu machines. */ failed = 0; pid = vfork(); if (pid < 0) /* error */ return pid; if (!pid) { /* child */ - /* Don't use BB_EXECVP tricks here! */ - execvp(argv[0], argv); + /* This macro is ok - it doesn't do NOEXEC/NOFORK tricks */ + BB_EXECVP(argv[0], argv); /* We are (maybe) sharing a stack with blocked parent, * let parent know we failed and then exit to unblock parent |