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 <pwd.h> 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
This commit is contained in:
Tom Lane 2022-01-09 19:19:02 -05:00
parent 6867f963e3
commit 376ce3e404
3 changed files with 51 additions and 26 deletions

View File

@ -558,19 +558,25 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
else else
{ {
#ifndef WIN32 #ifndef WIN32
struct passwd *pw; /* This should match get_home_path() */
dir = getenv("HOME");
if (dir == NULL || dir[0] == '\0')
{
uid_t user_id = geteuid(); uid_t user_id = geteuid();
struct passwd *pw;
errno = 0; /* clear errno before call */ errno = 0; /* clear errno before call */
pw = getpwuid(user_id); pw = getpwuid(user_id);
if (!pw) if (pw)
dir = pw->pw_dir;
else
{ {
pg_log_error("could not get home directory for user ID %ld: %s", pg_log_error("could not get home directory for user ID %ld: %s",
(long) user_id, (long) user_id,
errno ? strerror(errno) : _("user does not exist")); errno ? strerror(errno) : _("user does not exist"));
exit(EXIT_FAILURE); success = false;
}
} }
dir = pw->pw_dir;
#else /* WIN32 */ #else /* WIN32 */
/* /*
@ -581,7 +587,8 @@ exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
#endif /* WIN32 */ #endif /* WIN32 */
} }
if (chdir(dir) == -1) if (success &&
chdir(dir) < 0)
{ {
pg_log_error("\\%s: could not change directory to \"%s\": %m", pg_log_error("\\%s: could not change directory to \"%s\": %m",
cmd, dir); cmd, dir);

View File

@ -7267,6 +7267,11 @@ bool
pqGetHomeDirectory(char *buf, int bufsize) pqGetHomeDirectory(char *buf, int bufsize)
{ {
#ifndef WIN32 #ifndef WIN32
const char *home;
home = getenv("HOME");
if (home == NULL || home[0] == '\0')
{
char pwdbuf[BUFSIZ]; char pwdbuf[BUFSIZ];
struct passwd pwdstr; struct passwd pwdstr;
struct passwd *pwd = NULL; struct passwd *pwd = NULL;
@ -7274,7 +7279,9 @@ pqGetHomeDirectory(char *buf, int bufsize)
(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
if (pwd == NULL) if (pwd == NULL)
return false; return false;
strlcpy(buf, pwd->pw_dir, bufsize); home = pwd->pw_dir;
}
strlcpy(buf, home, bufsize);
return true; return true;
#else #else
char tmppath[MAX_PATH]; char tmppath[MAX_PATH];

View File

@ -807,6 +807,15 @@ bool
get_home_path(char *ret_path) get_home_path(char *ret_path)
{ {
#ifndef WIN32 #ifndef WIN32
/*
* We first consult $HOME. If that's unset, try to get the info from
* <pwd.h>.
*/
const char *home;
home = getenv("HOME");
if (home == NULL || home[0] == '\0')
{
char pwdbuf[BUFSIZ]; char pwdbuf[BUFSIZ];
struct passwd pwdstr; struct passwd pwdstr;
struct passwd *pwd = NULL; struct passwd *pwd = NULL;
@ -814,7 +823,9 @@ get_home_path(char *ret_path)
(void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd); (void) pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd);
if (pwd == NULL) if (pwd == NULL)
return false; return false;
strlcpy(ret_path, pwd->pw_dir, MAXPGPATH); home = pwd->pw_dir;
}
strlcpy(ret_path, home, MAXPGPATH);
return true; return true;
#else #else
char *tmppath; char *tmppath;