diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 706ccba56c871217ec9160e877d949e3dfcfb3c7..b35fa9c1ccf6f55162594a96ced1d6d49ea43c50 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.73 2006/08/08 19:15:07 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.74 2006/08/15 18:26:58 tgl Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -949,10 +949,10 @@ SET ENABLE_SEQSCAN TO OFF;
       </listitem>
      </varlistentry>
      
-     <varlistentry id="guc-preload-libraries" xreflabel="preload_libraries">
-      <term><varname>preload_libraries</varname> (<type>string</type>)</term>
+     <varlistentry id="guc-shared-preload-libraries" xreflabel="shared_preload_libraries">
+      <term><varname>shared_preload_libraries</varname> (<type>string</type>)</term>
       <indexterm>
-       <primary><varname>preload_libraries</> configuration parameter</primary>
+       <primary><varname>shared_preload_libraries</> configuration parameter</primary>
       </indexterm>
       <listitem>
        <para>
@@ -963,6 +963,7 @@ SET ENABLE_SEQSCAN TO OFF;
         <literal>mylib.so</> (or on some platforms,
         <literal>mylib.sl</>) to be preloaded from the installation's
         standard library directory.
+        This parameter can only be set at server start.
        </para>
 
        <para>
@@ -3642,6 +3643,60 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
        </para>
       </listitem>
      </varlistentry>
+     
+     <varlistentry id="guc-local-preload-libraries" xreflabel="local_preload_libraries">
+      <term><varname>local_preload_libraries</varname> (<type>string</type>)</term>
+      <indexterm>
+       <primary><varname>local_preload_libraries</> configuration parameter</primary>
+      </indexterm>
+      <indexterm>
+       <primary><filename>$libdir/plugins</></primary>
+      </indexterm>
+      <listitem>
+       <para>
+        This variable specifies one or more shared libraries that are
+        to be preloaded at connection start.  If more than one library
+        is to be loaded, separate their names with commas.
+        This parameter cannot be changed after the start of a particular
+        session.
+       </para>
+
+       <para>
+        Because this is not a superuser-only option, the libraries
+        that can be loaded are restricted to those appearing in the
+        <filename>plugins</> subdirectory of the installation's
+        standard library directory.  (It is the database administrator's
+        responsibility to ensure that only <quote>safe</> libraries
+        are installed there.)  Entries in <varname>local_preload_libraries</>
+        can specify this directory explicitly, for example
+        <literal>$libdir/plugins/mylib</literal>, or just specify
+        the library name &mdash; <literal>mylib</literal> would have
+        the same effect as <literal>$libdir/plugins/mylib</literal>.
+       </para>
+
+       <para>
+        There is no performance advantage to loading a library at session
+        start rather than when it is first used.  Rather, the intent of
+        this feature is to allow debugging or performance-measurement
+        libraries to be loaded into specific sessions without an explicit
+        <command>LOAD</> command being given.  For example, debugging could
+        be enabled for all sessions under a given user name by setting
+        this parameter with <command>ALTER USER SET</>.
+       </para>
+
+       <para>
+        If a specified library is not found,
+        the connection attempt will fail.
+       </para>
+
+       <para>
+        Every  PostgreSQL-supported library has a <quote>magic
+        block</> that is checked to guarantee compatibility.  
+        For this reason, non-PostgreSQL libraries cannot be 
+        loaded in this way.
+       </para>
+      </listitem>
+     </varlistentry>
 
      </variablelist>
     </sect2>
diff --git a/doc/src/sgml/ref/load.sgml b/doc/src/sgml/ref/load.sgml
index b29dfd4ed4197ce81b7cefd41735068853032796..6a6e9d9098e86024831d8bba4529d8f215aa6acc 100644
--- a/doc/src/sgml/ref/load.sgml
+++ b/doc/src/sgml/ref/load.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/load.sgml,v 1.21 2005/01/04 00:39:53 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/load.sgml,v 1.22 2006/08/15 18:26:58 tgl Exp $
 -->
 
 <refentry id="SQL-LOAD">
@@ -44,6 +44,19 @@ LOAD '<replaceable class="PARAMETER">filename</replaceable>'
    shared library file name extension.  See <xref linkend="xfunc-c"> for
    more information on this topic.
   </para>
