diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 4e46451..ec4ba77 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -7421,6 +7421,9 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
.pg_service.conf
+
+ pg_service.conf.d
+
The connection service file allows libpq connection parameters to be
@@ -7444,6 +7447,15 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough)
+ Additional connection service files can be placed in the system-wide
+ directory `pg_config --sysconfdir`/pg_service.conf.d
+ or in the subdirectory pg_service.conf.d below the
+ directory specified by the environment variable
+ PGSYSCONFDIR. These will have the lowest precedence,
+ following the files described above.
+
+
+
The file uses an INI file
format where the section
name is the service name and the parameters are connection
parameters; see for a list. For
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 8d54333..43ec0d5 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
#include "libpq-fe.h"
#include "libpq-int.h"
@@ -4492,10 +4493,14 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
{
const char *service = conninfo_getval(options, "service");
char serviceFile[MAXPGPATH];
+ char serviceDirPath[MAXPGPATH];
char *env;
bool group_found = false;
int status;
struct stat stat_buf;
+ DIR *serviceDir;
+ struct dirent *direntry;
+
/*
* We have to special-case the environment variable PGSERVICE here, since
@@ -4539,21 +4544,45 @@ next_file:
snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
if (stat(serviceFile, &stat_buf) != 0)
+ goto conf_dir;
+
+ status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
+ if (group_found || status != 0)
+ return status;
+
+conf_dir:
+
+ /*
+ * Try every file in pg_service.conf.d/*
+ */
+ snprintf(serviceDirPath, MAXPGPATH, "%s/pg_service.conf.d",
+ getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
+
+ if (stat(serviceDirPath, &stat_buf) != 0 || !S_ISDIR(stat_buf.st_mode) ||
+ (serviceDir = opendir(serviceDirPath)) == NULL)
goto last_file;
- status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
- if (status != 0)
- return status;
+ while ((direntry = readdir(serviceDir)) != NULL)
+ {
+ snprintf(serviceFile, MAXPGPATH, "%s/%s", serviceDirPath, direntry->d_name);
+
+ if (stat(serviceFile, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode) ||
+ access(serviceFile, R_OK))
+ continue;
+
+ status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
+ if (group_found || status != 0)
+ {
+ closedir(serviceDir);
+ return status;
+ }
+ }
+ closedir(serviceDir);
last_file:
- if (!group_found)
- {
- printfPQExpBuffer(errorMessage,
- libpq_gettext("definition of service \"%s\" not found\n"), service);
- return 3;
- }
-
- return 0;
+ printfPQExpBuffer(errorMessage,
+ libpq_gettext("definition of service \"%s\" not found\n"), service);
+ return 3;
}
static int