diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d1e628f..5df214e 100644
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** shared_buffers = 128MB
*** 74,96 ****
  
     <para>
      <indexterm>
-      <primary><literal>include</></primary>
-      <secondary>in configuration file</secondary>
-     </indexterm>
-     In addition to parameter settings, the <filename>postgresql.conf</>
-     file can contain <firstterm>include directives</>, which specify
-     another file to read and process as if it were inserted into the
-     configuration file at this point.  Include directives simply look like:
- <programlisting>
- include 'filename'
- </programlisting>
-     If the file name is not an absolute path, it is taken as relative to
-     the directory containing the referencing configuration file.
-     Inclusions can be nested.
-    </para>
- 
-    <para>
-     <indexterm>
       <primary>SIGHUP</primary>
      </indexterm>
      The configuration file is reread whenever the main server process receives a
--- 74,79 ----
*************** SET ENABLE_SEQSCAN TO OFF;
*** 178,184 ****
      any desired selection condition. It also contains more information about
      what values are allowed for the parameters.
     </para>
!   </sect1>
  
     <sect1 id="runtime-config-file-locations">
      <title>File Locations</title>
--- 161,273 ----
      any desired selection condition. It also contains more information about
      what values are allowed for the parameters.
     </para>
! 
!      <sect2 id="config-includes">
!       <title>Configuration file includes</title>
!        <para>
!        <indexterm>
!         <primary><literal>include</></primary>
!         <secondary>in configuration file</secondary>
!        </indexterm>
!        In addition to parameter settings, the <filename>postgresql.conf</>
!        file can contain <firstterm>include directives</>, which specify
!        another file to read and process as if it were inserted into the
!        configuration file at this point.  Include directives simply look like:
! <programlisting>
! include 'filename'
! </programlisting>
!        If the file name is not an absolute path, it is taken as relative to
!        the directory containing the referencing configuration file.
!        All types of inclusion directives can be nested.
!       </para>
! 
!       <para>
!        <indexterm>
!         <primary><literal>include_dir</></primary>
!         <secondary>in configuration file</secondary>
!        </indexterm>
!        The <filename>postgresql.conf</> file can also contain 
!        <firstterm>include_dir directives</>, which specify an entire directory
!        of configuration files to include.  It is used similarly:
! <programlisting>
! include_dir 'directory'
! </programlisting>
!        Non-absolute directory names follow the same rules as single file include
!        directives:  they are relative to the directory containing the referencing
!        configuration file.  Within that directory, only files whose names end
!        with the suffix <literal>.conf</literal> will be included.  File names
!        that start with the <literal>.</literal> character are also excluded,
!        to prevent mistakes as they are hidden on some platforms.  Multiple files
!        within an include directory are ordered by an alphanumeric sorting, so
!        that ones beginning with numbers are considered before those starting
!        with letters.
!       </para>
! 
!       <para>
!       Include files or directories can be used to logically separate portions
!       of the database configuration, rather than having a single large
!       <filename>postgresql.conf</> file.  Consider a company that has two
!       database servers, each with a different amount of memory.  There are likely
!       elements of the configuration both will share, for things such as logging.
!       But memory-related parameters on the server will vary between the two.  And
!       there might be server specific customizations too.  One way to manage this
!       situation is to break the custom configuration changes for your site into
!       three files.  You could add this to the end of your
!    <filename>postgresql.conf</> file to include them:
! <programlisting>
! include 'shared.conf'
! include 'memory.conf'
! include 'server.conf'
! </programlisting>
!       All systems would have the same <filename>shared.conf</>.  Each server
!       with a particular amount of memory could share the same
!       <filename>memory.conf</>; you might have one for all servers with 8GB of RAM,
!       another for those having 16GB.  And finally <filename>server.conf</> could
!       have truly server-specific configuration information in it.
!       </para>
! 
!       <para>
!       Another possibility for this same sort of organization is to create a
!       configuration file directory and put this information into files there.
!       Other programs such as <productname>Apache</productname> use a
!       <filename>conf.d</> directory for this purpose.  And using numbered names
!       to enforce an ordering is common in UNIX startup script directories named 
!       like <filename>/etc/rcN.d</filename>, where <literal>N</> gives the
!       associated system runlevel.  Both of these ideas might be combined by
!       adding a <filename>conf.d</> directory where the
!       <filename>postgresql.conf</> file is at, then referencing it at the end:
! <programlisting>
! include_dir 'conf.d'
! </programlisting>
!       Then you could name the files in the <filename>conf.d</> directory like this:
! <programlisting>
! include '00shared.conf'
! include '01memory.conf'
! include '02server.conf'
! </programlisting>
!       This shows a clear order in which these files will be loaded.  This is
!       important because only the last setting encountered when the server is
!       reading its configuration will be used.  Something set in
!       <filename>conf.d/02server.conf</> in this example would override a value
!       set in <filename>conf.d/01memory.conf</>.
!    </para>
! 
!    <para>
!       You might instead use this configuration directory approach while naming
!       these files more descriptively:
! <programlisting>
! 00shared.conf
! 01memory-8GB.conf
! 02server-foo.conf
! </programlisting>
!       This sort of arrangement gives a unique name for each configuration file
!       variation.  This can help eliminate ambiguity when several servers have
!       their configurations all stored in one place, such as in a version
!       control repository.  (Storing database configuration files under version
!       control is another good practice to consider).
!       </para>
!      </sect2>
!    </sect1>
  
     <sect1 id="runtime-config-file-locations">
      <title>File Locations</title>
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
index a094c7a..ae33fdd 100644
*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
*************** ProcessConfigFile(GucContext context)
*** 355,360 ****
--- 355,396 ----
  }
  
  /*
+  * Given a configuration file or directory location that may be a relative
+  * path, return an absolute one.  We consider the location to be relative to
+  * the directory holding the calling file.
+  */
+ static char *
+ AbsoluteConfigLocation(const char *location,
+ 				const char *calling_file)
+ {
+ 	char		abs_path[MAXPGPATH];
+ 
+ 	if (is_absolute_path(location))
+ 	{
+ 		return pstrdup(location);
+ 	}
+ 	else
+ 	{
+ 		if (calling_file != NULL)
+ 		{
+ 			strlcpy(abs_path, calling_file, sizeof(abs_path));
+ 			get_parent_directory(abs_path);
+ 			join_path_components(abs_path, abs_path, location);
+ 			canonicalize_path(abs_path);
+ 		}
+ 		else
+ 		{
+ 			/*
+ 			 * calling_file is NULL, we make an absolute path from $PGDATA
+ 			 */
+ 			join_path_components(abs_path, data_directory, location);
+ 			canonicalize_path(abs_path);
+ 		}
+ 		return pstrdup(abs_path);
+ 	}
+ }
+ 
+ /*
   * Read and parse a single configuration file.  This function recurses
   * to handle "include" directives.
   *
*************** ParseConfigFile(const char *config_file,
*** 370,376 ****
  {
  	bool		OK = true;
  	FILE	   *fp;
- 	char		abs_path[MAXPGPATH];
  
  	/*
  	 * Reject too-deep include nesting depth.  This is just a safety check
--- 406,411 ----
*************** ParseConfigFile(const char *config_file,
*** 386,416 ****
  		return false;
  	}
  
! 	/*
! 	 * If config_file is a relative path, convert to absolute.  We consider
! 	 * it to be relative to the directory holding the calling file.
! 	 */
! 	if (!is_absolute_path(config_file))
! 	{
! 		if (calling_file != NULL)
! 		{
! 			strlcpy(abs_path, calling_file, sizeof(abs_path));
! 			get_parent_directory(abs_path);
! 			join_path_components(abs_path, abs_path, config_file);
! 			canonicalize_path(abs_path);
! 			config_file = abs_path;
! 		}
! 		else
! 		{
! 			/*
! 			 * calling_file is NULL, we make an absolute path from $PGDATA
! 			 */
! 			join_path_components(abs_path, data_directory, config_file);
! 			canonicalize_path(abs_path);
! 			config_file = abs_path;
! 		}
! 	}
! 
  	fp = AllocateFile(config_file, "r");
  	if (!fp)
  	{
--- 421,427 ----
  		return false;
  	}
  
