From d97ae8230e0c5be122e71341fd65d3e3553ed010 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 6 Jan 2005 01:00:12 +0000
Subject: [PATCH] Make the various places that determine the user's "home
 directory" consistent.  On Unix we now always consult getpwuid(); $HOME isn't
 used at all.  On Windows the code currently consults $USERPROFILE, or $HOME
 if that's not defined, but I expect this will change as soon as the win32
 hackers come to a consensus.  Nothing done yet about changing the file names
 used underneath $USERPROFILE.

---
 src/include/port.h                |  8 +---
 src/interfaces/libpq/fe-connect.c | 66 +++++++++++++++++++------------
 src/interfaces/libpq/fe-secure.c  | 33 +---------------
 src/interfaces/libpq/libpq-int.h  |  3 +-
 src/port/path.c                   | 38 ++++++++++++------
 5 files changed, 72 insertions(+), 76 deletions(-)

diff --git a/src/include/port.h b/src/include/port.h
index 603361ad9b..54984fe437 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/port.h,v 1.68 2004/12/31 22:03:19 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/port.h,v 1.69 2005/01/06 00:59:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,12 +98,6 @@ extern int find_other_exec(const char *argv0, const char *target,
 #define SYSTEMQUOTE ""
 #endif
 
-#if defined(WIN32) && !defined(__CYGWIN__)
-#define HOMEDIR "USERPROFILE"
-#else
-#define HOMEDIR "HOME"
-#endif
-
 /* Portable delay handling */
 extern void pg_usleep(long microsec);
 
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 95ed43f83b..9f7bd09ce4 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.295 2005/01/04 23:18:25 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.296 2005/01/06 00:59:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3175,8 +3175,7 @@ static char *
 PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 {
 	FILE	   *fp;
-	char	   *pgpassfile;
-	char	   *home;
+	char		pgpassfile[MAXPGPATH];
 	struct stat stat_buf;
 
 #define LINELEN NAMEDATALEN*5
@@ -3194,32 +3193,16 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 	if (port == NULL)
 		port = DEF_PGPORT_STR;
 
-	/*
-	 * Look for it in the home dir. We don't use get_home_path() so we
-	 * don't pull path.c into our library.
-	 */
-	if (!(home = getenv(HOMEDIR)))
+	if (!pqGetHomeDirectory(pgpassfile, sizeof(pgpassfile)))
 		return NULL;
 
-	pgpassfile = malloc(strlen(home) + 1 + strlen(PGPASSFILE) + 1);
-	if (!pgpassfile)
-	{
-		fprintf(stderr, libpq_gettext("out of memory\n"));
-		return NULL;
-	}
-
-#ifndef WIN32
-	sprintf(pgpassfile, "%s/%s", home, PGPASSFILE);
-#else
-	sprintf(pgpassfile, "%s\\%s", home, PGPASSFILE);
-#endif
+	snprintf(pgpassfile + strlen(pgpassfile),
+			 sizeof(pgpassfile) - strlen(pgpassfile),
+			 "/%s", PGPASSFILE);
 
 	/* If password file cannot be opened, ignore it. */
 	if (stat(pgpassfile, &stat_buf) == -1)
-	{
-		free(pgpassfile);
 		return NULL;
-	}
 
 #ifndef WIN32
 	/* If password file is insecure, alert the user and ignore it. */
@@ -3228,13 +3211,11 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 		fprintf(stderr,
 				libpq_gettext("WARNING: Password file %s has world or group read access; permission should be u=rw (0600)\n"),
 				pgpassfile);
-		free(pgpassfile);
 		return NULL;
 	}
 #endif
 
 	fp = fopen(pgpassfile, "r");
-	free(pgpassfile);
 	if (fp == NULL)
 		return NULL;
 
@@ -3270,6 +3251,41 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 #undef LINELEN
 }
 
