diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval.c | 10 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 20 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 12 | ||||
-rw-r--r-- | src/nvim/os_unix.c | 3 | ||||
-rw-r--r-- | src/nvim/path.c | 16 | ||||
-rw-r--r-- | src/nvim/path.h | 2 | ||||
-rw-r--r-- | src/nvim/version.c | 2 |
7 files changed, 46 insertions, 19 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index fdeb2c1371..d84bdfebfe 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8692,7 +8692,11 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv) */ static void f_executable(typval_T *argvars, typval_T *rettv) { - rettv->vval.v_number = os_can_exe(get_tv_string(&argvars[0]), NULL); + char_u *name = get_tv_string(&argvars[0]); + + // Check in $PATH and also check directly if there is a directory name + rettv->vval.v_number = os_can_exe(name, NULL, true) + || (gettail_dir(name) != name && os_can_exe(name, NULL, false)); } /// "exepath()" function @@ -8701,7 +8705,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv) char_u *arg = get_tv_string(&argvars[0]); char_u *path = NULL; - (void)os_can_exe(arg, &path); + (void)os_can_exe(arg, &path, true); rettv->v_type = VAR_STRING; rettv->vval.v_string = path; @@ -11606,7 +11610,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd) assert(argl->lv_first); const char_u *exe = get_tv_string_chk(&argl->lv_first->li_tv); - if (!exe || !os_can_exe(exe, NULL)) { + if (!exe || !os_can_exe(exe, NULL, true)) { // String is not executable if (exe) { EMSG2(e_jobexe, exe); diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 7d911ee93e..1a410759a3 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -3983,6 +3983,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, char_u *s, *e; int flags = flagsarg; int ret; + bool did_curdir = false; /* for ":set path=" and ":set tags=" halve backslashes for escaped * space */ @@ -3991,7 +3992,7 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, if (pat[i] == '\\' && pat[i + 1] == ' ') STRMOVE(pat + i, pat + i + 1); - flags |= EW_FILE | EW_EXEC; + flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; bool mustfree = false; // Track memory allocation for *path. /* For an absolute name we don't use $PATH. */ @@ -4011,10 +4012,23 @@ static void expand_shellcmd(char_u *filepat, int *num_file, char_u ***file, /* * Go over all directories in $PATH. Expand matches in that directory and - * collect them in "ga". + * collect them in "ga". When "." is not in $PATH also expaned for the + * current directory, to find "subdir/cmd". */ ga_init(&ga, (int)sizeof(char *), 10); - for (s = path; *s != NUL; s = e) { + for (s = path; ; s = e) { + if (*s == NUL) + { + if (did_curdir) { + break; + } + // Find directories in the current directory, path is empty. + did_curdir = true; + } + else if (*s == '.') { + did_curdir = true; + } + if (*s == ' ') ++s; /* Skip space used for absolute path name. */ diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index abb71a2c15..a9c9eb608b 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -164,6 +164,7 @@ int os_nodetype(const char *name) /// /// @param[in] name Name of the executable. /// @param[out] abspath Path of the executable, if found and not `NULL`. +/// @param[in] use_path If 'false', only check if "name" is executable /// /// @return `true` if `name` is executable and /// - can be found in $PATH, @@ -171,15 +172,18 @@ int os_nodetype(const char *name) /// - is absolute. /// /// @return `false` otherwise. -bool os_can_exe(const char_u *name, char_u **abspath) +bool os_can_exe(const char_u *name, char_u **abspath, bool use_path) FUNC_ATTR_NONNULL_ARG(1) { - // If it's an absolute or relative path don't need to use $PATH. - if (path_is_absolute_path(name) + // when use_path is false or if it's an absolute or relative path don't + // need to use $PATH. + if (!use_path || path_is_absolute_path(name) || (name[0] == '.' && (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) { - if (is_executable(name)) { + // There must be a path separator, files in the current directory + // can't be executed + if (gettail_dir(name) != name && is_executable(name)) { if (abspath != NULL) { *abspath = save_absolute_path(name); } diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 63a3dbc054..cc4fb2653d 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -577,7 +577,8 @@ int mch_expand_wildcards(int num_pat, char_u **pat, int *num_file, continue; /* Skip files that are not executable if we check for that. */ - if (!dir && (flags & EW_EXEC) && !os_can_exe((*file)[i], NULL)) + if (!dir && (flags & EW_EXEC) + && !os_can_exe((*file)[i], NULL, !(flags & EW_SHELLCMD))) continue; p = xmalloc(STRLEN((*file)[i]) + 1 + dir); diff --git a/src/nvim/path.c b/src/nvim/path.c index 80ad643aa1..252e9430ec 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -981,12 +981,12 @@ static void uniquefy_paths(garray_T *gap, char_u *pattern) * "/path/file", "/path/dir/", "/path//dir", "/file" * ^ ^ ^ ^ */ -static char_u *gettail_dir(char_u *fname) +char_u *gettail_dir(const char_u *fname) { - char_u *dir_end = fname; - char_u *next_dir_end = fname; + const char_u *dir_end = fname; + const char_u *next_dir_end = fname; bool look_for_sep = true; - char_u *p; + const char_u *p; for (p = fname; *p != NUL; ) { if (vim_ispathsep(*p)) { @@ -1001,7 +1001,7 @@ static char_u *gettail_dir(char_u *fname) } mb_ptr_adv(p); } - return dir_end; + return (char_u *)dir_end; } @@ -1318,8 +1318,10 @@ void addfile( if ((isdir && !(flags & EW_DIR)) || (!isdir && !(flags & EW_FILE))) return; - /* If the file isn't executable, may not add it. Do accept directories. */ - if (!isdir && (flags & EW_EXEC) && !os_can_exe(f, NULL)) + // If the file isn't executable, may not add it. Do accept directories. + // When invoked from expand_shellcmd() do not use $PATH. + if (!isdir && (flags & EW_EXEC) + && !os_can_exe(f, NULL, !(flags & EW_SHELLCMD))) return; char_u *p = xmalloc(STRLEN(f) + 1 + isdir); diff --git a/src/nvim/path.h b/src/nvim/path.h index 88e5935c24..860cc0da86 100644 --- a/src/nvim/path.h +++ b/src/nvim/path.h @@ -21,6 +21,8 @@ /* Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND * is used when executing commands and EW_SILENT for interactive expanding. */ #define EW_ALLLINKS 0x1000 // also links not pointing to existing file +#define EW_SHELLCMD 0x2000 // called from expand_shellcmd(), don't check + // if executable is in $PATH #define EW_DODOT 0x4000 // also files starting with a dot #define EW_EMPTYOK 0x8000 // no matches is not an error diff --git a/src/nvim/version.c b/src/nvim/version.c index b9e97f205e..fbc9854dc1 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -1006,7 +1006,7 @@ static int included_patches[] = { 675, // 674 NA 673, - // 672, + 672, 671, 670, // 669 NA |