Index: doc/src/sgml/runtime.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/runtime.sgml,v
retrieving revision 1.265
diff -c -c -r1.265 runtime.sgml
*** doc/src/sgml/runtime.sgml	26 May 2004 18:51:43 -0000	1.265
--- doc/src/sgml/runtime.sgml	2 Jun 2004 20:31:36 -0000
***************
*** 563,568 ****
--- 563,625 ----
      any desired selection condition.
     
      
+    
+     Configuration Files
+ 
+      
+ 
+      
+       include (string)
+       
+        
+          Specifies an additional file to read for configuration settings.
+        
+       
+      
+ 
+      
+       hba_conf (string)
+       
+        
+          Specifies the file name to use for configuration of host-based 
+          authentication (HBA).
+        
+       
+      
+ 
+      
+       ident_conf (string)
+       
+        
+          Specifies the file name to use for configuration of 
+          ident> authentication.
+        
+       
+      
+ 
+      
+       pgdata (string)
+       
+        
+          Specifies the directory to use for data storage (everything except
+          configuration files).
+        
+       
+      
+ 
+      
+       external_pidfile (string)
+       
+        
+          Specifies the location of an additional postmaster>
+          process-id (PID) file for use by server administration programs.
+        
+       
+      
+ 
+      
+    
+ 
     
      Connections and Authentication
  
Index: doc/src/sgml/ref/postmaster.sgml
===================================================================
RCS file: /cvsroot/pgsql-server/doc/src/sgml/ref/postmaster.sgml,v
retrieving revision 1.49
diff -c -c -r1.49 postmaster.sgml
*** doc/src/sgml/ref/postmaster.sgml	23 Mar 2004 06:09:00 -0000	1.49
--- doc/src/sgml/ref/postmaster.sgml	2 Jun 2004 20:31:36 -0000
***************
*** 67,80 ****
     One postmaster always manages the data
     from exactly one database cluster.  A database cluster is a
     collection of databases that is stored at a common file system
!    location.  When the postmaster starts it needs to know the location
!    of the database cluster files (data area
).  This is
!    done with the  invocation option or the
!    PGDATA environment variable; there is no default.
!    More than one postmaster process can run on a system at one time,
!    as long as they use different data areas and different
     communication ports (see below).  A data area is created with .
    
   
  
--- 67,92 ----
     One postmaster always manages the data
     from exactly one database cluster.  A database cluster is a
     collection of databases that is stored at a common file system
!    location.  When the postmaster starts it needs 
!    to know the location of the database cluster files (data 
!    area
).  
!    More than one postmaster process can run on a system
!    at one time as long as they use different data areas and different
     communication ports (see below).  A data area is created with .
+   
+ 
+   
+    The data area> is specified by the  option
+    or the PGDATA environment variable; there is no default.
+    They typically point to a directory created by 
+    initdb>.  However, for administrative flexibility, you can
+    point directly to a configuration file like postgresql.conf>.
+    This file must then specify the location of data directory using
+    postgresql.conf>'s variable pgdata>.  
+    You can also point to a directory containing just configuration files, 
+    and use postgresql.conf>'s pgdata> to point 
+    to the directory containing the remaining files.
    
   
  
Index: src/backend/bootstrap/bootstrap.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/bootstrap/bootstrap.c,v
retrieving revision 1.182
diff -c -c -r1.182 bootstrap.c
*** src/backend/bootstrap/bootstrap.c	29 May 2004 22:48:18 -0000	1.182
--- src/backend/bootstrap/bootstrap.c	2 Jun 2004 20:31:37 -0000
***************
*** 213,219 ****
  	char	   *dbname;
  	int			flag;
  	int			xlogop = BS_XLOG_NOP;
! 	char	   *potential_DataDir = NULL;
  
  	/*
  	 * initialize globals
--- 213,219 ----
  	char	   *dbname;
  	int			flag;
  	int			xlogop = BS_XLOG_NOP;
! 	char	   *userPGDATA = NULL;
  
  	/*
  	 * initialize globals
***************
*** 237,244 ****
  	if (!IsUnderPostmaster)
  	{
  		InitializeGUCOptions();
! 		potential_DataDir = getenv("PGDATA");	/* Null if no PGDATA
! 												 * variable */
  	}
  
  	/* Ignore the initial -boot argument, if present */