+/*
+ * Obtain user's home directory, return in given buffer
+ *
+ * This is essentially the same as get_home_path(), but we don't use that
+ * because we don't want to pull path.c into libpq (it pollutes application
+ * namespace)
+ */
+bool
+pqGetHomeDirectory(char *buf, int bufsize)
+{
+#ifndef WIN32
+	char		pwdbuf[BUFSIZ];
+	struct passwd pwdstr;
+	struct passwd *pwd = NULL;
+
+	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
+		return false;
+	StrNCpy(buf, pwd->pw_dir, bufsize);
+	return true;
+
+#else
+
+	/* TEMPORARY PLACEHOLDER IMPLEMENTATION */
+	const char *homedir;
+
+	homedir = getenv("USERPROFILE");
+	if (homedir == NULL)
+		homedir = getenv("HOME");
+	if (homedir == NULL)
+		return false;
+	StrNCpy(buf, homedir, bufsize);
+	return true;
+#endif
+}
+
 /*
  * To keep the API consistent, the locking stubs are always provided, even
  * if they are not required.
diff --git a/src/interfaces/libpq/fe-secure.c b/src/interfaces/libpq/fe-secure.c
index 89064be506..a87d7221e2 100644
--- a/src/interfaces/libpq/fe-secure.c
+++ b/src/interfaces/libpq/fe-secure.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.62 2005/01/04 23:18:25 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-secure.c,v 1.63 2005/01/06 00:59:47 tgl Exp $
  *
  * NOTES
  *	  [ Most of these notes are wrong/obsolete, but perhaps not all ]
@@ -107,6 +107,7 @@
 #endif
 #include <arpa/inet.h>
 #endif
+#include <sys/stat.h>
 
 #ifdef ENABLE_THREAD_SAFETY
 #include <pthread.h>
@@ -116,11 +117,6 @@
 #include "strdup.h"
 #endif
 
-#ifndef WIN32
-#include <pwd.h>
-#endif
-#include <sys/stat.h>
-
 #ifdef USE_SSL
 #include <openssl/ssl.h>
 #include <openssl/dh.h>
@@ -493,31 +489,6 @@ pqsecure_write(PGconn *conn, const void *ptr, size_t len)
 /* ------------------------------------------------------------ */
 #ifdef USE_SSL
 
-/*
- * Obtain user's home directory, return in given buffer
- *
- * This code isn't really SSL-specific, but currently we only need it in
- * SSL-related places.
- */
-static bool
-pqGetHomeDirectory(char *buf, int bufsize)
-{
-#ifndef WIN32
-	char		pwdbuf[BUFSIZ];
-	struct passwd pwdstr;
-	struct passwd *pwd = NULL;
-
-	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
-		return false;
-	StrNCpy(buf, pwd->pw_dir, bufsize);
-	return true;
-
-#else
-
-	return false;				/* PLACEHOLDER */
-#endif
-}
-
 /*
  *	Certificate verification callback
  *
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 91b1ac4ea9..9862e01bc9 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.99 2004/12/31 22:03:50 pgsql Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.100 2005/01/06 00:59:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -377,6 +377,7 @@ extern char *const pgresStatus[];
 
 extern int pqPacketSend(PGconn *conn, char pack_type,
 			 const void *buf, size_t buf_len);
+extern bool pqGetHomeDirectory(char *buf, int bufsize);
 
 #ifdef ENABLE_THREAD_SAFETY
 extern pgthreadlock_t pg_g_threadlock;
diff --git a/src/port/path.c b/src/port/path.c
index f92b492894..204c782ff1 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/path.c,v 1.46 2004/12/31 22:03:53 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/port/path.c,v 1.47 2005/01/06 01:00:12 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,10 @@
 #include "c.h"
 
 #include <ctype.h>
+#include <sys/stat.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
 
 #include "pg_config_paths.h"
 
@@ -445,19 +449,29 @@ get_locale_path(const char *my_exec_path, char *ret_path)
 bool
 get_home_path(char *ret_path)
 {
-	const char *homedir = getenv(HOMEDIR);
+#ifndef WIN32
+	char		pwdbuf[BUFSIZ];
+	struct passwd pwdstr;
+	struct passwd *pwd = NULL;
 
-	if (homedir == NULL)
-	{
-		*ret_path = '\0';
+	if (pqGetpwuid(geteuid(), &pwdstr, pwdbuf, sizeof(pwdbuf), &pwd) != 0)
 		return false;
-	}
-	else
-	{
-		StrNCpy(ret_path, homedir, MAXPGPATH);
-		canonicalize_path(ret_path);
-		return true;
-	}
+	StrNCpy(ret_path, pwd->pw_dir, MAXPGPATH);
+	return true;
+
+#else
+
+	/* TEMPORARY PLACEHOLDER IMPLEMENTATION */
+	const char *homedir;
+
+	homedir = getenv("USERPROFILE");
+	if (homedir == NULL)
+		homedir = getenv("HOME");
+	if (homedir == NULL)
+		return false;
+	StrNCpy(ret_path, homedir, MAXPGPATH);
+	return true;
+#endif
 }