diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/main.c | 5 | ||||
| -rw-r--r-- | src/nvim/option.c | 6 | ||||
| -rw-r--r-- | src/nvim/os/env.c | 57 | ||||
| -rw-r--r-- | src/nvim/os/fs.c | 6 | ||||
| -rw-r--r-- | src/nvim/path.c | 47 | 
5 files changed, 87 insertions, 34 deletions
| diff --git a/src/nvim/main.c b/src/nvim/main.c index 40b553e93c..3831f0ac6b 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1223,7 +1223,8 @@ static void init_path(char *exename)    size_t exepathlen = MAXPATHL;    // Make v:progpath absolute.    if (os_exepath(exepath, &exepathlen) != 0) { -    EMSG2(e_intern2, "init_path()"); +    // Fall back to argv[0]. Missing procfs? #6734 +    path_guess_exepath(exename, exepath, sizeof(exepath));    }    set_vim_var_string(VV_PROGPATH, exepath, -1);    set_vim_var_string(VV_PROGNAME, (char *)path_tail((char_u *)exename), -1); @@ -1684,7 +1685,7 @@ static bool do_user_initialization(void)      do {        const char *dir;        size_t dir_len; -      iter = vim_colon_env_iter(config_dirs, iter, &dir, &dir_len); +      iter = vim_env_iter(':', config_dirs, iter, &dir, &dir_len);        if (dir == NULL || dir_len == 0) {          break;        } diff --git a/src/nvim/option.c b/src/nvim/option.c index c36ca1bfe9..392a2f3908 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -341,7 +341,7 @@ static inline size_t compute_double_colon_len(const char *const val,    do {      size_t dir_len;      const char *dir; -    iter = vim_colon_env_iter(val, iter, &dir, &dir_len); +    iter = vim_env_iter(':', val, iter, &dir, &dir_len);      if (dir != NULL && dir_len > 0) {        ret += ((dir_len + memcnt(dir, ',', dir_len) + common_suf_len                 + !after_pathsep(dir, dir + dir_len)) * 2 @@ -385,8 +385,8 @@ static inline char *add_colon_dirs(char *dest, const char *const val,    do {      size_t dir_len;      const char *dir; -    iter = (forward ? vim_colon_env_iter : vim_colon_env_iter_rev)( -        val, iter, &dir, &dir_len); +    iter = (forward ? vim_env_iter : vim_env_iter_rev)(':', val, iter, &dir, +                                                       &dir_len);      if (dir != NULL && dir_len > 0) {        dest = strcpy_comma_escaped(dest, dir, dir_len);        if (!after_pathsep(dest - 1, dest)) { diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c index 8f7a6e72b5..a7d1037cfc 100644 --- a/src/nvim/os/env.c +++ b/src/nvim/os/env.c @@ -521,10 +521,11 @@ static char *remove_tail(char *path, char *pend, char *dirname)    return pend;  } -/// Iterate over colon-separated list +/// Iterate over a delimited list.  ///  /// @note Environment variables must not be modified during iteration.  /// +/// @param[in]   delim Delimiter character.  /// @param[in]   val   Value of the environment variable to iterate over.  /// @param[in]   iter  Pointer used for iteration. Must be NULL on first  ///                    iteration. @@ -533,18 +534,19 @@ static char *remove_tail(char *path, char *pend, char *dirname)  /// @param[out]  len   Location where current directory length should be saved.  ///  /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter(const char *const val, -                               const void *const iter, -                               const char **const dir, -                               size_t *const len) -  FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter(const char delim, +                         const char *const val, +                         const void *const iter, +                         const char **const dir, +                         size_t *const len) +  FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT  {    const char *varval = (const char *) iter;    if (varval == NULL) {      varval = val;    }    *dir = varval; -  const char *const dirend = strchr(varval, ':'); +  const char *const dirend = strchr(varval, delim);    if (dirend == NULL) {      *len = strlen(varval);      return NULL; @@ -554,10 +556,11 @@ const void *vim_colon_env_iter(const char *const val,    }  } -/// Iterate over colon-separated list in reverse order +/// Iterate over a delimited list in reverse order.  ///  /// @note Environment variables must not be modified during iteration.  /// +/// @param[in]   delim Delimiter character.  /// @param[in]   val   Value of the environment variable to iterate over.  /// @param[in]   iter  Pointer used for iteration. Must be NULL on first  ///                    iteration. @@ -566,18 +569,19 @@ const void *vim_colon_env_iter(const char *const val,  /// @param[out]  len   Location where current directory length should be saved.  ///  /// @return Next iter argument value or NULL when iteration should stop. -const void *vim_colon_env_iter_rev(const char *const val, -                                   const void *const iter, -                                   const char **const dir, -                                   size_t *const len) -  FUNC_ATTR_NONNULL_ARG(1, 3, 4) FUNC_ATTR_WARN_UNUSED_RESULT +const void *vim_env_iter_rev(const char delim, +                             const char *const val, +                             const void *const iter, +                             const char **const dir, +                             size_t *const len) +  FUNC_ATTR_NONNULL_ARG(2, 4, 5) FUNC_ATTR_WARN_UNUSED_RESULT  {    const char *varend = (const char *) iter;    if (varend == NULL) {      varend = val + strlen(val) - 1;    } -  const size_t varlen = (size_t) (varend - val) + 1; -  const char *const colon = xmemrchr(val, ':', varlen); +  const size_t varlen = (size_t)(varend - val) + 1; +  const char *const colon = xmemrchr(val, (uint8_t)delim, varlen);    if (colon == NULL) {      *len = varlen;      *dir = val; @@ -634,18 +638,17 @@ char *vim_getenv(const char *name)      char exe_name[MAXPATHL];      // Find runtime path relative to the nvim binary: ../share/nvim/runtime      if (vim_path == NULL) { -      size_t exe_name_len = MAXPATHL; -      if (os_exepath(exe_name, &exe_name_len) == 0) { -        char *path_end = (char *)path_tail_with_sep((char_u *)exe_name); -        *path_end = '\0';  // remove the trailing "nvim.exe" -        path_end = (char *)path_tail((char_u *)exe_name); -        *path_end = '\0';  // remove the trailing "bin/" -        if (append_path( -            exe_name, -            "share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR, -            MAXPATHL) == OK) { -          vim_path = exe_name;  // -V507 -        } +      xstrlcpy(exe_name, (char *)get_vim_var_str(VV_PROGPATH), +               sizeof(exe_name)); +      char *path_end = (char *)path_tail_with_sep((char_u *)exe_name); +      *path_end = '\0';  // remove the trailing "nvim.exe" +      path_end = (char *)path_tail((char_u *)exe_name); +      *path_end = '\0';  // remove the trailing "bin/" +      if (append_path( +          exe_name, +          "share" _PATHSEPSTR "nvim" _PATHSEPSTR "runtime" _PATHSEPSTR, +          MAXPATHL) == OK) { +        vim_path = exe_name;  // -V507        }      } diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index aaa750db50..b9a9480cb8 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -196,11 +196,13 @@ int os_nodetype(const char *name)  }  /// Gets the absolute path of the currently running executable. +/// May fail if procfs is missing. #6734 +/// @see path_exepath  /// -/// @param[out] buffer Returns the path string. +/// @param[out] buffer Full path to the executable.  /// @param[in]  size   Size of `buffer`.  /// -/// @return `0` on success, or libuv error code on failure. +/// @return 0 on success, or libuv error code.  int os_exepath(char *buffer, size_t *size)    FUNC_ATTR_NONNULL_ALL  { diff --git a/src/nvim/path.c b/src/nvim/path.c index 12952f49db..23ed4d381e 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -2237,3 +2237,50 @@ int path_is_absolute_path(const char_u *fname)    return *fname == '/' || *fname == '~';  #endif  } + +/// Builds a full path from an invocation name `argv0`, based on heuristics. +/// +/// @param[in]  argv0     Name by which Nvim was invoked. +/// @param[out] buf       Guessed full path to `argv0`. +/// @param[in]  bufsize   Size of `buf`. +/// +/// @see os_exepath +void path_guess_exepath(const char *argv0, char *buf, size_t bufsize) +  FUNC_ATTR_NONNULL_ALL +{ +  char *path = getenv("PATH"); + +  if (path == NULL || path_is_absolute_path((char_u *)argv0)) { +    xstrlcpy(buf, argv0, bufsize); +  } else if (argv0[0] == '.' || strchr(argv0, PATHSEP)) { +    // Relative to CWD. +    if (os_dirname((char_u *)buf, MAXPATHL) != OK) { +      buf[0] = NUL; +    } +    xstrlcat(buf, PATHSEPSTR, bufsize); +    xstrlcat(buf, argv0, bufsize); +  } else { +    // Search $PATH for plausible location. +    const void *iter = NULL; +    do { +      const char *dir; +      size_t dir_len; +      iter = vim_env_iter(ENV_SEPCHAR, path, iter, &dir, &dir_len); +      if (dir == NULL || dir_len == 0) { +        break; +      } +      if (dir_len + 1 > sizeof(NameBuff)) { +        continue; +      } +      xstrlcpy((char *)NameBuff, dir, dir_len + 1); +      xstrlcat((char *)NameBuff, PATHSEPSTR, sizeof(NameBuff)); +      xstrlcat((char *)NameBuff, argv0, sizeof(NameBuff)); +      if (os_can_exe(NameBuff, NULL, false)) { +        xstrlcpy(buf, (char *)NameBuff, bufsize); +        return; +      } +    } while (iter != NULL); +    // Not found in $PATH, fall back to argv0. +    xstrlcpy(buf, argv0, bufsize); +  } +} | 