+
+  <indexterm>
+   <primary><filename>$libdir/plugins</></primary>
+  </indexterm>
+
+  <para>
+   Non-superusers may only apply <command>LOAD</> to library files
+   located in <filename>$libdir/plugins/</> &mdash; the specified
+   <replaceable class="PARAMETER">filename</replaceable> must begin
+   with exactly that string.  (It is the database administrator's
+   responsibility to ensure that only <quote>safe</> libraries
+   are installed there.)
+  </para>
  </refsect1>
 
  <refsect1 id="sql-load-compat">
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eefa974dee9f38a5d959e8ed40c6a8d2b9acb692..130415c74cb7e8b6dd8b42debdb88f068734d0a7 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.498 2006/08/08 19:15:07 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.499 2006/08/15 18:26:58 tgl Exp $
  *
  * NOTES
  *
@@ -709,7 +709,7 @@ PostmasterMain(int argc, char *argv[])
 	/*
 	 * process any libraries that should be preloaded at postmaster start
 	 */
-	process_preload_libraries();
+	process_shared_preload_libraries();
 
 	/*
 	 * Remove old temporary files.	At this point there can be no other
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 9cb61c16cb578c9efd643be36b8a9782557ce476..af9578b15ac32152cf30e7723ff26ae835b9f4b2 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.498 2006/08/13 22:18:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.499 2006/08/15 18:26:58 tgl Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -3000,6 +3000,12 @@ PostgresMain(int argc, char *argv[], const char *username)
 	if (IsUnderPostmaster && Log_disconnections)
 		on_proc_exit(log_disconnections, 0);
 
+	/*
+	 * process any libraries that should be preloaded at backend start
+	 * (this likewise can't be done until GUC settings are complete)
+	 */
+	process_local_preload_libraries();
+
 	/*
 	 * Send this backend's cancellation info to the frontend.
 	 */
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 7d6941ddcef93aa57f389711ae122666e8a63a09..ce86a90ba3f570e5f562851bead9d97486447e16 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.265 2006/08/12 20:05:56 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.266 2006/08/15 18:26:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -886,12 +886,9 @@ ProcessUtility(Node *parsetree,
 			{
 				LoadStmt   *stmt = (LoadStmt *) parsetree;
 
-				if (!superuser())
-					ereport(ERROR,
-							(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-							 errmsg("must be superuser to do LOAD")));
 				closeAllVfds(); /* probably not necessary... */
-				load_file(stmt->filename);
+				/* Allowed names are restricted if you're not superuser */
+				load_file(stmt->filename, !superuser());
 			}
 			break;
 
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index fd2c54c2118ae1a33519f6d49b38d0f4df54fa34..3c2b34e3e63fa0656be478a8f69ddd92a51dd8f1 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.87 2006/08/08 19:15:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.88 2006/08/15 18:26:58 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,12 +23,20 @@
 #endif
 #include "miscadmin.h"
 #include "utils/dynamic_loader.h"
+#include "utils/hsearch.h"
 
 
 /* signatures for PostgreSQL-specific library init/fini functions */
 typedef void (*PG_init_t)(void);
 typedef void (*PG_fini_t)(void);
 
+/* hashtable entry for rendezvous variables */
+typedef struct
+{ 
+	char	varName[NAMEDATALEN];	/* hash key (must be first) */
+	void   *varValue;
+} rendezvousHashEntry;
+
 /*
  * List of dynamically loaded files (kept in malloc'd memory).
  */
@@ -62,10 +70,13 @@ static DynamicFileList *file_tail = NULL;
 
 char	   *Dynamic_library_path;
 
+static void *internal_load_library(const char *libname);
+static void internal_unload_library(const char *libname);
 static bool file_exists(const char *name);
-static char *find_in_dynamic_libpath(const char *basename);
 static char *expand_dynamic_library_name(const char *name);
+static void check_restricted_library_name(const char *name);
 static char *substitute_libpath_macro(const char *name);
+static char *find_in_dynamic_libpath(const char *basename);
 
 /* Magic structure that module needs to match to be accepted */
 static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
@@ -73,7 +84,7 @@ static const Pg_magic_struct magic_data = PG_MODULE_MAGIC_DATA;
 
 /*
  * Load the specified dynamic-link library file, and look for a function
- * named funcname in it.  (funcname can be NULL to just load the file.)
+ * named funcname in it.
  *
  * If the function is not found, we raise an error if signalNotFound is true,
  * else return (PGFunction) NULL.  Note that errors in loading the library
@@ -88,37 +99,107 @@ PGFunction
 load_external_function(char *filename, char *funcname,
 					   bool signalNotFound, void **filehandle)
 {
-	DynamicFileList *file_scanner;
+	char	   *fullname;
+	void	   *lib_handle;
 	PGFunction	retval;
+
+	/* Expand the possibly-abbreviated filename to an exact path name */
+	fullname = expand_dynamic_library_name(filename);
+
+	/* Load the shared library, unless we already did */
+	lib_handle = internal_load_library(fullname);
+
+	/* Return handle if caller wants it */
+	if (filehandle)
+		*filehandle = lib_handle;
+
+	/* Look up the function within the library */
+	retval = pg_dlsym(lib_handle, funcname);
+
+	if (retval == NULL && signalNotFound)
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_FUNCTION),
+				 errmsg("could not find function \"%s\" in file \"%s\"",
+						funcname, fullname)));
+
+	pfree(fullname);
+	return retval;
+}
+
+/*
+ * This function loads a shlib file without looking up any particular
+ * function in it.	If the same shlib has previously been loaded,
+ * unload and reload it.
+ *
+ * When 'restrict' is true, only libraries in the presumed-secure
+ * directory $libdir/plugins may be referenced.
+ */
+void
+load_file(const char *filename, bool restrict)
+{
+	char	   *fullname;
+
+	/* Apply security restriction if requested */
+	if (restrict)
+		check_restricted_library_name(filename);
+
+	/* Expand the possibly-abbreviated filename to an exact path name */
+	fullname = expand_dynamic_library_name(filename);
+
+	/* Unload the library if currently loaded */
+	internal_unload_library(fullname);
+
+	/* Load the shared library */
+	(void) internal_load_library(fullname);
+
+	pfree(fullname);
+}
+
+/*
+ * Lookup a function whose library file is already loaded.
+ * Return (PGFunction) NULL if not found.
+ */
+PGFunction
+lookup_external_function(void *filehandle, char *funcname)
+{
+	return pg_dlsym(filehandle, funcname);
+}
+
+
+/*
+ * Load the specified dynamic-link library file, unless it already is
+ * loaded.  Return the pg_dl* handle for the file.
+ *
+ * Note: libname is expected to be an exact name for the library file.
+ */
+static void *
+internal_load_library(const char *libname)
+{
+	DynamicFileList *file_scanner;
 	PGModuleMagicFunction magic_func;
 	char	   *load_error;
 	struct stat stat_buf;
-	char	   *fullname;
 	PG_init_t	PG_init;
 
-	fullname = expand_dynamic_library_name(filename);
-	if (!fullname)
-		fullname = pstrdup(filename);
-	/* at this point fullname is always freshly palloc'd */
-
 	/*
 	 * Scan the list of loaded FILES to see if the file has been loaded.
 	 */
 	for (file_scanner = file_list;
 		 file_scanner != NULL &&
-		 strcmp(fullname, file_scanner->filename) != 0;
+		 strcmp(libname, file_scanner->filename) != 0;
 		 file_scanner = file_scanner->next)
 		;
+
 	if (file_scanner == NULL)
 	{
 		/*
 		 * Check for same files - different paths (ie, symlink or link)
 		 */
-		if (stat(fullname, &stat_buf) == -1)
+		if (stat(libname, &stat_buf) == -1)
 			ereport(ERROR,
 					(errcode_for_file_access(),
 					 errmsg("could not access file \"%s\": %m",
-							fullname)));
+							libname)));
 
 		for (file_scanner = file_list;
 			 file_scanner != NULL &&
@@ -133,21 +214,21 @@ load_external_function(char *filename, char *funcname,
 		 * File not loaded yet.
 		 */
 		file_scanner = (DynamicFileList *)
-			malloc(sizeof(DynamicFileList) + strlen(fullname));
+			malloc(sizeof(DynamicFileList) + strlen(libname));
 		if (file_scanner == NULL)
 			ereport(ERROR,
 					(errcode(ERRCODE_OUT_OF_MEMORY),
 					 errmsg("out of memory")));
 
 		MemSet(file_scanner, 0, sizeof(DynamicFileList));
-		strcpy(file_scanner->filename, fullname);
+		strcpy(file_scanner->filename, libname);
 		file_scanner->device = stat_buf.st_dev;
 #ifndef WIN32
 		file_scanner->inode = stat_buf.st_ino;
 #endif
 		file_scanner->next = NULL;
 
-		file_scanner->handle = pg_dlopen(fullname);
+		file_scanner->handle = pg_dlopen(file_scanner->filename);
 		if (file_scanner->handle == NULL)
 		{
 			load_error = (char *) pg_dlerror();
@@ -156,7 +237,7 @@ load_external_function(char *filename, char *funcname,
 			ereport(ERROR,
 					(errcode_for_file_access(),
 					 errmsg("could not load library \"%s\": %s",
-							fullname, load_error)));
+							libname, load_error)));
 		}
 
 		/* Check the magic function to determine compatibility */
