This is a patch that allows PostgreSQL to use a configuration
file that is outside the main database directory.

It adds one more command line parameter, "-C" which
specifies either the location of the postgres configuration
file or a directory containing the configuration files.

A patched version of PostgreSQL will function as:

--- Configuration file ---
postmaster -C /etc/postgres/postgresql.conf

This will direct the postmaster program to use the
configuration file "/etc/postgres/postgresql.conf"

--- Configuration Directory ---
postmaster -C /etc/postgres

This will direct the postmaster program to search the
directory "/etc/postgres" for the standard configuration
file names: posgresql.conf, pg_hba.conf, and pg_ident.conf.

--- postgresql.conf ---
Within the main configuration file  are four  additional
parameters: include, hba_conf,ident_conf, and data_dir.

They are used as:
include = '/etc/postgres/debug.conf'
data_dir = '/vol01/postgres'
hba_conf = '/etc/postgres/pg_hba_conf'
ident_conf = '/etc/postgres/pg_ident.conf'


The "-D" option on the command line overrides the "data_dir"
in the configuration file.

If no hba_conf and/or ident_conf setting is specified, the default
$PGDATA/pg_hba.conf and/or $PGDATA/pg_ident.conf will be used.

This patch is intended to move the PostgreSQL configuration out of the
data directory so that it can be modified and backed up.

This patch is also useful for running multiple servers with the same
parameters:

postmaster -C /etc/postgres/postgresql.conf -D /VOL01/postgres -p 5432
postmaster -C /etc/postgres/postgresql.conf -D /VOL02/postgres -p 5433

To apply the patch, enter your PostreSQL source directory, and run:

cat pgec-PGVERSON.patch | patch -p 1
Mon, 17 Feb 2003 15:25:47 -0500
mlw <pgsql@mohawksoft.com>
Yet another configuration patch with include, and configuration dir

mlw, would you modify this to use the config_path idea we agreed upon so
we can get this into 7.4?

---------------------------------------------------------------------------

mlw wrote:
> This is a patch that allows PostgreSQL to use a configuration
> file that is outside the main database directory.
> 
> It adds one more command line parameter, "-C" which
> specifies either the location of the postgres configuration
> file or a directory containing the configuration files.
> 
> A patched version of PostgreSQL will function as:
> 
> --- Configuration file ---
> postmaster -C /etc/postgres/postgresql.conf
> 
> This will direct the postmaster program to use the
> configuration file "/etc/postgres/postgresql.conf"
> 
> --- Configuration Directory ---
> postmaster -C /etc/postgres
> 
> This will direct the postmaster program to search the
> directory "/etc/postgres" for the standard configuration
> file names: posgresql.conf, pg_hba.conf, and pg_ident.conf.
> 
> --- postgresql.conf ---
> Within the main configuration file  are four  additional
> parameters: include, hba_conf,ident_conf, and data_dir.
> 
> They are used as:
> include = '/etc/postgres/debug.conf'
> data_dir = '/vol01/postgres'
> hba_conf = '/etc/postgres/pg_hba_conf'
> ident_conf = '/etc/postgres/pg_ident.conf'
> 
> 
> The "-D" option on the command line overrides the "data_dir"
> in the configuration file.
> 
> If no hba_conf and/or ident_conf setting is specified, the default
> $PGDATA/pg_hba.conf and/or $PGDATA/pg_ident.conf will be used.
> 
> This patch is intended to move the PostgreSQL configuration out of the
> data directory so that it can be modified and backed up.
> 
> This patch is also useful for running multiple servers with the same
> parameters:
> 
> postmaster -C /etc/postgres/postgresql.conf -D /VOL01/postgres -p 5432
> postmaster -C /etc/postgres/postgresql.conf -D /VOL02/postgres -p 5433
> 
> To apply the patch, enter your PostreSQL source directory, and run:
> 
> cat pgec-PGVERSON.patch | patch -p 1
> 

