diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index bc7a86dba1def93d415e554cd6aaea0c437a5878..f5ed95be5d4648dbe88312f09cfcea12edf10773 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.66 2001/05/12 22:51:35 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.67 2001/05/17 17:44:17 petere Exp $
 -->
 
 <Chapter Id="runtime">
@@ -996,6 +996,49 @@ env PGOPTIONS='-c geqo=off' psql
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term>DYNAMIC_LIBRARY_PATH (<type>string</type>)</term>
+      <listitem>
+       <para>
+        If a dynamically loadable module needs to be opened and the
+        specified name does not have a directory component (i.e., the
+        name does not contain a slash), the system will search this
+        path for the specified file.  (The name that is used is the
+        name specified in the <command>CREATE FUNCTION</command> or
+        <command>LOAD</command> command.)
+       </para>
+
+       <para>
+        The value for dynamic_library_path has to be a colon-separated
+        list of absolute directory names.  If a directory name starts
+        with the special value <literal>$libdir</literal>, the
+        compiled-in PostgreSQL library directory, which is where the
+        modules provided by the PostgreSQL distribution are installed,
+        is substituted.  An example value:
+        <informalexample>
+<programlisting>
+dynamic_library_path = '/usr/local/lib:/home/my_project/lib:$libdir:$libdir/contrib'
+</programlisting>
+        </informalexample>
+       </para>
+
+       <para>
+        The default value for this parameter is
+        <literal>$libdir</literal>.  If the value is set to the empty
+        string, the automatic path search is turned off.
+       </para>
+
+       <para>
+        This parameter can be changed at run time by superusers, but
+        note that a setting done that way will only persist till the
+        end of the client connection, so this method should be
+        reserved for development purposes.  The recommended way to set
+        this parameter is in the <filename>postgresql.conf</filename>
+        configuration file.
+       </para>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <indexterm>
        <primary>fsync</primary>
diff --git a/src/backend/utils/fmgr/Makefile b/src/backend/utils/fmgr/Makefile
index 1e7c19db3319f1193ce555ea95874ef3cbeb4b61..a449b80942b2694ca5aa382a6183ae53f960f9bb 100644
--- a/src/backend/utils/fmgr/Makefile
+++ b/src/backend/utils/fmgr/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for utils/fmgr
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.10 2000/08/31 16:10:50 petere Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/fmgr/Makefile,v 1.11 2001/05/17 17:44:18 petere Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -14,6 +14,9 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = dfmgr.o fmgr.o
 
+override CPPFLAGS += -DLIBDIR=\"$(libdir)\" -DDLSUFFIX=\"$(DLSUFFIX)\"
+
+
 all: SUBSYS.o
 
 SUBSYS.o: $(OBJS)
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index 49be6b37903bd2619b3847059b1e18e7f6a6b142..695fb1ed76e8c769d9bf72d4411bbd1f7122f350 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,16 +8,18 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.48 2001/03/22 03:59:58 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.49 2001/05/17 17:44:18 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "postgres.h"
 
+#include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "dynloader.h"
+#include "miscadmin.h"
 #include "utils/dynamic_loader.h"
 
 
@@ -44,6 +46,12 @@ static DynamicFileList *file_tail = (DynamicFileList *) NULL;
 
 #define SAME_INODE(A,B) ((A).st_ino == (B).inode && (A).st_dev == (B).device)
 