@@ -184,7 +265,7 @@ load_external_function(char *filename, char *funcname,
 				if (module_magic_data.version != magic_data.version)
 					ereport(ERROR,
 							(errmsg("incompatible library \"%s\": version mismatch",
-									fullname),
+									libname),
 							 errdetail("Server is version %d.%d, library is version %d.%d.",
 									   magic_data.version/100,
 									   magic_data.version % 100,
@@ -192,7 +273,7 @@ load_external_function(char *filename, char *funcname,
 									   module_magic_data.version % 100)));
 				ereport(ERROR,
 						(errmsg("incompatible library \"%s\": magic block mismatch",
-								fullname)));
+								libname)));
 			}
 		}
 		else
@@ -203,7 +284,7 @@ load_external_function(char *filename, char *funcname,
 			/* complain */
 			ereport(ERROR,
 					(errmsg("incompatible library \"%s\": missing magic block",
-							fullname),
+							libname),
 					 errhint("Extension libraries are now required to use the PG_MODULE_MAGIC macro.")));
 		}
 
@@ -222,77 +303,48 @@ load_external_function(char *filename, char *funcname,
 		file_tail = file_scanner;
 	}
 
-	/* Return handle if caller wants it. */
-	if (filehandle)
-		*filehandle = file_scanner->handle;
-
-	/*
-	 * If funcname is NULL, we only wanted to load the file.
-	 */
-	if (funcname == NULL)
-	{
-		pfree(fullname);
-		return NULL;
-	}
-
-	retval = pg_dlsym(file_scanner->handle, funcname);
-
-	if (retval == NULL && signalNotFound)
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_FUNCTION),
-				 errmsg("could not find function \"%s\" in file \"%s\"",
-						funcname, fullname)));
-
-	pfree(fullname);
-	return retval;
+	return file_scanner->handle;
 }
 
 /*
- * This function loads a shlib file without looking up any particular
- * function in it.	If the same shlib has previously been loaded,
- * unload and reload it.
+ * Unload the specified dynamic-link library file, if it is loaded.
+ *
+ * Note: libname is expected to be an exact name for the library file.
  */
-void
-load_file(char *filename)
+static void
+internal_unload_library(const char *libname)
 {
 	DynamicFileList *file_scanner,
 			   *prv,
 			   *nxt;
 	struct stat stat_buf;
-	char	   *fullname;
 	PG_fini_t	PG_fini;
 
-	fullname = expand_dynamic_library_name(filename);
-	if (!fullname)
-		fullname = pstrdup(filename);
-	/* at this point fullname is always freshly palloc'd */
-
 	/*
 	 * We need to do stat() in order to determine whether this is the same
 	 * file as a previously loaded file; it's also handy so as to give a good
 	 * error message if bogus file name given.
 	 */
-	if (stat(fullname, &stat_buf) == -1)
+	if (stat(libname, &stat_buf) == -1)
 		ereport(ERROR,
 				(errcode_for_file_access(),
-				 errmsg("could not access file \"%s\": %m", fullname)));
+				 errmsg("could not access file \"%s\": %m", libname)));
 
 	/*
 	 * We have to zap all entries in the list that match on either filename or
-	 * inode, else load_external_function() won't do anything.
+	 * inode, else internal_load_library() will still think it's present.
 	 */
 	prv = NULL;
 	for (file_scanner = file_list; file_scanner != NULL; file_scanner = nxt)
 	{
 		nxt = file_scanner->next;
-		if (strcmp(fullname, file_scanner->filename) == 0 ||
+		if (strcmp(libname, file_scanner->filename) == 0 ||
 			SAME_INODE(stat_buf, *file_scanner))
 		{
 			if (prv)
 				prv->next = nxt;
 			else
 				file_list = nxt;
-			clear_external_function_hash(file_scanner->handle);
 
 			/*
 			 * If the library has a _PG_fini() function, call it.
@@ -301,6 +353,7 @@ load_file(char *filename)
 			if (PG_fini)
 				(*PG_fini)();
 
+			clear_external_function_hash(file_scanner->handle);
 			pg_dlclose(file_scanner->handle);
 			free((char *) file_scanner);
 			/* prv does not change */
@@ -308,23 +361,8 @@ load_file(char *filename)
 		else
 			prv = file_scanner;
 	}
-
-	load_external_function(fullname, NULL, false, NULL);
-
-	pfree(fullname);
-}
-
-/*
- * Lookup a function whose library file is already loaded.
- * Return (PGFunction) NULL if not found.
- */
-PGFunction
-lookup_external_function(void *filehandle, char *funcname)
-{
-	return pg_dlsym(filehandle, funcname);
 }
 
-
 static bool
 file_exists(const char *name)
 {
@@ -353,9 +391,9 @@ file_exists(const char *name)
  * the name.  Else (no slash) try to expand using search path (see
  * find_in_dynamic_libpath below); if that works, return the fully
  * expanded file name.	If the previous failed, append DLSUFFIX and
- * try again.  If all fails, return NULL.
+ * try again.  If all fails, just return the original name.
  *
- * A non-NULL result will always be freshly palloc'd.
+ * The result will always be freshly palloc'd.
  */
 static char *
 expand_dynamic_library_name(const char *name)
@@ -402,9 +440,28 @@ expand_dynamic_library_name(const char *name)
 		pfree(full);
 	}
 
-	return NULL;
+	/*
+	 * If we can't find the file, just return the string as-is.
+	 * The ensuing load attempt will fail and report a suitable message.
+	 */
+	return pstrdup(name);
 }
 