--- 237,243 ----
  	if (!IsUnderPostmaster)
  	{
  		InitializeGUCOptions();
! 		userPGDATA = getenv("PGDATA");	/* Null if no PGDATA variable */
  	}
  
  	/* Ignore the initial -boot argument, if present */
***************
*** 253,259 ****
  		switch (flag)
  		{
  			case 'D':
! 				potential_DataDir = optarg;
  				break;
  			case 'd':
  				{
--- 252,258 ----
  		switch (flag)
  		{
  			case 'D':
! 				userPGDATA = optarg;
  				break;
  			case 'd':
  				{
***************
*** 327,333 ****
  
  	if (!IsUnderPostmaster)
  	{
! 		if (!potential_DataDir)
  		{
  			fprintf(stderr,
  					gettext("%s does not know where to find the database system data.\n"
--- 326,332 ----
  
  	if (!IsUnderPostmaster)
  	{
! 		if (!userPGDATA)
  		{
  			fprintf(stderr,
  					gettext("%s does not know where to find the database system data.\n"
***************
*** 337,343 ****
  					argv[0]);
  			proc_exit(1);
  		}
! 		SetDataDir(potential_DataDir);
  	}
  
  	/* Validate we have been given a reasonable-looking DataDir */
--- 336,342 ----
  					argv[0]);
  			proc_exit(1);
  		}
! 		SetDataDir(userPGDATA);
  	}
  
  	/* Validate we have been given a reasonable-looking DataDir */
Index: src/backend/libpq/hba.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/libpq/hba.c,v
retrieving revision 1.125
diff -c -c -r1.125 hba.c
*** src/backend/libpq/hba.c	30 May 2004 23:40:26 -0000	1.125
--- src/backend/libpq/hba.c	2 Jun 2004 20:31:38 -0000
***************
*** 35,40 ****
--- 35,41 ----
  #include "miscadmin.h"
  #include "nodes/pg_list.h"
  #include "storage/fd.h"
+ #include "utils/guc.h"
  
  
  /* Max size of username ident server can return */
***************
*** 1029,1045 ****
  void
  load_hba(void)
  {
- 	int			bufsize;
  	FILE	   *file;			/* The config file we have to read */
  	char	   *conf_file;		/* The name of the config file */
  
  	if (hba_lines || hba_line_nums)
  		free_lines(&hba_lines, &hba_line_nums);
  
! 	/* 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);
  
  	file = AllocateFile(conf_file, "r");
  	if (file == NULL)
--- 1030,1051 ----
  void
  load_hba(void)
  {
  	FILE	   *file;			/* The config file we have to read */
  	char	   *conf_file;		/* The name of the config file */
  
  	if (hba_lines || hba_line_nums)
  		free_lines(&hba_lines, &hba_line_nums);
  
! 	/* HBA filename in config file */
! 	if (guc_hbafile)
! 		conf_file = pstrdup(guc_hbafile);
! 	else
! 	{
! 		char *confloc = (user_pgconfig_is_dir) ? user_pgconfig : DataDir;
! 		/* put together the full pathname to the config file */
! 		conf_file = palloc(strlen(confloc) + strlen(CONF_FILE) + 2);
! 		sprintf(conf_file, "%s/%s", confloc, CONF_FILE);
! 	}
  
  	file = AllocateFile(conf_file, "r");
  	if (file == NULL)
***************
*** 1178,1193 ****
  	FILE	   *file;			/* The map file we have to read */
  	char	   *map_file;		/* The name of the map file we have to
  								 * read */
- 	int			bufsize;
- 
  	if (ident_lines || ident_line_nums)
  		free_lines(&ident_lines, &ident_line_nums);
  
! 	/* 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);
! 
  	file = AllocateFile(map_file, "r");
  	if (file == NULL)
  	{
--- 1184,1203 ----
  	FILE	   *file;			/* The map file we have to read */
  	char	   *map_file;		/* The name of the map file we have to
  								 * read */
  	if (ident_lines || ident_line_nums)
  		free_lines(&ident_lines, &ident_line_nums);
  
! 	/* IDENT filename in config file */
! 	if (guc_identfile)
! 		map_file = pstrdup(guc_identfile);
! 	else
! 	{
! 		/* put together the full pathname to the map file */
! 		char *confloc = (user_pgconfig_is_dir) ? user_pgconfig : DataDir;
! 		map_file = (char *) palloc(strlen(confloc) + strlen(USERMAP_FILE) + 2);
! 		sprintf(map_file, "%s/%s", confloc, USERMAP_FILE);
! 	}
!   
  	file = AllocateFile(map_file, "r");
  	if (file == NULL)
  	{
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.401
diff -c -c -r1.401 postmaster.c
*** src/backend/postmaster/postmaster.c	30 May 2004 03:50:11 -0000	1.401
--- src/backend/postmaster/postmaster.c	2 Jun 2004 20:31:41 -0000
***************
*** 226,231 ****
--- 226,232 ----
   * postmaster.c - function prototypes
   */
  static void checkDataDir(const char *checkdir);
+ static bool onlyConfigSpecified(const char *checkdir);
  #ifdef USE_RENDEZVOUS
  static void reg_reply(DNSServiceRegistrationReplyErrorType errorCode,
  					  void *context);
***************
*** 303,309 ****
  {
  	int			opt;
  	int			status;
! 	char	   *potential_DataDir = NULL;
  	int			i;
  
  	progname = get_progname(argv[0]);
--- 304,310 ----
  {
  	int			opt;
  	int			status;
! 	char	   *userPGDATA = NULL;
  	int			i;
  
  	progname = get_progname(argv[0]);
***************
*** 367,373 ****
  	 */
  	InitializeGUCOptions();
  
! 	potential_DataDir = getenv("PGDATA");		/* default value */
  
  	opterr = 1;
  
--- 368,374 ----
  	 */
  	InitializeGUCOptions();
  
! 	userPGDATA = getenv("PGDATA");		/* default value */
  
  	opterr = 1;
  
***************
*** 392,398 ****
  				/* Can no longer set the backend executable file to use. */
  				break;
  			case 'D':
! 				potential_DataDir = optarg;
  				break;
  			case 'd':
  				{
--- 393,399 ----
  				/* Can no longer set the backend executable file to use. */
  				break;
  			case 'D':
! 				userPGDATA = optarg;
  				break;
  			case 'd':
  				{
***************
*** 521,533 ****
  		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 timezone is not set, determine what the OS uses */
  	pg_timezone_initialize();
--- 522,565 ----
  		ExitPostmaster(1);
  	}
  
! 	if (onlyConfigSpecified(userPGDATA))
! 	{
! 		/*
! 		 *	It is either a file name or a directory with no
! 		 *	global/pg_control file, and hence not a data directory.
! 		 */
! 		user_pgconfig = userPGDATA;
! 		ProcessConfigFile(PGC_POSTMASTER);
! 
! 		if (!guc_pgdata)	/* Got a pgdata from the config file? */
! 			checkDataDir(NULL);		/* throw error */
! 
! 		checkDataDir(guc_pgdata);
! 		SetDataDir(guc_pgdata);
! 	}
! 	else
! 	{
! 		/* Now we can set the data directory, and then read postgresql.conf. */
! 		checkDataDir(userPGDATA);
! 		SetDataDir(userPGDATA);
! 		ProcessConfigFile(PGC_POSTMASTER);
! 	}
! 
! 	if (external_pidfile)
! 	{
! 		FILE *fpidfile = fopen(external_pidfile, "w");
  
! 		if (fpidfile)
! 		{
! 			fprintf(fpidfile, "%d\n", MyProcPid);
! 			fclose(fpidfile);
! 			/* Should we remove the pid file on postmaster exit? */
! 		}
! 		else
! 			fprintf(stderr,
! 				gettext("%s could not write to external pid file %s\n"),
! 				progname, external_pidfile);
! 	}
  
  	/* If timezone is not set, determine what the OS uses */
  	pg_timezone_initialize();
***************
*** 839,844 ****
--- 871,902 ----
  	ExitPostmaster(status != STATUS_OK);
  
  	return 0;					/* not reached */
+ }
+ 
+ 
+ 
+ static bool
+ onlyConfigSpecified(const char *checkdir)
+ {
+ 	char	path[MAXPGPATH];
+ 	struct stat stat_buf;
+ 
+ 	if (checkdir == NULL)			/* checkDataDir handles this */
+ 		return FALSE;
+ 
+ 	if (stat(checkdir, &stat_buf) == -1)	/* ditto */
+ 		return FALSE;
+ 
+ 	if (S_ISREG(stat_buf.st_mode))		/* It's a regular file, so assume it's explict */
+ 		return TRUE;
+ 	else if (S_ISDIR(stat_buf.st_mode))	/* It's a directory, is it a config or system dir? */
+ 	{
+ 		snprintf(path, MAXPGPATH, "%s/global/pg_control", checkdir);
+ 		/* If this is not found, it is a config-only directory */
+ 		if (stat(path, &stat_buf) == -1)
+ 			return TRUE;
+ 	}
+ 	return FALSE;
  }
  
  
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/tcop/postgres.c,v
retrieving revision 1.417
diff -c -c -r1.417 postgres.c
*** src/backend/tcop/postgres.c	29 May 2004 22:48:20 -0000	1.417
--- src/backend/tcop/postgres.c	2 Jun 2004 20:31:43 -0000
***************
*** 2137,2143 ****
  {
  	int			flag;
  	const char *dbname = NULL;
! 	char	   *potential_DataDir = NULL;
  	bool		secure;
  	int			errs = 0;
  	int			debug_flag = 0;
--- 2137,2143 ----
  {
  	int			flag;
  	const char *dbname = NULL;
! 	char	   *userPGDATA = NULL;
  	bool		secure;
  	int			errs = 0;
  	int			debug_flag = 0;
***************
*** 2208,2214 ****
  	if (!IsUnderPostmaster)
  	{
  		InitializeGUCOptions();
! 		potential_DataDir = getenv("PGDATA");
  	}
  
  	/* ----------------
--- 2208,2214 ----
  	if (!IsUnderPostmaster)
  	{
  		InitializeGUCOptions();
! 		userPGDATA = getenv("PGDATA");
  	}
  
  	/* ----------------
***************
*** 2256,2262 ****
  
  			case 'D':			/* PGDATA directory */
  				if (secure)
! 					potential_DataDir = optarg;
  				break;
  
  			case 'd':			/* debug level */
--- 2256,2262 ----
  
  			case 'D':			/* PGDATA directory */
  				if (secure)
! 					userPGDATA = optarg;
  				break;
  
  			case 'd':			/* debug level */
***************
*** 2547,2558 ****
  		 * set up handler to log session end.
  		 */
  		if (IsUnderPostmaster && Log_disconnections)
! 			on_proc_exit(log_disconnections,0);
  	}
  
  	if (!IsUnderPostmaster)
  	{
! 		if (!potential_DataDir)
  		{
  			fprintf(stderr,
  					gettext("%s does not know where to find the database system data.\n"
--- 2547,2558 ----
  		 * set up handler to log session end.
  		 */
  		if (IsUnderPostmaster && Log_disconnections)
! 			on_proc_exit(log_disconnections, 0);
  	}
  
  	if (!IsUnderPostmaster)
  	{
! 		if (!userPGDATA)
  		{
  			fprintf(stderr,
  					gettext("%s does not know where to find the database system data.\n"
***************
*** 2562,2568 ****
  					argv[0]);
  			proc_exit(1);
  		}
! 		SetDataDir(potential_DataDir);
  	}
  	Assert(DataDir);
  
--- 2562,2568 ----
  					argv[0]);
  			proc_exit(1);
  		}
! 		SetDataDir(userPGDATA);
  	}
  	Assert(DataDir);
  
Index: src/backend/utils/misc/guc-file.l
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc-file.l,v
retrieving revision 1.22
diff -c -c -r1.22 guc-file.l
*** src/backend/utils/misc/guc-file.l	26 May 2004 15:07:38 -0000	1.22
--- src/backend/utils/misc/guc-file.l	2 Jun 2004 20:31:44 -0000
***************
*** 129,162 ****
   * function does not return if an error occurs. If an error occurs, no
   * values will be changed.
   */
! void
! ProcessConfigFile(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) ? DEBUG4 : ERROR;
  
- 	/*
- 	 * Open file
- 	 */
- 	filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2);
- 	if (filename == NULL)
- 	{
- 		ereport(elevel,
- 				(errcode(ERRCODE_OUT_OF_MEMORY),
- 				 errmsg("out of memory")));
- 		return;
- 	}
- 	sprintf(filename, "%s/" CONFIG_FILENAME, DataDir);
- 
      fp = AllocateFile(filename, "r");
      if (!fp)
      {
--- 129,145 ----
   * function does not return if an error occurs. If an error occurs, no
   * values will be changed.
   */
! static void
! ReadConfigFile(char *filename, GucContext context)
  {
  	int token, parse_state;
  	char *opt_name, *opt_value;
  	struct name_value_pair *item, *head, *tail;
  	int elevel;
  	FILE * fp;
  
  	elevel = (context == PGC_SIGHUP) ? DEBUG4 : ERROR;
  
      fp = AllocateFile(filename, "r");
      if (!fp)
      {
***************
*** 165,171 ****
          if (errno != ENOENT)
              ereport(elevel,
  					(errcode_for_file_access(),
! 					 errmsg("could not open configuration file \"%s\": %m", CONFIG_FILENAME)));
  		return;
      }
  
--- 148,154 ----
          if (errno != ENOENT)
              ereport(elevel,
  					(errcode_for_file_access(),
! 					 errmsg("could not open configuration file \"%s\": %m", filename)));
  		return;
      }
  
***************
*** 197,203 ****
                      token = yylex();
  
                  if (token != GUC_ID && token != GUC_STRING && 
! 					token != GUC_INTEGER && token != GUC_REAL && 
  					token != GUC_UNQUOTED_STRING)
                      goto parse_error;
                  opt_value = strdup(yytext);
--- 180,187 ----
                      token = yylex();
  
                  if (token != GUC_ID && token != GUC_STRING && 
! 					token != GUC_INTEGER && 
! 					token != GUC_REAL && 
  					token != GUC_UNQUOTED_STRING)
                      goto parse_error;
                  opt_value = strdup(yytext);
***************
*** 259,265 ****
          }
  
  	FreeFile(fp);
- 	free(filename);
  
  	/*
  	 * Check if all options are valid
--- 243,248 ----
***************
*** 282,293 ****
  
   parse_error:
  	FreeFile(fp);
- 	free(filename);
  	free_name_value_list(head);
  	ereport(elevel,
  			(errcode(ERRCODE_SYNTAX_ERROR),
  			 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", 
! 					CONFIG_FILENAME, ConfigFileLineno, yytext)));
  	return;
  
   out_of_memory:
--- 265,275 ----
  
   parse_error:
  	FreeFile(fp);
  	free_name_value_list(head);
  	ereport(elevel,
  			(errcode(ERRCODE_SYNTAX_ERROR),
  			 errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", 
! 					filename, ConfigFileLineno, yytext)));
  	return;
  
   out_of_memory:
***************
*** 298,303 ****
--- 280,344 ----
  			(errcode(ERRCODE_OUT_OF_MEMORY),
  			 errmsg("out of memory")));
  	return;
+ }
+ 
+ /*
+  * Function to read and process the configuration file. The
+  * parameter indicates the context that 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 (user_pgconfig)
+ 	{
+ 		struct stat sb;
+ 
+ 		if (stat(user_pgconfig, &sb) != 0)
+ 		{
+ 			int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR;
+ 			elog(elevel, "Configuration file \"%s\" does not exist", user_pgconfig);
+ 			return;
+ 		}
+ 
+ 		if (S_ISDIR(sb.st_mode))
+ 		{
+ 			/* This will cause a small one time memory leak
+ 			 * if the user also specifies hba_conf,
+ 			 * ident_conf, and data_dir
+ 			 */
+ 			filename = malloc(strlen(user_pgconfig) + strlen(CONFIG_FILENAME) + 2);
+ 			sprintf(filename, "%s/%s", user_pgconfig, CONFIG_FILENAME);
+ 			user_pgconfig_is_dir = true;
+ 		}
+ 		else
+ 			filename = strdup(user_pgconfig);	/* Use explicit file */
+ 	}
+ 	else
+ 	{
+ 		/* Use datadir for 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;
+ 	}
+ 
+ 	ReadConfigFile(filename, context);
+ 
+ 	free(filename);
  }
  
  
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.210
diff -c -c -r1.210 guc.c
*** src/backend/utils/misc/guc.c	30 May 2004 23:40:38 -0000	1.210
--- src/backend/utils/misc/guc.c	2 Jun 2004 20:31:47 -0000
***************
*** 57,62 ****
--- 57,69 ----
  #include "utils/pg_locale.h"
  #include "pgstat.h"
  
+ char *guc_pgdata;
+ char *guc_hbafile;
+ char *guc_identfile;
+ char *external_pidfile;
+ 
+ char *user_pgconfig = NULL;
+ bool user_pgconfig_is_dir = false;
  
  #ifndef PG_KRB_SRVTAB
  #define PG_KRB_SRVTAB ""
***************
*** 106,111 ****
--- 113,119 ----
  static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
  static bool assign_log_stats(bool newval, bool doit, GucSource source);
  
+ static void ReadConfigFile(char *filename, GucContext context);
  
  /*
   * Debugging options
***************
*** 174,179 ****
--- 182,194 ----
  static int	block_size;
  static bool integer_datetimes;
  
+ 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) \
***************
*** 336,342 ****
  	 /* PGC_BOOL */ "bool",
  	 /* PGC_INT */ "integer",
  	 /* PGC_REAL */ "real",
! 	 /* PGC_STRING */ "string"
  };
  
  
--- 351,358 ----
  	 /* PGC_BOOL */ "bool",
  	 /* PGC_INT */ "integer",
  	 /* PGC_REAL */ "real",
! 	 /* PGC_STRING */ "string",
! 	 /* PGC_FUNCTION */ "function"
  };
  
  
***************
*** 1739,1753 ****
  		NULL, assign_custom_variable_classes, NULL
  	},
  
  	/* End-of-list marker */
  	{
  		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
  	}
  };
  
- /******** end of options list ********/
  
  
  /*
   * To allow continued support of obsolete names for GUC variables, we apply
   * the following mappings to any unrecognized name.  Note that an old name
--- 1755,1800 ----
  		NULL, assign_custom_variable_classes, NULL
  	},
  
+ 	{
+ 		{"pgdata", PGC_POSTMASTER, 0, gettext_noop("Sets the location of the data directory"), NULL}, 
+ 		&guc_pgdata,
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"hba_conf", PGC_SIGHUP, 0, gettext_noop("Sets the location of the \"hba\" configuration file"), NULL}, 
+ 		&guc_hbafile,
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"ident_conf", PGC_SIGHUP, 0, gettext_noop("Sets the location of the \"ident\" configuration file"), NULL}, 
+ 		&guc_identfile,
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
+ 		{"external_pidfile", PGC_POSTMASTER, 0, gettext_noop("Writes the postmaster PID to the specified file"), NULL},
+ 		&external_pidfile,
+ 		NULL, NULL, NULL
+ 	},
+ 
  	/* End-of-list marker */
  	{
  		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL
  	}
  };
  
  
+ static struct config_function ConfigureFunctions[] =
+ {
+         { {"include", PGC_POSTMASTER}, ReadConfigFile},
+         { {NULL,0}, NULL}
+ };
+ 
+ /******** end of options list ********/
  
+   
  /*
   * To allow continued support of obsolete names for GUC variables, we apply
   * the following mappings to any unrecognized name.  Note that an old name
***************
*** 1837,1842 ****
--- 1884,1897 ----
  		num_vars++;
  	}
  
+ 	for(i = 0; ConfigureFunctions[i].gen.name; i++)
+ 	{
+ 		struct config_function *conf = &ConfigureFunctions[i];
+ 
+ 		conf->gen.vartype = PGC_FUNCTION;
+ 		num_vars++;
+ 	}
+ 
  	/* Create table with 20% slack
  	 */
  	size_vars = num_vars + num_vars / 4;
***************
*** 1862,1867 ****
--- 1917,1925 ----
  	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;
+ 
  	if (guc_variables)
  		free(guc_variables);
  	guc_variables = guc_vars;
***************
*** 2193,2198 ****
--- 2251,2258 ----
  					conf->session_val = str;
  					break;
  				}
+ 			case PGC_FUNCTION: /* Nothing to do */
+ 				break;
  		}
  	}
  
***************
*** 2344,2349 ****
--- 2404,2411 ----
  					guc_dirty = true;
  					break;
  				}
+ 			case PGC_FUNCTION: /* Nothing to do */
+ 				break;
  		}
  
  		if (gconf->flags & GUC_REPORT)
***************
*** 2500,2505 ****
--- 2562,2569 ----
  					conf->gen.status = 0;
  					break;
  				}
+ 			case	PGC_FUNCTION: /* Nothing to do */
+ 				break;
  		}
  
  		if (changed && (gconf->flags & GUC_REPORT))
***************
*** 3301,3306 ****
--- 3365,3382 ----
  					free(newval);
  				break;
  			}
+ 
+ 		case PGC_FUNCTION:
+ 			if (!changeVal)
+ 			{
+ 				/* During the "checking" stage of configuration
+ 				 * read, run functions 
+ 				 */
+ 				struct config_function *fn = 
+ 					(struct config_function *)record;
+ 				fn->function((char *)value, context);
+ 			}
+ 			break;
  	}
  
  	if (changeVal && (record->flags & GUC_REPORT))
***************
*** 3361,3366 ****
--- 3437,3446 ----
  
  		case PGC_STRING:
  			return *((struct config_string *) record)->variable;
+ 
+ 		case PGC_FUNCTION:
+ 			/* Should never really happen */
+ 			return NULL;
  	}
  	return NULL;
  }
***************
*** 3397,3402 ****
--- 3477,3486 ----
  
  		case PGC_STRING:
  			return ((struct config_string *) record)->reset_val;
+ 
+ 		case PGC_FUNCTION:
+ 			/* Should never really happen */
+ 			return NULL;
  	}
  	return NULL;
  }
