88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.389 2010/03/03 20:31:09 tgl Exp $
11+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-connect.c,v 1.390 2010/03/13 14:55:57 momjian Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -91,6 +91,9 @@ static int ldapServiceLookup(const char *purl, PQconninfoOption *options,
9191 */
9292#define ERRCODE_APPNAME_UNKNOWN "42704"
9393
94+ /* This is part of the protocol so just define it */
95+ #define ERRCODE_INVALID_PASSWORD "28P01"
96+
9497/*
9598 * fall back options if they are not specified by arguments or defined
9699 * by environment variables
@@ -284,6 +287,8 @@ static int parseServiceFile(const char *serviceFile,
284287static char * pwdfMatchesString (char * buf ,char * token );
285288static char * PasswordFromFile (char * hostname ,char * port ,char * dbname ,
286289char * username );
290+ static bool getPgPassFilename (char * pgpassfile );
291+ static void dot_pg_pass_warning (PGconn * conn );
287292static void default_threadlock (int acquire );
288293
289294
@@ -652,6 +657,8 @@ connectOptions2(PGconn *conn)
652657conn -> dbName ,conn -> pguser );
653658if (conn -> pgpass == NULL )
654659conn -> pgpass = strdup (DefaultPassword );
660+ else
661+ conn -> dot_pgpass_used = true;
655662}
656663
657664/*
@@ -2133,6 +2140,8 @@ PQconnectPoll(PGconn *conn)
21332140
21342141error_return :
21352142
2143+ dot_pg_pass_warning (conn );
2144+
21362145/*
21372146 * We used to close the socket at this point, but that makes it awkward
21382147 * for those above us if they wish to remove this socket from their own
@@ -2191,6 +2200,7 @@ makeEmptyPGconn(void)
21912200conn -> verbosity = PQERRORS_DEFAULT ;
21922201conn -> sock = -1 ;
21932202conn -> password_needed = false;
2203+ conn -> dot_pgpass_used = false;
21942204#ifdef USE_SSL
21952205conn -> allow_ssl_try = true;
21962206conn -> wait_ssl_try = false;
@@ -4323,7 +4333,6 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
43234333FILE * fp ;
43244334char pgpassfile [MAXPGPATH ];
43254335struct stat stat_buf ;
4326- char * passfile_env ;
43274336
43284337#define LINELEN NAMEDATALEN*5
43294338char buf [LINELEN ];
@@ -4349,17 +4358,8 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
43494358if (port == NULL )
43504359port = DEF_PGPORT_STR ;
43514360
4352- if ((passfile_env = getenv ("PGPASSFILE" ))!= NULL )
4353- /* use the literal path from the environment, if set */
4354- strlcpy (pgpassfile ,passfile_env ,sizeof (pgpassfile ));
4355- else
4356- {
4357- char homedir [MAXPGPATH ];
4358-
4359- if (!pqGetHomeDirectory (homedir ,sizeof (homedir )))
4360- return NULL ;
4361- snprintf (pgpassfile ,MAXPGPATH ,"%s/%s" ,homedir ,PGPASSFILE );
4362- }
4361+ if (!getPgPassFilename (pgpassfile ))
4362+ return NULL ;
43634363
43644364/* If password file cannot be opened, ignore it. */
43654365if (stat (pgpassfile ,& stat_buf )!= 0 )
@@ -4426,6 +4426,51 @@ PasswordFromFile(char *hostname, char *port, char *dbname, char *username)
44264426#undef LINELEN
44274427}
44284428
4429+
4430+ static bool getPgPassFilename (char * pgpassfile )
4431+ {
4432+ char * passfile_env ;
4433+
4434+ if ((passfile_env = getenv ("PGPASSFILE" ))!= NULL )
4435+ /* use the literal path from the environment, if set */
4436+ strlcpy (pgpassfile ,passfile_env ,MAXPGPATH );
4437+ else
4438+ {
4439+ char homedir [MAXPGPATH ];
4440+
4441+ if (!pqGetHomeDirectory (homedir ,sizeof (homedir )))
4442+ return false;
4443+ snprintf (pgpassfile ,MAXPGPATH ,"%s/%s" ,homedir ,PGPASSFILE );
4444+ }
4445+ return true;
4446+ }
4447+
4448+ /*
4449+ *If the connection failed, we should mention if
4450+ *we got the password from .pgpass in case that
4451+ *password is wrong.
4452+ */
4453+ static void
4454+ dot_pg_pass_warning (PGconn * conn )
4455+ {
4456+ /* If it was 'invalid authorization', add .pgpass mention */
4457+ if (conn -> dot_pgpass_used && conn -> password_needed && conn -> result &&
4458+ /* only works with >= 9.0 servers */
4459+ strcmp (PQresultErrorField (conn -> result ,PG_DIAG_SQLSTATE ),
4460+ ERRCODE_INVALID_PASSWORD )== 0 )
4461+ {
4462+ char pgpassfile [MAXPGPATH ];
4463+
4464+ if (!getPgPassFilename (pgpassfile ))
4465+ return ;
4466+ appendPQExpBufferStr (& conn -> errorMessage ,
4467+ libpq_gettext ("password retrieved from " ));
4468+ appendPQExpBufferStr (& conn -> errorMessage ,pgpassfile );
4469+ appendPQExpBufferChar (& conn -> errorMessage ,'\n' );
4470+ }
4471+ }
4472+
4473+
44294474/*
44304475 * Obtain user's home directory, return in given buffer
44314476 *