+char * Dynamic_library_path;
+
+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);
+
 
 /*
  * Load the specified dynamic-link library file, and look for a function
@@ -60,6 +68,11 @@ load_external_function(char *filename, char *funcname,
 	PGFunction	retval;
 	char	   *load_error;
 	struct stat stat_buf;
+	char	   *fullname;
+
+	fullname = expand_dynamic_library_name(filename);
+	if (fullname)
+		filename = fullname;
 
 	/*
 	 * Scan the list of loaded FILES to see if the file has been loaded.
@@ -143,6 +156,11 @@ load_file(char *filename)
 	DynamicFileList *file_scanner,
 			   *p;
 	struct stat stat_buf;
+	char	   *fullname;
+
+	fullname = expand_dynamic_library_name(filename);
+	if (fullname)
+		filename = fullname;
 
 	/*
 	 * We need to do stat() in order to determine whether this is the same
@@ -181,3 +199,181 @@ load_file(char *filename)
 
 	load_external_function(filename, (char *) NULL, false);
 }
+
+
+
+static bool
+file_exists(const char *name)
+{
+	struct stat st;
+
+	AssertArg(name != NULL);
+
+	if (stat(name, &st) == 0)
+		return true;
+	else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES))
+			elog(ERROR, "stat failed on %s: %s", name, strerror(errno));
+
+	return false;
+}
+
+
+/* Example format: ".so" */
+#ifndef DLSUFFIX
+#error "DLSUFFIX must be defined to compile this file."
+#endif
+
+/* Example format: "/usr/local/pgsql/lib" */
+#ifndef LIBDIR
+#error "LIBDIR needs to be defined to compile this file."
+#endif
+
+
+/*
+ * If name contains a slash, check if the file exists, if so return
+ * 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.  The return value is
+ * palloc'ed.
+ */
+static char *
+expand_dynamic_library_name(const char *name)
+{
+	bool have_slash;
+	char * new;
+	size_t len;
+
+	AssertArg(name);
+
+	have_slash = (strchr(name, '/') != NULL);
+
+	if (!have_slash)
+	{
+		char * full;
+
+		full = find_in_dynamic_libpath(name);
+		if (full)
+			return full;
+	}
+	else
+	{
+		if (file_exists(name))
+			return pstrdup(name);
+	}
+
+	len = strlen(name);
+
+	new = palloc(len + strlen(DLSUFFIX) + 1);
+	strcpy(new, name);
+	strcpy(new + len, DLSUFFIX);
+
+	if (!have_slash)
+	{
+		char * full;
+
+		full = find_in_dynamic_libpath(new);
+		pfree(new);
+		if (full)
+			return full;
+	}
+	else
+	{
+		if (file_exists(new))
+			return new;
+	}
+		
+	return NULL;
+}
+
+
+
+/*
+ * Search for a file called 'basename' in the colon-separated search
+ * path 'path'.  If the file is found, the full file name is returned
+ * in palloced memory.  The the file is not found, return NULL.
+ */
+static char *
+find_in_dynamic_libpath(const char * basename)
+{
+	const char *p;
+	char *full;
+	size_t len;
+	size_t baselen;
+
+	AssertArg(basename != NULL);
+	AssertArg(strchr(basename, '/') == NULL);
+	AssertState(Dynamic_library_path != NULL);
+
+	p = Dynamic_library_path;
+	if (strlen(p) == 0)
+		return NULL;
+
+	baselen = strlen(basename);
+
+	do {
+		len = strcspn(p, ":");
+
+		if (len == 0)
+			elog(ERROR, "zero length dynamic_library_path component");
+
+		/* substitute special value */
+		if (p[0] == '$')
+		{
+			size_t varname_len = strcspn(p + 1, "/") + 1;
+			const char * replacement = NULL;
+			size_t repl_len;
+
+			if (strncmp(p, "$libdir", varname_len)==0)
+				replacement = LIBDIR;
+			else
+				elog(ERROR, "invalid dynamic_library_path specification");
+
+			repl_len = strlen(replacement);
+
+			if (p[varname_len] == '\0')
+			{
+				full = palloc(repl_len + 1 + baselen + 1);
+				snprintf(full, repl_len + 1 + baselen + 1,
+						 "%s/%s", replacement, basename);
+			}
+			else
+			{
+				full = palloc(repl_len + (len - varname_len) + 1 + baselen + 1);
+
+				strcpy(full, replacement);
+				strncat(full, p + varname_len, len - varname_len);
+				full[repl_len + (len - varname_len)] = '\0';
+				strcat(full, "/");
+				strcat(full, basename);
+			}
+		}
+
+		/* regular case */
+		else
+		{
+			/* only absolute paths */
+			if (p[0] != '/')
+				elog(ERROR, "dynamic_library_path component is not absolute");
+
+			full = palloc(len + 1 + baselen + 1);
+			strncpy(full, p, len);
+			full[len] = '/';
+			strcpy(full + len + 1, basename);
+		}
+
+		if (DebugLvl > 1)
+			elog(DEBUG, "find_in_dynamic_libpath: trying %s", full);
+
+		if (file_exists(full))
+			return full;
+
+		pfree(full);
+		if (p[len] == '\0')
+			break;
+		else
+			p += len + 1;
+	} while(1);
+
+	return NULL;
+}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 1d779979a194f92584d2597d3abccf3d97ad22fc..6e080594f8b6662891da9be5b2bb5a0c566f22d2 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -4,7 +4,7 @@
  * Support for grand unified configuration scheme, including SET
  * command, configuration file, and command line options.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.35 2001/03/22 17:41:47 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.36 2001/05/17 17:44:18 petere Exp $
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  * Written by Peter Eisentraut <peter_e@gmx.net>.
@@ -22,6 +22,7 @@
 
 #include "access/xlog.h"
 #include "commands/async.h"
+#include "fmgr.h"
 #include "libpq/auth.h"
 #include "libpq/pqcomm.h"
 #include "miscadmin.h"
@@ -328,6 +329,9 @@ static struct config_real
 static struct config_string
 			ConfigureNamesString[] =
 {
+	{"dynamic_library_path", PGC_SUSET, &Dynamic_library_path,
+	 "$libdir", NULL, NULL},
+
 	{"krb_server_keyfile", PGC_POSTMASTER, &pg_krb_server_keyfile,
 	PG_KRB_SRVTAB, NULL, NULL},
 
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 3ccd1c39c615e7fe8659bcf04e4618676703de6d..44641bdcb1829dab3f070500a4cb2655a51ebf5c 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fmgr.h,v 1.13 2001/03/22 04:00:25 momjian Exp $
+ * $Id: fmgr.h,v 1.14 2001/05/17 17:44:18 petere Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -350,6 +350,7 @@ extern Oid	fmgr_internal_function(const char *proname);
 extern PGFunction load_external_function(char *filename, char *funcname,
 					   bool signalNotFound);
 extern void load_file(char *filename);
+extern char * Dynamic_library_path;
 
 
 /*