***************
*** 4351,4356 ****
--- 4435,4443 ----
  						fprintf(fp, "%s", *conf->variable);
  					}
  					break;
+ 
+ 				case PGC_FUNCTION:	/* do nothing */
+ 					break;
  			}
  
  			fputc(0, fp);
***************
*** 5131,5133 ****
--- 5218,5221 ----
  
  
  #include "guc-file.c"
+ 
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.113
diff -c -c -r1.113 postgresql.conf.sample
*** src/backend/utils/misc/postgresql.conf.sample	7 Apr 2004 05:05:50 -0000	1.113
--- src/backend/utils/misc/postgresql.conf.sample	2 Jun 2004 20:31:47 -0000
***************
*** 22,27 ****
--- 22,38 ----
  
  
  #---------------------------------------------------------------------------
+ # CONFIGURATION FILES
+ #---------------------------------------------------------------------------
+ 
+ # include = '/somedir/pgdefs.conf'		# include another file
+ # hba_conf = '/etc/postgres/pg_hba.conf' 	# use file in another directory
+ # ident_conf = '/etc/postgres/pg_ident.conf'	# use file in another directory
+ # pgdata = '/usr/local/pgsql/data'		# use /data in another directory
+ # external_pidfile= '/var/run/postgresql.pid'	# write an extra pid file
+ 
+ 
+ #---------------------------------------------------------------------------
  # CONNECTIONS AND AUTHENTICATION
  #---------------------------------------------------------------------------
  
