diff --git a/configure b/configure
index 9403fa4537390212a8bfcf3a0ba261fe078cbe1a..9deb026c4a3ff1786006fec60ce145cbf1986db0 100755
--- a/configure
+++ b/configure
@@ -12011,7 +12011,6 @@ case $host_os in mingw*)
 LIBOBJS="$LIBOBJS copydir.$ac_objext"
 LIBOBJS="$LIBOBJS gettimeofday.$ac_objext"
 LIBOBJS="$LIBOBJS open.$ac_objext"
-LIBOBJS="$LIBOBJS pipe.$ac_objext"
 LIBOBJS="$LIBOBJS rand.$ac_objext"
 
 cat >>confdefs.h <<\_ACEOF
diff --git a/configure.in b/configure.in
index 1cad0dbe281914a70b36ad359c720123baa7b669..8947a815830f5f32baca99fd09c0e6913a6f7893 100644
--- a/configure.in
+++ b/configure.in
@@ -1,5 +1,5 @@
 dnl Process this file with autoconf to produce a configure script.
-dnl $PostgreSQL: pgsql/configure.in,v 1.345 2004/05/07 00:24:57 tgl Exp $
+dnl $PostgreSQL: pgsql/configure.in,v 1.346 2004/05/11 21:57:13 momjian Exp $
 dnl
 dnl Developers, please strive to achieve this order:
 dnl
@@ -892,7 +892,6 @@ case $host_os in mingw*)
 AC_LIBOBJ(copydir)
 AC_LIBOBJ(gettimeofday)
 AC_LIBOBJ(open)
-AC_LIBOBJ(pipe)
 AC_LIBOBJ(rand)
 AC_DEFINE(USE_PGTZ, 1,
 	[Define to 1 to use our own timezone library])
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 9dda9bf8b0026542a04b09bea923fd61600f64ae..e87c1ba8efc475cfde15149b01bdf09cf00841c8 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -1,5 +1,5 @@
 # -*-makefile-*-
-# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.181 2004/05/07 00:24:57 tgl Exp $
+# $PostgreSQL: pgsql/src/Makefile.global.in,v 1.182 2004/05/11 21:57:14 momjian Exp $
 
 #------------------------------------------------------------------------------
 # All PostgreSQL makefiles include this file and use the variables it sets,
@@ -339,7 +339,7 @@ endif
 #
 # substitute implementations of the C library
 
-LIBOBJS = @LIBOBJS@ noblock.o path.o pgsleep.o pgstrcasecmp.o sprompt.o thread.o
+LIBOBJS = @LIBOBJS@ exec.o noblock.o path.o pipe.o pgsleep.o pgstrcasecmp.o sprompt.o thread.o
 
 ifneq (,$(LIBOBJS))
 LIBS += -lpgport
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 1d781d0bb5afb2b346fcceeabeb2c76e30700e85..e3df517d1ea148919d2428852294c3786f237bfe 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.382 2004/05/06 19:23:25 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/postmaster/postmaster.c,v 1.383 2004/05/11 21:57:14 momjian Exp $
  *
  * NOTES
  *
@@ -692,7 +692,7 @@ PostmasterMain(int argc, char *argv[])
 	/*
 	 * On some systems our dynloader code needs the executable's pathname.
 	 */
-	if (FindExec(pg_pathname, progname, "postgres") < 0)
+	if (find_my_binary(pg_pathname, progname, "postgres") < 0)
 		ereport(FATAL,
 				(errmsg("%s: could not locate postgres executable",
 						progname)));
@@ -3222,7 +3222,7 @@ CreateOptsFile(int argc, char *argv[])
 	FILE	   *fp;
 	int			i;
 
