From 376ce3e404b75d267089c4bc6dc7c18d0b38728b Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 9 Jan 2022 19:19:02 -0500 Subject: [PATCH] Prefer $HOME when looking up the current user's home directory. When we need to identify the home directory on non-Windows, first consult getenv("HOME"). If that's empty or unset, fall back on our previous method of checking the database. Preferring $HOME allows the user to intentionally point at some other directory, and it seems to be in line with the behavior of most other utilities. However, we shouldn't rely on it completely, as $HOME is likely to be unset when running as a daemon. Anders Kaseorg Discussion: https://postgr.es/m/1634252654444.90107@mit.edu --- src/bin/psql/command.c | 31 +++++++++++++++++++------------ src/interfaces/libpq/fe-connect.c | 21 ++++++++++++++------- src/port/path.c | 25 ++++++++++++++++++------- 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 053332e7af5..f5904748553 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -558,19 +558,25 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd) else { #ifndef WIN32 - struct passwd *pw; - uid_t user_id = geteuid(); - - errno = 0; /* clear errno before call */ - pw = getpwuid(user_id); - if (!pw) + /* This should match get_home_path() */ + dir = getenv("HOME"); + if (dir == NULL || dir[0] == '\0') { - pg_log_error("could not get home directory for user ID %ld: %s", - (long) user_id, - errno ? strerror(errno) : _("user does not exist")); - exit(EXIT_FAILURE); + uid_t user_id = geteuid(); + struct passwd *pw; + + errno = 0; /* clear errno before call */ + pw = getpwuid(user_id); + if (pw) + dir = pw->pw_dir; + else + { + pg_log_error("could not get home directory for user ID %ld: %s", + (long) user_id, + errno ? strerror(errno) : _("user does not exist")); + success = false; + } } - dir = pw->pw_dir; #else /* WIN32 */ /* @@ -581,7 +587,8 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd) #endif /* WIN32 */ } - if (chdir(dir) == -1) + if (success && + chdir(dir) < 0) { pg_log_error("\\%s: could not change directory to \"%s\": %m", cmd, dir); diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 72914116ee6..a12e0180fdb 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -7267,14 +7267,21 @@ bool pqGetHomeDirectory(char *buf, int bufsize) { #ifndef WIN32 - char pwdbuf[BUFSIZ]; - struct passwd pwdstr; - struct passwd *pwd = NULL; + const char *home; - (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); - if (pwd == NULL) - return false; - strlcpy(buf, pwd->pw_dir, bufsize); + home = getenv("HOME"); + if (home == NULL || home[0] == '\0') + { + char pwdbuf[BUFSIZ]; + struct passwd pwdstr; + struct passwd *pwd = NULL; + + (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); + if (pwd == NULL) + return false; + home = pwd->pw_dir; + } + strlcpy(buf, home, bufsize); return true; #else char tmppath[MAX_PATH]; diff --git a/src/port/path.c b/src/port/path.c index ee4227ec983..5ac26f4bcf7 100644 --- a/src/port/path.c +++ b/src/port/path.c @@ -807,14 +807,25 @@ bool get_home_path(char *ret_path) { #ifndef WIN32 - char pwdbuf[BUFSIZ]; - struct passwd pwdstr; - struct passwd *pwd = NULL; + /* + * We first consult $HOME. If that's unset, try to get the info from + * . + */ + const char *home; - (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); - if (pwd == NULL) - return false; - strlcpy(ret_path, pwd->pw_dir, MAXPGPATH); + home = getenv("HOME"); + if (home == NULL || home[0] == '\0') + { + char pwdbuf[BUFSIZ]; + struct passwd pwdstr; + struct passwd *pwd = NULL; + + (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); + if (pwd == NULL) + return false; + home = pwd->pw_dir; + } + strlcpy(ret_path, home, MAXPGPATH); return true; #else char *tmppath;