*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
***************
*** 53,58 **** static bool ParseConfigFile(const char *config_file, const char *calling_file,
--- 53,62 ----
  							int depth, GucContext context, int elevel,
  							struct name_value_pair **head_p,
  							struct name_value_pair **tail_p);
+ static bool ParseConfigDirectory(const char *configdir,
+ 							GucContext context, int elevel,
+ 							struct name_value_pair **head_p,
+ 							struct name_value_pair **tail_p);
  static void free_name_value_list(struct name_value_pair * list);
  static char *GUC_scanstr(const char *s);
  
***************
*** 146,151 **** ProcessConfigFile(GucContext context)
--- 150,163 ----
  		goto cleanup_list;
  
  	/*
+ 	 * Parse all config files in subdirectory, in alphabetical order, and
+ 	 * append them to the list of option names and values.
+ 	 */
+ 	if (!ParseConfigDirectory(ConfigDir, context, elevel,
+ 							  &head, &tail))
+ 		goto cleanup_list;
+ 
+ 	/*
  	 * We need the proposed new value of custom_variable_classes to check
  	 * custom variables with.  ParseConfigFile ensured that if it's in
  	 * the file, it's first in the list.  But first check to see if we
***************
*** 571,576 **** cleanup_exit:
--- 583,693 ----
  	return OK;
  }
  
+ static int
+ comparestr(const void *a, const void *b)
+ {
+ 	return strcmp(*(char **) a, *(char **) b);
+ }
+ 
+ 
+ /*
+  * Read and parse all config files in a subdirectory in alphabetical order
+  */
+ static bool
+ ParseConfigDirectory(const char *configdir,
+ 					GucContext context, int elevel,
+ 					struct name_value_pair **head_p,
+ 					struct name_value_pair **tail_p)
+ {
+ 	DIR *d;
+ 	struct dirent *de;
+ 	char directory[MAXPGPATH];
+ 	char **filenames = NULL;
+ 	int num_filenames = 0;
+ 	int size_filenames = 0;
+ 	bool status;
+ 
+ 	sprintf(directory, "%s/pg_config", configdir);
+ 	d = AllocateDir(directory);
+ 	if (d == NULL)
+ 	{
+ 		/*
+ 		 * Not finding the configuration directory is not fatal, because we
+ 		 * still have the main postgresql.conf file. Return true so the
+ 		 * complete config parsing doesn't fail in this case. Also avoid
+ 		 * logging this, since it can be a normal situtation.
+ 		 */
+ 		return true;
+ 	}
+ 
+ 	/*
+ 	 * Read the directory and put the filenames in an array, so we can sort
+ 	 * them prior to processing the contents.
+ 	 */
+ 	while ((de = ReadDir(d, directory)) != NULL)
+ 	{
+ 		struct stat st;
+ 		char filename[MAXPGPATH];
+ 
+ 		/*
+ 		 * Only parse files with names ending in ".conf".
+ 		 * This automtically excludes things like "." and ".."
+ 		 */
+ 		if (strlen(de->d_name) < 6)
+ 			continue;
+ 		if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
+ 			continue;
+ 
+ 		snprintf(filename, MAXPGPATH, "%s/%s", directory, de->d_name);
+ 		if (stat(filename, &st) == 0)
+ 		{
+ 			if (!S_ISDIR(st.st_mode))
+ 			{
+ 				/* Add file to list */
+ 				if (num_filenames == size_filenames)
+ 				{
+ 					/* Increase size of array in blocks of 32 */
+ 					size_filenames += 32;
+ 					filenames = guc_realloc(elevel, filenames, size_filenames * sizeof(char *));
+ 				}
+ 				filenames[num_filenames] = strdup(filename);
+ 				num_filenames++;
+ 			}
+ 		}
+ 	}
+ 	if (num_filenames > 0)
+ 	{
+ 		int i;
+ 
+ 		qsort(filenames, num_filenames, sizeof(char *), comparestr);
+ 
+ 		for (i = 0; i < num_filenames; i++)
+ 		{
+ 			if (!ParseConfigFile(filenames[i], NULL,
+ 								 0, context, elevel,
+ 								 head_p, tail_p))
+ 			{
+ 				status = false;
+ 				goto cleanup;
+ 			}
+ 		}
+ 	}
+ 	status = true;
+ 
+ cleanup:
+ 	if (num_filenames > 0)
+ 	{
+ 		int i;
+ 
+ 		for (i = 0; i < num_filenames; i++)
+ 		{
+ 			free(filenames[i]);
+ 		}
+ 		free(filenames);
+ 	}
+ 	FreeDir(d);
+ 	return status;
+ }
  
  /*
   * Free a list of name/value pairs, including the names and the values
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 370,375 **** int			log_temp_files = -1;
--- 370,376 ----
  int			num_temp_buffers = 1000;
  
  char	   *ConfigFileName;
+ char	   *ConfigDir;
  char	   *HbaFileName;
  char	   *IdentFileName;
  char	   *external_pid_file;
***************
*** 2465,2470 **** static struct config_string ConfigureNamesString[] =
--- 2466,2481 ----
  	},
  
  	{
+ 		{"config_dir", PGC_POSTMASTER, FILE_LOCATIONS,
+ 			gettext_noop("Sets the servers main configuration directory."),
+ 			NULL,
+ 			GUC_DISALLOW_IN_FILE | GUC_SUPERUSER_ONLY
+ 		},
+ 		&ConfigDir,
+ 		NULL, NULL, NULL
+ 	},
+ 
+ 	{
  		{"hba_file", PGC_POSTMASTER, FILE_LOCATIONS,
  			gettext_noop("Sets the server's \"hba\" configuration file."),
  			NULL,
***************
*** 2754,2760 **** static bool is_newvalue_equal(struct config_generic * record, const char *newval
  /*
   * Some infrastructure for checking malloc/strdup/realloc calls
   */