-	if (FindExec(fullprogname, argv[0], "postmaster") < 0)
+	if (find_my_binary(fullprogname, argv[0], "postmaster") < 0)
 	{
 		elog(LOG, "could not locate postmaster");
 		return false;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 89ec36287c759756eb085fd375ed94f6c3e33e5c..caeef3cd5708dec8ccd66661bde25e46edf3285e 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.402 2004/05/07 01:53:41 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.403 2004/05/11 21:57:14 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2649,7 +2649,7 @@ PostgresMain(int argc, char *argv[], const char *username)
 		 * On some systems our dynloader code needs the executable's
 		 * pathname.  (If under postmaster, this was done already.)
 		 */
-		if (FindExec(pg_pathname, argv[0], "postgres") < 0)
+		if (find_my_binary(pg_pathname, argv[0], "postgres") < 0)
 			ereport(FATAL,
 					(errmsg("%s: could not locate postgres executable",
 							argv[0])));
diff --git a/src/backend/utils/init/Makefile b/src/backend/utils/init/Makefile
index d5dc43ca5cab1948c02539b12359e7c0f472dbc1..8415de8b2a42a82b7c17582191480284a24ce29b 100644
--- a/src/backend/utils/init/Makefile
+++ b/src/backend/utils/init/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for utils/init
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/utils/init/Makefile,v 1.16 2003/11/29 19:52:01 pgsql Exp $
+#    $PostgreSQL: pgsql/src/backend/utils/init/Makefile,v 1.17 2004/05/11 21:57:14 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/utils/init
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = findbe.o globals.o miscinit.o postinit.o
+OBJS = globals.o miscinit.o postinit.o
 
 all: SUBSYS.o
 
diff --git a/src/bin/initdb/Makefile b/src/bin/initdb/Makefile
index 5bcaae92f755bf5c62561ea88d8644ee0fc5c986..d709f6076678cb990b5ab019a501cce8750637c6 100644
--- a/src/bin/initdb/Makefile
+++ b/src/bin/initdb/Makefile
@@ -5,7 +5,7 @@
 # Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $PostgreSQL: pgsql/src/bin/initdb/Makefile,v 1.36 2004/04/26 17:40:48 momjian Exp $
+# $PostgreSQL: pgsql/src/bin/initdb/Makefile,v 1.37 2004/05/11 21:57:14 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -13,15 +13,19 @@ subdir = src/bin/initdb
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-override CPPFLAGS := -DPGBINDIR=\"$(bindir)\" -DPGDATADIR=\"$(datadir)\" -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
+override CPPFLAGS := -DPGDATADIR=\"$(datadir)\" -DFRONTEND -I$(libpq_srcdir) $(CPPFLAGS)
 
-OBJS=	initdb.o
+OBJS=	initdb.o \
+	$(filter exec.o, $(LIBOBJS))
 
 all: submake-libpq submake-libpgport initdb
 
 initdb: $(OBJS) $(libpq_builddir)/libpq.a
 	$(CC) $(CFLAGS) $(OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@$(X)
 
+exec.c: % : $(top_srcdir)/src/port/%
+	rm -f $@ && $(LN_S) $< .
+
 install: all installdirs
 	$(INSTALL_PROGRAM) initdb$(X) $(DESTDIR)$(bindir)/initdb$(X)
 
@@ -32,8 +36,8 @@ uninstall:
 	rm -f $(DESTDIR)$(bindir)/initdb$(X)
 
 clean distclean maintainer-clean:
-	rm -f initdb$(X) $(OBJS)
+	rm -f initdb$(X) $(OBJS) exec.c
 
 
-# ensure that changes in bindir etc. propagate into object file
+# ensure that changes in datadir propagate into object file
 initdb.o: initdb.c $(top_builddir)/src/Makefile.global
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 7b03c404ea3790fe5faacb38e8c040e464dd00c2..fa8bf28da865750fecba578d8767cbdbf66bb14a 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -25,10 +25,6 @@
  *
  * template0 is made just by copying the completed template1.
  *
- *
- * TODO:
- *	 - clean up find_postgres code and return values
- *
  * Note:
  *	 The program has some memory leakage - it isn't worth cleaning it up.
  *
@@ -43,7 +39,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  * Portions taken from FreeBSD.
  *
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.26 2004/05/10 20:51:58 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.27 2004/05/11 21:57:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,7 +48,6 @@
 
 #include <dirent.h>
 #include <sys/stat.h>
-#include <sys/wait.h>
 #include <unistd.h>
 #include <locale.h>
 #include <signal.h>
@@ -78,7 +73,6 @@ int			optreset;
  * Note that "datadir" is not the directory we're going to initialize,
  * it's merely how Autoconf names PREFIX/share.
  */
-char	   *bindir = PGBINDIR;
 char	   *datadir = PGDATADIR;
 
 /* values to be obtained from arguments */
@@ -100,7 +94,6 @@ bool		show_setting = false;
 
 /* internal vars */
 char	   *progname;
-char	   *self_path;
 char	   *postgres;
 char	   *encodingid = "0";
 char	   *bki_file;
@@ -135,25 +128,9 @@ static const char *boot_options = "-F";
 static const char *backend_options = "-F -O -c search_path=pg_catalog -c exit_on_error=true";
 
 
-/* platform specific path stuff */
-#if defined(__CYGWIN__) || defined(WIN32)
-#define EXE ".exe"
-#define DEVNULL "nul"
-#else
-#define EXE ""
-#define DEVNULL "/dev/null"
-#endif
-
-
-/* detected path to postgres and (we assume) friends */
-char	   *pgpath;
-
-/* forward declare all our functions */
-#ifdef WIN32
-static char *expanded_path(char *);
-#else
-#define expanded_path(x) (x)
-#endif
+/* path to 'initdb' binary directory */
+char	   bindir[MAXPGPATH];
+char	   backendbin[MAXPGPATH];
 
 static void *xmalloc(size_t size);
 static char *xstrdup(const char *s);
@@ -161,7 +138,6 @@ static bool rmtree(char *path, bool rmtopdir);
 static char **replace_token(char **lines, char *token, char *replacement);
 static char **readfile(char *path);
 static void writefile(char *path, char **lines);
-static void pclose_check(FILE *stream);
 static int mkdir_p(char *path, mode_t omode);
 static void exit_nicely(void);
 static char *get_id(void);
@@ -171,8 +147,6 @@ static int check_data_dir(void);
 static bool mkdatadir(char *subdir);
 static void set_input(char **dest, char *filename);
 static void check_input(char *path);
-static int find_postgres(char *path);
-static int set_paths(void);
 static void set_short_version(char *short_version, char *extrapath);
 static void set_null_conf(void);
 static void test_connections(void);
@@ -216,7 +190,8 @@ do { \
 
 #define PG_CMD_CLOSE \
 do { \
-	pclose_check(pg); \
+	if (pclose_check(pg)) \
+		exit_nicely(); \
 } while (0)
 
 #define PG_CMD_PUTLINE \
@@ -437,41 +412,6 @@ writefile(char *path, char **lines)
 		exit_nicely();
 }
 
-/* pclose() plus useful error reporting */
-static void
-pclose_check(FILE *stream)
-{
-	int		exitstatus;
-
-	exitstatus = pclose(stream);
-
-	if (exitstatus == 0)
-		return;					/* all is well */
-
-	if (exitstatus == -1)
-	{
-		/* pclose() itself failed, and hopefully set errno */
-		perror("pclose failed");
-	}
-	else if (WIFEXITED(exitstatus))
-	{
-		fprintf(stderr, _("%s: child process exited with exit code %d\n"),
-				progname, WEXITSTATUS(exitstatus));
-	}
-	else if (WIFSIGNALED(exitstatus))
-	{
-		fprintf(stderr, _("%s: child process was terminated by signal %d\n"),
-				progname, WTERMSIG(exitstatus));
-	}
-	else
-	{
-		fprintf(stderr, _("%s: child process exited with unrecognized status %d\n"),
-				progname, exitstatus);
-	}
-
-	exit_nicely();
-}
-
 /* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
 
 /*
@@ -814,193 +754,6 @@ check_input(char *path)
 
 }
 
-/*
- * TODO - clean this up and handle the errors properly
- * don't overkill
- */
-#define FIND_SUCCESS 0
-#define FIND_NOT_FOUND 1
-#define FIND_STAT_ERR 2
-#define FIND_NOT_REGFILE 3
-#define FIND_BAD_PERM 4
-#define FIND_EXEC_ERR 5
-#define FIND_WRONG_VERSION 6
-
-/*
- * see if there is a postgres executable in the given path, and giving the
- * right version number
- */
-static int
-find_postgres(char *path)
-{
-	char		fn[MAXPGPATH];
-	char		cmd[MAXPGPATH];
-	char		line[100];
-
-#ifndef WIN32
-	int			permmask = S_IROTH | S_IXOTH;
-#endif
-
-	struct stat statbuf;
-	FILE	   *pgver;
-	int			plen = strlen(path);
-
-	if (plen > 0 && path[plen - 1] != '/')
-		snprintf(fn, sizeof(fn), "%s/postgres%s", path, EXE);
-	else
-		snprintf(fn, sizeof(fn), "%spostgres%s", path, EXE);
-
-	if (stat(fn, &statbuf) != 0)
-	{
-		if (errno == ENOENT)
-			return FIND_NOT_FOUND;
-		else
-			return FIND_STAT_ERR;
-	}
-	if (!S_ISREG(statbuf.st_mode))
-		return FIND_NOT_REGFILE;
-
-#ifndef WIN32
-
-	/*
-	 * Only unix requires this test, on WIN32 an .exe file should be
-	 * executable
-	 */
-	if ((statbuf.st_mode & permmask) != permmask)
-		return FIND_BAD_PERM;
-#endif
-
-	snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -V 2>%s", path, DEVNULL);
-
-	/* flush output buffers in case popen does not... */
-	fflush(stdout);
-	fflush(stderr);
-
-	if ((pgver = popen(cmd, "r")) == NULL)
-		return FIND_EXEC_ERR;
-
-	if (fgets(line, sizeof(line), pgver) == NULL)
-		perror("fgets failure");
-
-	pclose_check(pgver);
-
-	if (strcmp(line, PG_VERSIONSTR) != 0)
-		return FIND_WRONG_VERSION;
-
-	return FIND_SUCCESS;
-}
-
-/*
- * Windows doesn't like relative paths to executables (other things work fine)
- * so we call its builtin function to expand them. Elsewhere this is a NOOP
- */
-#ifdef WIN32
-static char *
-expanded_path(char *path)
-{
-	char		abspath[MAXPGPATH];
-
-	if (_fullpath(abspath, path, sizeof(abspath)) == NULL)
-	{
-		perror("expanded path");
-		return path;
-	}
-	canonicalize_path(abspath);
-	return xstrdup(abspath);
-}
-#endif
-
-/*
- * set the paths pointing to postgres
- *
- * look for it in the same place we found this program, or in the environment
- * path, or in the configured bindir.
- * We do it in this order because during upgrades users might move
- * their trees to backup places, so the hard-wired bindir might be inaccurate.
- *
- * XXX this needs work, as its error handling is vastly inferior to the
- * shell-script version, in particular the case where a postgres executable
- * is failing
- */
-static int
-set_paths(void)
-{
-	if (testpath && !self_path)
-	{
-		char	   *path,
-				   *cursor;
-		int			pathlen,
-					i,
-					pathsegs;
-		char	  **pathbits;
-		char		buf[MAXPGPATH];
-		struct stat statbuf;
-
-		path = xstrdup(getenv("PATH"));
-		pathlen = strlen(path);
-
-		for (i = 0, pathsegs = 1; i < pathlen; i++)
-		{
-			if (path[i] == PATHSEP)
-				pathsegs++;
-		}
-
-		pathbits = (char **) xmalloc(pathsegs * sizeof(char *));
-		for (i = 0, pathsegs = 0, cursor = path; i <= pathlen; i++)
-		{
-			if (path[i] == PATHSEP || path[i] == 0)
-			{
-				path[i] = 0;
-				if (strlen(cursor) == 0)
-				{
-					/* empty path segment means current directory */
-					pathbits[pathsegs] = xstrdup(".");
-				}
-				else
-				{
-					canonicalize_path(cursor);
-					pathbits[pathsegs] = cursor;
-				}
-				pathsegs++;
-				cursor = path + i + 1;
-			}
-		}
-
-		for (i = 0; i < pathsegs; i++)
-		{
-			snprintf(buf, sizeof(buf), "%s/%s%s", pathbits[i], progname, EXE);
-			if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
-			{
-				self_path = pathbits[i];
-				break;
-			}
-		}
-	}
-
-	if (testpath && self_path &&
-		(find_postgres(expanded_path(self_path)) == 0))
-	{
-		/* we found postgres on out own path */
-		pgpath = expanded_path(self_path);
-	}
-	else
-	{
-		/* look in the hardcoded bindir */
-		int			res;
-		char	   *cbindir;
-
-		cbindir = xstrdup(bindir);
-		canonicalize_path(cbindir);
-		res = find_postgres(expanded_path(cbindir));
-		if (res == 0)
-			pgpath = expanded_path(cbindir);
-		else
-			return 1;
-	}
-
-	return 0;
-}
-
 /*
  * write out the PG_VERSION file in the data dir, or its subdirectory
  * if extrapath is not NULL
@@ -1063,10 +816,10 @@ test_connections(void)
 	for (i = 0; i < len; i++)
 	{
 		snprintf(cmd, sizeof(cmd),
-				 "\"%s/postgres\" -boot -x0 %s "
+				 "\"%s\" -boot -x0 %s "
 				 "-c shared_buffers=%d -c max_connections=%d template1 "
 				 "<%s >%s 2>&1",
-				 pgpath, boot_options,
+				 backendbin, boot_options,
 				 conns[i] * 5, conns[i],
 				 DEVNULL, DEVNULL);
 		status = system(cmd);
@@ -1099,10 +852,10 @@ test_buffers(void)
 	for (i = 0; i < len; i++)
 	{
 		snprintf(cmd, sizeof(cmd),
-				 "\"%s/postgres\" -boot -x0 %s "
+				 "\"%s\" -boot -x0 %s "
 				 "-c shared_buffers=%d -c max_connections=%d template1 "
 				 "<%s >%s 2>&1",
-				 pgpath, boot_options,
+				 backendbin, boot_options,
 				 bufs[i], n_connections,
 				 DEVNULL, DEVNULL);
 		status = system(cmd);
@@ -1250,8 +1003,8 @@ bootstrap_template1(char *short_version)
 	unsetenv("PGCLIENTENCODING");
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" -boot -x1 %s %s template1",
-			 pgpath, boot_options, talkargs);
+			 "\"%s\" -boot -x1 %s %s template1",
+			 backendbin, boot_options, talkargs);
 
 	PG_CMD_OPEN;
 
@@ -1300,8 +1053,8 @@ setup_shadow(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1340,8 +1093,8 @@ get_set_pwd(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1394,8 +1147,8 @@ unlimit_systables(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1467,8 +1220,8 @@ setup_depend(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1500,8 +1253,8 @@ setup_sysviews(void)
 	 * We use -N here to avoid backslashing stuff in system_views.sql
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s -N template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s -N template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1532,8 +1285,8 @@ setup_description(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1580,8 +1333,8 @@ setup_conversion(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1636,8 +1389,8 @@ setup_privileges(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1699,8 +1452,8 @@ setup_schema(void)
 	 * We use -N here to avoid backslashing stuff in information_schema.sql
 	 */
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s -N template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s -N template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1716,8 +1469,8 @@ setup_schema(void)
 	PG_CMD_CLOSE;
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1756,8 +1509,8 @@ vacuum_db(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -1812,8 +1565,8 @@ make_template0(void)
 	fflush(stdout);
 
 	snprintf(cmd, sizeof(cmd),
-			 "\"%s/postgres\" %s template1 >%s",
-			 pgpath, backend_options,
+			 "\"%s\" %s template1 >%s",
+			 backendbin, backend_options,
 			 DEVNULL);
 
 	PG_CMD_OPEN;
@@ -2043,48 +1796,17 @@ main(int argc, char *argv[])
 	};
 
 	int			c,
-				i;
+				i,
+				ret;
 	int			option_index;
 	char	   *short_version;
 	char	   *pgdenv;			/* PGDATA value got from sent to
 								 * environment */
 	char	   *subdirs[] =
 	{"global", "pg_xlog", "pg_clog", "base", "base/1"};
-	char	   *lastsep;
-	char	   *carg0;
-#if defined(__CYGWIN__) || defined(WIN32)
-	char	   *exe;			/* location of exe suffix in progname */
-#endif
-
 	init_nls();
 
-	/* parse argv[0] - detect explicit path if there was one */
-	carg0 = xstrdup(argv[0]);
-	canonicalize_path(carg0);
-
-	lastsep = strrchr(carg0, '/');
-	progname = lastsep ? xstrdup(lastsep + 1) : carg0;
-
-#if defined(__CYGWIN__) || defined(WIN32)
-	if (strlen(progname) > 4 &&
-		(exe = progname + (strlen(progname) - 4)) &&
-		stricmp(exe, EXE) == 0)
-	{
-		/* strip .exe suffix, regardless of case */
-		*exe = '\0';
-	}
-#endif
-
-	if (lastsep)
-	{
-		self_path = carg0;
-		*lastsep = '\0';
-	}
-	else
-	{
-		/* no path known to ourselves from argv[0] */
-		self_path = NULL;
-	}
+	progname = get_progname(argv[0]);
 
     if (argc > 1)
     {
@@ -2210,16 +1932,28 @@ main(int argc, char *argv[])
 	sprintf(pgdenv, "PGDATA=%s", pg_data);
 	putenv(pgdenv);
 
-	if (set_paths() != 0)
+	if ((ret = find_other_binary(backendbin, argv[0], progname, "postgres",
+						   PG_VERSIONSTR)) < 0)
 	{
-		fprintf(stderr,
-				_("The program \"postgres\" is needed by %s "
-				"but was not found in \n"
-				"the directory \"%s\". Check your installation.\n"),
-				progname, bindir);
+		if (ret == -1)
+			fprintf(stderr,
+						_("The program \"postgres\" is needed by %s "
+						"but was not found in the same directory as \"%s\".\n"
+						"Check your installation.\n"),
+						progname, progname);
+		else
+			fprintf(stderr,
+						_("The program \"postgres\" was found by %s "
+						"but was not the same version as \"%s\".\n"
+						"Check your installation.\n"),
+						progname, progname);
 		exit(1);
 	}
 
+	/* store binary directory */
+	strcpy(bindir, backendbin);
+	*last_path_separator(bindir) = '\0';
+	
 	if ((short_version = get_short_version()) == NULL)
 	{
 		fprintf(stderr, _("%s: could not determine valid short version string\n"), progname);
@@ -2255,7 +1989,7 @@ main(int argc, char *argv[])
 				"POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
 				"PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
 				PG_VERSION,
-				pg_data, datadir, pgpath,
+				pg_data, datadir, bindir,
 				encoding, encodingid,
 				username, bki_file,
 				desc_file, conf_file,
@@ -2448,8 +2182,8 @@ main(int argc, char *argv[])
 		   "    %s%s%s/postmaster -D %s%s%s\n"
 		   "or\n"
 		   "    %s%s%s/pg_ctl -D %s%s%s -l logfile start\n\n"),
-		 QUOTE_PATH, pgpath, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
-		QUOTE_PATH, pgpath, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);
+		 QUOTE_PATH, bindir, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
+		QUOTE_PATH, bindir, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);
 
 	return 0;
 }
diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
index 59722363a5d9657b62163e15a19fbc074cb253aa..414194cd30bfd8d065073981253a37dcd4e6c275 100644
--- a/src/bin/pg_dump/Makefile
+++ b/src/bin/pg_dump/Makefile
@@ -5,7 +5,7 @@
 # Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $PostgreSQL: pgsql/src/bin/pg_dump/Makefile,v 1.46 2004/04/30 20:01:39 momjian Exp $
+# $PostgreSQL: pgsql/src/bin/pg_dump/Makefile,v 1.47 2004/05/11 21:57:14 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -18,10 +18,11 @@ override CPPFLAGS += -DFRONTEND
 OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
 	pg_backup_files.o pg_backup_null.o pg_backup_tar.o \
 	dumputils.o
+PG_DUMPALL_OBJS =	$(filter exec.o, $(LIBOBJS))
 
 EXTRA_OBJS = $(top_builddir)/src/backend/parser/keywords.o
 
-override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS) -DBINDIR=\"$(bindir)\"
+override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 
 all: submake-libpq submake-libpgport submake-backend pg_dump pg_restore pg_dumpall
@@ -32,8 +33,11 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(libpq_builddir)/libpq.a
 pg_restore: pg_restore.o $(OBJS) $(libpq_builddir)/libpq.a
 	$(CC) $(CFLAGS) pg_restore.o $(OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o $(libpq_builddir)/libpq.a
-	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@$(X)
+pg_dumpall: pg_dumpall.o dumputils.o $(PG_DUMPALL_OBJS) $(libpq_builddir)/libpq.a
+	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(PG_DUMPALL_OBJS) $(EXTRA_OBJS) $(libpq) $(LDFLAGS) $(LIBS) -o $@$(X)
+
+exec.c: % : $(top_srcdir)/src/port/%
+	rm -f $@ && $(LN_S) $< .
 
 .PHONY: submake-backend
 submake-backend:
@@ -52,8 +56,4 @@ uninstall:
 	rm -f $(addprefix $(DESTDIR)$(bindir)/, pg_dump$(X) pg_restore$(X) pg_dumpall$(X))
 
 clean distclean maintainer-clean:
-	rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_dump_sort.o pg_restore.o pg_dumpall.o
-
-
-# ensure that changes in bindir etc. propagate into object file
-pg_dumpall.o: pg_dumpall.c $(top_builddir)/src/Makefile.global
+	rm -f pg_dump$(X) pg_restore$(X) pg_dumpall$(X) $(OBJS) pg_dump.o common.o pg_dump_sort.o pg_restore.o pg_dumpall.o exec.c
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index f15ddc206dcfc25d25ee3ac0546b3d2844693e6a..0817cabfb95df3531e64291866c78a701053f078 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.30 2004/01/22 19:09:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dumpall.c,v 1.31 2004/05/11 21:57:14 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,9 @@ int			optreset;
 
 #define _(x) gettext((x))
 
+/* version string we expect back from postgres */
+#define PG_VERSIONSTR "pg_dump (PostgreSQL) " PG_VERSION "\n"
+
 
 static char *progname;
 
@@ -52,10 +55,9 @@ static int	runPgDump(const char *dbname);
 static PGconn *connectDatabase(const char *dbname, const char *pghost, const char *pgport,
 				const char *pguser, bool require_password);
 static PGresult *executeQuery(PGconn *conn, const char *query);
-static char *findPgDump(const char *argv0);
 
 
-char	   *pgdumploc;
+char	    pg_dump_bin[MAXPGPATH];
 PQExpBuffer pgdumpopts;
 bool		output_clean = false;
 bool		skip_acls = false;
@@ -75,7 +77,7 @@ main(int argc, char *argv[])
 	bool		globals_only = false;
 	bool		schema_only = false;
 	PGconn	   *conn;
-	int			c;
+	int			c, ret;
 
 	static struct option long_options[] = {
 		{"data-only", no_argument, NULL, 'a'},
@@ -121,7 +123,24 @@ main(int argc, char *argv[])
 		}
 	}
 