! 	config_file=AbsoluteConfigLocation(config_file,calling_file);
  	fp = AllocateFile(config_file, "r");
  	if (!fp)
  	{
*************** ParseConfigFp(FILE *fp, const char *conf
*** 512,518 ****
  		}
  
  		/* OK, process the option name and value */
! 		if (guc_name_compare(opt_name, "include") == 0)
  		{
  			/*
  			 * An include directive isn't a variable and should be processed
--- 523,546 ----
  		}
  
  		/* OK, process the option name and value */
! 		if (guc_name_compare(opt_name, "include_dir") == 0)
! 		{
! 			/*
! 			 * An include_dir directive isn't a variable and should be processed
! 			 * immediately.
! 			 */
! 			unsigned int save_ConfigFileLineno = ConfigFileLineno;
! 
! 			if (!ParseConfigDirectory(opt_value, config_file,
! 								 depth + 1, elevel,
! 								 head_p, tail_p))
! 				OK = false;
! 			yy_switch_to_buffer(lex_buffer);
! 			ConfigFileLineno = save_ConfigFileLineno;
! 			pfree(opt_name);
! 			pfree(opt_value);
! 		}
! 		else if (guc_name_compare(opt_name, "include") == 0)
  		{
  			/*
  			 * An include directive isn't a variable and should be processed
*************** ParseConfigFp(FILE *fp, const char *conf
*** 599,604 ****
--- 627,747 ----
  	return OK;
  }
  
+ /*
+  * String comparison code for use by qsort.  Borrowed from
+  * src/backend/tsearch/ts_utils.c
+  */
+ 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
+  */
+ bool
+ ParseConfigDirectory(const char *includedir,
+ 				const char *calling_file,
+ 				int depth, int elevel,
+ 				ConfigVariable **head_p,
+ 				ConfigVariable **tail_p)
+ {
+ 	char *directory;
+ 	DIR *d;
+ 	struct dirent *de;
+ 	char **filenames = NULL;
+ 	int num_filenames = 0;
+ 	int size_filenames = 0;
+ 	bool status;
+ 
+ 	directory=AbsoluteConfigLocation(includedir,calling_file);
+ 	d = AllocateDir(directory);
+ 	if (d == NULL)
+ 	{
+ 		ereport(elevel,
+ 				(errcode_for_file_access(),
+ 				 errmsg("could not open configuration directory \"%s\": %m",
+ 						directory)));
+ 		return false;
+ 
+ 	}
+ 
+ 	/*
+ 	 * 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".  Explicitly reject
+ 		 * files starting with ".".  This excludes things like "." and "..", 
+ 		 * as well as typical hidden files, backup files, and editor debris.
+ 		 */
+ 		if (strlen(de->d_name) < 6)
+ 			continue;
+ 		if (strncmp(de->d_name, ".", 1) == 0)
+ 			continue;
+ 		if (strcmp(de->d_name + strlen(de->d_name) - 5, ".conf") != 0)
+ 			continue;
+ 
+ 		join_path_components(filename, directory, de->d_name);
+ 		if (stat(filename, &st) == 0)
+ 		{
+ 			if (!S_ISDIR(st.st_mode))
+ 			{
+ 				/* Add file to list, increasing its size in blocks of 32 */
+ 				if (num_filenames == size_filenames)
+ 				{
+ 					size_filenames += 32;
+ 					if (num_filenames == 0)
+ 						/* Must initialize, repalloc won't take NULL input */
+ 						filenames = palloc(size_filenames * sizeof(char *));
+ 					else
+ 						filenames = repalloc(filenames, size_filenames * sizeof(char *));
+ 				}
+ 				filenames[num_filenames] = pstrdup(filename);
+ 				num_filenames++;
+ 			}
+ 		else
+ 			/* 
+ 			 * stat does not care about permissions, so the most likely reason
+ 			 * a file can't be accessed now is if it was removed between the
+ 			 * directory listing and now.
+ 			 */
+ 			{
+ 			ereport(elevel,
+ 					(errcode_for_file_access(),
+ 					 errmsg("configuration file \"%s\" can no longer be accessed: %m",
+ 							filename)));
+ 			return false;
+ 			}
+ 		}
+ 	}
+ 
+ 	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, elevel,head_p, tail_p))
+ 			{
+ 				status = false;
+ 				goto cleanup;
+ 			}
+ 		}
+ 	}
+ 	status = true;
+ 
+ cleanup:
+ 	FreeDir(d);
+ 	return status;
+ }
  
  /*
   * Free a list of ConfigVariables, including the names and the values
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
index 8e3057a..2005ce9 100644
*** a/src/include/utils/guc.h
--- b/src/include/utils/guc.h
*************** extern bool ParseConfigFile(const char *
*** 116,121 ****
--- 116,126 ----
  extern bool ParseConfigFp(FILE *fp, const char *config_file,
  			  int depth, int elevel,
  			  ConfigVariable **head_p, ConfigVariable **tail_p);
+ extern bool ParseConfigDirectory(const char *includedir,
+ 			  const char *calling_file,
+ 			  int depth, int elevel,
+ 			  ConfigVariable **head_p,
+ 			  ConfigVariable **tail_p);
  extern void FreeConfigVariables(ConfigVariable *list);
  
  /*
