Alright, here goes another one:
1. Cleaned up the clutter with getPgPassFilename - the function is now named fillDefaultPGPassFile() and only does exactly that. 2. Since a connection option "pgpassfile" or environment variable "PGPASSFILE" are picked up in conninfo_add_defaults() or in case a password was needed, but neither a pgpassfile connection option or environment variable were set, we'd have filled the conn->pgpassfile field with the "default" ~/.pgpass stuff. Thus, when returning with an error, if conn->pgpassfile was set and a password was necessary, we must have tried that pgpassfile, so i got rid of the field "dot_pgpass_used" in the pg_conn struct and the pgpassfile string is always used in the error message.
3. Going on, I renamed "dot_pg_pass_warning()" to "PGPassFileWarning()"

Kind regards,
Julian Markwort
diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 4e34f00..1bd5597 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -930,7 +930,7 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
         Note that authentication is likely to fail if <literal>host</>
         is not the name of the server at network address <literal>hostaddr</>.
         Also, note that <literal>host</> rather than <literal>hostaddr</>
-        is used to identify the connection in <filename>~/.pgpass</> (see
+        is used to identify the connection in a password file (see
         <xref linkend="libpq-pgpass">).
        </para>
 
@@ -986,6 +986,16 @@ postgresql://%2Fvar%2Flib%2Fpostgresql/dbname
       </listitem>
      </varlistentry>
 
+     <varlistentry id="libpq-connect-pgpassfile" xreflabel="pgpassfile">
+      <term><literal>pgpassfile</literal></term>
+      <listitem>
+      <para>
+        Specifies the name of the file used to lookup passwords.
+        Defaults to the password file (see <xref linkend="libpq-pgpass">).
+      </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry id="libpq-connect-connect-timeout" 
xreflabel="connect_timeout">
       <term><literal>connect_timeout</literal></term>
       <listitem>
@@ -6862,9 +6872,8 @@ myEventProc(PGEventId evtId, void *evtInfo, void 
*passThrough)
       <indexterm>
        <primary><envar>PGPASSFILE</envar></primary>
       </indexterm>
-      <envar>PGPASSFILE</envar> specifies the name of the password file to
-      use for lookups.  If not set, it defaults to <filename>~/.pgpass</>
-      (see <xref linkend="libpq-pgpass">).
+      <envar>PGPASSFILE</envar> behaves the same as the <xref
+      linkend="libpq-connect-pgpassfile"> connection parameter.
      </para>
     </listitem>
 
@@ -7136,13 +7145,15 @@ myEventProc(PGEventId evtId, void *evtInfo, void 
*passThrough)
   </indexterm>
 
   <para>
-   The file <filename>.pgpass</filename> in a user's home directory or the
-   file referenced by <envar>PGPASSFILE</envar> can contain passwords to
+   The file <filename>.pgpass</filename> in a user's home directory can 
contain passwords to
    be used if the connection requires a password (and no password has been
    specified  otherwise). On Microsoft Windows the file is named
    <filename>%APPDATA%\postgresql\pgpass.conf</> (where
    <filename>%APPDATA%</> refers to the Application Data subdirectory in
    the user's profile).
+   Alternatively, a password file can be specified
+   using the connection parameter <xref linkend="libpq-connect-pgpassfile">
+   or the environment variable <envar>PGPASSFILE</envar>.
   </para>
 
   <para>
diff --git a/src/interfaces/libpq/fe-connect.c 
b/src/interfaces/libpq/fe-connect.c
index f3a9e5a..e8f8fe1 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -184,6 +184,10 @@ static const internalPQconninfoOption PQconninfoOptions[] 
= {
                "Database-Password", "*", 20,
        offsetof(struct pg_conn, pgpass)},
 
+       {"pgpassfile", "PGPASSFILE", NULL, NULL,
+               "Database-Password-File", "", 64,
+       offsetof(struct pg_conn, pgpassfile)},
+
        {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
                "Connect-timeout", "", 10,              /* strlen(INT32_MAX) == 
10 */
        offsetof(struct pg_conn, connect_timeout)},
@@ -375,9 +379,9 @@ static int parseServiceFile(const char *serviceFile,
                                 bool *group_found);
 static char *pwdfMatchesString(char *buf, char *token);
 static char *PasswordFromFile(char *hostname, char *port, char *dbname,
-                                char *username);
-static bool getPgPassFilename(char *pgpassfile);
-static void dot_pg_pass_warning(PGconn *conn);
+                                char *username, char *pgpassfile);
+static bool fillDefaultPGPassFile(PGconn *conn);
+static void PGPassFileWarning(PGconn *conn);
 static void default_threadlock(int acquire);
 
 
@@ -804,18 +808,22 @@ connectOptions2(PGconn *conn)
         */
        if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
        {
+               if(!conn->pgpassfile || conn->pgpassfile[0] =='\0')
+               {
+                       fillDefaultPGPassFile(conn);
+               }
+
                if (conn->pgpass)
                        free(conn->pgpass);
+               /* We'll pass conn->pgpassfile regardless of it's contents - 
checks happen in PasswordFromFile() */
                conn->pgpass = PasswordFromFile(conn->pghost, conn->pgport,
-                                                                               
conn->dbName, conn->pguser);
+                                                                               
conn->dbName, conn->pguser, conn->pgpassfile);
                if (conn->pgpass == NULL)
                {
                        conn->pgpass = strdup(DefaultPassword);
                        if (!conn->pgpass)
                                goto oom_error;
                }
-               else
-                       conn->dot_pgpass_used = true;
        }
 
        /*
@@ -2661,7 +2669,7 @@ keep_going:                                               
/* We will come back to here until there is
 
 error_return:
 
-       dot_pg_pass_warning(conn);
+       PGPassFileWarning(conn);
 
        /*
         * We used to close the socket at this point, but that makes it awkward
@@ -2792,7 +2800,6 @@ makeEmptyPGconn(void)
        conn->sock = PGINVALID_SOCKET;
        conn->auth_req_received = false;
        conn->password_needed = false;
-       conn->dot_pgpass_used = false;
 #ifdef USE_SSL
        conn->allow_ssl_try = true;
        conn->wait_ssl_try = false;
@@ -2888,6 +2895,8 @@ freePGconn(PGconn *conn)
                free(conn->pguser);
        if (conn->pgpass)
                free(conn->pgpass);
+       if(conn->pgpassfile)
+               free(conn->pgpassfile);
        if (conn->keepalives)
                free(conn->keepalives);
        if (conn->keepalives_idle)
@@ -5703,12 +5712,11 @@ pwdfMatchesString(char *buf, char *token)
        return NULL;
 }
 
-/* Get a password from the password file. Return value is malloc'd. */
+/* Get a password from the password file or the user-specified pgpassfile. 
Return value is malloc'd. */
 static char *
-PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
+PasswordFromFile(char *hostname, char *port, char *dbname, char *username, 
char *pgpassfile)
 {
        FILE       *fp;
-       char            pgpassfile[MAXPGPATH];
        struct stat stat_buf;
 
 #define LINELEN NAMEDATALEN*5
@@ -5735,9 +5743,6 @@ PasswordFromFile(char *hostname, char *port, char 
*dbname, char *username)
        if (port == NULL)
                port = DEF_PGPORT_STR;
 
-       if (!getPgPassFilename(pgpassfile))
-               return NULL;
-
        /* If password file cannot be opened, ignore it. */
        if (stat(pgpassfile, &stat_buf) != 0)
                return NULL;
@@ -5824,21 +5829,19 @@ PasswordFromFile(char *hostname, char *port, char 
*dbname, char *username)
 
 
 static bool
-getPgPassFilename(char *pgpassfile)
+fillDefaultPGPassFile(PGconn *conn)
 {
-       char       *passfile_env;
-
-       if ((passfile_env = getenv("PGPASSFILE")) != NULL)
-               /* use the literal path from the environment, if set */
-               strlcpy(pgpassfile, passfile_env, MAXPGPATH);
-       else
-       {
-               char            homedir[MAXPGPATH];
-
-               if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
-                       return false;
-               snprintf(pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
-       }
+       char            homedir[MAXPGPATH];
+
+       if(conn->pgpassfile)
+               free(conn->pgpassfile);
+
+       conn->pgpassfile = malloc(MAXPGPATH);
+
+       if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
+               return false;
+       snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
+
        return true;
 }
 
@@ -5848,21 +5851,17 @@ getPgPassFilename(char *pgpassfile)
  *     password is wrong.
  */
 static void
-dot_pg_pass_warning(PGconn *conn)
+PGPassFileWarning(PGconn *conn)
 {
-       /* If it was 'invalid authorization', add .pgpass mention */
+       /* If it was 'invalid authorization', add pgpassfile mention */
        /* only works with >= 9.0 servers */
-       if (conn->dot_pgpass_used && conn->password_needed && conn->result &&
+       if (conn->pgpassfile && conn->password_needed && conn->result &&
                strcmp(PQresultErrorField(conn->result, PG_DIAG_SQLSTATE),
                           ERRCODE_INVALID_PASSWORD) == 0)
        {
-               char            pgpassfile[MAXPGPATH];
-
-               if (!getPgPassFilename(pgpassfile))
-                       return;
                appendPQExpBuffer(&conn->errorMessage,
                                          libpq_gettext("password retrieved 
from file \"%s\"\n"),
-                                                 pgpassfile);
+                                                 conn->pgpassfile);
        }
 }
 
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 7007692..ec96420 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -317,6 +317,7 @@ struct pg_conn
        char       *replication;        /* connect as the replication standby? 
*/
        char       *pguser;                     /* Postgres username and 
password, if any */
        char       *pgpass;
+       char       *pgpassfile;         /* path to a file containing the 
password */
        char       *keepalives;         /* use TCP keepalives? */
        char       *keepalives_idle;    /* time between TCP keepalives */
        char       *keepalives_interval;        /* time between TCP keepalive
@@ -373,7 +374,6 @@ struct pg_conn
        bool            auth_req_received;              /* true if any type of 
auth req
                                                                                
 * received */
        bool            password_needed;        /* true if server demanded a 
password */
-       bool            dot_pgpass_used;        /* true if used .pgpass */
        bool            sigpipe_so;             /* have we masked SIGPIPE via 
SO_NOSIGPIPE? */
        bool            sigpipe_flag;   /* can we mask SIGPIPE via 
MSG_NOSIGNAL? */
 
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to