-	pgdumploc = findPgDump(argv[0]);
+	if ((ret = find_other_binary(pg_dump_bin, argv[0], progname, "pg_dump",
+						   PG_VERSIONSTR)) < 0)
+	{
+		if (ret == -1)
+			fprintf(stderr,
+						_("The program \"pg_dump\" is needed by %s "
+						"but was not found in the same directory as \"%s\".\n"
+						"Check your installation.\n"),
+						progname, progname);
+		else
+			fprintf(stderr,
+						_("The program \"pg_dump\" was found by %s "
+						"but was not the same version as \"%s\".\n"
+						"Check your installation.\n"),
+						progname, progname);
+		exit(1);
+	}
+
 	pgdumpopts = createPQExpBuffer();
 
 	while ((c = getopt_long(argc, argv, "acdDgh:iop:sU:vWx", long_options, &optindex)) != -1)
@@ -667,7 +686,7 @@ runPgDump(const char *dbname)
 	const char *p;
 	int			ret;
 
-	appendPQExpBuffer(cmd, "%s %s -Fp '", pgdumploc, pgdumpopts->data);
+	appendPQExpBuffer(cmd, "\"%s\" %s -Fp '", pg_dump_bin, pgdumpopts->data);
 
 	/* Shell quoting is not quite like SQL quoting, so can't use fmtId */
 	for (p = dbname; *p; p++)
@@ -792,51 +811,3 @@ executeQuery(PGconn *conn, const char *query)
 
 	return res;
 }
-
-
-
-/*
- * Find location of pg_dump executable.
- */
-static char *
-findPgDump(const char *argv0)
-{
-	char	   *last;
-	PQExpBuffer cmd;
-	static char *result = NULL;
-
-	if (result)
-		return result;
-
-	cmd = createPQExpBuffer();
-	last = last_path_separator(argv0);
-
-	if (!last)
-		appendPQExpBuffer(cmd, "pg_dump");
-	else
-	{
-		char	   *dir = strdup(argv0);
-
-		*(dir + (last - argv0)) = '\0';
-		appendPQExpBuffer(cmd, "%s/pg_dump", dir);
-	}
-
-	result = strdup(cmd->data);
-
-	appendPQExpBuffer(cmd, " -V >/dev/null 2>&1");
-	if (system(cmd->data) == 0)
-		goto end;
-
-	result = BINDIR "/pg_dump";
-	if (system(BINDIR "/pg_dump -V >/dev/null 2>&1") == 0)
-		goto end;
-
-	fprintf(stderr, _("%s: could not find pg_dump\n"
-		"Make sure it is in the path or in the same directory as %s.\n"),
-			progname, progname);
-	exit(1);
-
-end:
-	destroyPQExpBuffer(cmd);
-	return result;
-}
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 76f2d086aea08298cbc087e6c05bc8db552e2f8a..fc312b3d74baafee9656be7851ae25e00ecb30b7 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.156 2004/04/12 16:19:18 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.157 2004/05/11 21:57:15 momjian Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to
@@ -254,10 +254,6 @@ extern void SetSessionAuthorization(AclId userid, bool is_superuser);
 
 extern void SetDataDir(const char *dir);
 