+/*
+ * Check a restricted library name.  It must begin with "$libdir/plugins/"
+ * and there must not be any directory separators after that (this is
+ * sufficient to prevent ".." style attacks).
+ */
+static void
+check_restricted_library_name(const char *name)
+{
+	if (strncmp(name, "$libdir/plugins/", 16) != 0 ||
+		first_dir_separator(name + 16) != NULL)
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("access to library \"%s\" is not allowed",
+						name)));
+}
 
 /*
  * Substitute for any macros appearing in the given string.
@@ -418,6 +475,7 @@ substitute_libpath_macro(const char *name)
 
 	AssertArg(name != NULL);
 
+	/* Currently, we only recognize $libdir at the start of the string */
 	if (name[0] != '$')
 		return pstrdup(name);
 
@@ -428,7 +486,8 @@ substitute_libpath_macro(const char *name)
 		strncmp(name, "$libdir", strlen("$libdir")) != 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_NAME),
-			errmsg("invalid macro name in dynamic library path: %s", name)));
+				 errmsg("invalid macro name in dynamic library path: %s",
+						name)));
 
 	ret = palloc(strlen(pkglib_path) + strlen(sep_ptr) + 1);
 
@@ -513,3 +572,58 @@ find_in_dynamic_libpath(const char *basename)
 
 	return NULL;
 }
