From e5aef92e22172d36152bae6e15d5c0419c758121 Mon Sep 17 00:00:00 2001 From: Eric Andersen Date: Fri, 17 Nov 2000 18:25:26 +0000 Subject: [PATCH] Fix up builtin overrides, and hack in the binary search for finding matching applets into the shell. --- Config.h | 10 ++++---- applets/busybox.c | 8 ------- busybox.c | 8 ------- busybox.h | 2 ++ include/busybox.h | 2 ++ lash.c | 60 +++++++++++++++++++++++++---------------------- sh.c | 60 +++++++++++++++++++++++++---------------------- shell/lash.c | 60 +++++++++++++++++++++++++---------------------- utility.c | 8 +++++++ 9 files changed, 113 insertions(+), 105 deletions(-) diff --git a/Config.h b/Config.h index c010671b5..82c17d63a 100644 --- a/Config.h +++ b/Config.h @@ -235,11 +235,11 @@ #define BB_FEATURE_SH_STANDALONE_SHELL // //When this is enabled, busybox shell builtins can be called using full path -//names. This causes builtins (which includes every single busybox command -//when you enable BB_FEATURE_SH_STANDALONE_SHELL) to override real commands on -//the filesystem. When this is enabled, if you run /bin/cat, it will use -//BusyBox cat even if /bin/cat exists on the filesystem and is _not_ busybox. -//Some systems want this, others do not. Choose wisely. :-) +//names. This causes builtins (i.e. every single busybox command) to override +//real commands on the filesystem. For example, if you run run /bin/cat, it +//will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_ +//busybox. Some systems want this, others do not. Choose wisely. :-) This +//only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled. //BB_FEATURE_SH_BUILTINS_ALWAYS_WIN // // Enable tab completion in the shell (not yet diff --git a/applets/busybox.c b/applets/busybox.c index d356e4cae..0a3333d99 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -81,14 +81,6 @@ static void install_links(const char *busybox, int use_symbolic_links) #endif /* BB_FEATURE_INSTALLER */ -static int applet_name_compare(const void *x, const void *y) -{ - const struct BB_applet *applet1 = x; - const struct BB_applet *applet2 = y; - - return strcmp(applet1->name, applet2->name); -} - int main(int argc, char **argv) { struct BB_applet search_applet, *applet; diff --git a/busybox.c b/busybox.c index d356e4cae..0a3333d99 100644 --- a/busybox.c +++ b/busybox.c @@ -81,14 +81,6 @@ static void install_links(const char *busybox, int use_symbolic_links) #endif /* BB_FEATURE_INSTALLER */ -static int applet_name_compare(const void *x, const void *y) -{ - const struct BB_applet *applet1 = x; - const struct BB_applet *applet2 = y; - - return strcmp(applet1->name, applet2->name); -} - int main(int argc, char **argv) { struct BB_applet search_applet, *applet; diff --git a/busybox.h b/busybox.h index d947ba328..2bc1c997e 100644 --- a/busybox.h +++ b/busybox.h @@ -108,6 +108,8 @@ struct BB_applet { /* From busybox.c */ extern const struct BB_applet applets[]; +extern int applet_name_compare(const void *x, const void *y); + extern int ar_main(int argc, char **argv); extern int basename_main(int argc, char **argv); extern int bogomips_main(int argc, char **argv); diff --git a/include/busybox.h b/include/busybox.h index d947ba328..2bc1c997e 100644 --- a/include/busybox.h +++ b/include/busybox.h @@ -108,6 +108,8 @@ struct BB_applet { /* From busybox.c */ extern const struct BB_applet applets[]; +extern int applet_name_compare(const void *x, const void *y); + extern int ar_main(int argc, char **argv); extern int basename_main(int argc, char **argv); extern int bogomips_main(int argc, char **argv); diff --git a/lash.c b/lash.c index d6ac1fc17..1e0803f77 100644 --- a/lash.c +++ b/lash.c @@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int int pipefds[2]; /* pipefd[0] is for reading */ struct builtInCommand *x; #ifdef BB_FEATURE_SH_STANDALONE_SHELL - const struct BB_applet *a = applets; + struct BB_applet search_applet, *applet = applets; #endif nextin = 0, nextout = 1; @@ -1214,40 +1214,44 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int } } #ifdef BB_FEATURE_SH_STANDALONE_SHELL - /* Check if the command matches any busybox internal commands here */ - while (a->name != 0) { + /* Check if the command matches any busybox internal + * commands ("applets") here. Following discussions from + * November 2000 on busybox@opensource.lineo.com, don't use + * get_last_path_component(). This way explicit (with + * slashes) filenames will never be interpreted as an + * applet, just like with builtins. This way the user can + * override an applet with an explicit filename reference. + * The only downside to this change is that an explicit + * /bin/foo invocation fill fork and exec /bin/foo, even if + * /bin/foo is a symlink to busybox. + */ + search_applet.name = newJob->progs[i].argv[0]; + #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN - if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), - a->name) == 0) -#else - /* Check if the command matches any busybox internal - * commands ("applets") here. Following discussions from - * November 2000 on busybox@opensource.lineo.com, don't use - * get_last_path_component(). This way explicit (with - * slashes) filenames will never be interpreted as an - * applet, just like with builtins. This way the user can - * override an applet with an explicit filename reference. - * The only downside to this change is that an explicit - * /bin/foo invocation fill fork and exec /bin/foo, even if - * /bin/foo is a symlink to busybox. - */ - if (strcmp(newJob->progs[i].argv[0], a->name) == 0) + /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then + * if you run /bin/cat, it will use BusyBox cat even if + * /bin/cat exists on the filesystem and is _not_ busybox. + * Some systems want this, others do not. Choose wisely. :-) + */ + search_applet.name = get_last_path_component(search_applet.name); #endif - { - int argc_l; - char** argv=newJob->progs[i].argv; - for(argc_l=0;*argv!=NULL; argv++, argc_l++); - applet_name=a->name; - optind = 1; - exit((*(a->main)) (argc_l, newJob->progs[i].argv)); - } - a++; + + /* Do a binary search to find the applet entry given the name. */ + applet = bsearch(&search_applet, applets, NUM_APPLETS, + sizeof(struct BB_applet), applet_name_compare); + if (applet != NULL) { + int argc_l; + char** argv=newJob->progs[i].argv; + for(argc_l=0;*argv!=NULL; argv++, argc_l++); + applet_name=applet->name; + optind = 1; + exit((*(applet->main)) (argc_l, newJob->progs[i].argv)); } #endif execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); fatalError("%s: %s\n", newJob->progs[i].argv[0], - strerror(errno)); + strerror(errno)); } if (outPipe[1]!=-1) { close(outPipe[1]); diff --git a/sh.c b/sh.c index d6ac1fc17..1e0803f77 100644 --- a/sh.c +++ b/sh.c @@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int int pipefds[2]; /* pipefd[0] is for reading */ struct builtInCommand *x; #ifdef BB_FEATURE_SH_STANDALONE_SHELL - const struct BB_applet *a = applets; + struct BB_applet search_applet, *applet = applets; #endif nextin = 0, nextout = 1; @@ -1214,40 +1214,44 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int } } #ifdef BB_FEATURE_SH_STANDALONE_SHELL - /* Check if the command matches any busybox internal commands here */ - while (a->name != 0) { + /* Check if the command matches any busybox internal + * commands ("applets") here. Following discussions from + * November 2000 on busybox@opensource.lineo.com, don't use + * get_last_path_component(). This way explicit (with + * slashes) filenames will never be interpreted as an + * applet, just like with builtins. This way the user can + * override an applet with an explicit filename reference. + * The only downside to this change is that an explicit + * /bin/foo invocation fill fork and exec /bin/foo, even if + * /bin/foo is a symlink to busybox. + */ + search_applet.name = newJob->progs[i].argv[0]; + #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN - if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), - a->name) == 0) -#else - /* Check if the command matches any busybox internal - * commands ("applets") here. Following discussions from - * November 2000 on busybox@opensource.lineo.com, don't use - * get_last_path_component(). This way explicit (with - * slashes) filenames will never be interpreted as an - * applet, just like with builtins. This way the user can - * override an applet with an explicit filename reference. - * The only downside to this change is that an explicit - * /bin/foo invocation fill fork and exec /bin/foo, even if - * /bin/foo is a symlink to busybox. - */ - if (strcmp(newJob->progs[i].argv[0], a->name) == 0) + /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then + * if you run /bin/cat, it will use BusyBox cat even if + * /bin/cat exists on the filesystem and is _not_ busybox. + * Some systems want this, others do not. Choose wisely. :-) + */ + search_applet.name = get_last_path_component(search_applet.name); #endif - { - int argc_l; - char** argv=newJob->progs[i].argv; - for(argc_l=0;*argv!=NULL; argv++, argc_l++); - applet_name=a->name; - optind = 1; - exit((*(a->main)) (argc_l, newJob->progs[i].argv)); - } - a++; + + /* Do a binary search to find the applet entry given the name. */ + applet = bsearch(&search_applet, applets, NUM_APPLETS, + sizeof(struct BB_applet), applet_name_compare); + if (applet != NULL) { + int argc_l; + char** argv=newJob->progs[i].argv; + for(argc_l=0;*argv!=NULL; argv++, argc_l++); + applet_name=applet->name; + optind = 1; + exit((*(applet->main)) (argc_l, newJob->progs[i].argv)); } #endif execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); fatalError("%s: %s\n", newJob->progs[i].argv[0], - strerror(errno)); + strerror(errno)); } if (outPipe[1]!=-1) { close(outPipe[1]); diff --git a/shell/lash.c b/shell/lash.c index d6ac1fc17..1e0803f77 100644 --- a/shell/lash.c +++ b/shell/lash.c @@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int int pipefds[2]; /* pipefd[0] is for reading */ struct builtInCommand *x; #ifdef BB_FEATURE_SH_STANDALONE_SHELL - const struct BB_applet *a = applets; + struct BB_applet search_applet, *applet = applets; #endif nextin = 0, nextout = 1; @@ -1214,40 +1214,44 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int } } #ifdef BB_FEATURE_SH_STANDALONE_SHELL - /* Check if the command matches any busybox internal commands here */ - while (a->name != 0) { + /* Check if the command matches any busybox internal + * commands ("applets") here. Following discussions from + * November 2000 on busybox@opensource.lineo.com, don't use + * get_last_path_component(). This way explicit (with + * slashes) filenames will never be interpreted as an + * applet, just like with builtins. This way the user can + * override an applet with an explicit filename reference. + * The only downside to this change is that an explicit + * /bin/foo invocation fill fork and exec /bin/foo, even if + * /bin/foo is a symlink to busybox. + */ + search_applet.name = newJob->progs[i].argv[0]; + #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN - if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), - a->name) == 0) -#else - /* Check if the command matches any busybox internal - * commands ("applets") here. Following discussions from - * November 2000 on busybox@opensource.lineo.com, don't use - * get_last_path_component(). This way explicit (with - * slashes) filenames will never be interpreted as an - * applet, just like with builtins. This way the user can - * override an applet with an explicit filename reference. - * The only downside to this change is that an explicit - * /bin/foo invocation fill fork and exec /bin/foo, even if - * /bin/foo is a symlink to busybox. - */ - if (strcmp(newJob->progs[i].argv[0], a->name) == 0) + /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then + * if you run /bin/cat, it will use BusyBox cat even if + * /bin/cat exists on the filesystem and is _not_ busybox. + * Some systems want this, others do not. Choose wisely. :-) + */ + search_applet.name = get_last_path_component(search_applet.name); #endif - { - int argc_l; - char** argv=newJob->progs[i].argv; - for(argc_l=0;*argv!=NULL; argv++, argc_l++); - applet_name=a->name; - optind = 1; - exit((*(a->main)) (argc_l, newJob->progs[i].argv)); - } - a++; + + /* Do a binary search to find the applet entry given the name. */ + applet = bsearch(&search_applet, applets, NUM_APPLETS, + sizeof(struct BB_applet), applet_name_compare); + if (applet != NULL) { + int argc_l; + char** argv=newJob->progs[i].argv; + for(argc_l=0;*argv!=NULL; argv++, argc_l++); + applet_name=applet->name; + optind = 1; + exit((*(applet->main)) (argc_l, newJob->progs[i].argv)); } #endif execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); fatalError("%s: %s\n", newJob->progs[i].argv[0], - strerror(errno)); + strerror(errno)); } if (outPipe[1]!=-1) { close(outPipe[1]); diff --git a/utility.c b/utility.c index e79e44136..c23ebcd96 100644 --- a/utility.c +++ b/utility.c @@ -1775,6 +1775,14 @@ FILE *xfopen(const char *path, const char *mode) } #endif +int applet_name_compare(const void *x, const void *y) +{ + const struct BB_applet *applet1 = x; + const struct BB_applet *applet2 = y; + + return strcmp(applet1->name, applet2->name); +} + /* END CODE */ /* Local Variables: