From 130f89e93f59cdb4b160cbc31e6929de25d13794 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Sun, 11 Jul 2004 00:18:45 +0000
Subject: [PATCH] Allow configuration files to be placed outside the data
 directory.

Add new postgresql.conf variables to point to data, pg_hba.conf, and
pg_ident.conf files.

Needs more documentation.
---
 doc/src/sgml/ref/postmaster.sgml              | 27 ++++--
 doc/src/sgml/runtime.sgml                     | 50 +++++++++-
 src/backend/bootstrap/bootstrap.c             | 13 ++-
 src/backend/libpq/hba.c                       | 36 ++++---
 src/backend/postmaster/postmaster.c           | 91 ++++++++++++++---
 src/backend/tcop/postgres.c                   | 14 +--
 src/backend/utils/misc/guc-file.l             | 97 +++++++++++++------
 src/backend/utils/misc/guc.c                  | 37 ++++++-
 src/backend/utils/misc/postgresql.conf.sample | 10 ++
 src/include/utils/guc.h                       |  9 +-
 10 files changed, 303 insertions(+), 81 deletions(-)

diff --git a/doc/src/sgml/ref/postmaster.sgml b/doc/src/sgml/ref/postmaster.sgml
index 96bacf054af..0e22d342136 100644
--- a/doc/src/sgml/ref/postmaster.sgml
+++ b/doc/src/sgml/ref/postmaster.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.50 2004/06/21 04:06:04 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/postmaster.sgml,v 1.51 2004/07/11 00:18:41 momjian Exp $
 PostgreSQL documentation
 -->
 
@@ -67,15 +67,28 @@ PostgreSQL documentation
    One <command>postmaster</command> 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 <command>postmaster</command> starts it needs to know the location
-   of the database cluster files (<quote>data area</quote>).  This is
-   done with the <option>-D</option> invocation option or the
-   <envar>PGDATA</envar> environment variable; there is no default.
-   More than one <command>postmaster</command> process can run on a system at one time,
-   as long as they use different data areas and different
+   location.  When the <command>postmaster</command> starts it needs 
+   to know the location of the database cluster files (<quote>data 
+   area</quote>).  
+   More than one <command>postmaster</command> 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 <xref
    linkend="app-initdb">.
   </para>
+
+  <para>
+   The <quote>data area</> is specified by the <option>-D</option> option
+   or the <envar>PGDATA</envar> environment variable; there is no default.
+   Typically, it points to a directory created by <application>
+   initdb</>.  However, for administrative flexibility, you can
+   point to a directory containing only configuration files:
+   <filename>postgresql.conf</>, <filename>pg_hba.conf</>, and
+   <filename>pg_ident.conf</>. You can then set
+   <filename>postgresql.conf</>'s <varname>pgdata</> to point to the
+   data directory. You can also point just to the server configuration file
+   like <filename>postgresql.conf</> and set its variables to point to the
+   other configuration files and the data directory.
+  </para>
  </refsect1>
 
  <refsect1 id="app-postmaster-options">
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 69871d474ce..b249d9a5c24 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.268 2004/06/27 22:58:19 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.269 2004/07/11 00:18:40 momjian Exp $
 -->
 
 <Chapter Id="runtime">
@@ -563,6 +563,54 @@ SET ENABLE_SEQSCAN TO OFF;
     any desired selection condition.
    </para>
     
+   <sect2 id="runtime-config-configuration-files">
+    <title>Configuration Files</title>
+
+     <variablelist>
+
+     <varlistentry id="guc-pgdata" xreflabel="pgdata">
+      <term><varname>pgdata</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+         Specifies the directory to use for data storage (everything except
+         configuration files).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-hba-conf" xreflabel="hba-conf">
+      <term><varname>hba_conf</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+         Specifies the file name to use for configuration of host-based 
+         authentication (HBA).
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="guc-ident-conf" xreflabel="ident-conf">
+      <term><varname>ident_conf</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+         Specifies the file name to use for configuration of 
+         <application>ident</> authentication.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry id="external-pidfile" xreflabel="external-pidfile">
+      <term><varname>external_pidfile</varname> (<type>string</type>)</term>
+      <listitem>
+       <para>
+         Specifies the location of an additional <application>postmaster</>
+         process-id (PID) file for use by server administration programs.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     </variablelist>
+   </sect2>
+
    <sect2 id="runtime-config-connection">
     <title>Connections and Authentication</title>
 
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index ccf0595835e..7fe2ea02a65 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.185 2004/06/24 21:02:24 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.186 2004/07/11 00:18:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -212,7 +212,7 @@ BootstrapMain(int argc, char *argv[])
 	char	   *dbname;
 	int			flag;
 	int			xlogop = BS_XLOG_NOP;
-	char	   *potential_DataDir = NULL;
+	char	   *userPGDATA = NULL;
 
 	/*
 	 * initialize globals
@@ -236,8 +236,7 @@ BootstrapMain(int argc, char *argv[])
 	if (!IsUnderPostmaster)
 	{
 		InitializeGUCOptions();
-		potential_DataDir = getenv("PGDATA");	/* Null if no PGDATA
-												 * variable */
+		userPGDATA = getenv("PGDATA");	/* Null if no PGDATA variable */
 	}
 
 	/* Ignore the initial -boot argument, if present */
