aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-09 13:04:50 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-09 13:04:50 +0000
commit68a4a5b8a86e3c0f0f371e6d3ad04cb513f10d19 (patch)
tree9aa16703d48b9a7a38ccaec3759a19e95e976383
parent4565afa16cb2dd94d5aac41b6627e0a5240fbbe0 (diff)
downloadbusybox-w32-68a4a5b8a86e3c0f0f371e6d3ad04cb513f10d19.tar.gz
busybox-w32-68a4a5b8a86e3c0f0f371e6d3ad04cb513f10d19.tar.bz2
busybox-w32-68a4a5b8a86e3c0f0f371e6d3ad04cb513f10d19.zip
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 git-svn-id: svn://busybox.net/trunk/busybox@18372 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--Config.in3
-rw-r--r--coreutils/echo.c75
-rw-r--r--findutils/find.c25
-rw-r--r--include/applets.h7
-rw-r--r--libbb/process_escape_sequence.c9
-rw-r--r--libbb/vfork_daemon_rexec.c8
6 files changed, 77 insertions, 50 deletions
diff --git a/Config.in b/Config.in
index fea408148..59d7d6731 100644
--- a/Config.in
+++ b/Config.in
@@ -244,7 +244,8 @@ config FEATURE_EXEC_PREFER_APPLETS
244 help 244 help
245 This is an experimental option which directs applets about to 245 This is an experimental option which directs applets about to
246 call 'exec' to try and find an applicable busybox applet before 246 call 'exec' to try and find an applicable busybox applet before
247 searching the executable path for a binary or symlink to execute. 247 searching the PATH. This may affect shell, find -exec, xargs and
248 similar programs.
248 249
249config BUSYBOX_EXEC_PATH 250config BUSYBOX_EXEC_PATH
250 string "Path to BusyBox executable" 251 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 @@
20 * 1) In handling '\c' escape, the previous version only suppressed the 20 * 1) In handling '\c' escape, the previous version only suppressed the
21 * trailing newline. SUSv3 specifies _no_ output after '\c'. 21 * trailing newline. SUSv3 specifies _no_ output after '\c'.
22 * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}. 22 * 2) SUSv3 specifies that octal escapes are of the form \0{#{#{#}}}.
23 * The previous version version did not allow 4-digit octals. 23 * The previous version did not allow 4-digit octals.
24 */ 24 */
25 25
26
27#include <stdio.h>
28#include <string.h>
29#include <stdlib.h>
30#include "busybox.h" 26#include "busybox.h"
31 27
32int bb_echo(char **argv) 28int bb_echo(char **argv)
33{ 29{
34#ifndef CONFIG_FEATURE_FANCY_ECHO 30 const char *arg;
31#if !ENABLE_FEATURE_FANCY_ECHO
35#define eflag '\\' 32#define eflag '\\'
36 ++argv; 33 ++argv;
37#else 34#else
38 const char *p; 35 const char *p;
39 int nflag = 1; 36 char nflag = 1;
40 int eflag = 0; 37 char eflag = 0;
38
39 while (1) {
40 arg = *++argv;
41 if (!arg)
42 goto ret;
43 if (*arg != '-')
44 break;
41 45
42 while (*++argv && (**argv == '-')) {
43 /* If it appears that we are handling options, then make sure 46 /* If it appears that we are handling options, then make sure
44 * that all of the options specified are actually valid. 47 * that all of the options specified are actually valid.
45 * Otherwise, the string should just be echoed. 48 * Otherwise, the string should just be echoed.
46 */ 49 */
47 50 p = arg + 1;
48 if (!*(p = *argv + 1)) { /* A single '-', so echo it. */ 51 if (!*p) /* A single '-', so echo it. */
49 goto just_echo; 52 goto just_echo;
50 }
51 53
52 do { 54 do {
53 if (strrchr("neE", *p) == 0) { 55 if (!strrchr("neE", *p))
54 goto just_echo; 56 goto just_echo;
55 }
56 } while (*++p); 57 } while (*++p);
57 58
58 /* All of the options in this arg are valid, so handle them. */ 59 /* All of the options in this arg are valid, so handle them. */
59 p = *argv + 1; 60 p = arg + 1;
60 do { 61 do {
61 if (*p == 'n') { 62 if (*p == 'n')
62 nflag = 0; 63 nflag = 0;
63 } else if (*p == 'e') { 64 if (*p == 'e')
64 eflag = '\\'; 65 eflag = '\\';
65 } else {
66 eflag = 0;
67 }
68 } while (*++p); 66 } while (*++p);
69 } 67 }
70 68 just_echo:
71just_echo:
72#endif 69#endif
73 while (*argv) { 70 while (1) {
71 /* arg is already = *argv and isn't NULL */
74 int c; 72 int c;
75 73
76 while ((c = *(*argv)++)) { 74 while ((c = *arg++)) {
77 if (c == eflag) { /* Check for escape seq. */ 75 if (c == eflag) { /* Check for escape seq. */
78 if (**argv == 'c') { 76 if (*arg == 'c') {
79 /* '\c' means cancel newline and 77 /* '\c' means cancel newline and
80 * ignore all subsequent chars. */ 78 * ignore all subsequent chars. */
81 return 0; 79 goto ret;
82 } 80 }
83#ifndef CONFIG_FEATURE_FANCY_ECHO 81#if !ENABLE_FEATURE_FANCY_ECHO
84 /* SUSv3 specifies that octal escapes must begin with '0'. */ 82 /* SUSv3 specifies that octal escapes must begin with '0'. */
85 if (((unsigned int)(**argv - '1')) >= 7) 83 if ( (((unsigned char)*arg) - '1') >= 7)
86#endif 84#endif
87 { 85 {
88 /* Since SUSv3 mandates a first digit of 0, 4-digit octals 86 /* Since SUSv3 mandates a first digit of 0, 4-digit octals
89 * of the form \0### are accepted. */ 87 * of the form \0### are accepted. */
90 if ((**argv == '0') && (((unsigned int)(argv[0][1] - '0')) < 8)) { 88 if (*arg == '0' && ((unsigned char)(arg[1]) - '0') < 8) {
91 (*argv)++; 89 arg++;
92 } 90 }
93 /* bb_process_escape_sequence can handle nul correctly */ 91 /* bb_process_escape_sequence can handle nul correctly */
94 c = bb_process_escape_sequence((const char **) argv); 92 c = bb_process_escape_sequence(&arg);
95 } 93 }
96 } 94 }
97 putchar(c); 95 putchar(c);
98 } 96 }
99 97
100 if (*++argv) { 98 arg = *++argv;
101 putchar(' '); 99 if (!arg)
102 } 100 break;
101 putchar(' ');
103 } 102 }
104 103
105#ifdef CONFIG_FEATURE_FANCY_ECHO 104#ifdef CONFIG_FEATURE_FANCY_ECHO
@@ -109,14 +108,16 @@ just_echo:
109#else 108#else
110 putchar('\n'); 109 putchar('\n');
111#endif 110#endif
112 return 0; 111 ret:
112 return fflush(stdout);
113} 113}
114 114
115/* This is a NOFORK applet. Be very careful! */
116
115int echo_main(int argc, char** argv); 117int echo_main(int argc, char** argv);
116int echo_main(int argc, char** argv) 118int echo_main(int argc, char** argv)
117{ 119{
118 (void)bb_echo(argv); 120 return bb_echo(argv);
119 fflush_stdout_and_exit(EXIT_SUCCESS);
120} 121}
121 122
122/*- 123/*-
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)
242 for (i = 0; i < ap->exec_argc; i++) 242 for (i = 0; i < ap->exec_argc; i++)
243 argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName); 243 argv[i] = subst(ap->exec_argv[i], ap->subst_count[i], fileName);
244 argv[i] = NULL; /* terminate the list */ 244 argv[i] = NULL; /* terminate the list */
245 rc = wait4pid(spawn(argv)); 245
246 if (rc) 246 if (ENABLE_FEATURE_EXEC_PREFER_APPLETS) {
247 const struct BB_applet *a = find_applet_by_name(argv[0]);
248 if (a) {
249 if (a->nofork) {
250 rc = a->main(ap->exec_argc, argv);
251 goto f;
252 }
253#ifndef BB_NOMMU
254 if (a->noexec) {
255 rc = fork();
256 if (rc) goto w;
257 current_applet = a;
258 run_current_applet_and_exit(ap->exec_argc, argv);
259 }
260#endif
261 }
262 }
263 rc = spawn(argv);
264 w:
265 rc = wait4pid(rc);
266 if (rc < 0)
247 bb_perror_msg("%s", argv[0]); 267 bb_perror_msg("%s", argv[0]);
268 f:
248 for (i = 0; i < ap->exec_argc; i++) 269 for (i = 0; i < ap->exec_argc; i++)
249 free(argv[i]); 270 free(argv[i]);
250 return rc == 0; /* return 1 if success */ 271 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:
28# define APPLET_NOUSAGE(name,main,l,s) int main##_main(int argc, char **argv); 28# define APPLET_NOUSAGE(name,main,l,s) int main##_main(int argc, char **argv);
29# define APPLET_ODDNAME(name,main,l,s,name2) int main##_main(int argc, char **argv); 29# define APPLET_ODDNAME(name,main,l,s,name2) int main##_main(int argc, char **argv);
30# define APPLET_NOEXEC(name,main,l,s,name2) int main##_main(int argc, char **argv); 30# define APPLET_NOEXEC(name,main,l,s,name2) int main##_main(int argc, char **argv);
31# define APPLET_NOFORK(name,main,l,s,name2) int main##_main(int argc, char **argv);
31 32
32#elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE 33#elif defined(MAKE_USAGE) && ENABLE_FEATURE_VERBOSE_USAGE
33# define APPLET(name,l,s) name##_trivial_usage "\n\n" name##_full_usage "\0" 34# define APPLET(name,l,s) name##_trivial_usage "\n\n" name##_full_usage "\0"
34# define APPLET_NOUSAGE(name,main,l,s) "\b\0" 35# define APPLET_NOUSAGE(name,main,l,s) "\b\0"
35# define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0" 36# define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0"
36# define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0" 37# define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0"
38# define APPLET_NOFORK(name,main,l,s,name2) name2##_trivial_usage "\n\n" name2##_full_usage "\0"
37 39
38#elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE 40#elif defined(MAKE_USAGE) && !ENABLE_FEATURE_VERBOSE_USAGE
39# define APPLET(name,l,s) name##_trivial_usage "\0" 41# define APPLET(name,l,s) name##_trivial_usage "\0"
40# define APPLET_NOUSAGE(name,main,l,s) "\b\0" 42# define APPLET_NOUSAGE(name,main,l,s) "\b\0"
41# define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\0" 43# define APPLET_ODDNAME(name,main,l,s,name2) name2##_trivial_usage "\0"
42# define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\0" 44# define APPLET_NOEXEC(name,main,l,s,name2) name2##_trivial_usage "\0"
45# define APPLET_NOFORK(name,main,l,s,name2) name2##_trivial_usage "\0"
43 46
44#elif defined(MAKE_LINKS) 47#elif defined(MAKE_LINKS)
45# define APPLET(name,l,c) LINK l name 48# define APPLET(name,l,c) LINK l name
46# define APPLET_NOUSAGE(name,main,l,s) LINK l name 49# define APPLET_NOUSAGE(name,main,l,s) LINK l name
47# define APPLET_ODDNAME(name,main,l,s,name2) LINK l name 50# define APPLET_ODDNAME(name,main,l,s,name2) LINK l name
48# define APPLET_NOEXEC(name,main,l,s,name2) LINK l name 51# define APPLET_NOEXEC(name,main,l,s,name2) LINK l name
52# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
49 53
50#else 54#else
51 const struct BB_applet applets[] = { /* name,main,location,need_suid */ 55 const struct BB_applet applets[] = { /* name,main,location,need_suid */
@@ -53,6 +57,7 @@ s - suid type:
53# define APPLET_NOUSAGE(name,main,l,s) {#name,main##_main,l,s}, 57# define APPLET_NOUSAGE(name,main,l,s) {#name,main##_main,l,s},
54# define APPLET_ODDNAME(name,main,l,s,name2) {#name,main##_main,l,s}, 58# define APPLET_ODDNAME(name,main,l,s,name2) {#name,main##_main,l,s},
55# define APPLET_NOEXEC(name,main,l,s,name2) {#name,main##_main,l,s,1}, 59# define APPLET_NOEXEC(name,main,l,s,name2) {#name,main##_main,l,s,1},
60# define APPLET_NOFORK(name,main,l,s,name2) {#name,main##_main,l,s,1,1},
56#endif 61#endif
57 62
58#if ENABLE_INSTALL_NO_USR 63#if ENABLE_INSTALL_NO_USR
@@ -118,7 +123,7 @@ USE_DUMPKMAP(APPLET(dumpkmap, _BB_DIR_BIN, _BB_SUID_NEVER))
118USE_APP_DUMPLEASES(APPLET(dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 123USE_APP_DUMPLEASES(APPLET(dumpleases, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
119//USE_E2FSCK(APPLET(e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER)) 124//USE_E2FSCK(APPLET(e2fsck, _BB_DIR_SBIN, _BB_SUID_NEVER))
120//USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER)) 125//USE_E2LABEL(APPLET_NOUSAGE(e2label, tune2fs, _BB_DIR_SBIN, _BB_SUID_NEVER))
121USE_ECHO(APPLET_NOEXEC(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER, echo)) 126USE_ECHO(APPLET_NOFORK(echo, echo, _BB_DIR_BIN, _BB_SUID_NEVER, echo))
122USE_ED(APPLET(ed, _BB_DIR_BIN, _BB_SUID_NEVER)) 127USE_ED(APPLET(ed, _BB_DIR_BIN, _BB_SUID_NEVER))
123USE_FEATURE_GREP_EGREP_ALIAS(APPLET_NOUSAGE(egrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER)) 128USE_FEATURE_GREP_EGREP_ALIAS(APPLET_NOUSAGE(egrep, grep, _BB_DIR_BIN, _BB_SUID_NEVER))
124USE_EJECT(APPLET(eject, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 129USE_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 @@
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 */ 9 */
10 10
11#include <stdio.h>
12#include <limits.h>
13#include <ctype.h>
14#include "libbb.h" 11#include "libbb.h"
15 12
16#define WANT_HEX_ESCAPES 1 13#define WANT_HEX_ESCAPES 1
@@ -46,10 +43,10 @@ char bb_process_escape_sequence(const char **ptr)
46#endif 43#endif
47 44
48 do { 45 do {
49 d = (unsigned int)(*q - '0'); 46 d = (unsigned char)(*q) - '0';
50#ifdef WANT_HEX_ESCAPES 47#ifdef WANT_HEX_ESCAPES
51 if (d >= 10) { 48 if (d >= 10) {
52 d = ((unsigned int)(_tolower(*q) - 'a')) + 10; 49 d = (unsigned char)(_tolower(*q)) - 'a' + 10;
53 } 50 }
54#endif 51#endif
55 52
@@ -80,7 +77,7 @@ char bb_process_escape_sequence(const char **ptr)
80 break; 77 break;
81 } 78 }
82 } while (*++p); 79 } while (*++p);
83 n = *(p+(sizeof(charmap)/2)); 80 n = *(p + (sizeof(charmap)/2));
84 } 81 }
85 82
86 *ptr = q; 83 *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)
26 volatile int failed; 26 volatile int failed;
27 pid_t pid; 27 pid_t pid;
28 28
29 // Be nice to nommu machines. 29// Ain't it a good place to fflush(NULL)?
30
31 /* Be nice to nommu machines. */
30 failed = 0; 32 failed = 0;
31 pid = vfork(); 33 pid = vfork();
32 if (pid < 0) /* error */ 34 if (pid < 0) /* error */
33 return pid; 35 return pid;
34 if (!pid) { /* child */ 36 if (!pid) { /* child */
35 /* Don't use BB_EXECVP tricks here! */ 37 /* This macro is ok - it doesn't do NOEXEC/NOFORK tricks */
36 execvp(argv[0], argv); 38 BB_EXECVP(argv[0], argv);
37 39
38 /* We are (maybe) sharing a stack with blocked parent, 40 /* We are (maybe) sharing a stack with blocked parent,
39 * let parent know we failed and then exit to unblock parent 41 * let parent know we failed and then exit to unblock parent