diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml
index 141eaaa0bf178789cf6af154f48fd7574fc3cd6a..fbfed9220b3bd13b621524bc9296ad92f655e9a8 100644
--- a/doc/src/sgml/regress.sgml
+++ b/doc/src/sgml/regress.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/regress.sgml,v 1.53 2006/07/19 02:37:00 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/regress.sgml,v 1.54 2006/07/19 17:02:59 tgl Exp $ -->
 
  <chapter id="regress">
   <title id="regress-title">Regression Tests</title>
@@ -96,11 +96,10 @@ gmake check
    <para>
     The parallel regression test starts quite a few processes under your
     user ID.  Presently, the maximum concurrency is twenty parallel test
-    scripts, which means sixty processes: there's a server process, a
-    <application>psql</>, and usually a shell parent process for the
-    <application>psql</> for each test script.
+    scripts, which means forty processes: there's a server process and a
+    <application>psql</> process for each test script.
     So if your system enforces a per-user limit on the number of processes,
-    make sure this limit is at least seventy-five or so, else you may get
+    make sure this limit is at least fifty or so, else you may get
     random-seeming failures in the parallel test.  If you are not in
     a position to raise the limit, you can cut down the degree of parallelism
     by setting the <literal>MAX_CONNECTIONS</> parameter.  For example,
diff --git a/src/test/regress/GNUmakefile b/src/test/regress/GNUmakefile
index c9081d503f7da1cbb0ad007df52857428e4bd9e2..792ff4a98fc7376858d3c416a888b512805ca8c1 100644
--- a/src/test/regress/GNUmakefile
+++ b/src/test/regress/GNUmakefile
@@ -6,7 +6,7 @@
 # Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
 # Portions Copyright (c) 1994, Regents of the University of California
 #
-# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.59 2006/07/19 04:02:31 tgl Exp $
+# $PostgreSQL: pgsql/src/test/regress/GNUmakefile,v 1.60 2006/07/19 17:02:59 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -39,7 +39,8 @@ EXTRADEFS = '-DPGBINDIR="$(bindir)"' \
 	'-DLIBDIR="$(libdir)"' \
 	'-DPGSHAREDIR="$(datadir)"' \
 	'-DHOST_TUPLE="$(host_tuple)"' \
-	'-DMAKEPROG="$(MAKE)"'
+	'-DMAKEPROG="$(MAKE)"' \
+	'-DSHELLPROG="$(SHELL)"'
 
 ##
 ## Prepare for tests
diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c
index 1704da5033ddfc4bec7f01488d9ba64d639e17c1..ad3d0cd3e1bc0bbd6463627421f1fc7c7014f413 100644
--- a/src/test/regress/pg_regress.c
+++ b/src/test/regress/pg_regress.c
@@ -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/test/regress/pg_regress.c,v 1.4 2006/07/19 16:23:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/test/regress/pg_regress.c,v 1.5 2006/07/19 17:02:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -60,6 +60,7 @@ static char *libdir = LIBDIR;
 static char *datadir = PGSHAREDIR;
 static char *host_platform = HOST_TUPLE;
 static char *makeprog = MAKEPROG;
+static char *shellprog = SHELLPROG;
 
 /* currently we can use the same diff switches on all platforms */
 static const char *basic_diff_opts = "-w";
@@ -630,8 +631,20 @@ spawn_process(const char *cmdline)
 	}
 	if (pid == 0)
 	{
-		/* In child */
-		exit(system(cmdline) ? 1 : 0);
+		/*
+		 * In child
+		 *
+		 * Instead of using system(), exec the shell directly, and tell it
+		 * to "exec" the command too.  This saves two useless processes
+		 * per parallel test case.
+		 */
+		char *cmdline2 = malloc(strlen(cmdline) + 6);
+
+		sprintf(cmdline2, "exec %s", cmdline);
+		execl(shellprog, shellprog, "-c", cmdline2, NULL);
+		fprintf(stderr, _("%s: could not exec \"%s\": %s\n"),
+				progname, shellprog, strerror(errno));
+		exit(1);				/* not exit_nicely here... */
 	}
 	/* in parent */
 	return pid;
@@ -648,7 +661,7 @@ spawn_process(const char *cmdline)
 
 	if (!CreateProcess(NULL, cmdline2, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
 	{
-		fprintf(stderr, _("failed to start process for \"%s\": %lu\n"),
+		fprintf(stderr, _("could not start process for \"%s\": %lu\n"),
 				cmdline2, GetLastError());
 		exit_nicely(2);
 	}
@@ -684,7 +697,7 @@ psql_start_test(const char *testname)
 
 	if (pid == INVALID_PID)
 	{
-		fprintf(stderr, _("failed to start process for test %s\n"),
+		fprintf(stderr, _("could not start process for test %s\n"),
 				testname);
 		exit_nicely(2);
 	}
@@ -918,7 +931,7 @@ wait_for_tests(PID_TYPE *pids, int num_tests)
 
 		if (p == -1)
 		{
-			fprintf(stderr, _("failed to wait(): %s\n"), strerror(errno));
+			fprintf(stderr, _("could not wait(): %s\n"), strerror(errno));
 			exit_nicely(2);
 		}
 		for (i=0; i < num_tests; i++)
@@ -938,7 +951,7 @@ wait_for_tests(PID_TYPE *pids, int num_tests)
 	r = WaitForMultipleObjects(num_tests, pids, TRUE, INFINITE);
 	if (r != WAIT_OBJECT_0)
 	{
-		fprintf(stderr, _("failed to wait for commands to finish: %lu\n"),
+		fprintf(stderr, _("could not wait for commands to finish: %lu\n"),
 				GetLastError());
 		exit_nicely(2);
 	}
@@ -1228,7 +1241,7 @@ main(int argc, char *argv[])
 	int c;
 	int i;
 	int option_index;
-	char buf[MAXPGPATH];
+	char buf[MAXPGPATH * 4];
 
 	static struct option long_options[] = {
 		{"help", no_argument, NULL, 'h'},
@@ -1431,14 +1444,6 @@ main(int argc, char *argv[])
 			exit_nicely(2);
 		}
 
-		/*
-		 * XXX Note that because we use system() to launch the subprocess,
-		 * the returned postmaster_pid is not really the PID of the
-		 * postmaster itself; on most systems it'll be the PID of a parent
-		 * shell process.  This is OK for the limited purposes we currently
-		 * use postmaster_pid for, but beware!
-		 */
-
 		/*
 		 * Wait till postmaster is able to accept connections (normally only
 		 * a second or so, but Cygwin is reportedly *much* slower).  Don't