+
+
+/*
+ * Find (or create) a rendezvous variable that one dynamically 
+ * loaded library can use to meet up with another.
+ *
+ * On the first call of this function for a particular varName,
+ * a "rendezvous variable" is created with the given name.
+ * The value of the variable is a void pointer (initially set to NULL).
+ * Subsequent calls with the same varName just return the address of
+ * the existing variable.  Once created, a rendezvous variable lasts
+ * for the life of the process.
+ *
+ * Dynamically loaded libraries can use rendezvous variables
+ * to find each other and share information: they just need to agree
+ * on the variable name and the data it will point to.
+ */
+void **
+find_rendezvous_variable(const char *varName)
+{
+	static HTAB         *rendezvousHash = NULL;
+
+	char			     key[NAMEDATALEN];
+	rendezvousHashEntry *hentry;
+	bool				 found;
+
+	/* Create a hashtable if we haven't already done so in this process */
+	if (rendezvousHash == NULL)
+	{
+		HASHCTL ctl;
+
+		MemSet(&ctl, 0, sizeof(ctl));
+		ctl.keysize    = NAMEDATALEN;
+		ctl.entrysize  = sizeof(rendezvousHashEntry);
+		rendezvousHash = hash_create("Rendezvous variable hash",
+									 16,
+									 &ctl,
+									 HASH_ELEM);
+	}
+
+	/* Turn the varName into a fixed-size string */
+	StrNCpy(key, varName, sizeof(key));
+
+	/* Find or create the hashtable entry for this varName */
+	hentry = (rendezvousHashEntry *) hash_search(rendezvousHash,
+												 key,
+												 HASH_ENTER,
+												 &found);
+
+	/* Initialize to NULL if first time */
+	if (!found)
+		hentry->varValue = NULL;
+
+	return &hentry->varValue;
+}
diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c
index b238aaec5ce7ad90295e5e128abc4f11d8b923b4..3b2cb2f9c89554fd08a69a34e4e8f40871f8b3b1 100644
--- a/src/backend/utils/init/miscinit.c
+++ b/src/backend/utils/init/miscinit.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.156 2006/08/08 19:15:08 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.157 2006/08/15 18:26:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1097,24 +1097,31 @@ ValidatePgVersion(const char *path)
  *-------------------------------------------------------------------------
  */
 
-/* GUC variable: list of library names to be preloaded */
-char	   *preload_libraries_string = NULL;
+/* 
+ * GUC variables: lists of library names to be preloaded at postmaster
+ * start and at backend start
+ */
+char	   *shared_preload_libraries_string = NULL;
+char	   *local_preload_libraries_string = NULL;
 
 /*
- * process any libraries that should be preloaded at postmaster start
+ * load the shared libraries listed in 'libraries'
+ *
+ * 'gucname': name of GUC variable, for error reports
+ * 'restrict': if true, force libraries to be in $libdir/plugins/
  */
-void
-process_preload_libraries(void)
+static void
+load_libraries(const char *libraries, const char *gucname, bool restrict)
 {
 	char	   *rawstring;
 	List	   *elemlist;
 	ListCell   *l;
 
-	if (preload_libraries_string == NULL)
-		return;
+	if (libraries == NULL || libraries[0] == '\0')
+		return;					/* nothing to do */
 
 	/* Need a modifiable copy of string */
-	rawstring = pstrdup(preload_libraries_string);
+	rawstring = pstrdup(libraries);
 
 	/* Parse string into list of identifiers */
 	if (!SplitIdentifierString(rawstring, ',', &elemlist))
@@ -1124,7 +1131,8 @@ process_preload_libraries(void)
 		list_free(elemlist);
 		ereport(LOG,
 				(errcode(ERRCODE_SYNTAX_ERROR),
-		 errmsg("invalid list syntax for parameter \"preload_libraries\"")));
+				 errmsg("invalid list syntax in parameter \"%s\"",
+						gucname)));
 		return;
 	}
 
@@ -1135,12 +1143,45 @@ process_preload_libraries(void)
 
 		filename = pstrdup(tok);
 		canonicalize_path(filename);
-		(void) load_external_function(filename, NULL, true, NULL);
+		/* If restricting, insert $libdir/plugins if not mentioned already */
+		if (restrict && first_dir_separator(filename) == NULL)
+		{
+			char   *expanded;
+
+			expanded = palloc(strlen("$libdir/plugins/") + strlen(filename) + 1);
+			strcpy(expanded, "$libdir/plugins/");
+			strcat(expanded, filename);
+			pfree(filename);
+			filename = expanded;
+		}
+		load_file(filename, restrict);
 		ereport(LOG,
-				(errmsg("preloaded library \"%s\"", filename)));
+				(errmsg("loaded library \"%s\"", filename)));
 		pfree(filename);
 	}
 
 	pfree(rawstring);
 	list_free(elemlist);
 }
