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