mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 15:08:35 +00:00
win: Append process dir to $PATH
This allows executables to be found by :!, system(), and executable() if
they live next to ("sibling" to) nvim.exe. This is what gvim on Windows
does, and also matches the behavior of Win32 SearchPath().
c4a249a736/src/os_win32.c (L354-L370)
This commit is contained in:
@@ -238,9 +238,7 @@ int main(int argc, char **argv)
|
||||
// Check if we have an interactive window.
|
||||
check_and_set_isatty(¶ms);
|
||||
|
||||
// Get the name with which Nvim was invoked, with and without path.
|
||||
set_vim_var_string(VV_PROGPATH, argv[0], -1);
|
||||
set_vim_var_string(VV_PROGNAME, (char *) path_tail((char_u *) argv[0]), -1);
|
||||
init_path(argv[0]);
|
||||
|
||||
event_init();
|
||||
/*
|
||||
@@ -1194,9 +1192,27 @@ static void check_and_set_isatty(mparm_T *paramp)
|
||||
paramp->err_isatty = os_isatty(fileno(stderr));
|
||||
TIME_MSG("window checked");
|
||||
}
|
||||
/*
|
||||
* Get filename from command line, given that there is one.
|
||||
*/
|
||||
|
||||
// Sets v:progname and v:progpath. Also modifies $PATH on Windows.
|
||||
static void init_path(char *exename)
|
||||
{
|
||||
char exepath[MAXPATHL] = { 0 };
|
||||
size_t exepathlen = MAXPATHL;
|
||||
// Make v:progpath absolute.
|
||||
if (os_exepath(exepath, &exepathlen) != 0) {
|
||||
EMSG2(e_intern2, "init_path()");
|
||||
}
|
||||
set_vim_var_string(VV_PROGPATH, exepath, -1);
|
||||
set_vim_var_string(VV_PROGNAME, (char *)path_tail((char_u *)exename), -1);
|
||||
|
||||
#ifdef WIN32
|
||||
// Append the process start directory to $PATH, so that ":!foo" finds tools
|
||||
// shipped with Windows package. This also mimics SearchPath().
|
||||
os_setenv_append_path(exepath);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Get filename from command line, if any.
|
||||
static char_u *get_fname(mparm_T *parmp, char_u *cwd)
|
||||
{
|
||||
#if !defined(UNIX)
|
||||
|
@@ -831,3 +831,43 @@ char_u *get_env_name(expand_T *xp, int idx)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Appends the head of `fname` to $PATH and sets it in the environment.
|
||||
///
|
||||
/// @param fname Full path whose parent directory will be appended to $PATH.
|
||||
///
|
||||
/// @return true if `path` was appended-to
|
||||
bool os_setenv_append_path(const char *fname)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
#ifdef WIN32
|
||||
// 8191 (plus NUL) is considered the practical maximum.
|
||||
# define MAX_ENVPATHLEN 8192
|
||||
#else
|
||||
// No prescribed maximum on unix.
|
||||
# define MAX_ENVPATHLEN INT_MAX
|
||||
#endif
|
||||
if (!path_is_absolute_path((char_u *)fname)) {
|
||||
EMSG2(_(e_intern2), "os_setenv_append_path()");
|
||||
return false;
|
||||
}
|
||||
const char *tail = (char *)path_tail_with_sep((char_u *)fname);
|
||||
const char *dir = (char *)vim_strnsave((char_u *)fname,
|
||||
(size_t)(tail - fname));
|
||||
const char *path = os_getenv("PATH");
|
||||
const size_t pathlen = path ? strlen(path) : 0;
|
||||
const size_t newlen = pathlen + strlen(dir) + 2;
|
||||
if (newlen < MAX_ENVPATHLEN) {
|
||||
char *temp = xmalloc(newlen);
|
||||
if (pathlen == 0) {
|
||||
temp[0] = NUL;
|
||||
} else {
|
||||
xstrlcpy(temp, path, newlen);
|
||||
xstrlcat(temp, ENV_SEPSTR, newlen);
|
||||
}
|
||||
xstrlcat(temp, dir, newlen);
|
||||
os_setenv("PATH", temp, 1);
|
||||
xfree(temp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -224,7 +224,7 @@ bool os_can_exe(const char_u *name, char_u **abspath, bool use_path)
|
||||
if (!use_path || path_is_absolute_path(name)
|
||||
|| (name[0] == '.'
|
||||
&& (name[1] == '/' || (name[1] == '.' && name[2] == '/')))) {
|
||||
#if WIN32
|
||||
#ifdef WIN32
|
||||
bool ok = is_executable(name);
|
||||
#else
|
||||
// Must have path separator, cannot execute files in the current directory.
|
||||
@@ -255,7 +255,7 @@ static bool is_executable(const char_u *name)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WIN32
|
||||
#ifdef WIN32
|
||||
// Windows does not have exec bit; just check if the file exists and is not
|
||||
// a directory.
|
||||
return (S_ISREG(mode));
|
||||
@@ -281,7 +281,7 @@ static bool is_executable_in_path(const char_u *name, char_u **abspath)
|
||||
#ifdef WIN32
|
||||
// Prepend ".;" to $PATH.
|
||||
size_t pathlen = strlen(path_env);
|
||||
char *path = memcpy(xmallocz(pathlen + 3), ".;", 2);
|
||||
char *path = memcpy(xmallocz(pathlen + 3), "." ENV_SEPSTR, 2);
|
||||
memcpy(path + 2, path_env, pathlen);
|
||||
#else
|
||||
char *path = xstrdup(path_env);
|
||||
@@ -1027,7 +1027,7 @@ shortcut_end:
|
||||
int os_translate_sys_error(int sys_errno) {
|
||||
#ifdef HAVE_UV_TRANSLATE_SYS_ERROR
|
||||
return uv_translate_sys_error(sys_errno);
|
||||
#elif WIN32
|
||||
#elif defined(WIN32)
|
||||
// TODO(equalsraf): libuv does not yet expose uv_translate_sys_error()
|
||||
// in its public API, include a version here until it can be used.
|
||||
// See https://github.com/libuv/libuv/issues/79
|
||||
|
@@ -16,7 +16,8 @@
|
||||
// Special wildcards that need to be handled by the shell.
|
||||
#define SPECIAL_WILDCHAR "`'{"
|
||||
|
||||
// Separator character for environment variables.
|
||||
// Character that separates entries in $PATH.
|
||||
#define ENV_SEPCHAR ':'
|
||||
#define ENV_SEPSTR ":"
|
||||
|
||||
#endif // NVIM_OS_UNIX_DEFS_H
|
||||
|
@@ -20,8 +20,9 @@
|
||||
|
||||
#define FNAME_ILLEGAL "\"*?><|"
|
||||
|
||||
// Separator character for environment variables.
|
||||
// Character that separates entries in $PATH.
|
||||
#define ENV_SEPCHAR ';'
|
||||
#define ENV_SEPSTR ";"
|
||||
|
||||
#define USE_CRNL
|
||||
|
||||
|
Reference in New Issue
Block a user