-extern int FindExec(char *full_path, const char *argv0,
-		 const char *binary_name);
-extern int	CheckPathAccess(char *path, char *name, int open_mode);
-
 /* in utils/misc/superuser.c */
 extern bool superuser(void);	/* current user is superuser */
 extern bool superuser_arg(AclId userid);		/* given user is superuser */
diff --git a/src/include/port.h b/src/include/port.h
index 2f5123483bf204b7f2d92698b8f79f95c4748dc2..177c82f8c4e7b8f64a6056db64991f3ad4f5ab2b 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/port.h,v 1.28 2004/05/07 00:24:58 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/port.h,v 1.29 2004/05/11 21:57:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,20 @@ extern char *last_path_separator(const char *filename);
 extern void canonicalize_path(char *path);
 extern char *get_progname(char *argv0);
 
+/* Portable way to find binaries */
+extern int find_my_binary(char *full_path, const char *argv0,
+					 const char *binary_name);
+extern int find_other_binary(char *retpath, const char *argv0, const char *progname,
+					   char const *target, const char *versionstr);
+
+#if defined(__CYGWIN__) || defined(WIN32)
+#define EXE ".exe"
+#define DEVNULL "nul"
+#else
+#define EXE ""
+#define DEVNULL "/dev/null"
+#endif
+
 /* Portable delay handling */
 extern void pg_usleep(long microsec);
 
@@ -57,6 +71,7 @@ extern int pgpipe(int handles[2]);
 extern int piperead(int s, char* buf, int len);
 #define pipewrite(a,b,c)	send(a,b,c,0)
 #endif
+extern int pclose_check(FILE *stream);
 
 #if defined(__MINGW32__) || defined(__CYGWIN__)
 /*
diff --git a/src/backend/utils/init/findbe.c b/src/port/exec.c
similarity index 55%
rename from src/backend/utils/init/findbe.c
rename to src/port/exec.c
index 035ff0553aa8033386e8132a4d35df68f61d40a3..27e66cc0c8f74d99809839b1ed4baf11a48b6c5e 100644
--- a/src/backend/utils/init/findbe.c
+++ b/src/port/exec.c
@@ -1,17 +1,22 @@
 /*-------------------------------------------------------------------------
  *
- * findbe.c
+ * exec.c
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/init/findbe.c,v 1.42 2004/03/15 16:18:43 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/port/exec.c,v 1.1 2004/05/11 21:57:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
+
+#ifndef FRONTEND
 #include "postgres.h"
+#else
+#include "postgres_fe.h"
+#endif
 
 #include <grp.h>
 #include <pwd.h>
@@ -32,16 +37,24 @@
 #define S_IXOTH		 ((S_IXUSR)>>6)
 #endif
 
+#ifndef FRONTEND
+/* We use only 3-parameter elog calls in this file, for simplicity */
+#define log_debug(str, param)	elog(DEBUG2, str, param)
+#else
+#define log_debug(str, param)	{}	/* do nothing */
+#endif
+
+static void win32_make_absolute(char *path);
 
 /*
- * ValidateBinary -- validate "path" as a POSTMASTER/POSTGRES executable file
+ * validate_exec -- validate "path" as an executable file
  *
  * returns 0 if the file is found and no error is encountered.
  *		  -1 if the regular file "path" does not exist or cannot be executed.
  *		  -2 if the file is otherwise valid but cannot be read.
  */
 static int
