From 4ec457ad581fff37dda7739ac61d6912c6538e48 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 30 Jan 2003 19:49:54 +0000
Subject: [PATCH] Fix regression in .pgpass support.  From Neil Conway.

---
 doc/src/sgml/libpq.sgml           | 47 +++++++++++++++++++++++--------
 src/interfaces/libpq/fe-connect.c | 47 ++++++++++++++++++-------------
 2 files changed, 63 insertions(+), 31 deletions(-)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 562604f182..55ad984318 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.106 2003/01/19 00:13:28 momjian Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.107 2003/01/30 19:49:54 tgl Exp $
 -->
 
  <chapter id="libpq">
@@ -203,9 +203,12 @@ PGconn *PQconnectdb(const char *conninfo)
      <term><literal>requiressl</literal></term>
      <listitem>
      <para>
-      Set to 1 to require SSL connection to the backend. <application>Libpq</>
-      will then refuse to connect if the server does not support
-      SSL. Set to 0 (default) to negotiate with server.
+      Set to 1 to require <acronym>SSL</acronym> connection to the server.
+      <application>Libpq</> will then refuse to connect if the server does not
+      accept an <acronym>SSL</acronym> connection.
+      Set to 0 (default) to negotiate with server.
+      This option is only available if
+      <productname>PostgreSQL</> is compiled with SSL support.
      </para>
      </listitem>
     </varlistentry>
@@ -2010,10 +2013,11 @@ routines like <function>PQgetvalue</function>.
 
 <para>
 The following environment variables can be used to select default
-connection parameter values, which will be used by <function>PQconnectdb</function> or
-<function>PQsetdbLogin</function> if no value is directly specified by the calling code.
-These are useful to avoid hard-coding database names into simple
-application programs.
+connection parameter values, which will be used by
+<function>PQconnectdb</>, <function>PQsetdbLogin</> and
+<function>PQsetdb</> if no value is directly specified by the calling
+code.  These are useful to avoid hard-coding database connection
+information into simple client applications.
 
 <itemizedlist>
 <listitem>
@@ -2091,6 +2095,25 @@ the <productname>PostgreSQL</productname> backend.
 messages from the backend server are displayed.
 </para>
 </listitem>
+<listitem>
+<para>
+<envar>PGREQUIRESSL</envar> sets whether or not the connection must be
+made over <acronym>SSL</acronym>. If set to
+<quote>1</quote>, <application>libpq</>
+will refuse to connect if the server does not accept
+an <acronym>SSL</acronym> connection.
+This option is only available if
+<productname>PostgreSQL</> is compiled with SSL support.
+</para>
+</listitem>
+<listitem>
+<para>
+<envar>PGCONNECT_TIMEOUT</envar> sets the maximum number of seconds
+that <application>libpq</application> will wait when attempting to
+connect to the <productname>PostgreSQL</productname> server. This
+option should be set to at least 2 seconds.
+</para>
+</listitem>
 </itemizedlist>
 </para>
 
@@ -2161,10 +2184,10 @@ a password. This file should have the format:
 <synopsis>
 <replaceable>hostname</replaceable>:<replaceable>port</replaceable>:<replaceable>database</replaceable>:<replaceable>username</replaceable>:<replaceable>password</replaceable>
 </synopsis>
-Any of these may be a literal name, or <literal>*</literal>, which matches
-anything.  The first match will be used so put more specific entries first.
-Entries with <literal>:</literal> or <literal>\</literal> should be escaped
-with <literal>\</literal>.
+Any of these may be a literal name, or <literal>*</literal>, which
+matches anything.  The first matching entry will be used, so put more-specific
+entries first.  When an entry contains <literal>:</literal> or
+<literal>\</literal>, it must be escaped with <literal>\</literal>.
 </para>
 <para>
 The permissions on <filename>.pgpass</filename> must disallow any
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 57108df1ff..a3368a83b5 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.221 2003/01/08 21:33:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.222 2003/01/30 19:49:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -123,7 +123,7 @@ static const PQconninfoOption PQconninfoOptions[] = {
 	"Database-Password", "*", 20},
 
 	{"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
-	"Connect-timeout", "", 10}, /* strlen( INT32_MAX) == 10 */
+	"Connect-timeout", "", 10}, /* strlen(INT32_MAX) == 10 */
 
 	{"dbname", "PGDATABASE", NULL, NULL,
 	"Database-Name", "", 20},
@@ -315,8 +315,14 @@ PQconnectStart(const char *conninfo)
 	tmp = conninfo_getval(connOptions, "password");
 	conn->pgpass = tmp ? strdup(tmp) : NULL;
 	if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
+	{
+		if (conn->pgpass)
+			free(conn->pgpass);
 		conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
-									 conn->dbName, conn->pguser);
+										conn->dbName, conn->pguser);
+		if (conn->pgpass == NULL)
+			conn->pgpass = strdup(DefaultPassword);
+	}
 	tmp = conninfo_getval(connOptions, "connect_timeout");
 	conn->connect_timeout = tmp ? strdup(tmp) : NULL;
 #ifdef USE_SSL
@@ -506,14 +512,13 @@ PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions,
 	else
 		conn->dbName = strdup(dbName);
 
-	/*
-	 * getPasswordFromFile mallocs its result, so we don't need strdup
-	 * here
-	 */
 	if (pwd)
 		conn->pgpass = strdup(pwd);
 	else if ((tmp = getenv("PGPASSWORD")) != NULL)
 		conn->pgpass = strdup(tmp);
+	else if ((tmp = PasswordFromFile(conn->pghost, conn->pgport,
+									 conn->dbName, conn->pguser)) != NULL)
+		conn->pgpass = tmp;
 	else
 		conn->pgpass = strdup(DefaultPassword);
 
@@ -2946,7 +2951,7 @@ pwdfMatchesString(char *buf, char *token)
 	return NULL;
 }
 
-/* get a password from the password file. */
+/* Get a password from the password file. Return value is malloc'd. */
 char *
 PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 {
@@ -2972,17 +2977,15 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 
 	/* Look for it in the home dir */
 	home = getenv("HOME");
-	if (home)
+	if (!home)
+		return NULL;
+
+	pgpassfile = malloc(strlen(home) + 1 + strlen(PGPASSFILE) + 1);
+	if (!pgpassfile)
 	{
-		pgpassfile = malloc(strlen(home) + 1 + strlen(PGPASSFILE) + 1);
-		if (!pgpassfile)
-		{
-			fprintf(stderr, libpq_gettext("out of memory\n"));
-			return NULL;
-		}
-	}
-	else
+		fprintf(stderr, libpq_gettext("out of memory\n"));
 		return NULL;
+	}
 
 	sprintf(pgpassfile, "%s/%s", home, PGPASSFILE);
 
@@ -3014,12 +3017,18 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
 	{
 		char	   *t = buf,
 				   *ret;
+		int			len;
 
 		fgets(buf, LINELEN - 1, fp);
-		if (strlen(buf) == 0)
+
+		len = strlen(buf);
+		if (len == 0)
 			continue;
 
-		buf[strlen(buf) - 1] = 0;
+		/* Remove trailing newline */
+		if (buf[len - 1] == '\n')
+			buf[len - 1] = 0;
+
 		if ((t = pwdfMatchesString(t, hostname)) == NULL ||
 			(t = pwdfMatchesString(t, port)) == NULL ||
 			(t = pwdfMatchesString(t, dbname)) == NULL ||
-- 
2.40.0