diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-28 06:49:03 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-28 06:49:03 +0000 |
commit | 1aa7e477b1b727db77cac2d717f0fcca40587f78 (patch) | |
tree | 247171517f0e01d32a71a5e96f4bef462cc0e9c6 | |
parent | 79c6904faff1ebd4bf4b7d9cd0c20ca70f4cec75 (diff) | |
download | busybox-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-- | Makefile | 2 | ||||
-rw-r--r-- | applets/Kbuild | 12 | ||||
-rw-r--r-- | applets/applets.c | 2 | ||||
-rw-r--r-- | include/applets.h | 13 | ||||
-rw-r--r-- | include/busybox.h | 46 | ||||
-rw-r--r-- | include/libbb.h | 11 | ||||
-rw-r--r-- | libbb/appletlib.c | 87 | ||||
-rw-r--r-- | libbb/execable.c | 2 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 22 | ||||
-rw-r--r-- | shell/ash.c | 30 | ||||
-rw-r--r-- | shell/hush.c | 16 | ||||
-rw-r--r-- | shell/lash_unused.c | 6 | ||||
-rw-r--r-- | shell/msh.c | 16 |
13 files changed, 137 insertions, 128 deletions
@@ -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 := | |||
8 | obj-y += applets.o | 8 | obj-y += applets.o |
9 | 9 | ||
10 | hostprogs-y:= | 10 | hostprogs-y:= |
11 | hostprogs-y += usage | 11 | hostprogs-y += usage applet_tables |
12 | 12 | ||
13 | always:= $(hostprogs-y) | 13 | always:= $(hostprogs-y) |
14 | 14 | ||
@@ -19,7 +19,15 @@ quiet_cmd_gen_usage_compressed = GEN include/usage_compressed.h | |||
19 | 19 | ||
20 | HOSTCFLAGS_usage.o = -I$(srctree)/include | 20 | HOSTCFLAGS_usage.o = -I$(srctree)/include |
21 | 21 | ||
22 | applets/applets.o: include/usage_compressed.h | 22 | applets/applets.o: include/usage_compressed.h include/applet_tables.h |
23 | |||
23 | applets/usage: .config $(srctree)/applets/usage_compressed | 24 | applets/usage: .config $(srctree)/applets/usage_compressed |
25 | |||
24 | include/usage_compressed.h: applets/usage $(srctree)/applets/usage_compressed | 26 | include/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 | ||
31 | include/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)) | |||
385 | USE_ZCIP(APPLET(zcip, _BB_DIR_SBIN, _BB_SUID_NEVER)) | 385 | USE_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 */ | ||
14 | typedef enum bb_install_loc_t { | 13 | typedef 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 | ||
24 | typedef enum bb_suid_t { | 21 | typedef 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 | ||
31 | struct 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 | 30 | extern const char applet_names[]; |
35 | __extension__ enum bb_install_loc_t install_loc:8; | 31 | extern int (*const applet_mains[])(int argc, char **argv); |
32 | |||
33 | #if ENABLE_FEATURE_INSTALLER || ENABLE_FEATURE_PREFER_APPLETS | ||
34 | extern const uint32_t applet_nameofs[]; | ||
35 | #else | ||
36 | extern 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 */ | ||
53 | extern const struct bb_applet applets[]; | ||
54 | extern 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); | |||
550 | enum { USERNAME_MAX_SIZE = 16 - sizeof(int) }; | 550 | enum { USERNAME_MAX_SIZE = 16 - sizeof(int) }; |
551 | 551 | ||
552 | 552 | ||
553 | struct bb_applet; | ||
554 | int execable_file(const char *name); | 553 | int execable_file(const char *name); |
555 | char *find_execable(const char *filename); | 554 | char *find_execable(const char *filename); |
556 | int exists_execable(const char *filename); | 555 | int exists_execable(const char *filename); |
@@ -562,7 +561,7 @@ int exists_execable(const char *filename); | |||
562 | int bb_execvp(const char *file, char *const argv[]); | 561 | int 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 { | |||
600 | void save_nofork_data(struct nofork_save_area *save); | 599 | void save_nofork_data(struct nofork_save_area *save); |
601 | void restore_nofork_data(struct nofork_save_area *save); | 600 | void 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 */ |
603 | int run_nofork_applet(const struct bb_applet *a, char **argv); | 602 | int run_nofork_applet(int applet_no, char **argv); |
604 | int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv); | 603 | int 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 |
789 | extern const struct bb_applet *find_applet_by_name(const char *name); | 788 | extern int find_applet_by_name(const char *name); |
790 | /* Returns only if applet is not found. */ | 789 | /* Returns only if applet is not found. */ |
791 | extern void run_applet_and_exit(const char *name, char **argv); | 790 | extern void run_applet_and_exit(const char *name, char **argv); |
792 | extern void run_appletstruct_and_exit(const struct bb_applet *a, char **argv) ATTRIBUTE_NORETURN; | 791 | extern void run_applet_no_and_exit(int a, char **argv) ATTRIBUTE_NORETURN; |
793 | #endif | 792 | #endif |
794 | 793 | ||
795 | extern int match_fstype(const struct mntent *mt, const char *fstypes); | 794 | extern 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" |
41 | const 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 | ||
110 | static int applet_name_compare(const void *name, const void *vapplet) | 104 | static 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 | ||
117 | const struct bb_applet *find_applet_by_name(const char *name) | 110 | int 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 */ |
168 | static struct BB_suid_config { | 166 | static 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 |
444 | static void check_suid(const struct bb_applet *applet) | 442 | static 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 | ||
632 | void run_appletstruct_and_exit(const struct bb_applet *applet, char **argv) | 631 | void 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 | ||
651 | void run_applet_and_exit(const char *name, char **argv) | 650 | void 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 | */ |
66 | int bb_execvp(const char *file, char *const argv[]) | 66 | int 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 | ||
123 | int run_nofork_applet_prime(struct nofork_save_area *old, const struct bb_applet *a, char **argv) | 123 | int 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 | ||
158 | int run_nofork_applet(const struct bb_applet *a, char **argv) | 158 | int 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 | ||
84 | extern char **environ; /* This is in <unistd.h>, but protected with __USE_GNU */ | 84 | extern 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__)) |
48 | static char *find_applet_by_name(const char *applet) | 48 | static int find_applet_by_name(const char *applet) |
49 | { | 49 | { |
50 | return NULL; | 50 | return -1; |
51 | } | 51 | } |
52 | static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen) | 52 | static 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 */ |
87 | extern char **environ; | 87 | extern 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 |