-ValidateBinary(char *path)
+validate_exec(char *path)
 {
 	struct stat buf;
 
@@ -59,7 +72,8 @@ ValidateBinary(char *path)
 
 #ifdef WIN32
 	/* Win32 requires a .exe suffix for stat() */
-	if (strlen(path) >= 4 && strcmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
+	if (strlen(path) >= strlen(".exe") &&
+		pg_strcasecmp(path + strlen(path) - strlen(".exe"), ".exe") != 0)
 	{
 		strcpy(path_exe, path);
 		strcat(path_exe, ".exe");
@@ -75,22 +89,18 @@ ValidateBinary(char *path)
 	 */
 	if (stat(path, &buf) < 0)
 	{
-		elog(DEBUG3, "could not stat \"%s\": %m", path);
+		log_debug("could not stat \"%s\": %m", path);
 		return -1;
 	}
 
 	if ((buf.st_mode & S_IFMT) != S_IFREG)
 	{
-		elog(DEBUG3, "\"%s\" is not a regular file", path);
+		log_debug("\"%s\" is not a regular file", path);
 		return -1;
 	}
 
 	/*
-	 * Ensure that we are using an authorized backend.
-	 *
-	 * XXX I'm open to suggestions here.  I would like to enforce ownership
-	 * of binaries by user "postgres" but people seem to like to run as
-	 * users other than "postgres"...
+	 * Ensure that we are using an authorized executable.
 	 */
 
 	/*
@@ -103,23 +113,28 @@ ValidateBinary(char *path)
 	return is_x ? (is_r ? 0 : -2) : -1;
 #else
 	euid = geteuid();
+
+	/* If owned by us, just check owner bits */
 	if (euid == buf.st_uid)
 	{
 		is_r = buf.st_mode & S_IRUSR;
 		is_x = buf.st_mode & S_IXUSR;
 		if (!(is_r && is_x))
-			elog(DEBUG3, "\"%s\" is not user read/execute", path);
+			log_debug("\"%s\" is not user read/execute", path);
 		return is_x ? (is_r ? 0 : -2) : -1;
 	}
-	pwp = getpwuid(euid);
+
+	/* OK, check group bits */
+	
+	pwp = getpwuid(euid);	/* not thread-safe */
 	if (pwp)
 	{
-		if (pwp->pw_gid == buf.st_gid)
+		if (pwp->pw_gid == buf.st_gid)	/* my primary group? */
 			++in_grp;
 		else if (pwp->pw_name &&
-				 (gp = getgrgid(buf.st_gid)) != NULL &&
+				 (gp = getgrgid(buf.st_gid)) != NULL && /* not thread-safe */
 				 gp->gr_mem != NULL)
-		{
+		{	/* try list of member groups */
 			for (i = 0; gp->gr_mem[i]; ++i)
 			{
 				if (!strcmp(gp->gr_mem[i], pwp->pw_name))
@@ -134,28 +149,35 @@ ValidateBinary(char *path)
 			is_r = buf.st_mode & S_IRGRP;
 			is_x = buf.st_mode & S_IXGRP;
 			if (!(is_r && is_x))
-				elog(DEBUG3, "\"%s\" is not group read/execute", path);
+				log_debug("\"%s\" is not group read/execute", path);
 			return is_x ? (is_r ? 0 : -2) : -1;
 		}
 	}
+
+	/* Check "other" bits */
 	is_r = buf.st_mode & S_IROTH;
 	is_x = buf.st_mode & S_IXOTH;
 	if (!(is_r && is_x))
-		elog(DEBUG3, "\"%s\" is not other read/execute", path);
+		log_debug("\"%s\" is not other read/execute", path);
 	return is_x ? (is_r ? 0 : -2) : -1;
+
 #endif
 }
 
 /*
- * FindExec -- find an absolute path to a valid backend executable
+ * find_my_binary -- find an absolute path to a valid executable
  *
  * The reason we have to work so hard to find an absolute path is that
  * on some platforms we can't do dynamic loading unless we know the
  * executable's location.  Also, we need a full path not a relative
  * path because we will later change working directory.
+ *
+ * This function is not thread-safe because of it calls validate_exec(),
+ * which calls getgrgid().  This function should be used only in
+ * non-threaded binaries, not in library routines.
  */
 int
-FindExec(char *full_path, const char *argv0, const char *binary_name)
+find_my_binary(char *full_path, const char *argv0, const char *binary_name)
 {
 	char		buf[MAXPGPATH + 2];
 	char	   *p;
@@ -164,13 +186,13 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 			   *endp;
 
 	/*
-	 * for the postmaster: First try: use the binary that's located in the
-	 * same directory as the postmaster, if it was invoked with an
-	 * explicit path. Presumably the user used an explicit path because it
+	 * First try: use the binary that's located in the
+	 * same directory if it was invoked with an explicit path.
+	 * Presumably the user used an explicit path because it
 	 * wasn't in PATH, and we don't want to use incompatible executables.
 	 *
 	 * This has the neat property that it works for installed binaries, old
-	 * source trees (obj/support/post{master,gres}) and new marc source
+	 * source trees (obj/support/post{master,gres}) and new source
 	 * trees (obj/post{master,gres}) because they all put the two binaries
 	 * in the same place.
 	 *
@@ -187,13 +209,14 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 		strcat(buf, argv0);
 		p = last_path_separator(buf);
 		strcpy(++p, binary_name);
-		if (ValidateBinary(buf) == 0)
+		if (validate_exec(buf) == 0)
 		{
 			strncpy(full_path, buf, MAXPGPATH);
-			elog(DEBUG2, "found \"%s\" using argv[0]", full_path);
+			win32_make_absolute(full_path);
+			log_debug("found \"%s\" using argv[0]", full_path);
 			return 0;
 		}
-		elog(DEBUG2, "invalid binary \"%s\"", buf);
+		log_debug("invalid binary \"%s\"", buf);
 		return -1;
 	}
 
@@ -203,7 +226,7 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 	 */
 	if ((p = getenv("PATH")) && *p)
 	{
-		elog(DEBUG2, "searching PATH for executable");
+		log_debug("searching PATH for executable%s", "");
 		path = strdup(p);		/* make a modifiable copy */
 		for (startp = path, endp = strchr(path, PATHSEP);
 			 startp && *startp;
@@ -220,17 +243,18 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 			strcat(buf, startp);
 			strcat(buf, "/");
 			strcat(buf, binary_name);
-			switch (ValidateBinary(buf))
+			switch (validate_exec(buf))
 			{
 				case 0: /* found ok */
 					strncpy(full_path, buf, MAXPGPATH);
-					elog(DEBUG2, "found \"%s\" using PATH", full_path);
+					win32_make_absolute(full_path);
+					log_debug("found \"%s\" using PATH", full_path);
 					free(path);
 					return 0;
 				case -1:		/* wasn't even a candidate, keep looking */
 					break;
 				case -2:		/* found but disqualified */
-					elog(DEBUG2, "could not read binary \"%s\"", buf);
+					log_debug("could not read binary \"%s\"", buf);
 					free(path);
 					return -1;
 			}
@@ -240,6 +264,77 @@ FindExec(char *full_path, const char *argv0, const char *binary_name)
 		free(path);
 	}
 
-	elog(DEBUG2, "could not find a \"%s\" to execute", binary_name);
+	log_debug("could not find a \"%s\" to execute", binary_name);
 	return -1;
 }
+
+
+/*
+ * Find our binary directory, then make sure the "target" executable
+ * is the proper version.
+ */
+int find_other_binary(char *retpath, const char *argv0, const char *progname,
+			    char const *target, const char *versionstr)
+{
+	char		cmd[MAXPGPATH];
+	char		line[100];
+	FILE	   *pgver;
+
+	if (find_my_binary(retpath, argv0, progname) < 0)
+		return -1;
+
+	/* Trim off program name and keep just directory */	
+	*last_path_separator(retpath) = '\0';
+
+	snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
+			 "/%s%s", target, EXE);
+
+	if (validate_exec(retpath))
+		return -1;
+	
+	snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL);
+
+	/* flush output buffers in case popen does not... */
+	fflush(stdout);
+	fflush(stderr);
+
+	if ((pgver = popen(cmd, "r")) == NULL)
+		return -1;
+
+	if (fgets(line, sizeof(line), pgver) == NULL)
+		perror("fgets failure");
+
+	if (pclose_check(pgver))
+		return -1;
+
+	if (strcmp(line, versionstr) != 0)
+		return -2;
+
+	return 0;
+}
+
+
+/*
+ * Windows doesn't like relative paths to executables (other things work fine)
+ * so we call its builtin function to expand them. Elsewhere this is a NOOP
+ *
+ * Returns malloc'ed memory.
+ */
+static void
+win32_make_absolute(char *path)
+{
+#ifdef WIN32
+	char		abspath[MAXPGPATH];
+
+	if (_fullpath(abspath, path, MAXPGPATH) == NULL)
+	{
+		log_debug("Win32 path expansion failed:  %s", strerror());
+		return path;
+	}
+	canonicalize_path(abspath);
+
+	StrNCpy(path, abspath, MAXPGPATH);
+#endif
+	return;
+}
+
diff --git a/src/port/path.c b/src/port/path.c
index 3f672d5b22e72789646193c5a7a4e51df5ec2c87..965d63ea330f5e32be8a510b1947dfde84e393bb 100644
--- a/src/port/path.c
+++ b/src/port/path.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/path.c,v 1.5 2004/03/09 04:49:02 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/port/path.c,v 1.6 2004/05/11 21:57:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,3 +121,4 @@ get_progname(char *argv0)
 	else
 		return last_path_separator(argv0) + 1;
 }
+
diff --git a/src/port/pipe.c b/src/port/pipe.c
index 4a707f7335c677a6d30a0fb21452391581833c50..9fdab8ca738777e8d804c980ab76b6c0dae643d2 100644
--- a/src/port/pipe.c
+++ b/src/port/pipe.c
@@ -10,13 +10,18 @@
  *	must be replaced with recv/send.
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/pipe.c,v 1.2 2004/04/19 17:42:59 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/port/pipe.c,v 1.3 2004/05/11 21:57:15 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include <sys/wait.h>
+
+#define _(x) gettext((x))
+
+#ifdef WIN32
 int
 pgpipe(int handles[2])
 {
@@ -63,3 +68,42 @@ int piperead(int s, char* buf, int len)
 		ret = 0;
 	return ret;
 }
+#endif
+
+/*
+ * pclose() plus useful error reporting
+ * Is this necessary?  bjm 2004-05-11
+ */
+int
+pclose_check(FILE *stream)
+{
+	int		exitstatus;
+
+	exitstatus = pclose(stream);
+
+	if (exitstatus == 0)
+		return 0;					/* all is well */
+
+	if (exitstatus == -1)
+	{
+		/* pclose() itself failed, and hopefully set errno */
+		perror("pclose failed");
+	}
+	else if (WIFEXITED(exitstatus))
+	{
+		fprintf(stderr, _("child process exited with exit code %d\n"),
+				WEXITSTATUS(exitstatus));
+	}
+	else if (WIFSIGNALED(exitstatus))
+	{
+		fprintf(stderr, _("child process was terminated by signal %d\n"),
+				WTERMSIG(exitstatus));
+	}
+	else
+	{
+		fprintf(stderr, _("child process exited with unrecognized status %d\n"),
+				exitstatus);
+	}
+
+	return -1;
+}