> diff -u -r postgresql-7.3.2/src/backend/libpq/hba.c postgresql-7.3.2.ec/src/backend/libpq/hba.c
> --- postgresql-7.3.2/src/backend/libpq/hba.c	Sat Dec 14 13:49:43 2002
> +++ postgresql-7.3.2.ec/src/backend/libpq/hba.c	Mon Feb 17 14:57:37 2003
> @@ -35,6 +35,7 @@
>  #include "miscadmin.h"
>  #include "nodes/pg_list.h"
>  #include "storage/fd.h"
> +#include "utils/guc.h"
>  
>  
>  #define IDENT_USERNAME_MAX 512
> @@ -837,10 +838,22 @@
>  	if (hba_lines)
>  		free_lines(&hba_lines);
>  
> -	/* Put together the full pathname to the config file. */
> -	bufsize = (strlen(DataDir) + strlen(CONF_FILE) + 2) * sizeof(char);
> -	conf_file = (char *) palloc(bufsize);
> -	snprintf(conf_file, bufsize, "%s/%s", DataDir, CONF_FILE);
> +	/* Explicit HBA in config file */
> +	if(explicit_hbafile && strlen(explicit_hbafile))
> +	{
> +		bufsize = strlen(explicit_hbafile)+1;
> +		conf_file = (char *) palloc(bufsize);
> +		strcpy(conf_file, explicit_hbafile);
> +	}
> +	else
> +	{
> +		char *confloc = (explicit_isdir) ? explicit_pgconfig : DataDir;
> +		/* put together the full pathname to the config file */
> +		bufsize = (strlen(confloc) + strlen(CONF_FILE) + 2) * sizeof(char);
> +		conf_file = (char *) palloc(bufsize);
> +		snprintf(conf_file, bufsize, "%s/%s", confloc, CONF_FILE);
> +	}
> +	/* printf("hba_conf: %s\n", conf_file); */
>  
>  	file = AllocateFile(conf_file, "r");
>  	if (file == NULL)
> @@ -979,10 +992,22 @@
>  	if (ident_lines)
>  		free_lines(&ident_lines);
>  
> -	/* put together the full pathname to the map file */
> -	bufsize = (strlen(DataDir) + strlen(USERMAP_FILE) + 2) * sizeof(char);
> -	map_file = (char *) palloc(bufsize);
> -	snprintf(map_file, bufsize, "%s/%s", DataDir, USERMAP_FILE);
> +	/* Explicit IDENT in config file */
> +	if(explicit_identfile && strlen(explicit_identfile))
> +	{
> +		bufsize = strlen(explicit_identfile)+1;
> +		map_file = (char *) palloc(bufsize);
> +		strcpy(map_file, explicit_identfile);
> +	}
> +	else
> +	{
> +		/* put together the full pathname to the map file */
> +		char *confloc = (explicit_isdir) ? explicit_pgconfig : DataDir;
> +		bufsize = (strlen(confloc) + strlen(USERMAP_FILE) + 2) * sizeof(char);
> +		map_file = (char *) palloc(bufsize);
> +		snprintf(map_file, bufsize, "%s/%s", confloc, USERMAP_FILE);
> +	}
> +	/* printf("ident_conf: %s\n", map_file); */
>  
>  	file = AllocateFile(map_file, "r");
>  	if (file == NULL)
> diff -u -r postgresql-7.3.2/src/backend/postmaster/postmaster.c postgresql-7.3.2.ec/src/backend/postmaster/postmaster.c
> --- postgresql-7.3.2/src/backend/postmaster/postmaster.c	Wed Jan 15 19:27:17 2003
> +++ postgresql-7.3.2.ec/src/backend/postmaster/postmaster.c	Mon Feb 17 12:14:12 2003
> @@ -421,7 +421,7 @@
>  
>  	opterr = 1;
>  
> -	while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)
> +	while ((opt = getopt(argc, argv, "A:a:B:b:C:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1)
>  	{
>  		switch (opt)
>  		{
> @@ -441,6 +441,9 @@
>  			case 'b':
>  				/* Can no longer set the backend executable file to use. */
>  				break;
> +			case 'C': // MLW
> +				explicit_pgconfig = optarg;
> +				break;
>  			case 'D':
>  				potential_DataDir = optarg;
>  				break;
> @@ -564,13 +567,23 @@
>  		ExitPostmaster(1);
>  	}
>  
> -	/*
> -	 * Now we can set the data directory, and then read postgresql.conf.
> -	 */
> -	checkDataDir(potential_DataDir);	/* issues error messages */
> -	SetDataDir(potential_DataDir);
> -
> -	ProcessConfigFile(PGC_POSTMASTER);
> +	if(explicit_pgconfig)
> +	{
> +		ProcessConfigFile(PGC_POSTMASTER);
> +		if(!potential_DataDir && pgdatadir)
> +			potential_DataDir = pgdatadir;
> +		checkDataDir(potential_DataDir);	/* issues error messages */
> +		SetDataDir(potential_DataDir);
> +	}
> +	else
> +	{
> +		/*
> +		 * Now we can set the data directory, and then read postgresql.conf.
> +		 */
> +		checkDataDir(potential_DataDir);	/* issues error messages */
> +		SetDataDir(potential_DataDir);
> +		ProcessConfigFile(PGC_POSTMASTER);
> +	}
>  
>  	/*
>  	 * Check for invalid combinations of GUC settings.
> diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc-file.c postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.c
> --- postgresql-7.3.2/src/backend/utils/misc/guc-file.c	Mon Feb  3 15:22:34 2003
> +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.c	Mon Feb 17 14:58:11 2003
> @@ -2,7 +2,6 @@
>  
>  /* Scanner skeleton version:
>   * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $
> - * $FreeBSD: src/usr.bin/lex/flex.skl,v 1.4 1999/10/27 07:56:44 obrien Exp $
>   */
>  
>  #define FLEX_SCANNER
> @@ -10,6 +9,7 @@
>  #define YY_FLEX_MINOR_VERSION 5
>  
>  #include <stdio.h>
> +#include <unistd.h>
>  
>  
>  /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
> @@ -23,7 +23,6 @@
>  #ifdef __cplusplus
>  
>  #include <stdlib.h>
> -#include <unistd.h>
>  
>  /* Use prototypes in function declarations. */
>  #define YY_USE_PROTOS
> @@ -443,7 +442,7 @@
>  char *GUC_scanstr(char *);
>  #define YY_NEVER_INTERACTIVE 1
>  #define YY_NO_UNPUT 1
> -#line 447 "lex.GUC_yy.c"
> +#line 446 "lex.GUC_yy.c"
>  
>  /* Macros after this point can all be overridden by user definitions in
>   * section 1.
> @@ -591,13 +590,13 @@
>  YY_DECL
>  	{
>  	register GUC_yy_state_type GUC_yy_current_state;
> -	register char *GUC_yy_cp, *GUC_yy_bp;
> +	register char *GUC_yy_cp = NULL, *GUC_yy_bp = NULL;
>  	register int GUC_yy_act;
>  
>  #line 71 "guc-file.l"
>  
>  
> -#line 601 "lex.GUC_yy.c"
> +#line 600 "lex.GUC_yy.c"
>  
>  	if ( GUC_yy_init )
>  		{
> @@ -738,7 +737,7 @@
>  #line 86 "guc-file.l"
>  ECHO;
>  	YY_BREAK
> -#line 742 "lex.GUC_yy.c"
> +#line 741 "lex.GUC_yy.c"
>  case YY_STATE_EOF(INITIAL):
>  	GUC_yyterminate();
>  
> @@ -1302,11 +1301,6 @@
>  	}
>  
>  
> -#ifndef YY_ALWAYS_INTERACTIVE
> -#ifndef YY_NEVER_INTERACTIVE
> -extern int isatty YY_PROTO(( int ));
> -#endif
> -#endif
>  
>  #ifdef YY_USE_PROTOS
>  void GUC_yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
> @@ -1658,51 +1652,27 @@
>  	}
>  }
>  
> +#define ELEVEL_FROM_CONTEXT(ctx)	(ctx == PGC_SIGHUP) ? DEBUG3 : ERROR
>  
> -/*
> - * Official function to read and process the configuration file. The
> - * parameter indicates in what context the file is being read
> - * (postmaster startup, backend startup, or SIGHUP). All options
> - * mentioned in the configuration file are set to new values. This
> - * function does not return if an error occurs. If an error occurs, no
> - * values will be changed.
> - */
> -void
> -ProcessConfigFile(GucContext context)
> +static void 
> +ReadConfigFile(char *filename, GucContext context)
>  {
>  	int token, parse_state;
>  	char *opt_name, *opt_value;
> -	char *filename;
>  	struct name_value_pair *item, *head, *tail;
> -	int elevel;
> -	FILE * fp;
> -
> -	Assert(context == PGC_POSTMASTER || context == PGC_BACKEND 
> -		|| context == PGC_SIGHUP);
> -	Assert(DataDir);
> -	elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +	FILE *fp;
> +	int elevel = ELEVEL_FROM_CONTEXT(context);
>  
> -	/*
> -	 * Open file
> -	 */
> -	filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2);
> -	if (filename == NULL)
> -	{
> -		elog(elevel, "out of memory");
> -		return;
> -	}
> -	sprintf(filename, "%s/" CONFIG_FILENAME, DataDir);
> -
> -    fp = AllocateFile(filename, "r");
> -    if (!fp)
> -    {
> +    	fp = AllocateFile(filename, "r");
> +	if (!fp)
> +    	{
> +        	/* File not found is fine */
> +        	if (errno != ENOENT)
> +            		elog(elevel, "could not read configuration file %s: %s", 
> +				filename, strerror(errno));
>  		free(filename);
> -        /* File not found is fine */
> -        if (errno != ENOENT)
> -            elog(elevel, "could not read configuration file `" CONFIG_FILENAME "': %s", strerror(errno));
>  		return;
> -    }
> -
> +    	}
>  	/*
>  	 * Parse
>  	 */
> @@ -1731,7 +1701,8 @@
>                      token = GUC_yylex();
>  
>                  if (token != GUC_ID && token != GUC_STRING && 
> -					token != GUC_INTEGER && token != GUC_REAL && 
> +					token != GUC_INTEGER && 
> +					token != GUC_REAL && 
>  					token != GUC_UNQUOTED_STRING)
>                      goto parse_error;
>                  opt_value = strdup(GUC_yytext);
> @@ -1775,7 +1746,6 @@
>          }
>  
>  	FreeFile(fp);
> -	free(filename);
>  
>  	/*
>  	 * Check if all options are valid
> @@ -1798,7 +1768,6 @@
>  
>   parse_error:
>  	FreeFile(fp);
> -	free(filename);
>  	free_name_value_list(head);
>  	elog(elevel, CONFIG_FILENAME ":%u: syntax error, token=\"%s\"", 
>  		ConfigFileLineno,GUC_yytext);
> @@ -1806,12 +1775,78 @@
>  
>   out_of_memory:
>  	FreeFile(fp);
> -	free(filename);
>  	free_name_value_list(head);
>  	elog(elevel, "out of memory");
>  	return;
>  }
> +/*
> + * Official function to read and process the configuration file. The
> + * parameter indicates in what context the file is being read
> + * (postmaster startup, backend startup, or SIGHUP). All options
> + * mentioned in the configuration file are set to new values. This
> + * function does not return if an error occurs. If an error occurs, no
> + * values will be changed.
> + */
> +void
> +ProcessConfigFile(GucContext context)
> +{
> +	char *filename;
> +
> +	Assert(context == PGC_POSTMASTER || context == PGC_BACKEND 
> +		|| context == PGC_SIGHUP);
>  
> +	/* Added for explicit config file */
> +	if(explicit_pgconfig)
> +	{
> +		struct stat sb;
> +
> +		if(stat(explicit_pgconfig, &sb)!=0)
> +		{
> +			int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +			elog(elevel, "Invalid configuration parameter");
> +			return ;
> +		}
> +			
> +
> +		if((sb.st_mode & S_IFDIR) == S_IFDIR)
> +		{
> +			/* This will cause a small one time memory leak
> +			 * if the user also specifies hba_conf,
> +			 * ident_conf, and data_dir
> +			 */
> +			filename = malloc(strlen(explicit_pgconfig) + strlen(CONFIG_FILENAME) + 2);
> +			sprintf(filename, "%s/%s", explicit_pgconfig, CONFIG_FILENAME);
> +			explicit_isdir = true;
> +		}
> +		else
> +		{	 
> +			/*
> +			 * Use explicit file
> +			 */
> +			filename = strdup(explicit_pgconfig);
> +		}
> +	}
> +	else
> +	{
> +		/*
> +		 * Use environmental config
> +		 */
> +		filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2);
> +		sprintf(filename, "%s/%s", DataDir, CONFIG_FILENAME);
> +	}
> +
> +	if (filename == NULL)
> +	{
> +		int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +		elog(elevel, "out of memory");
> +		return;
> +	}
> +	/* printf("Using: %s\n", filename); */
> +
> +	ReadConfigFile(filename, context);
> +
> +	free(filename);
> +}
>  
>  
>  /* ----------------
> diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc-file.l postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.l
> --- postgresql-7.3.2/src/backend/utils/misc/guc-file.l	Tue Jul 30 12:33:08 2002
> +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.l	Mon Feb 17 14:58:07 2003
> @@ -116,51 +116,27 @@
>  	}
>  }
>  
> +#define ELEVEL_FROM_CONTEXT(ctx)	(ctx == PGC_SIGHUP) ? DEBUG3 : ERROR
>  
> -/*
> - * Official function to read and process the configuration file. The
> - * parameter indicates in what context the file is being read
> - * (postmaster startup, backend startup, or SIGHUP). All options
> - * mentioned in the configuration file are set to new values. This
> - * function does not return if an error occurs. If an error occurs, no
> - * values will be changed.
> - */
> -void
> -ProcessConfigFile(GucContext context)
> +static void 
> +ReadConfigFile(char *filename, GucContext context)
>  {
>  	int token, parse_state;
>  	char *opt_name, *opt_value;
> -	char *filename;
>  	struct name_value_pair *item, *head, *tail;
> -	int elevel;
> -	FILE * fp;
> -
> -	Assert(context == PGC_POSTMASTER || context == PGC_BACKEND 
> -		|| context == PGC_SIGHUP);
> -	Assert(DataDir);
> -	elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +	FILE *fp;
> +	int elevel = ELEVEL_FROM_CONTEXT(context);
>  
> -	/*
> -	 * Open file
> -	 */
> -	filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2);
> -	if (filename == NULL)
> -	{
> -		elog(elevel, "out of memory");
> -		return;
> -	}
> -	sprintf(filename, "%s/" CONFIG_FILENAME, DataDir);
> -
> -    fp = AllocateFile(filename, "r");
> -    if (!fp)
> -    {
> +    	fp = AllocateFile(filename, "r");
> +	if (!fp)
> +    	{
> +        	/* File not found is fine */
> +        	if (errno != ENOENT)
> +            		elog(elevel, "could not read configuration file %s: %s", 
> +				filename, strerror(errno));
>  		free(filename);
> -        /* File not found is fine */
> -        if (errno != ENOENT)
> -            elog(elevel, "could not read configuration file `" CONFIG_FILENAME "': %s", strerror(errno));
>  		return;
> -    }
> -
> +    	}
>  	/*
>  	 * Parse
>  	 */
> @@ -189,7 +165,8 @@
>                      token = yylex();
>  
>                  if (token != GUC_ID && token != GUC_STRING && 
> -					token != GUC_INTEGER && token != GUC_REAL && 
> +					token != GUC_INTEGER && 
> +					token != GUC_REAL && 
>  					token != GUC_UNQUOTED_STRING)
>                      goto parse_error;
>                  opt_value = strdup(yytext);
> @@ -233,7 +210,6 @@
>          }
>  
>  	FreeFile(fp);
> -	free(filename);
>  
>  	/*
>  	 * Check if all options are valid
> @@ -256,7 +232,6 @@
>  
>   parse_error:
>  	FreeFile(fp);
> -	free(filename);
>  	free_name_value_list(head);
>  	elog(elevel, CONFIG_FILENAME ":%u: syntax error, token=\"%s\"", 
>  		ConfigFileLineno,yytext);
> @@ -264,12 +239,78 @@
>  
>   out_of_memory:
>  	FreeFile(fp);
> -	free(filename);
>  	free_name_value_list(head);
>  	elog(elevel, "out of memory");
>  	return;
>  }
> +/*
> + * Official function to read and process the configuration file. The
> + * parameter indicates in what context the file is being read
> + * (postmaster startup, backend startup, or SIGHUP). All options
> + * mentioned in the configuration file are set to new values. This
> + * function does not return if an error occurs. If an error occurs, no
> + * values will be changed.
> + */
> +void
> +ProcessConfigFile(GucContext context)
> +{
> +	char *filename;
> +
> +	Assert(context == PGC_POSTMASTER || context == PGC_BACKEND 
> +		|| context == PGC_SIGHUP);
> +
> +	/* Added for explicit config file */
> +	if(explicit_pgconfig)
> +	{
> +		struct stat sb;
> +
> +		if(stat(explicit_pgconfig, &sb)!=0)
> +		{
> +			int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +			elog(elevel, "Invalid configuration parameter");
> +			return ;
> +		}
> +			
> +
> +		if((sb.st_mode & S_IFDIR) == S_IFDIR)
> +		{
> +			/* This will cause a small one time memory leak
> +			 * if the user also specifies hba_conf,
> +			 * ident_conf, and data_dir
> +			 */
> +			filename = malloc(strlen(explicit_pgconfig) + strlen(CONFIG_FILENAME) + 2);
> +			sprintf(filename, "%s/%s", explicit_pgconfig, CONFIG_FILENAME);
> +			explicit_isdir = true;
> +		}
> +		else
> +		{	 
> +			/*
> +			 * Use explicit file
> +			 */
> +			filename = strdup(explicit_pgconfig);
> +		}
> +	}
> +	else
> +	{
> +		/*
> +		 * Use environmental config
> +		 */
> +		filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2);
> +		sprintf(filename, "%s/%s", DataDir, CONFIG_FILENAME);
> +	}
> +
> +	if (filename == NULL)
> +	{
> +		int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
> +		elog(elevel, "out of memory");
> +		return;
> +	}
> +	/* printf("Using: %s\n", filename); */
>  
> +	ReadConfigFile(filename, context);
> +
> +	free(filename);
> +}
>  
>  
>  /* ----------------
> diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc.c postgresql-7.3.2.ec/src/backend/utils/misc/guc.c
> --- postgresql-7.3.2/src/backend/utils/misc/guc.c	Tue Jan 28 13:04:13 2003
> +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc.c	Mon Feb 17 14:38:34 2003
> @@ -51,6 +51,12 @@
>  #include "utils/pg_locale.h"
>  #include "pgstat.h"
>  
> +/* Added for config file only startup MLW */
> +char *explicit_pgconfig = NULL;
> +char *explicit_hbafile = NULL;
> +char *explicit_identfile = NULL;
> +bool explicit_isdir=false;
> +char *pgdatadir = NULL;
>  
>  /* XXX these should be in other modules' header files */
>  extern bool Log_connections;
> @@ -113,6 +119,7 @@
>  char	   *client_min_messages_str = NULL;
>  const char	client_min_messages_str_default[] = "notice";
>  
> +static void ReadConfigFile(char *filename, GucContext context);
>  
>  #ifndef PG_KRB_SRVTAB
>  #define PG_KRB_SRVTAB ""
> @@ -146,7 +153,8 @@
>  	PGC_BOOL,
>  	PGC_INT,
>  	PGC_REAL,
> -	PGC_STRING
> +	PGC_STRING,
> +	PGC_FUNCTION
>  };
>  
>  /* Generic fields applicable to all types of variables */
> @@ -239,6 +247,13 @@
>  	char	   *tentative_val;
>  };
>  
> +struct config_function
> +{
> +	struct config_generic gen;
> +	void (*function)(char *param, GucContext context);
> +};
> +
> +
>  /* Macros for freeing malloc'd pointers only if appropriate to do so */
>  /* Some of these tests are probably redundant, but be safe ... */
>  #define SET_STRING_VARIABLE(rec, newval) \
> @@ -853,10 +868,32 @@
>  	},
>  
>  	{
> +		{"data_dir", PGC_POSTMASTER}, &pgdatadir,
> +		"", NULL, NULL
> +	},
> +
> +	{
> +		{"hba_conf", PGC_POSTMASTER}, &explicit_hbafile,
> +		"", NULL, NULL
> +	},
> +
> +	{
> +		{"ident_conf", PGC_POSTMASTER}, &explicit_identfile,
> +		"", NULL, NULL
> +	},
> +
> +	{
>  		{NULL, 0}, NULL, NULL, NULL, NULL
>  	}
>  };
>  
> +
> +static struct config_function ConfigureFunctions[] =
> +{
> +	{ {"include", PGC_POSTMASTER}, ReadConfigFile},
> +	{ {NULL,0}, NULL}
> +};
> +
>  /******** end of options list ********/
>  
>  
> @@ -919,6 +956,12 @@
>  		conf->gen.vartype = PGC_STRING;
>  		num_vars++;
>  	}
> +	for(i = 0; ConfigureFunctions[i].gen.name; i++)
> +	{
> +		struct config_function *conf = &ConfigureFunctions[i];
> +		conf->gen.vartype = PGC_FUNCTION;
> +		num_vars++;
> +	}
>  
>  	guc_vars = (struct config_generic **)
>  		malloc(num_vars * sizeof(struct config_generic *));
> @@ -939,6 +982,9 @@
>  	for (i = 0; ConfigureNamesString[i].gen.name; i++)
>  		guc_vars[num_vars++] = &ConfigureNamesString[i].gen;
>  
> +	for (i = 0; ConfigureFunctions[i].gen.name; i++)
> +		guc_vars[num_vars++] = &ConfigureFunctions[i].gen;
> +
>  	qsort((void *) guc_vars, num_vars, sizeof(struct config_generic *),
>  		  guc_var_compare);
>  
> @@ -1135,6 +1181,8 @@
>  					conf->session_val = str;
>  					break;
>  				}
> +			case PGC_FUNCTION: /* Nothing to do */
> +				break;
>  		}
>  	}
>  
> @@ -1280,6 +1328,8 @@
>  					guc_dirty = true;
>  					break;
>  				}
> +			case PGC_FUNCTION: /* Nothing to do */
> +				break;
>  		}
>  	}
>  }
> @@ -1421,6 +1471,8 @@
>  					conf->gen.status = 0;
>  					break;
>  				}
> +			case	PGC_FUNCTION: /* Nothing to do */
> +				break;
>  		}
>  	}
>  
> @@ -1684,6 +1736,17 @@
>  	 */
>  	switch (record->vartype)
>  	{
> +		case PGC_FUNCTION:
> +			if(!DoIt)
> +			{
> +				/* During the "checking" stage of configuration
> +				 * read, run functions 
> +				 */
> +				struct config_function *fn = 
> +					(struct config_function *)record;
> +				fn->function((char *)value, context);
> +			}
> +			break;
>  		case PGC_BOOL:
>  			{
>  				struct config_bool *conf = (struct config_bool *) record;
> @@ -2063,6 +2126,9 @@
>  
>  		case PGC_STRING:
>  			return *((struct config_string *) record)->variable;
> +		case PGC_FUNCTION:
> +			/* Should never really happen */
> +			return NULL;
>  	}
>  	return NULL;
>  }
> @@ -2097,6 +2163,9 @@
>  
>  		case PGC_STRING:
>  			return ((struct config_string *) record)->reset_val;
> +		case PGC_FUNCTION:
> +			/* Should never really happen */
> +			return NULL;
>  	}
>  	return NULL;
>  }
> diff -u -r postgresql-7.3.2/src/backend/utils/misc/postgresql.conf.sample postgresql-7.3.2.ec/src/backend/utils/misc/postgresql.conf.sample
> --- postgresql-7.3.2/src/backend/utils/misc/postgresql.conf.sample	Mon Jan 27 22:44:09 2003
> +++ postgresql-7.3.2.ec/src/backend/utils/misc/postgresql.conf.sample	Mon Feb 17 12:14:12 2003
> @@ -23,6 +23,21 @@
>  
>  #========================================================================
>  
> +# Allows PostgreSQL to include another file
> +# include = '/somedir/pgdefs.conf'
> +
> +# Allows PostgreSQL to use a pg_hba.conf file
> +# which is not in the database directory.
> +# hba_conf = '/etc/postgres/pg_hba.conf'
> +
> +# Allows PostgreSQL to use a pg_ident.conf file
> +# which is not in the database directory.
> +# ident_conf = '/etc/postgres/pg_ident.conf'
> +
> +# Allows Postgres to find its data directory
> +# from this configuration file.
> +# data_dir = '/RAID0/postgres'
> +
>  
>  #
>  #	Connection Parameters
> diff -u -r postgresql-7.3.2/src/include/utils/guc.h postgresql-7.3.2.ec/src/include/utils/guc.h
> --- postgresql-7.3.2/src/include/utils/guc.h	Mon Oct 21 14:57:35 2002
> +++ postgresql-7.3.2.ec/src/include/utils/guc.h	Mon Feb 17 14:40:57 2003
> @@ -137,5 +137,11 @@
>  extern char *client_min_messages_str;
>  
>  extern const char client_min_messages_str_default[];
> +/* Added MLW */
> +extern char *explicit_pgconfig;
> +extern char *explicit_hbafile;
> +extern char *explicit_identfile;
> +extern bool explicit_isdir;
> +extern char *pgdatadir;
>  
>  #endif   /* GUC_H */

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 3: if posting/reading through Usenet, please send an appropriate
> subscribe-nomail command to majordomo@postgresql.org so that your
> message can get through to the mailing list cleanly

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Wed, 19 Mar 2003 16:03:47 -0500 (EST)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: Yet another configuration patch with include, and configuration