@@ -252,7 +251,7 @@ BootstrapMain(int argc, char *argv[])
 		switch (flag)
 		{
 			case 'D':
-				potential_DataDir = optarg;
+				userPGDATA = optarg;
 				break;
 			case 'd':
 				{
@@ -326,7 +325,7 @@ BootstrapMain(int argc, char *argv[])
 
 	if (!IsUnderPostmaster)
 	{
-		if (!potential_DataDir)
+		if (!userPGDATA)
 		{
 			write_stderr("%s does not know where to find the database system data.\n"
 						 "You must specify the directory that contains the database system\n"
@@ -335,7 +334,7 @@ BootstrapMain(int argc, char *argv[])
 						 argv[0]);
 			proc_exit(1);
 		}
-		SetDataDir(potential_DataDir);
+		SetDataDir(userPGDATA);
 	}
 
 	/* Validate we have been given a reasonable-looking DataDir */
diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c
index d15e8f6aff4..4577aec4935 100644
--- a/src/backend/libpq/hba.c
+++ b/src/backend/libpq/hba.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.125 2004/05/30 23:40:26 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/libpq/hba.c,v 1.126 2004/07/11 00:18:43 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,7 @@
 #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,17 +1030,22 @@ load_user(void)
 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);
+	/* 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,16 +1184,20 @@ load_ident(void)
 	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);
-
+	/* 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)
 	{
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index ee934711ff7..d68279b7f6a 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -37,7 +37,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.406 2004/07/10 23:29:16 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.407 2004/07/11 00:18:43 momjian Exp $
  *
  * NOTES
  *
@@ -233,6 +233,7 @@ extern int	optreset;
  * 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);
@@ -306,7 +307,7 @@ PostmasterMain(int argc, char *argv[])
 {
 	int			opt;
 	int			status;
-	char	   *potential_DataDir = NULL;
+	char	   *userPGDATA = NULL;
 	int			i;
 
 	progname = get_progname(argv[0]);
@@ -370,7 +371,7 @@ PostmasterMain(int argc, char *argv[])
 	 */
 	InitializeGUCOptions();
 
-	potential_DataDir = getenv("PGDATA");		/* default value */
+	userPGDATA = getenv("PGDATA");		/* default value */
 
 	opterr = 1;
 
@@ -395,7 +396,7 @@ PostmasterMain(int argc, char *argv[])
 				/* Can no longer set the backend executable file to use. */
 				break;
 			case 'D':
-				potential_DataDir = optarg;
+				userPGDATA = optarg;
 				break;
 			case 'd':
 				{
@@ -524,13 +525,49 @@ PostmasterMain(int argc, char *argv[])
 		ExitPostmaster(1);
 	}
 
-	/*
-	 * Now we can set the data directory, and then read postgresql.conf.
-	 */
-	checkDataDir(potential_DataDir);	/* issues error messages */
-	SetDataDir(potential_DataDir);
+	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);
 
-	ProcessConfigFile(PGC_POSTMASTER);
+		if (!guc_pgdata)	/* Got a pgdata from the config file? */
+		{
+			write_stderr("%s does not know where to find the database system data.\n"
+						 "This should be specified as 'pgdata' in %s%s.\n",
+						 progname, userPGDATA,
+						 user_pgconfig_is_dir ? "/postgresql.conf" : "");
+			ExitPostmaster(2);
+		}
+		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();
@@ -848,6 +885,32 @@ PostmasterMain(int argc, char *argv[])
 }
 
 
+
+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;
+}
+
+
 /*
  * Validate the proposed data directory
  */
@@ -862,8 +925,8 @@ checkDataDir(const char *checkdir)
 	{
 		write_stderr("%s does not know where to find the database system data.\n"
 					 "You must specify the directory that contains the database system\n"
-					 "either by specifying the -D invocation option or by setting the\n"
-					 "PGDATA environment variable.\n",
+					 "or configuration files by either specifying the -D invocation option\n"
+					 "or by setting the PGDATA environment variable.\n",
 					 progname);
 		ExitPostmaster(2);
 	}
