aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-11-28 06:49:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-11-28 06:49:03 +0000
commit1aa7e477b1b727db77cac2d717f0fcca40587f78 (patch)
tree247171517f0e01d32a71a5e96f4bef462cc0e9c6
parent79c6904faff1ebd4bf4b7d9cd0c20ca70f4cec75 (diff)
downloadbusybox-w32-1aa7e477b1b727db77cac2d717f0fcca40587f78.tar.gz
busybox-w32-1aa7e477b1b727db77cac2d717f0fcca40587f78.tar.bz2
busybox-w32-1aa7e477b1b727db77cac2d717f0fcca40587f78.zip
reorganize applet table. Eliminates pointers to names.
Should be a big win for libbusybox. busybox wins too: text data bss dec hex filename 776524 929 9100 786553 c0079 busybox_old 775903 929 9100 785932 bfe0c busybox_unstripped
-rw-r--r--Makefile2
-rw-r--r--applets/Kbuild12
-rw-r--r--applets/applets.c2
-rw-r--r--include/applets.h13
-rw-r--r--include/busybox.h46
-rw-r--r--include/libbb.h11
-rw-r--r--libbb/appletlib.c87
-rw-r--r--libbb/execable.c2
-rw-r--r--libbb/vfork_daemon_rexec.c22
-rw-r--r--shell/ash.c30
-rw-r--r--shell/hush.c16
-rw-r--r--shell/lash_unused.c6
-rw-r--r--shell/msh.c16
13 files changed, 137 insertions, 128 deletions
diff --git a/Makefile b/Makefile
index cfa1acad9..5de426ad3 100644
--- a/Makefile
+++ b/Makefile
@@ -928,6 +928,8 @@ MRPROPER_FILES += .config .config.old include/asm .version .old_version \
928 include/autoconf.h \ 928 include/autoconf.h \
929 include/bbconfigopts.h \ 929 include/bbconfigopts.h \
930 include/usage_compressed.h \ 930 include/usage_compressed.h \
931 include/applet_tables.h \
932 applets/usage \
931 .kernelrelease Module.symvers tags TAGS cscope* 933 .kernelrelease Module.symvers tags TAGS cscope*
932 934
933# clean - Delete most, but leave enough to build external modules 935# clean - Delete most, but leave enough to build external modules
diff --git a/applets/Kbuild b/applets/Kbuild
index 289c5def4..b9dba03e1 100644
--- a/applets/Kbuild
+++ b/applets/Kbuild
@@ -8,7 +8,7 @@ obj-y :=
8obj-y += applets.o 8obj-y += applets.o
9 9
10hostprogs-y:= 10hostprogs-y:=
11hostprogs-y += usage 11hostprogs-y += usage applet_tables
12 12
13always:= $(hostprogs-y) 13always:= $(hostprogs-y)
14 14
@@ -19,7 +19,15 @@ quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h
19 19
20HOSTCFLAGS_usage.o = -I$(srctree)/include 20HOSTCFLAGS_usage.o = -I$(srctree)/include
21 21
22applets/applets.o: include/usage_compressed.h 22applets/applets.o: include/usage_compressed.h include/applet_tables.h
23
23applets/usage: .config $(srctree)/applets/usage_compressed 24applets/usage: .config $(srctree)/applets/usage_compressed
25
24include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed 26include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed
25 $(call cmd,gen_usage_compressed) 27 $(call cmd,gen_usage_compressed)
28
29# Two-stage file creation, to avoid having target file still created
30# in case applet_tables fails
31include/applet_tables.h: applets/applet_tables
32 applets/applet_tables >include/applet_tables.h.tmp
33 mv include/applet_tables.h.tmp include/applet_tables.h
diff --git a/applets/applets.c b/applets/applets.c
index 636b5c91e..33951fa8f 100644
--- a/applets/applets.c
+++ b/applets/applets.c
@@ -2,7 +2,7 @@
2/* 2/*
3 * Stub for linking busybox binary against libbusybox. 3 * Stub for linking busybox binary against libbusybox.
4 * 4 *
5 * Copyright (C) 2007 Denis Vlasenko 5 * Copyright (C) 2007 Denys Vlasenko <vda.linux@googlemail.com>
6 * 6 *
7 * Licensed under GPLv2, see file License in this tarball for details. 7 * Licensed under GPLv2, see file License in this tarball for details.
8 */ 8 */
diff --git a/include/applets.h b/include/applets.h
index 2f31a587f..f35a1d80b 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -59,12 +59,12 @@ s - suid type:
59# define APPLET_NOFORK(name,main,l,s,name2) LINK l name 59# define APPLET_NOFORK(name,main,l,s,name2) LINK l name
60 60
61#else 61#else
62 const struct bb_applet applets[] = { /* name, main, location, need_suid */ 62 static struct bb_applet applets[] = { /* name, main, location, need_suid */
63# define APPLET(name,l,s) { #name, name##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) }, 63# define APPLET(name,l,s) { #name, #name, l, s },
64# define APPLET_NOUSAGE(name,main,l,s) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) }, 64# define APPLET_NOUSAGE(name,main,l,s) { #name, #main, l, s },
65# define APPLET_ODDNAME(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) }, 65# define APPLET_ODDNAME(name,main,l,s,name2) { #name, #main, l, s },
66# define APPLET_NOEXEC(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_PREFER_APPLETS(,1) }, 66# define APPLET_NOEXEC(name,main,l,s,name2) { #name, #main, l, s, 1 },
67# define APPLET_NOFORK(name,main,l,s,name2) { #name, main##_main USE_FEATURE_INSTALLER(,l) USE_FEATURE_SUID(,s) USE_FEATURE_PREFER_APPLETS(,1 ,1) }, 67# define APPLET_NOFORK(name,main,l,s,name2) { #name, #main, l, s, 1, 1 },
68#endif 68#endif
69 69
70#if ENABLE_INSTALL_NO_USR 70#if ENABLE_INSTALL_NO_USR
@@ -385,7 +385,6 @@ USE_GUNZIP(APPLET_ODDNAME(zcat, gunzip, _BB_DIR_BIN, _BB_SUID_NEVER, zcat))
385USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER)) 385USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER))
386 386
387#if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE) 387#if !defined(PROTOTYPES) && !defined(NAME_MAIN_CNAME) && !defined(MAKE_USAGE)
388 { NULL }
389}; 388};
390#endif 389#endif
391 390
diff --git a/include/busybox.h b/include/busybox.h
index 7ef36901a..f99901aa3 100644
--- a/include/busybox.h
+++ b/include/busybox.h
@@ -9,8 +9,7 @@
9 9
10#include "libbb.h" 10#include "libbb.h"
11 11
12#if ENABLE_FEATURE_INSTALLER 12/* order matters: used as index into "install_dir[]" in appletlib.c */
13/* order matters: used as index into "install_dir[]" in busybox.c */
14typedef enum bb_install_loc_t { 13typedef enum bb_install_loc_t {
15 _BB_DIR_ROOT = 0, 14 _BB_DIR_ROOT = 0,
16 _BB_DIR_BIN, 15 _BB_DIR_BIN,
@@ -18,40 +17,41 @@ typedef enum bb_install_loc_t {
18 _BB_DIR_USR_BIN, 17 _BB_DIR_USR_BIN,
19 _BB_DIR_USR_SBIN 18 _BB_DIR_USR_SBIN
20} bb_install_loc_t; 19} bb_install_loc_t;
21#endif
22 20
23#if ENABLE_FEATURE_SUID
24typedef enum bb_suid_t { 21typedef enum bb_suid_t {
25 _BB_SUID_NEVER = 0, 22 _BB_SUID_NEVER = 0,
26 _BB_SUID_MAYBE, 23 _BB_SUID_MAYBE,
27 _BB_SUID_ALWAYS 24 _BB_SUID_ALWAYS
28} bb_suid_t; 25} bb_suid_t;
29#endif
30 26
31struct bb_applet { 27
32 const char *name; 28/* Defined in appletlib.c (by including generated applet_tables.h) */
33 int (*main) (int argc, char **argv); 29/* Keep in sync with applets/applet_tables.c! */
34#if ENABLE_FEATURE_INSTALLER 30extern const char applet_names[];
35 __extension__ enum bb_install_loc_t install_loc:8; 31extern int (*const applet_mains[])(int argc, char **argv);
32
33#if ENABLE_FEATURE_INSTALLER || ENABLE_FEATURE_PREFER_APPLETS
34extern const uint32_t applet_nameofs[];
35#else
36extern const uint16_t applet_nameofs[];
36#endif 37#endif
38
37#if ENABLE_FEATURE_SUID 39#if ENABLE_FEATURE_SUID
38 __extension__ enum bb_suid_t need_suid:8; 40#define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0x3fff))
41#define APPLET_SUID(i) ((applet_nameofs[i] >> 14) & 0x3)
42#else
43#define APPLET_NAME(i) (applet_names + (applet_nameofs[i] & 0xffff))
39#endif 44#endif
40#if ENABLE_FEATURE_PREFER_APPLETS 45
41 /* true if instead of fork(); exec("applet"); waitpid(); 46#if ENABLE_FEATURE_INSTALLER
42 * one can do fork(); exit(applet_main(argc,argv)); waitpid(); */ 47#define APPLET_INSTALL_LOC(i) ((applet_nameofs[i] >> 16) & 0x7)
43 unsigned char noexec;
44 /* Even nicer */
45 /* true if instead of fork(); exec("applet"); waitpid();
46 * one can simply call applet_main(argc,argv); */
47 unsigned char nofork;
48#endif 48#endif
49};
50 49
50#if ENABLE_FEATURE_PREFER_APPLETS
51#define APPLET_IS_NOFORK(i) (applet_nameofs[i] & (1 << 19))
52#define APPLET_IS_NOEXEC(i) (applet_nameofs[i] & (1 << 20))
53#endif
51 54
52/* Defined in appletlib.c */
53extern const struct bb_applet applets[];
54extern const unsigned short NUM_APPLETS;
55 55
56/* Length of these names has effect on size of libbusybox 56/* Length of these names has effect on size of libbusybox
57 * and "individual" binaries. Keep them short. 57 * and "individual" binaries. Keep them short.
diff --git a/include/libbb.h b/include/libbb.h
index 095647dd4..2b928215f 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -550,7 +550,6 @@ void clear_username_cache(void);
550enum { USERNAME_MAX_SIZE = 16 - sizeof(int) }; 550enum { USERNAME_MAX_SIZE = 16 - sizeof(int) };
551 551
552 552
553struct bb_applet;
554int execable_file(const char *name); 553int execable_file(const char *name);
555char *find_execable(const char *filename); 554char *find_execable(const char *filename);
556int exists_execable(const char *filename); 555int exists_execable(const char *filename);
@@ -562,7 +561,7 @@ int exists_execable(const char *filename);
562int bb_execvp(const char *file, char *const argv[]); 561int bb_execvp(const char *file, char *const argv[]);
563#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd) 562#define BB_EXECVP(prog,cmd) bb_execvp(prog,cmd)
564#define BB_EXECLP(prog,cmd,...) \ 563#define BB_EXECLP(prog,cmd,...) \
565 execlp((find_applet_by_name(prog)) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \ 564 execlp((find_applet_by_name(prog) >= 0) ? CONFIG_BUSYBOX_EXEC_PATH : prog, \
566 cmd, __VA_ARGS__) 565 cmd, __VA_ARGS__)
567#else 566#else
568#define BB_EXECVP(prog,cmd) execvp(prog,cmd) 567#define BB_EXECVP(prog,cmd) execvp(prog,cmd)
@@ -600,8 +599,8 @@ struct nofork_save_area {
600void save_nofork_data(struct nofork_save_area *save); 599void save_nofork_data(struct nofork_save_area *save);
601void restore_nofork_data(struct nofork_save_area *save); 600void restore_nofork_data(struct nofork_save_area *save);
602/* Does NOT check that applet is NOFORK, just blindly runs it */ 601/* Does NOT check that applet is NOFORK, just blindly runs it */
603int run_nofork_applet(const struct bb_applet *a, char **argv); 602int run_nofork_applet(int applet_no, char **argv);
604int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv); 603int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv);
605 604
606/* Helpers for daemonization. 605/* Helpers for daemonization.
607 * 606 *
@@ -786,10 +785,10 @@ const struct hwtype *get_hwntype(int type);
786 785
787 786
788#ifndef BUILD_INDIVIDUAL 787#ifndef BUILD_INDIVIDUAL
789extern const struct bb_applet *find_applet_by_name(const char *name); 788extern int find_applet_by_name(const char *name);
790/* Returns only if applet is not found. */ 789/* Returns only if applet is not found. */
791extern void run_applet_and_exit(const char *name, char **argv); 790extern void run_applet_and_exit(const char *name, char **argv);
792extern void run_appletstruct_and_exit(const struct bb_applet *a, char **argv) ATTRIBUTE_NORETURN; 791extern void run_applet_no_and_exit(int a, char **argv) ATTRIBUTE_NORETURN;
793#endif 792#endif
794 793
795extern int match_fstype(const struct mntent *mt, const char *fstypes); 794extern int match_fstype(const struct mntent *mt, const char *fstypes);
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 4bd60d049..dcf24f5a9 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -33,13 +33,9 @@ static const char usage_messages[] ALIGN1 = ""
33#define usage_messages 0 33#define usage_messages 0
34#endif /* SHOW_USAGE */ 34#endif /* SHOW_USAGE */
35 35
36/* Define struct bb_applet applets[] */
37#include "applets.h"
38 36
39#if ENABLE_FEATURE_SH_STANDALONE 37/* Include generated applet names, pointers to <apllet>_main, etc */
40/* -1 because last entry is NULL */ 38#include "applet_tables.h"
41const unsigned short NUM_APPLETS = ARRAY_SIZE(applets) - 1;
42#endif
43 39
44 40
45#if ENABLE_FEATURE_COMPRESS_USAGE 41#if ENABLE_FEATURE_COMPRESS_USAGE
@@ -84,16 +80,14 @@ void bb_show_usage(void)
84 const char *format_string; 80 const char *format_string;
85 const char *p; 81 const char *p;
86 const char *usage_string = p = unpack_usage_messages(); 82 const char *usage_string = p = unpack_usage_messages();
87 const struct bb_applet *ap = find_applet_by_name(applet_name); 83 int ap = find_applet_by_name(applet_name);
88 int i;
89 84
90 if (!ap) /* never happens, paranoia */ 85 if (ap < 0) /* never happens, paranoia */
91 xfunc_die(); 86 xfunc_die();
92 87
93 i = ap - applets; 88 while (ap) {
94 while (i) {
95 while (*p++) continue; 89 while (*p++) continue;
96 i--; 90 ap--;
97 } 91 }
98 92
99 fprintf(stderr, "%s multi-call binary\n", bb_banner); 93 fprintf(stderr, "%s multi-call binary\n", bb_banner);
@@ -107,18 +101,22 @@ void bb_show_usage(void)
107} 101}
108 102
109 103
110static int applet_name_compare(const void *name, const void *vapplet) 104static int applet_name_compare(const void *name, const void *v)
111{ 105{
112 const struct bb_applet *applet = vapplet; 106 int i = (const char *)v - applet_names;
113 107 return strcmp(name, APPLET_NAME(i));
114 return strcmp(name, applet->name);
115} 108}
116 109
117const struct bb_applet *find_applet_by_name(const char *name) 110int find_applet_by_name(const char *name)
118{ 111{
112 const char *p;
119 /* Do a binary search to find the applet entry given the name. */ 113 /* Do a binary search to find the applet entry given the name. */
120 return bsearch(name, applets, ARRAY_SIZE(applets)-1, sizeof(applets[0]), 114
121 applet_name_compare); 115 /* NB: any char pointer will work as well, not necessarily applet_names */
116 p = bsearch(name, applet_names, ARRAY_SIZE(applet_mains), 1, applet_name_compare);
117 if (!p)
118 return -1;
119 return p - applet_names;
122} 120}
123 121
124 122
@@ -166,7 +164,7 @@ USE_FEATURE_SUID(static uid_t ruid;) /* real uid */
166 164
167/* applets[] is const, so we have to define this "override" structure */ 165/* applets[] is const, so we have to define this "override" structure */
168static struct BB_suid_config { 166static struct BB_suid_config {
169 const struct bb_applet *m_applet; 167 int m_applet;
170 uid_t m_uid; 168 uid_t m_uid;
171 gid_t m_gid; 169 gid_t m_gid;
172 mode_t m_mode; 170 mode_t m_mode;
@@ -232,7 +230,7 @@ static void parse_config_file(void)
232{ 230{
233 struct BB_suid_config *sct_head; 231 struct BB_suid_config *sct_head;
234 struct BB_suid_config *sct; 232 struct BB_suid_config *sct;
235 const struct bb_applet *applet; 233 int applet_no;
236 FILE *f; 234 FILE *f;
237 const char *errmsg; 235 const char *errmsg;
238 char *s; 236 char *s;
@@ -343,14 +341,14 @@ static void parse_config_file(void)
343 * applet is currently built in and ignore it otherwise. 341 * applet is currently built in and ignore it otherwise.
344 * Note: this can hide config file bugs which only pop 342 * Note: this can hide config file bugs which only pop
345 * up when the busybox configuration is changed. */ 343 * up when the busybox configuration is changed. */
346 applet = find_applet_by_name(s); 344 applet_no = find_applet_by_name(s);
347 if (applet) { 345 if (applet_no >= 0) {
348 /* Note: We currently don't check for duplicates! 346 /* Note: We currently don't check for duplicates!
349 * The last config line for each applet will be the 347 * The last config line for each applet will be the
350 * one used since we insert at the head of the list. 348 * one used since we insert at the head of the list.
351 * I suppose this could be considered a feature. */ 349 * I suppose this could be considered a feature. */
352 sct = xmalloc(sizeof(struct BB_suid_config)); 350 sct = xmalloc(sizeof(struct BB_suid_config));
353 sct->m_applet = applet; 351 sct->m_applet = applet_no;
354 sct->m_mode = 0; 352 sct->m_mode = 0;
355 sct->m_next = sct_head; 353 sct->m_next = sct_head;
356 sct_head = sct; 354 sct_head = sct;
@@ -441,7 +439,7 @@ static inline void parse_config_file(void)
441 439
442 440
443#if ENABLE_FEATURE_SUID 441#if ENABLE_FEATURE_SUID
444static void check_suid(const struct bb_applet *applet) 442static void check_suid(int applet_no)
445{ 443{
446 gid_t rgid; /* real gid */ 444 gid_t rgid; /* real gid */
447 445
@@ -456,7 +454,7 @@ static void check_suid(const struct bb_applet *applet)
456 mode_t m; 454 mode_t m;
457 455
458 for (sct = suid_config; sct; sct = sct->m_next) { 456 for (sct = suid_config; sct; sct = sct->m_next) {
459 if (sct->m_applet == applet) 457 if (sct->m_applet == applet_no)
460 goto found; 458 goto found;
461 } 459 }
462 goto check_need_suid; 460 goto check_need_suid;
@@ -504,12 +502,12 @@ static void check_suid(const struct bb_applet *applet)
504#endif 502#endif
505 check_need_suid: 503 check_need_suid:
506#endif 504#endif
507 if (applet->need_suid == _BB_SUID_ALWAYS) { 505 if (APPLET_SUID(applet_no) == _BB_SUID_ALWAYS) {
508 /* Real uid is not 0. If euid isn't 0 too, suid bit 506 /* Real uid is not 0. If euid isn't 0 too, suid bit
509 * is most probably not set on our executable */ 507 * is most probably not set on our executable */
510 if (geteuid()) 508 if (geteuid())
511 bb_error_msg_and_die("must be suid to work properly"); 509 bb_error_msg_and_die("must be suid to work properly");
512 } else if (applet->need_suid == _BB_SUID_NEVER) { 510 } else if (APPLET_SUID(applet_no) == _BB_SUID_NEVER) {
513 xsetgid(rgid); /* drop all privileges */ 511 xsetgid(rgid); /* drop all privileges */
514 xsetuid(ruid); 512 xsetuid(ruid);
515 } 513 }
@@ -536,18 +534,19 @@ static void install_links(const char *busybox, int use_symbolic_links)
536 usr_sbin 534 usr_sbin
537 }; 535 };
538 536
539 int (*lf)(const char *, const char *) = link; 537 int (*lf)(const char *, const char *);
540 char *fpc; 538 char *fpc;
541 int i; 539 int i;
542 int rc; 540 int rc;
543 541
542 lf = link;
544 if (use_symbolic_links) 543 if (use_symbolic_links)
545 lf = symlink; 544 lf = symlink;
546 545
547 for (i = 0; applets[i].name != NULL; i++) { 546 for (i = 0; i < ARRAY_SIZE(applet_mains); i++) {
548 fpc = concat_path_file( 547 fpc = concat_path_file(
549 install_dir[applets[i].install_loc], 548 install_dir[APPLET_INSTALL_LOC(i)],
550 applets[i].name); 549 APPLET_NAME(i));
551 rc = lf(busybox, fpc); 550 rc = lf(busybox, fpc);
552 if (rc != 0 && errno != EEXIST) { 551 if (rc != 0 && errno != EEXIST) {
553 bb_simple_perror_msg(fpc); 552 bb_simple_perror_msg(fpc);
@@ -564,7 +563,7 @@ static int busybox_main(char **argv)
564{ 563{
565 if (!argv[1]) { 564 if (!argv[1]) {
566 /* Called without arguments */ 565 /* Called without arguments */
567 const struct bb_applet *a; 566 const char *a;
568 int col, output_width; 567 int col, output_width;
569 help: 568 help:
570 output_width = 80; 569 output_width = 80;
@@ -588,14 +587,14 @@ static int busybox_main(char **argv)
588 "\twill act like whatever it was invoked as!\n" 587 "\twill act like whatever it was invoked as!\n"
589 "\nCurrently defined functions:\n"); 588 "\nCurrently defined functions:\n");
590 col = 0; 589 col = 0;
591 a = applets; 590 a = applet_names;
592 while (a->name) { 591 while (*a) {
593 if (col > output_width) { 592 if (col > output_width) {
594 puts(","); 593 puts(",");
595 col = 0; 594 col = 0;
596 } 595 }
597 col += printf("%s%s", (col ? ", " : "\t"), a->name); 596 col += printf("%s%s", (col ? ", " : "\t"), a);
598 a++; 597 a += strlen(a) + 1;
599 } 598 }
600 puts("\n"); 599 puts("\n");
601 return 0; 600 return 0;
@@ -629,7 +628,7 @@ static int busybox_main(char **argv)
629 bb_error_msg_and_die("applet not found"); 628 bb_error_msg_and_die("applet not found");
630} 629}
631 630
632void run_appletstruct_and_exit(const struct bb_applet *applet, char **argv) 631void run_applet_no_and_exit(int applet_no, char **argv)
633{ 632{
634 int argc = 1; 633 int argc = 1;
635 634
@@ -640,19 +639,19 @@ void run_appletstruct_and_exit(const struct bb_applet *applet, char **argv)
640 optind = 1; 639 optind = 1;
641 xfunc_error_retval = EXIT_FAILURE; 640 xfunc_error_retval = EXIT_FAILURE;
642 641
643 applet_name = applet->name; 642 applet_name = APPLET_NAME(applet_no);
644 if (argc == 2 && !strcmp(argv[1], "--help")) 643 if (argc == 2 && !strcmp(argv[1], "--help"))
645 bb_show_usage(); 644 bb_show_usage();
646 if (ENABLE_FEATURE_SUID) 645 if (ENABLE_FEATURE_SUID)
647 check_suid(applet); 646 check_suid(applet_no);
648 exit(applet->main(argc, argv)); 647 exit(applet_mains[applet_no](argc, argv));
649} 648}
650 649
651void run_applet_and_exit(const char *name, char **argv) 650void run_applet_and_exit(const char *name, char **argv)
652{ 651{
653 const struct bb_applet *applet = find_applet_by_name(name); 652 int applet = find_applet_by_name(name);
654 if (applet) 653 if (applet >= 0)
655 run_appletstruct_and_exit(applet, argv); 654 run_applet_no_and_exit(applet, argv);
656 if (!strncmp(name, "busybox", 7)) 655 if (!strncmp(name, "busybox", 7))
657 exit(busybox_main(argv)); 656 exit(busybox_main(argv));
658} 657}
diff --git a/libbb/execable.c b/libbb/execable.c
index f679108be..2649a6cfe 100644
--- a/libbb/execable.c
+++ b/libbb/execable.c
@@ -65,7 +65,7 @@ int exists_execable(const char *filename)
65 */ 65 */
66int bb_execvp(const char *file, char *const argv[]) 66int bb_execvp(const char *file, char *const argv[])
67{ 67{
68 return execvp(find_applet_by_name(file) ? bb_busybox_exec_path : file, 68 return execvp(find_applet_by_name(file) >= 0 ? bb_busybox_exec_path : file,
69 argv); 69 argv);
70} 70}
71#endif 71#endif
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index a01065d69..1d6817ee6 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -16,7 +16,7 @@
16 */ 16 */
17 17
18#include <paths.h> 18#include <paths.h>
19#include "busybox.h" /* for struct bb_applet */ 19#include "busybox.h" /* uses applet tables */
20 20
21/* This does a fork/exec in one call, using vfork(). Returns PID of new child, 21/* This does a fork/exec in one call, using vfork(). Returns PID of new child,
22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */ 22 * -1 for failure. Runs argv[0], searching path if that has no / in it. */
@@ -120,11 +120,11 @@ void restore_nofork_data(struct nofork_save_area *save)
120 die_sleep = save->die_sleep; 120 die_sleep = save->die_sleep;
121} 121}
122 122
123int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv) 123int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv)
124{ 124{
125 int rc, argc; 125 int rc, argc;
126 126
127 applet_name = a->name; 127 applet_name = APPLET_NAME(applet_no);
128 xfunc_error_retval = EXIT_FAILURE; 128 xfunc_error_retval = EXIT_FAILURE;
129 /*option_mask32 = 0; - not needed */ 129 /*option_mask32 = 0; - not needed */
130 /* special flag for xfunc_die(). If xfunc will "die" 130 /* special flag for xfunc_die(). If xfunc will "die"
@@ -143,7 +143,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
143 char *tmp_argv[argc+1]; 143 char *tmp_argv[argc+1];
144 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); 144 memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
145 /* Finally we can call NOFORK applet's main() */ 145 /* Finally we can call NOFORK applet's main() */
146 rc = a->main(argc, tmp_argv); 146 rc = applet_mains[applet_no](argc, tmp_argv);
147 } else { /* xfunc died in NOFORK applet */ 147 } else { /* xfunc died in NOFORK applet */
148 /* in case they meant to return 0... */ 148 /* in case they meant to return 0... */
149 if (rc == -2222) 149 if (rc == -2222)
@@ -155,13 +155,13 @@ int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet
155 return rc; 155 return rc;
156} 156}
157 157
158int run_nofork_applet(const struct bb_applet *a, char **argv) 158int run_nofork_applet(int applet_no, char **argv)
159{ 159{
160 struct nofork_save_area old; 160 struct nofork_save_area old;
161 161
162 /* Saving globals */ 162 /* Saving globals */
163 save_nofork_data(&old); 163 save_nofork_data(&old);
164 return run_nofork_applet_prime(&old, a, argv); 164 return run_nofork_applet_prime(&old, applet_no, argv);
165} 165}
166#endif /* FEATURE_PREFER_APPLETS */ 166#endif /* FEATURE_PREFER_APPLETS */
167 167
@@ -169,15 +169,15 @@ int spawn_and_wait(char **argv)
169{ 169{
170 int rc; 170 int rc;
171#if ENABLE_FEATURE_PREFER_APPLETS 171#if ENABLE_FEATURE_PREFER_APPLETS
172 const struct bb_applet *a = find_applet_by_name(argv[0]); 172 int a = find_applet_by_name(argv[0]);
173 173
174 if (a && (a->nofork 174 if (a >= 0 && (APPLET_IS_NOFORK(a)
175#if BB_MMU 175#if BB_MMU
176 || a->noexec /* NOEXEC trick needs fork() */ 176 || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */
177#endif 177#endif
178 )) { 178 )) {
179#if BB_MMU 179#if BB_MMU
180 if (a->nofork) 180 if (APPLET_IS_NOFORK(a))
181#endif 181#endif
182 { 182 {
183 return run_nofork_applet(a, argv); 183 return run_nofork_applet(a, argv);
@@ -190,7 +190,7 @@ int spawn_and_wait(char **argv)
190 return wait4pid(rc); 190 return wait4pid(rc);
191 /* child */ 191 /* child */
192 xfunc_error_retval = EXIT_FAILURE; 192 xfunc_error_retval = EXIT_FAILURE;
193 run_appletstruct_and_exit(a, argv); 193 run_applet_no_and_exit(a, argv);
194#endif 194#endif
195 } 195 }
196#endif /* FEATURE_PREFER_APPLETS */ 196#endif /* FEATURE_PREFER_APPLETS */
diff --git a/shell/ash.c b/shell/ash.c
index 8f388f59b..9b9fe5b6d 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -53,7 +53,7 @@
53#if DEBUG 53#if DEBUG
54#define _GNU_SOURCE 54#define _GNU_SOURCE
55#endif 55#endif
56#include "busybox.h" /* for struct bb_applet */ 56#include "busybox.h" /* for applet_names */
57#include <paths.h> 57#include <paths.h>
58#include <setjmp.h> 58#include <setjmp.h>
59#include <fnmatch.h> 59#include <fnmatch.h>
@@ -6479,12 +6479,10 @@ tryexec(char *cmd, char **argv, char **envp)
6479 6479
6480#if ENABLE_FEATURE_SH_STANDALONE 6480#if ENABLE_FEATURE_SH_STANDALONE
6481 if (strchr(cmd, '/') == NULL) { 6481 if (strchr(cmd, '/') == NULL) {
6482 const struct bb_applet *a; 6482 int a = find_applet_by_name(cmd);
6483 6483 if (a >= 0) {
6484 a = find_applet_by_name(cmd); 6484 if (APPLET_IS_NOEXEC(a))
6485 if (a) { 6485 run_applet_no_and_exit(a, argv);
6486 if (a->noexec)
6487 run_appletstruct_and_exit(a, argv);
6488 /* re-exec ourselves with the new arguments */ 6486 /* re-exec ourselves with the new arguments */
6489 execve(bb_busybox_exec_path, argv, envp); 6487 execve(bb_busybox_exec_path, argv, envp);
6490 /* If they called chroot or otherwise made the binary no longer 6488 /* If they called chroot or otherwise made the binary no longer
@@ -6539,7 +6537,7 @@ shellexec(char **argv, const char *path, int idx)
6539 envp = environment(); 6537 envp = environment();
6540 if (strchr(argv[0], '/') 6538 if (strchr(argv[0], '/')
6541#if ENABLE_FEATURE_SH_STANDALONE 6539#if ENABLE_FEATURE_SH_STANDALONE
6542 || find_applet_by_name(argv[0]) 6540 || find_applet_by_name(argv[0]) >= 0
6543#endif 6541#endif
6544 ) { 6542 ) {
6545 tryexec(argv[0], argv, envp); 6543 tryexec(argv[0], argv, envp);
@@ -11117,7 +11115,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
11117 } 11115 }
11118 11116
11119#if ENABLE_FEATURE_SH_STANDALONE 11117#if ENABLE_FEATURE_SH_STANDALONE
11120 if (find_applet_by_name(name)) { 11118 if (find_applet_by_name(name) >= 0) {
11121 entry->cmdtype = CMDNORMAL; 11119 entry->cmdtype = CMDNORMAL;
11122 entry->u.index = -1; 11120 entry->u.index = -1;
11123 return; 11121 return;
@@ -11298,11 +11296,15 @@ helpcmd(int argc, char **argv)
11298 } 11296 }
11299 } 11297 }
11300#if ENABLE_FEATURE_SH_STANDALONE 11298#if ENABLE_FEATURE_SH_STANDALONE
11301 for (i = 0; i < NUM_APPLETS; i++) { 11299 {
11302 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name); 11300 const char *a = applet_names;
11303 if (col > 60) { 11301 while (*a) {
11304 out1fmt("\n"); 11302 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), a);
11305 col = 0; 11303 if (col > 60) {
11304 out1fmt("\n");
11305 col = 0;
11306 }
11307 a += strlen(a) + 1;
11306 } 11308 }
11307 } 11309 }
11308#endif 11310#endif
diff --git a/shell/hush.c b/shell/hush.c
index f7e2a4a14..8e42a8f3f 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -83,7 +83,7 @@
83 83
84extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ 84extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */
85 85
86#include "busybox.h" /* for struct bb_applet */ 86#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
87 87
88 88
89#if !BB_MMU 89#if !BB_MMU
@@ -1464,12 +1464,12 @@ static void pseudo_exec_argv(char **argv)
1464 /* Check if the command matches any busybox applets */ 1464 /* Check if the command matches any busybox applets */
1465#if ENABLE_FEATURE_SH_STANDALONE 1465#if ENABLE_FEATURE_SH_STANDALONE
1466 if (strchr(argv[0], '/') == NULL) { 1466 if (strchr(argv[0], '/') == NULL) {
1467 const struct bb_applet *a = find_applet_by_name(argv[0]); 1467 int a = find_applet_by_name(argv[0]);
1468 if (a) { 1468 if (a >= 0) {
1469 if (a->noexec) { 1469 if (APPLET_IS_NOEXEC(a)) {
1470 debug_printf_exec("running applet '%s'\n", argv[0]); 1470 debug_printf_exec("running applet '%s'\n", argv[0]);
1471// is it ok that run_appletstruct_and_exit() does exit(), not _exit()? 1471// is it ok that run_applet_no_and_exit() does exit(), not _exit()?
1472 run_appletstruct_and_exit(a, argv); 1472 run_applet_no_and_exit(a, argv);
1473 } 1473 }
1474 /* re-exec ourselves with the new arguments */ 1474 /* re-exec ourselves with the new arguments */
1475 debug_printf_exec("re-execing applet '%s'\n", argv[0]); 1475 debug_printf_exec("re-execing applet '%s'\n", argv[0]);
@@ -1855,8 +1855,8 @@ static int run_pipe_real(struct pipe *pi)
1855 } 1855 }
1856#if ENABLE_FEATURE_SH_STANDALONE 1856#if ENABLE_FEATURE_SH_STANDALONE
1857 { 1857 {
1858 const struct bb_applet *a = find_applet_by_name(argv[i]); 1858 int a = find_applet_by_name(argv[i]);
1859 if (a && a->nofork) { 1859 if (a >= 0 && APPLET_IS_NOFORK(a)) {
1860 setup_redirects(child, squirrel); 1860 setup_redirects(child, squirrel);
1861 save_nofork_data(&nofork_save); 1861 save_nofork_data(&nofork_save);
1862 argv_expanded = argv + i; 1862 argv_expanded = argv + i;
diff --git a/shell/lash_unused.c b/shell/lash_unused.c
index 781dfdb5a..10a9120e2 100644
--- a/shell/lash_unused.c
+++ b/shell/lash_unused.c
@@ -23,7 +23,7 @@
23#include <getopt.h> 23#include <getopt.h>
24#include <glob.h> 24#include <glob.h>
25 25
26#include "busybox.h" /* for struct bb_applet */ 26#include "libbb.h"
27 27
28#define expand_t glob_t 28#define expand_t glob_t
29 29
@@ -1253,8 +1253,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
1253 } 1253 }
1254#if ENABLE_FEATURE_SH_STANDALONE 1254#if ENABLE_FEATURE_SH_STANDALONE
1255 { 1255 {
1256 const struct bb_applet *a = find_applet_by_name(child->argv[i]); 1256 int a = find_applet_by_name(child->argv[i]);
1257 if (a && a->nofork) { 1257 if (a >= 0 && APPLET_IS_NOFORK(a)) {
1258 setup_redirects(child, squirrel); 1258 setup_redirects(child, squirrel);
1259 rcode = run_nofork_applet(a, child->argv + i); 1259 rcode = run_nofork_applet(a, child->argv + i);
1260 restore_redirects(squirrel); 1260 restore_redirects(squirrel);
diff --git a/shell/msh.c b/shell/msh.c
index 7efd7f96e..32953f4ed 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -45,9 +45,9 @@
45# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1]) 45# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
46# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1]) 46# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
47# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__)) 47# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
48static char *find_applet_by_name(const char *applet) 48static int find_applet_by_name(const char *applet)
49{ 49{
50 return NULL; 50 return -1;
51} 51}
52static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) 52static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
53{ 53{
@@ -83,7 +83,7 @@ static char *itoa(int n)
83 return local_buf; 83 return local_buf;
84} 84}
85#else 85#else
86# include "busybox.h" 86# include "busybox.h" /* for applet_names */
87extern char **environ; 87extern char **environ;
88#endif 88#endif
89 89
@@ -3057,7 +3057,7 @@ static const char *rexecve(char *c, char **v, char **envp)
3057 char *name = c; 3057 char *name = c;
3058 3058
3059 if (ENABLE_FEATURE_SH_STANDALONE) { 3059 if (ENABLE_FEATURE_SH_STANDALONE) {
3060 if (find_applet_by_name(name)) { 3060 if (find_applet_by_name(name) >= 0) {
3061 /* We have to exec here since we vforked. Running 3061 /* We have to exec here since we vforked. Running
3062 * run_applet_and_exit() won't work and bad things 3062 * run_applet_and_exit() won't work and bad things
3063 * will happen. */ 3063 * will happen. */
@@ -3188,15 +3188,15 @@ static int dohelp(struct op *t)
3188 } 3188 }
3189#if ENABLE_FEATURE_SH_STANDALONE 3189#if ENABLE_FEATURE_SH_STANDALONE
3190 { 3190 {
3191 const struct bb_applet *applet = applets; 3191 const char *applet = applet_names;
3192 3192
3193 while (applet->name) { 3193 while (*applet) {
3194 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet->name); 3194 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet);
3195 if (col > 60) { 3195 if (col > 60) {
3196 bb_putchar('\n'); 3196 bb_putchar('\n');
3197 col = 0; 3197 col = 0;
3198 } 3198 }
3199 applet++; 3199 applet += strlen(applet) + 1;
3200 } 3200 }
3201 } 3201 }
3202#endif 3202#endif