diff options
-rw-r--r-- | src/misc1.c | 21 | ||||
-rw-r--r-- | src/os/os.h | 1 | ||||
-rw-r--r-- | src/os/users.c | 22 | ||||
-rw-r--r-- | src/os_unix_defs.h | 4 | ||||
-rw-r--r-- | test/unit/os/users.moon | 13 |
5 files changed, 41 insertions, 20 deletions
diff --git a/src/misc1.c b/src/misc1.c index e78343291b..4c3e21735f 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -2895,25 +2895,14 @@ expand_env_esc ( *var = NUL; # ifdef UNIX /* - * If the system supports getpwnam(), use it. - * Otherwise, or if getpwnam() fails, the shell is used to - * expand ~user. This is slower and may fail if the shell + * Use mch_get_user_directory() to get the user directory. + * If this function fails, the shell is used to + * expand ~user. This is slower and may fail if the shell * does not support ~user (old versions of /bin/sh). */ -# if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) - { - struct passwd *pw; - - /* Note: memory allocated by getpwnam() is never freed. - * Calling endpwent() apparently doesn't help. */ - pw = getpwnam((char *)dst + 1); - if (pw != NULL) - var = (char_u *)pw->pw_dir; - else - var = NULL; - } + var = (char_u *)mch_get_user_directory((char *)dst + 1); + mustfree = TRUE; if (var == NULL) -# endif { expand_T xpc; diff --git a/src/os/os.h b/src/os/os.h index d94f8bdc57..9ed5379e34 100644 --- a/src/os/os.h +++ b/src/os/os.h @@ -16,5 +16,6 @@ char *mch_getenvname_at_index(size_t index); int mch_get_usernames(garray_T *usernames); int mch_get_user_name(char *s, size_t len); int mch_get_uname(uid_t uid, char *s, size_t len); +char *mch_get_user_directory(const char *name); #endif diff --git a/src/os/users.c b/src/os/users.c index fa8971be61..2d33688d97 100644 --- a/src/os/users.c +++ b/src/os/users.c @@ -84,3 +84,25 @@ int mch_get_uname(uid_t uid, char *s, size_t len) return FAIL; // a number is not a name } +/* + * Returns the user directory for the given username. + * The caller has to free() the returned string. + * If the username is not found, NULL is returned. + */ +char *mch_get_user_directory(const char *name) +{ +#if defined(HAVE_GETPWNAM) && defined(HAVE_PWD_H) + struct passwd *pw; + if (name == NULL) { + return NULL; + } + pw = getpwnam(name); + if (pw != NULL) { + // save the string from the static passwd entry into malloced memory + char *user_directory = (char *)vim_strsave((char_u *)pw->pw_dir); + return user_directory; + } +#endif + return NULL; +} + diff --git a/src/os_unix_defs.h b/src/os_unix_defs.h index 98ba40037c..b881e2c5c9 100644 --- a/src/os_unix_defs.h +++ b/src/os_unix_defs.h @@ -121,10 +121,6 @@ #define BASENAMELEN (MAXNAMLEN - 5) -#ifdef HAVE_PWD_H -# include <pwd.h> -#endif - /* * Unix system-dependent file names */ diff --git a/test/unit/os/users.moon b/test/unit/os/users.moon index 2f08bdbdf5..76f51c94f2 100644 --- a/test/unit/os/users.moon +++ b/test/unit/os/users.moon @@ -14,6 +14,7 @@ typedef struct growarray { int mch_get_usernames(garray_T *usernames); int mch_get_user_name(char *s, size_t len); int mch_get_uname(int uid, char *s, size_t len); +char *mch_get_user_directory(const char *name); int getuid(void); ]] @@ -75,3 +76,15 @@ describe 'users function', -> eq FAIL, users.mch_get_uname(user_id, name_out, 100) eq '2342', ffi.string name_out + describe 'mch_get_user_directory', -> + + it 'should return NULL if called with NULL', -> + eq NULL, users.mch_get_user_directory NULL + + it 'should return $HOME for the current user', -> + home = os.getenv('HOME') + eq home, ffi.string (users.mch_get_user_directory current_username) + + it 'should return NULL if the user is not found', -> + eq NULL, users.mch_get_user_directory 'neovim_user_not_found_test' + |