Prefer $HOME when looking up the current user's home directory.
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 10 Jan 2022 00:19:02 +0000 (19:19 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 10 Jan 2022 00:19:02 +0000 (19:19 -0500)
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

src/bin/psql/command.c
src/interfaces/libpq/fe-connect.c
src/port/path.c

index 053332e7af5529fb4c18e1d2a3ca7135d2f26750..f5904748553f7a644b188449f5c063e3672fe5d0 100644 (file)
@@ -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);
index 72914116ee6f54e4fcd8dc45879443cb0d406ef9..a12e0180fdbb3068c3a7488e892871e2290cbfc7 100644 (file)
@@ -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];
index ee4227ec983fe5a6abeae2823737c7fb8c02a2ba..5ac26f4bcf77fec4da0ff431e72fa72efef3c608 100644 (file)
@@ -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
+        * <pwd.h>.
+        */
+       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;