Where are we on this patch for specifying the location of configuration
files?  I thought the final agreement was for us to allow multiple
directories as part of -C, like $PATH, and search those paths.  I think
we then don't need additional GUC variables for each config file, and -C
should specify only directories.  mlw, do you want to make those changes
so we can get it into 7.4?

On a related note, should we move the config files into a separate
directory in the default /data install?  It makes it clear exactly which
files are user-modifyable, but it does break backward compatibility. 
However, for people who prefer symlinks, it does make it even easier to
share those files _without_ -C.

---------------------------------------------------------------------------

mlw wrote:
> This is a patch that allows PostgreSQL to use a configuration
> file that is outside the main database directory.
> 
> It adds one more command line parameter, "-C" which
> specifies either the location of the postgres configuration
> file or a directory containing the configuration files.
> 
> A patched version of PostgreSQL will function as:
> 
> --- Configuration file ---
> postmaster -C /etc/postgres/postgresql.conf
> 
> This will direct the postmaster program to use the
> configuration file "/etc/postgres/postgresql.conf"
> 
> --- Configuration Directory ---
> postmaster -C /etc/postgres
> 
> This will direct the postmaster program to search the
> directory "/etc/postgres" for the standard configuration
> file names: posgresql.conf, pg_hba.conf, and pg_ident.conf.
> 
> --- postgresql.conf ---
> Within the main configuration file  are four  additional
> parameters: include, hba_conf,ident_conf, and data_dir.
> 
> They are used as:
> include = '/etc/postgres/debug.conf'
> data_dir = '/vol01/postgres'
> hba_conf = '/etc/postgres/pg_hba_conf'
> ident_conf = '/etc/postgres/pg_ident.conf'
> 
> 
> The "-D" option on the command line overrides the "data_dir"
> in the configuration file.
> 
> If no hba_conf and/or ident_conf setting is specified, the default
> $PGDATA/pg_hba.conf and/or $PGDATA/pg_ident.conf will be used.
> 
> This patch is intended to move the PostgreSQL configuration out of the
> data directory so that it can be modified and backed up.
> 
> This patch is also useful for running multiple servers with the same
> parameters:
> 
> postmaster -C /etc/postgres/postgresql.conf -D /VOL01/postgres -p 5432
> postmaster -C /etc/postgres/postgresql.conf -D /VOL02/postgres -p 5433
> 
> To apply the patch, enter your PostreSQL source directory, and run:
> 
> cat pgec-PGVERSON.patch | patch -p 1
> 

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

Sat, 24 May 2003 11:57:34 -0400 (EDT)
Bruce Momjian <pgman@candle.pha.pa.us>
Re: Yet another configuration patch with include, and configuration