Fix up builtin overrides, and hack in the binary search for finding

matching applets into the shell.
This commit is contained in:
Eric Andersen 2000-11-17 18:25:26 +00:00
parent cf32e23796
commit e5aef92e22
9 changed files with 113 additions and 105 deletions

View File

@ -235,11 +235,11 @@
#define BB_FEATURE_SH_STANDALONE_SHELL #define BB_FEATURE_SH_STANDALONE_SHELL
// //
//When this is enabled, busybox shell builtins can be called using full path //When this is enabled, busybox shell builtins can be called using full path
//names. This causes builtins (which includes every single busybox command //names. This causes builtins (i.e. every single busybox command) to override
//when you enable BB_FEATURE_SH_STANDALONE_SHELL) to override real commands on //real commands on the filesystem. For example, if you run run /bin/cat, it
//the filesystem. When this is enabled, if you run /bin/cat, it will use //will use BusyBox cat even if /bin/cat exists on the filesystem and is _not_
//BusyBox cat even if /bin/cat exists on the filesystem and is _not_ busybox. //busybox. Some systems want this, others do not. Choose wisely. :-) This
//Some systems want this, others do not. Choose wisely. :-) //only has meaning when BB_FEATURE_SH_STANDALONE_SHELL is enabled.
//BB_FEATURE_SH_BUILTINS_ALWAYS_WIN //BB_FEATURE_SH_BUILTINS_ALWAYS_WIN
// //
// Enable tab completion in the shell (not yet // Enable tab completion in the shell (not yet

View File

