aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/hush.c86
1 files changed, 57 insertions, 29 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 6b6ec7c6b..04dda0734 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1022,6 +1022,13 @@ struct globals {
1022#if HUSH_DEBUG >= 2 1022#if HUSH_DEBUG >= 2
1023 int debug_indent; 1023 int debug_indent;
1024#endif 1024#endif
1025#if ENABLE_HUSH_TEST || BASH_TEST2
1026 /* Cached supplementary group array (for testing executable'ity of files) */
1027 struct cached_groupinfo groupinfo;
1028# define GROUPINFO_INIT { G.groupinfo.euid = -1; G.groupinfo.egid = -1; }
1029#else
1030# define GROUPINFO_INIT /* nothing */
1031#endif
1025 struct sigaction sa; 1032 struct sigaction sa;
1026 char optstring_buf[sizeof("eixcs")]; 1033 char optstring_buf[sizeof("eixcs")];
1027#if BASH_EPOCH_VARS 1034#if BASH_EPOCH_VARS
@@ -1040,6 +1047,7 @@ struct globals {
1040 /* memset(&G.sa, 0, sizeof(G.sa)); */ \ 1047 /* memset(&G.sa, 0, sizeof(G.sa)); */ \
1041 sigfillset(&G.sa.sa_mask); \ 1048 sigfillset(&G.sa.sa_mask); \
1042 G.sa.sa_flags = SA_RESTART; \ 1049 G.sa.sa_flags = SA_RESTART; \
1050 GROUPINFO_INIT; \
1043} while (0) 1051} while (0)
1044 1052
1045/* Function prototypes for builtins */ 1053/* Function prototypes for builtins */
@@ -8193,38 +8201,53 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp)
8193 return 0; 8201 return 0;
8194} 8202}
8195 8203
8196static char *find_in_path(const char *arg) 8204/* Find a file in PATH, not necessarily executable
8205 * Name is known to not contain '/'.
8206 */
8207//TODO: shares code with find_executable() in libbb, factor out?
8208static char *find_in_PATH(const char *name)
8197{ 8209{
8198 char *ret = NULL; 8210 char *p = (char*) get_local_var_value("PATH");
8199 const char *PATH = get_local_var_value("PATH");
8200 8211
8201 if (!PATH) 8212 if (!p)
8202 return NULL; 8213 return NULL;
8203
8204 while (1) { 8214 while (1) {
8205 const char *end = strchrnul(PATH, ':'); 8215 const char *end = strchrnul(p, ':');
8206 int sz = end - PATH; /* must be int! */ 8216 int sz = end - p; /* must be int! */
8207 8217
8208 free(ret);
8209 if (sz != 0) { 8218 if (sz != 0) {
8210 ret = xasprintf("%.*s/%s", sz, PATH, arg); 8219 p = xasprintf("%.*s/%s", sz, p, name);
8211 } else { 8220 } else {
8212 /* We have xxx::yyyy in $PATH, 8221 /* We have xxx::yyy in $PATH,
8213 * it means "use current dir" */ 8222 * it means "use current dir" */
8214 ret = xstrdup(arg); 8223 p = xstrdup(name);
8215 } 8224 }
8216 if (access(ret, F_OK) == 0) 8225 if (access(p, F_OK) == 0)
8217 break; 8226 return p;
8218 8227 free(p);
8219 if (*end == '\0') { 8228 if (*end == '\0')
8220 free(ret);
8221 return NULL; 8229 return NULL;
8222 } 8230 p = (char *) end + 1;
8223 PATH = end + 1;
8224 } 8231 }
8232}
8225 8233
8226 return ret; 8234#if ENABLE_HUSH_TYPE || ENABLE_HUSH_COMMAND
8235static char *find_executable_in_PATH(const char *name)
8236{
8237 const char *PATH;
8238 if (strchr(name, '/')) {
8239 /* Name with '/' is tested verbatim, with no PATH traversal:
8240 * "cd /bin; type ./cat" should print "./cat is ./cat",
8241 * NOT "./cat is /bin/./cat"
8242 */
8243 if (file_is_executable(name))
8244 return xstrdup(name);
8245 return NULL;
8246 }
8247 PATH = get_local_var_value("PATH");
8248 return find_executable(name, &PATH); /* path == NULL is ok */
8227} 8249}
8250#endif
8228 8251
8229static const struct built_in_command *find_builtin_helper(const char *name, 8252static const struct built_in_command *find_builtin_helper(const char *name,
8230 const struct built_in_command *x, 8253 const struct built_in_command *x,
@@ -8635,10 +8658,11 @@ static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *exp
8635 8658
8636 to_free = NULL; 8659 to_free = NULL;
8637 if (!explanation) { 8660 if (!explanation) {
8638 char *path = getenv("PATH"); 8661 explanation = to_free = find_executable_in_PATH(cmd);
8639 explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */ 8662 if (!explanation) {
8640 if (!explanation) 8663 bb_error_msg("%s: %s: not found", "command", cmd);
8641 _exit(1); /* PROG was not found */ 8664 _exit(1); /* PROG was not found */
8665 }
8642 if (opt_vV != 'V') 8666 if (opt_vV != 'V')
8643 cmd = to_free; /* -v PROG prints "/path/to/PROG" */ 8667 cmd = to_free; /* -v PROG prints "/path/to/PROG" */
8644 } 8668 }
@@ -10870,7 +10894,8 @@ static NOINLINE int run_applet_main(char **argv, int (*applet_main_func)(int arg
10870#if ENABLE_HUSH_TEST || BASH_TEST2 10894#if ENABLE_HUSH_TEST || BASH_TEST2
10871static int FAST_FUNC builtin_test(char **argv) 10895static int FAST_FUNC builtin_test(char **argv)
10872{ 10896{
10873 return run_applet_main(argv, test_main); 10897 int argc = string_array_len(argv);
10898 return test_main2(&G.groupinfo, argc, argv);
10874} 10899}
10875#endif 10900#endif
10876#if ENABLE_HUSH_ECHO 10901#if ENABLE_HUSH_ECHO
@@ -11063,12 +11088,15 @@ static int FAST_FUNC builtin_type(char **argv)
11063# endif 11088# endif
11064 else if (find_builtin(*argv)) 11089 else if (find_builtin(*argv))
11065 type = "a shell builtin"; 11090 type = "a shell builtin";
11066 else if ((path = find_in_path(*argv)) != NULL)
11067 type = path;
11068 else { 11091 else {
11069 bb_error_msg("type: %s: not found", *argv); 11092 path = find_executable_in_PATH(*argv);
11070 ret = EXIT_FAILURE; 11093 if (path)
11071 continue; 11094 type = path;
11095 else {
11096 bb_error_msg("%s: %s: not found", "type", *argv);
11097 ret = EXIT_FAILURE;
11098 continue;
11099 }
11072 } 11100 }
11073 11101
11074 printf("%s is %s\n", *argv, type); 11102 printf("%s is %s\n", *argv, type);
@@ -11695,7 +11723,7 @@ static int FAST_FUNC builtin_source(char **argv)
11695 } 11723 }
11696 arg_path = NULL; 11724 arg_path = NULL;
11697 if (!strchr(filename, '/')) { 11725 if (!strchr(filename, '/')) {
11698 arg_path = find_in_path(filename); 11726 arg_path = find_in_PATH(filename);
11699 if (arg_path) 11727 if (arg_path)
11700 filename = arg_path; 11728 filename = arg_path;
11701 else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) { 11729 else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {