I love centralizing connection service definitions in <sysconfdir>/pg_service.conf, but for a large enterprise, sometimes we have multiple sets of connection service definitions independently managed.
The convention widely adopted for this type of thing is to allow multiple config files to be in a directory, usually the '.d' version of the config filename. See, for example: http://blog.siphos.be/2013/05/the-linux-d-approach/ https://lists.debian.org/debian-devel/2010/04/msg00352.html This patch adds an extra search for service connection definitions if the current places fail to find the service (~/.pg_service.conf <sysconfdir>/pg_service.conf). It will then search every readable file in the directory <sysconfdir>/pg_service.conf.d. What do you think? Curt
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) <indexterm zone="libpq-pgservice"> <primary>.pg_service.conf</primary> </indexterm> + <indexterm zone="libpq-pgservice"> + <primary>pg_service.conf.d</primary> + </indexterm> <para> The connection service file allows libpq connection parameters to be @@ -7444,6 +7447,15 @@ myEventProc(PGEventId evtId, void *evtInfo, void *passThrough) </para> <para> + Additional connection service files can be placed in the system-wide + directory <filename>`pg_config --sysconfdir`/pg_service.conf.d</filename> + or in the subdirectory <filename>pg_service.conf.d</filename> below the + directory specified by the environment variable + <envar>PGSYSCONFDIR</envar>. These will have the lowest precedence, + following the files described above. + </para> + + <para> The file uses an <quote>INI file</quote> format where the section name is the service name and the parameters are connection parameters; see <xref linkend="libpq-paramkeywords"/> 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 <ctype.h> #include <time.h> #include <unistd.h> +#include <dirent.h> #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