@@ -873,12 +936,12 @@ checkDataDir(const char *checkdir)
 		if (errno == ENOENT)
 			ereport(FATAL,
 					(errcode_for_file_access(),
-					 errmsg("data directory \"%s\" does not exist",
+					 errmsg("data or configuration location \"%s\" does not exist",
 							checkdir)));
 		else
 			ereport(FATAL,
 					(errcode_for_file_access(),
-			 errmsg("could not read permissions of directory \"%s\": %m",
+			 errmsg("could not read permissions of \"%s\": %m",
 					checkdir)));
 	}
 
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index c42bd6c7bfb..54ba0a1fe6f 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.422 2004/07/01 00:51:11 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.423 2004/07/11 00:18:44 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2164,7 +2164,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 {
 	int			flag;
 	const char *dbname = NULL;
-	char	   *potential_DataDir = NULL;
+	char	   *userPGDATA = NULL;
 	bool		secure;
 	int			errs = 0;
 	int			debug_flag = 0;
@@ -2235,7 +2235,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 	if (!IsUnderPostmaster)
 	{
 		InitializeGUCOptions();
-		potential_DataDir = getenv("PGDATA");
+		userPGDATA = getenv("PGDATA");
 	}
 
 	/* ----------------
@@ -2283,7 +2283,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 
 			case 'D':			/* PGDATA directory */
 				if (secure)
-					potential_DataDir = optarg;
+					userPGDATA = optarg;
 				break;
 
 			case 'd':			/* debug level */
@@ -2574,12 +2574,12 @@ PostgresMain(int argc, char *argv[], const char *username)
 		 * set up handler to log session end.
 		 */
 		if (IsUnderPostmaster && Log_disconnections)
-			on_proc_exit(log_disconnections,0);
+			on_proc_exit(log_disconnections, 0);
 	}
 
 	if (!IsUnderPostmaster)
 	{
-		if (!potential_DataDir)
+		if (!userPGDATA)
 		{
 			write_stderr("%s does not know where to find the database system data.\n"
 						 "You must specify the directory that contains the database system\n"
@@ -2588,7 +2588,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 						 argv[0]);
 			proc_exit(1);
 		}
-		SetDataDir(potential_DataDir);
+		SetDataDir(userPGDATA);
 	}
 	Assert(DataDir);
 
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index cb95347e592..08b4ec4ad46 100644
--- a/src/backend/utils/misc/guc-file.l
+++ b/src/backend/utils/misc/guc-file.l
@@ -4,7 +4,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.22 2004/05/26 15:07:38 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.23 2004/07/11 00:18:44 momjian Exp $
  */
 
 %{
@@ -129,43 +129,24 @@ free_name_value_list(struct name_value_pair * list)
  * 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) ? 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)
     {
 		free(filename);
-        /* File not found is fine */
-        if (errno != ENOENT)
-            ereport(elevel,
-					(errcode_for_file_access(),
-					 errmsg("could not open configuration file \"%s\": %m", CONFIG_FILENAME)));
+		ereport(elevel,
+			(errcode_for_file_access(),
+			 errmsg("could not open configuration file \"%s\": %m", filename)));
 		return;
     }
 
@@ -197,7 +178,8 @@ ProcessConfigFile(GucContext context)
                     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);
@@ -259,7 +241,6 @@ ProcessConfigFile(GucContext context)
         }
 
 	FreeFile(fp);
-	free(filename);
 
 	/*
 	 * Check if all options are valid
@@ -282,12 +263,11 @@ ProcessConfigFile(GucContext context)
 
  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)));
+					filename, ConfigFileLineno, yytext)));
 	return;
 
  out_of_memory:
@@ -300,6 +280,65 @@ ProcessConfigFile(GucContext context)
 	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);
+}
+
 
 
 /* ----------------
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 7e4f0ebc001..9c8f8b5cc6d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.213 2004/07/05 23:14:14 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.214 2004/07/11 00:18:44 momjian Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -57,6 +57,13 @@
 #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 ""
@@ -107,6 +114,7 @@ static bool assign_stage_log_stats(bool newval, bool doit, GucSource source);
 static bool assign_log_stats(bool newval, bool doit, GucSource source);
 static bool assign_transaction_read_only(bool newval, bool doit, GucSource source);
 
+static void ReadConfigFile(char *filename, GucContext context);
 
 /*
  * Debugging options
@@ -1701,15 +1709,40 @@ static struct config_string ConfigureNamesString[] =
 		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
 	}
 };
 
-/******** end of options list ********/
 
+/******** 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
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 7983abbf7f0..bc772b2a7a1 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -21,6 +21,16 @@
 # "pg_ctl reload".
 
 
+#---------------------------------------------------------------------------
+# CONFIGURATION FILES
+#---------------------------------------------------------------------------
+
+# pgdata = '/usr/local/pgsql/data'		# use data in another directory
+# hba_conf = '/etc/pgsql/pg_hba.conf' 		# use hba info in another directory
+# ident_conf = '/etc/pgsql/pg_ident.conf'	# use ident info in another directory
+# external_pidfile= '/var/run/postgresql.pid'	# write an extra pid file
+
+
 #---------------------------------------------------------------------------
 # CONNECTIONS AND AUTHENTICATION
 #---------------------------------------------------------------------------
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 0a510cd6653..2a58ad048a4 100644
--- a/src/include/utils/guc.h
+++ b/src/include/utils/guc.h
@@ -7,7 +7,7 @@
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
- * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.48 2004/07/01 00:51:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.49 2004/07/11 00:18:45 momjian Exp $
  *--------------------------------------------------------------------
  */
 #ifndef GUC_H
@@ -135,6 +135,13 @@ extern int	log_min_messages;
 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);
-- 
GitLab