+
+/*
+ * process any libraries that should be preloaded at postmaster start
+ */
+void
+process_shared_preload_libraries(void)
+{
+	load_libraries(shared_preload_libraries_string,
+				   "shared_preload_libraries",
+				   false);
+}
+
+/*
+ * process any libraries that should be preloaded at backend start
+ */
+void
+process_local_preload_libraries(void)
+{
+	load_libraries(local_preload_libraries_string,
+				   "local_preload_libraries",
+				   true);
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0e16035ef6a14629c8745b7a46e7e9c15530e800..69c67471fc0d1ef19ae25d1b3cdcb5156ba8471c 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.341 2006/08/14 02:27:26 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.342 2006/08/15 18:26:59 tgl Exp $
  *
  *--------------------------------------------------------------------
  */
@@ -1964,12 +1964,22 @@ static struct config_string ConfigureNamesString[] =
 	},
 
 	{
-		{"preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
+		{"shared_preload_libraries", PGC_POSTMASTER, RESOURCES_KERNEL,
 			gettext_noop("Lists shared libraries to preload into server."),
 			NULL,
 			GUC_LIST_INPUT | GUC_LIST_QUOTE | GUC_SUPERUSER_ONLY
 		},
-		&preload_libraries_string,
+		&shared_preload_libraries_string,
+		"", NULL, NULL
+	},
+
+	{
+		{"local_preload_libraries", PGC_BACKEND, CLIENT_CONN_OTHER,
+			gettext_noop("Lists shared libraries to preload into each backend."),
+			NULL,
+			GUC_LIST_INPUT | GUC_LIST_QUOTE
+		},
+		&local_preload_libraries_string,
 		"", NULL, NULL
 	},
 
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index edecda549ee894975d1daaa6465ace403e7b4287..b0c6cdf7634d12f4281beccfc60e253181277346 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -120,7 +120,7 @@
 
 #max_files_per_process = 1000		# min 25
 					# (change requires restart)
-#preload_libraries = ''			# (change requires restart)
+#shared_preload_libraries = ''		# (change requires restart)
 
 # - Cost-Based Vacuum Delay -
 
@@ -419,6 +419,7 @@
 
 #explain_pretty_print = on
 #dynamic_library_path = '$libdir'
+#local_preload_libraries = ''
 
 
 #---------------------------------------------------------------------------
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 5b904cbad429daff466cd9f5d99ca1b8c0601b55..2e9e3f718209f7c19029ee27a8dbaa710c038cd9 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.45 2006/05/31 20:58:09 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/fmgr.h,v 1.46 2006/08/15 18:26:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -488,7 +488,8 @@ extern char *Dynamic_library_path;
 extern PGFunction load_external_function(char *filename, char *funcname,
 					   bool signalNotFound, void **filehandle);
 extern PGFunction lookup_external_function(void *filehandle, char *funcname);
-extern void load_file(char *filename);
+extern void load_file(const char *filename, bool restrict);
+extern void **find_rendezvous_variable(const char *varName);
 
 
 /*
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 07590c92942327858045e83ff73cfc252367a76f..8a050f5b7dc5a239642be27b76de4a355a339e2c 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.187 2006/08/08 19:15:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.188 2006/08/15 18:26:59 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to other files.
@@ -307,7 +307,8 @@ extern void BaseInit(void);
 
 /* in utils/init/miscinit.c */
 extern bool IgnoreSystemIndexes;
-extern char *preload_libraries_string;
+extern char *shared_preload_libraries_string;
+extern char *local_preload_libraries_string;
 
 extern void SetReindexProcessing(Oid heapOid, Oid indexOid);
 extern void ResetReindexProcessing(void);
@@ -319,6 +320,7 @@ extern void TouchSocketLockFile(void);
 extern void RecordSharedMemoryInLockFile(unsigned long id1,
 							 unsigned long id2);
 extern void ValidatePgVersion(const char *path);
-extern void process_preload_libraries(void);
+extern void process_shared_preload_libraries(void);
+extern void process_local_preload_libraries(void);
 
 #endif   /* MISCADMIN_H */