! static void *
  guc_malloc(int elevel, size_t size)
  {
  	void	   *data;
--- 2765,2771 ----
  /*
   * Some infrastructure for checking malloc/strdup/realloc calls
   */
! void *
  guc_malloc(int elevel, size_t size)
  {
  	void	   *data;
***************
*** 2767,2773 **** guc_malloc(int elevel, size_t size)
  	return data;
  }
  
! static void *
  guc_realloc(int elevel, void *old, size_t size)
  {
  	void	   *data;
--- 2778,2784 ----
  	return data;
  }
  
! void *
  guc_realloc(int elevel, void *old, size_t size)
  {
  	void	   *data;
***************
*** 3468,3478 **** SelectConfigFiles(const char *userDoption, const char *progname)
  	}
  
  	/*
! 	 * Set the ConfigFileName GUC variable to its final value, ensuring that
! 	 * it can't be overridden later.
  	 */
  	SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
  	free(fname);
  
  	/*
  	 * Now read the config file for the first time.
--- 3479,3491 ----
  	}
  
  	/*
! 	 * Set the ConfigFileName  and ConfigDir GUC variables to their final values,
! 	 * ensuring that they can't be overridden later.
  	 */
  	SetConfigOption("config_file", fname, PGC_POSTMASTER, PGC_S_OVERRIDE);
+ 	SetConfigOption("config_dir", configdir, PGC_POSTMASTER, PGC_S_OVERRIDE);
  	free(fname);
+ 	free(configdir);
  
  	/*
  	 * Now read the config file for the first time.
*** a/src/bin/initdb/initdb.c
--- b/src/bin/initdb/initdb.c
***************
*** 2483,2489 **** main(int argc, char *argv[])
  		"base",
  		"base/1",
  		"pg_tblspc",
! 		"pg_stat_tmp"
  	};
  
  	progname = get_progname(argv[0]);
--- 2483,2490 ----
  		"base",
  		"base/1",
  		"pg_tblspc",
! 		"pg_stat_tmp",
! 		"pg_config"
  	};
  
  	progname = get_progname(argv[0]);
*** a/src/include/utils/guc.h
--- b/src/include/utils/guc.h
***************
*** 177,182 **** extern int	log_temp_files;
--- 177,183 ----
  extern int	num_temp_buffers;
  
  extern char *ConfigFileName;
+ extern char *ConfigDir;
  extern char *HbaFileName;
  extern char *IdentFileName;
  extern char *external_pid_file;
***************
*** 295,300 **** extern void read_nondefault_variables(void);
--- 296,307 ----
  #endif
  
  /*
+  * Functions used for memory allocation in guc.
+  */
+ void *guc_malloc(int elevel, size_t size);
+ void *guc_realloc(int elevel, void *old, size_t size);
+ 
+ /*
   * The following functions are not in guc.c, but are declared here to avoid
   * having to include guc.h in some widely used headers that it really doesn't
   * belong in.