@ -81,14 +81,6 @@ static void install_links(const char *busybox, int use_symbolic_links)
#endif /* BB_FEATURE_INSTALLER */ #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) int main(int argc, char **argv)
{ {
struct BB_applet search_applet, *applet; struct BB_applet search_applet, *applet;

View File

@ -81,14 +81,6 @@ static void install_links(const char *busybox, int use_symbolic_links)
#endif /* BB_FEATURE_INSTALLER */ #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) int main(int argc, char **argv)
{ {
struct BB_applet search_applet, *applet; struct BB_applet search_applet, *applet;

View File

@ -108,6 +108,8 @@ struct BB_applet {
/* From busybox.c */ /* From busybox.c */
extern const struct BB_applet applets[]; 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 ar_main(int argc, char **argv);
extern int basename_main(int argc, char **argv); extern int basename_main(int argc, char **argv);
extern int bogomips_main(int argc, char **argv); extern int bogomips_main(int argc, char **argv);

View File

@ -108,6 +108,8 @@ struct BB_applet {
/* From busybox.c */ /* From busybox.c */
extern const struct BB_applet applets[]; 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 ar_main(int argc, char **argv);
extern int basename_main(int argc, char **argv); extern int basename_main(int argc, char **argv);
extern int bogomips_main(int argc, char **argv); extern int bogomips_main(int argc, char **argv);

60
lash.c
View File

@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
int pipefds[2]; /* pipefd[0] is for reading */ int pipefds[2]; /* pipefd[0] is for reading */
struct builtInCommand *x; struct builtInCommand *x;
#ifdef BB_FEATURE_SH_STANDALONE_SHELL #ifdef BB_FEATURE_SH_STANDALONE_SHELL
const struct BB_applet *a = applets; struct BB_applet search_applet, *applet = applets;
#endif #endif
nextin = 0, nextout = 1; 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 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
/* Check if the command matches any busybox internal commands here */ /* Check if the command matches any busybox internal
while (a->name != 0) { * 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 #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then
a->name) == 0) * if you run /bin/cat, it will use BusyBox cat even if
#else * /bin/cat exists on the filesystem and is _not_ busybox.
/* Check if the command matches any busybox internal * Some systems want this, others do not. Choose wisely. :-)
* commands ("applets") here. Following discussions from */
* November 2000 on busybox@opensource.lineo.com, don't use search_applet.name = get_last_path_component(search_applet.name);
* 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)
#endif #endif
{
int argc_l; /* Do a binary search to find the applet entry given the name. */
char** argv=newJob->progs[i].argv; applet = bsearch(&search_applet, applets, NUM_APPLETS,
for(argc_l=0;*argv!=NULL; argv++, argc_l++); sizeof(struct BB_applet), applet_name_compare);
applet_name=a->name; if (applet != NULL) {
optind = 1; int argc_l;
exit((*(a->main)) (argc_l, newJob->progs[i].argv)); char** argv=newJob->progs[i].argv;
} for(argc_l=0;*argv!=NULL; argv++, argc_l++);
a++; applet_name=applet->name;
optind = 1;
exit((*(applet->main)) (argc_l, newJob->progs[i].argv));
} }
#endif #endif
execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); execvp(newJob->progs[i].argv[0], newJob->progs[i].argv);
fatalError("%s: %s\n", newJob->progs[i].argv[0], fatalError("%s: %s\n", newJob->progs[i].argv[0],
strerror(errno)); strerror(errno));
} }
if (outPipe[1]!=-1) { if (outPipe[1]!=-1) {
close(outPipe[1]); close(outPipe[1]);

60
sh.c
View File

@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
int pipefds[2]; /* pipefd[0] is for reading */ int pipefds[2]; /* pipefd[0] is for reading */
struct builtInCommand *x; struct builtInCommand *x;
#ifdef BB_FEATURE_SH_STANDALONE_SHELL #ifdef BB_FEATURE_SH_STANDALONE_SHELL
const struct BB_applet *a = applets; struct BB_applet search_applet, *applet = applets;
#endif #endif
nextin = 0, nextout = 1; 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 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
/* Check if the command matches any busybox internal commands here */ /* Check if the command matches any busybox internal
while (a->name != 0) { * 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 #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then
a->name) == 0) * if you run /bin/cat, it will use BusyBox cat even if
#else * /bin/cat exists on the filesystem and is _not_ busybox.
/* Check if the command matches any busybox internal * Some systems want this, others do not. Choose wisely. :-)
* commands ("applets") here. Following discussions from */
* November 2000 on busybox@opensource.lineo.com, don't use search_applet.name = get_last_path_component(search_applet.name);
* 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)
#endif #endif
{
int argc_l; /* Do a binary search to find the applet entry given the name. */
char** argv=newJob->progs[i].argv; applet = bsearch(&search_applet, applets, NUM_APPLETS,
for(argc_l=0;*argv!=NULL; argv++, argc_l++); sizeof(struct BB_applet), applet_name_compare);
applet_name=a->name; if (applet != NULL) {
optind = 1; int argc_l;
exit((*(a->main)) (argc_l, newJob->progs[i].argv)); char** argv=newJob->progs[i].argv;
} for(argc_l=0;*argv!=NULL; argv++, argc_l++);
a++; applet_name=applet->name;
optind = 1;
exit((*(applet->main)) (argc_l, newJob->progs[i].argv));
} }
#endif #endif
execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); execvp(newJob->progs[i].argv[0], newJob->progs[i].argv);
fatalError("%s: %s\n", newJob->progs[i].argv[0], fatalError("%s: %s\n", newJob->progs[i].argv[0],
strerror(errno)); strerror(errno));
} }
if (outPipe[1]!=-1) { if (outPipe[1]!=-1) {
close(outPipe[1]); close(outPipe[1]);

View File

@ -1152,7 +1152,7 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int
int pipefds[2]; /* pipefd[0] is for reading */ int pipefds[2]; /* pipefd[0] is for reading */
struct builtInCommand *x; struct builtInCommand *x;
#ifdef BB_FEATURE_SH_STANDALONE_SHELL #ifdef BB_FEATURE_SH_STANDALONE_SHELL
const struct BB_applet *a = applets; struct BB_applet search_applet, *applet = applets;
#endif #endif
nextin = 0, nextout = 1; 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 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
/* Check if the command matches any busybox internal commands here */ /* Check if the command matches any busybox internal
while (a->name != 0) { * 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 #ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN
if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then
a->name) == 0) * if you run /bin/cat, it will use BusyBox cat even if
#else * /bin/cat exists on the filesystem and is _not_ busybox.
/* Check if the command matches any busybox internal * Some systems want this, others do not. Choose wisely. :-)
* commands ("applets") here. Following discussions from */
* November 2000 on busybox@opensource.lineo.com, don't use search_applet.name = get_last_path_component(search_applet.name);
* 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)
#endif #endif
{
int argc_l; /* Do a binary search to find the applet entry given the name. */
char** argv=newJob->progs[i].argv; applet = bsearch(&search_applet, applets, NUM_APPLETS,
for(argc_l=0;*argv!=NULL; argv++, argc_l++); sizeof(struct BB_applet), applet_name_compare);
applet_name=a->name; if (applet != NULL) {
optind = 1; int argc_l;
exit((*(a->main)) (argc_l, newJob->progs[i].argv)); char** argv=newJob->progs[i].argv;
} for(argc_l=0;*argv!=NULL; argv++, argc_l++);
a++; applet_name=applet->name;
optind = 1;
exit((*(applet->main)) (argc_l, newJob->progs[i].argv));
} }
#endif #endif
execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); execvp(newJob->progs[i].argv[0], newJob->progs[i].argv);
fatalError("%s: %s\n", newJob->progs[i].argv[0], fatalError("%s: %s\n", newJob->progs[i].argv[0],
strerror(errno)); strerror(errno));
} }
if (outPipe[1]!=-1) { if (outPipe[1]!=-1) {
close(outPipe[1]); close(outPipe[1]);

View File

@ -1775,6 +1775,14 @@ FILE *xfopen(const char *path, const char *mode)
} }
#endif #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 */ /* END CODE */
/* /*
Local Variables: Local Variables: