hush: fix "type ./cat" and "command -v ./cat" to not scan PATH
function old new delta find_executable_in_PATH - 67 +67 if_command_vV_print_and_exit 114 116 +2 .rodata 105712 105710 -2 builtin_type 137 128 -9 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/2 up/down: 69/-11) Total: 58 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
baa49bdc1b
commit
8c4bccb83e
1 changed files with 33 additions and 13 deletions
46
shell/hush.c
46
shell/hush.c
|
@ -8201,27 +8201,29 @@ static int setup_redirects(struct command *prog, struct squirrel **sqp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a file in PATH, not necessarily executable */
|
/* Find a file in PATH, not necessarily executable
|
||||||
|
* Name is known to not contain '/'.
|
||||||
|
*/
|
||||||
//TODO: shares code with find_executable() in libbb, factor out?
|
//TODO: shares code with find_executable() in libbb, factor out?
|
||||||
static char *find_in_path(const char *arg)
|
static char *find_in_PATH(const char *name)
|
||||||
{
|
{
|
||||||
char *ret = NULL;
|
char *ret;
|
||||||
const char *PATH = get_local_var_value("PATH");
|
const char *PATH = get_local_var_value("PATH");
|
||||||
|
|
||||||
if (!PATH)
|
if (!PATH)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
ret = NULL;
|
||||||
while (1) {
|
while (1) {
|
||||||
const char *end = strchrnul(PATH, ':');
|
const char *end = strchrnul(PATH, ':');
|
||||||
int sz = end - PATH; /* must be int! */
|
int sz = end - PATH; /* must be int! */
|
||||||
|
|
||||||
free(ret);
|
free(ret);
|
||||||
if (sz != 0) {
|
if (sz != 0) {
|
||||||
ret = xasprintf("%.*s/%s", sz, PATH, arg);
|
ret = xasprintf("%.*s/%s", sz, PATH, name);
|
||||||
} else {
|
} else {
|
||||||
/* We have xxx::yyyy in $PATH,
|
/* We have xxx::yyyy in $PATH,
|
||||||
* it means "use current dir" */
|
* it means "use current dir" */
|
||||||
ret = xstrdup(arg);
|
ret = xstrdup(name);
|
||||||
}
|
}
|
||||||
if (access(ret, F_OK) == 0)
|
if (access(ret, F_OK) == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -8236,6 +8238,24 @@ static char *find_in_path(const char *arg)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_HUSH_TYPE || ENABLE_HUSH_COMMAND
|
||||||
|
static char *find_executable_in_PATH(const char *name)
|
||||||
|
{
|
||||||
|
char *PATH;
|
||||||
|
if (strchr(name, '/')) {
|
||||||
|
/* Name with '/' is tested verbatim, with no PATH traversal:
|
||||||
|
* "cd /bin; type ./cat" should print "./cat is ./cat",
|
||||||
|
* NOT "./cat is /bin/./cat"
|
||||||
|
*/
|
||||||
|
if (file_is_executable(name))
|
||||||
|
return xstrdup(name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PATH = (char*)get_local_var_value("PATH");
|
||||||
|
return find_executable(name, &PATH); /* path == NULL is ok */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct built_in_command *find_builtin_helper(const char *name,
|
static const struct built_in_command *find_builtin_helper(const char *name,
|
||||||
const struct built_in_command *x,
|
const struct built_in_command *x,
|
||||||
const struct built_in_command *end)
|
const struct built_in_command *end)
|
||||||
|
@ -8645,10 +8665,11 @@ static void if_command_vV_print_and_exit(char opt_vV, char *cmd, const char *exp
|
||||||
|
|
||||||
to_free = NULL;
|
to_free = NULL;
|
||||||
if (!explanation) {
|
if (!explanation) {
|
||||||
char *path = (char*)get_local_var_value("PATH");
|
explanation = to_free = find_executable_in_PATH(cmd);
|
||||||
explanation = to_free = find_executable(cmd, &path); /* path == NULL is ok */
|
if (!explanation) {
|
||||||
if (!explanation)
|
bb_error_msg("%s: %s: not found", "command", cmd);
|
||||||
_exit(1); /* PROG was not found */
|
_exit(1); /* PROG was not found */
|
||||||
|
}
|
||||||
if (opt_vV != 'V')
|
if (opt_vV != 'V')
|
||||||
cmd = to_free; /* -v PROG prints "/path/to/PROG" */
|
cmd = to_free; /* -v PROG prints "/path/to/PROG" */
|
||||||
}
|
}
|
||||||
|
@ -11075,12 +11096,11 @@ static int FAST_FUNC builtin_type(char **argv)
|
||||||
else if (find_builtin(*argv))
|
else if (find_builtin(*argv))
|
||||||
type = "a shell builtin";
|
type = "a shell builtin";
|
||||||
else {
|
else {
|
||||||
char *pathvar = (char*)get_local_var_value("PATH");
|
path = find_executable_in_PATH(*argv);
|
||||||
path = find_executable(*argv, &pathvar);
|
|
||||||
if (path)
|
if (path)
|
||||||
type = path;
|
type = path;
|
||||||
else {
|
else {
|
||||||
bb_error_msg("type: %s: not found", *argv);
|
bb_error_msg("%s: %s: not found", "type", *argv);
|
||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -11710,7 +11730,7 @@ static int FAST_FUNC builtin_source(char **argv)
|
||||||
}
|
}
|
||||||
arg_path = NULL;
|
arg_path = NULL;
|
||||||
if (!strchr(filename, '/')) {
|
if (!strchr(filename, '/')) {
|
||||||
arg_path = find_in_path(filename);
|
arg_path = find_in_PATH(filename);
|
||||||
if (arg_path)
|
if (arg_path)
|
||||||
filename = arg_path;
|
filename = arg_path;
|
||||||
else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
|
else if (!ENABLE_HUSH_BASH_SOURCE_CURDIR) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue