aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/libpq/fe-connect.c109
1 files changed, 63 insertions, 46 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 5f798036071..6bcf60a712c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -1063,52 +1063,51 @@ connectOptions2(PGconn *conn)
*/
if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
{
- int i;
-
+ /* If password file wasn't specified, use ~/PGPASSFILE */
if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
{
- /* Identify password file to use; fail if we can't */
char homedir[MAXPGPATH];
- if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
+ if (pqGetHomeDirectory(homedir, sizeof(homedir)))
{
- conn->status = CONNECTION_BAD;
- printfPQExpBuffer(&conn->errorMessage,
- libpq_gettext("could not get home directory to locate password file\n"));
- return false;
+ if (conn->pgpassfile)
+ free(conn->pgpassfile);
+ conn->pgpassfile = malloc(MAXPGPATH);
+ if (!conn->pgpassfile)
+ goto oom_error;
+ snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
+ homedir, PGPASSFILE);
}
-
- if (conn->pgpassfile)
- free(conn->pgpassfile);
- conn->pgpassfile = malloc(MAXPGPATH);
- if (!conn->pgpassfile)
- goto oom_error;
-
- snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s", homedir, PGPASSFILE);
}
- for (i = 0; i < conn->nconnhost; i++)
+ if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
{
- /*
- * Try to get a password for this host from pgpassfile. We use
- * host name rather than host address in the same manner to
- * PQhost().
- */
- char *pwhost = conn->connhost[i].host;
-
- if (conn->connhost[i].type == CHT_HOST_ADDRESS &&
- conn->connhost[i].host != NULL && conn->connhost[i].host[0] != '\0')
- pwhost = conn->connhost[i].hostaddr;
-
- conn->connhost[i].password =
- passwordFromFile(pwhost,
- conn->connhost[i].port,
- conn->dbName,
- conn->pguser,
- conn->pgpassfile);
- /* If we got one, set pgpassfile_used */
- if (conn->connhost[i].password != NULL)
- conn->pgpassfile_used = true;
+ int i;
+
+ for (i = 0; i < conn->nconnhost; i++)
+ {
+ /*
+ * Try to get a password for this host from pgpassfile. We use
+ * host name rather than host address in the same manner as
+ * PQhost().
+ */
+ char *pwhost = conn->connhost[i].host;
+
+ if (conn->connhost[i].type == CHT_HOST_ADDRESS &&
+ conn->connhost[i].host != NULL &&
+ conn->connhost[i].host[0] != '\0')
+ pwhost = conn->connhost[i].hostaddr;
+
+ conn->connhost[i].password =
+ passwordFromFile(pwhost,
+ conn->connhost[i].port,
+ conn->dbName,
+ conn->pguser,
+ conn->pgpassfile);
+ /* If we got one, set pgpassfile_used */
+ if (conn->connhost[i].password != NULL)
+ conn->pgpassfile_used = true;
+ }
}
}
@@ -4469,6 +4468,16 @@ ldapServiceLookup(const char *purl, PQconninfoOption *options,
#define MAXBUFSIZE 256
+/*
+ * parseServiceInfo: if a service name has been given, look it up and absorb
+ * connection options from it into *options.
+ *
+ * Returns 0 on success, nonzero on failure. On failure, if errorMessage
+ * isn't null, also store an error message there. (Note: the only reason
+ * this function and related ones don't dump core on errorMessage == NULL
+ * is the undocumented fact that printfPQExpBuffer does nothing when passed
+ * a null PQExpBuffer pointer.)
+ */
static int
parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
{
@@ -4487,9 +4496,14 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
if (service == NULL)
service = getenv("PGSERVICE");
+ /* If no service name given, nothing to do */
if (service == NULL)
return 0;
+ /*
+ * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
+ * exists).
+ */
if ((env = getenv("PGSERVICEFILE")) != NULL)
strlcpy(serviceFile, env, sizeof(serviceFile));
else
@@ -4497,13 +4511,9 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
char homedir[MAXPGPATH];
if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
- {
- printfPQExpBuffer(errorMessage, libpq_gettext("could not get home directory to locate service definition file"));
- return 1;
- }
+ goto next_file;
snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
- errno = 0;
- if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
+ if (stat(serviceFile, &stat_buf) != 0)
goto next_file;
}
@@ -4519,8 +4529,7 @@ next_file:
*/
snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
- errno = 0;
- if (stat(serviceFile, &stat_buf) != 0 && errno == ENOENT)
+ if (stat(serviceFile, &stat_buf) != 0)
goto last_file;
status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
@@ -6510,7 +6519,15 @@ pgpassfileWarning(PGconn *conn)
*
* 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)
+ * namespace).
+ *
+ * Returns true on success, false on failure to obtain the directory name.
+ *
+ * CAUTION: although in most situations failure is unexpected, there are users
+ * who like to run applications in a home-directory-less environment. On
+ * failure, you almost certainly DO NOT want to report an error. Just act as
+ * though whatever file you were hoping to find in the home directory isn't
+ * there (which it isn't).
*/
bool
pqGetHomeDirectory(char *buf, int bufsize)