Index: src/include/utils/guc.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/guc.h,v
retrieving revision 1.47
diff -c -c -r1.47 guc.h
*** src/include/utils/guc.h	28 May 2004 05:13:32 -0000	1.47
--- src/include/utils/guc.h	2 Jun 2004 20:31:48 -0000
***************
*** 135,140 ****
--- 135,147 ----
  extern int	client_min_messages;
  extern int	log_min_duration_statement;
  
+ extern char *guc_pgdata;
+ extern char *guc_hbafile;
+ extern char *guc_identfile;
+ extern char *external_pidfile;
+ 
+ extern char *user_pgconfig;
+ extern bool user_pgconfig_is_dir;
  
  extern void SetConfigOption(const char *name, const char *value,
  				GucContext context, GucSource source);
Index: src/include/utils/guc_tables.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/utils/guc_tables.h,v
retrieving revision 1.11
diff -c -c -r1.11 guc_tables.h
*** src/include/utils/guc_tables.h	26 May 2004 15:07:41 -0000	1.11
--- src/include/utils/guc_tables.h	2 Jun 2004 20:31:48 -0000
***************
*** 63,69 ****
  	PGC_BOOL,
  	PGC_INT,
  	PGC_REAL,
! 	PGC_STRING
  };
  
  /*
--- 63,70 ----
  	PGC_BOOL,
  	PGC_INT,
  	PGC_REAL,
! 	PGC_STRING,
! 	PGC_FUNCTION
  };
  
  /*