@@ -201,6 +201,10 @@ static const internalPQconninfoOption PQconninfoOptions[] = {
201201 "Database-Service" , "" , 20 ,
202202 offsetof(struct pg_conn , pgservice )},
203203
204+ {"servicefile" , "PGSERVICEFILE" , NULL , NULL ,
205+ "Database-Service-File" , "" , 64 ,
206+ offsetof(struct pg_conn , pgservicefile )},
207+
204208 {"user" , "PGUSER" , NULL , NULL ,
205209 "Database-User" , "" , 20 ,
206210 offsetof(struct pg_conn , pguser )},
@@ -5062,6 +5066,7 @@ freePGconn(PGconn *conn)
50625066 free (conn -> dbName );
50635067 free (conn -> replication );
50645068 free (conn -> pgservice );
5069+ free (conn -> pgservicefile );
50655070 free (conn -> pguser );
50665071 if (conn -> pgpass )
50675072 {
@@ -5914,6 +5919,7 @@ static int
59145919parseServiceInfo (PQconninfoOption * options , PQExpBuffer errorMessage )
59155920{
59165921 const char * service = conninfo_getval (options , "service" );
5922+ const char * service_fname = conninfo_getval (options , "servicefile" );
59175923 char serviceFile [MAXPGPATH ];
59185924 char * env ;
59195925 bool group_found = false;
@@ -5933,10 +5939,13 @@ parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
59335939 return 0 ;
59345940
59355941 /*
5936- * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5937- * exists).
5942+ * First, try the "servicefile" option in connection string. Then, try
5943+ * the PGSERVICEFILE environment variable. Finally, check
5944+ * ~/.pg_service.conf (if that exists).
59385945 */
5939- if ((env = getenv ("PGSERVICEFILE" )) != NULL )
5946+ if (service_fname != NULL )
5947+ strlcpy (serviceFile , service_fname , sizeof (serviceFile ));
5948+ else if ((env = getenv ("PGSERVICEFILE" )) != NULL )
59405949 strlcpy (serviceFile , env , sizeof (serviceFile ));
59415950 else
59425951 {
@@ -6092,7 +6101,17 @@ parseServiceFile(const char *serviceFile,
60926101 if (strcmp (key , "service" ) == 0 )
60936102 {
60946103 libpq_append_error (errorMessage ,
6095- "nested service specifications not supported in service file \"%s\", line %d" ,
6104+ "nested \"service\" specifications not supported in service file \"%s\", line %d" ,
6105+ serviceFile ,
6106+ linenr );
6107+ result = 3 ;
6108+ goto exit ;
6109+ }
6110+
6111+ if (strcmp (key , "servicefile" ) == 0 )
6112+ {
6113+ libpq_append_error (errorMessage ,
6114+ "nested \"servicefile\" specifications not supported in service file \"%s\", line %d" ,
60966115 serviceFile ,
60976116 linenr );
60986117 result = 3 ;
@@ -6135,6 +6154,34 @@ parseServiceFile(const char *serviceFile,
61356154 }
61366155
61376156exit :
6157+
6158+ /*
6159+ * If a service has been successfully found, set the "servicefile" option
6160+ * if not already set. This matters for the cases where we use a default
6161+ * service file or a service file set with PGSERVICEFILE, where we want to
6162+ * be able track the value used.
6163+ */
6164+ if (* group_found && result == 0 )
6165+ {
6166+ for (i = 0 ; options [i ].keyword ; i ++ )
6167+ {
6168+ if (strcmp (options [i ].keyword , "servicefile" ) != 0 )
6169+ continue ;
6170+
6171+ /* If value is already set, nothing to do */
6172+ if (options [i ].val != NULL )
6173+ break ;
6174+
6175+ options [i ].val = strdup (serviceFile );
6176+ if (options [i ].val == NULL )
6177+ {
6178+ libpq_append_error (errorMessage , "out of memory" );
6179+ result = 3 ;
6180+ }
6181+ break ;
6182+ }
6183+ }
6184+
61386185 fclose (f );
61396186
61406187 return result ;
0 commit comments