diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 96d7d1e3ad9c1bdd64445084b46f65d2a350eed5..6334cdd7e37a9d826c4e008a529aed0f676c0ef5 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -28,7 +28,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.217 2001/06/07 04:50:57 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.218 2001/06/11 04:12:29 tgl Exp $
  *
  * NOTES
  *
@@ -243,9 +243,14 @@ static void RandomSalt(char *salt);
 static void SignalChildren(int signal);
 static int	CountChildren(void);
 static bool CreateOptsFile(int argc, char *argv[]);
-static void postmaster_error(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
-
 static pid_t SSDataBase(int xlop);
+#ifdef __GNUC__
+/* This checks the format string for consistency. */
+static void postmaster_error(const char *fmt, ...)
+	__attribute__((format(printf, 1, 2)));
+#else
+static void postmaster_error(const char *fmt, ...);
+#endif
 
 #define StartupDataBase()		SSDataBase(BS_XLOG_STARTUP)
 #define CheckPointDataBase()	SSDataBase(BS_XLOG_CHECKPOINT)
@@ -253,7 +258,6 @@ static pid_t SSDataBase(int xlop);
 
 #ifdef USE_SSL
 static void InitSSL(void);
-
 #endif
 
 
@@ -596,6 +600,12 @@ PostmasterMain(int argc, char *argv[])
 	if (!CreateDataDirLockFile(DataDir, true))
 		ExitPostmaster(1);
 
+	/*
+	 * Remove old temporary files.  At this point there can be no other
+	 * Postgres processes running in this directory, so this should be safe.
+	 */
+	RemovePgTempFiles();
+
 	/*
 	 * Establish input sockets.
 	 */
@@ -613,7 +623,8 @@ PostmasterMain(int argc, char *argv[])
 	if (NetServer)
 	{
 		status = StreamServerPort(AF_INET, VirtualHost,
-						  (unsigned short) PostPortNumber, UnixSocketDir,
+								  (unsigned short) PostPortNumber,
+								  UnixSocketDir,
 								  &ServerSock_INET);
 		if (status != STATUS_OK)
 		{
@@ -624,7 +635,8 @@ PostmasterMain(int argc, char *argv[])
 
 #ifdef HAVE_UNIX_SOCKETS
 	status = StreamServerPort(AF_UNIX, VirtualHost,
-						  (unsigned short) PostPortNumber, UnixSocketDir,
+							  (unsigned short) PostPortNumber,
+							  UnixSocketDir,
 							  &ServerSock_UNIX);
 	if (status != STATUS_OK)
 	{
diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c
index 237ae0a442807ba6238e6b12950d5037ab586d1d..f37a9573df935b313d2f996783925803a54d559c 100644
--- a/src/backend/storage/file/fd.c
+++ b/src/backend/storage/file/fd.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.80 2001/06/06 17:07:46 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/file/fd.c,v 1.81 2001/06/11 04:12:29 tgl Exp $
  *
  * NOTES:
  *
@@ -44,6 +44,7 @@
 #include <sys/file.h>
 #include <sys/param.h>
 #include <sys/stat.h>
+#include <dirent.h>
 #include <errno.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -51,6 +52,12 @@
 #include "miscadmin.h"
 #include "storage/fd.h"
 
+
+/* Filename components for OpenTemporaryFile */
+#define PG_TEMP_FILES_DIR "pg_tempfiles"
+#define PG_TEMP_FILE_PREFIX "pg_temp"
+
+
 /*
  * Problem: Postgres does a system(ld...) to do dynamic loading.
  * This will open several extra files in addition to those used by
@@ -189,7 +196,7 @@ static void FreeVfd(File file);
 
 static int	FileAccess(File file);
 static File fileNameOpenFile(FileName fileName, int fileFlags, int fileMode);
-static char *filepath(char *filename);
+static char *filepath(const char *filename);
 static long pg_nofile(void);
 
 /*
@@ -568,28 +575,27 @@ FreeVfd(File file)
 /* filepath()
  * Convert given pathname to absolute.
  *
+ * Result is a palloc'd string.
+ *
  * (Generally, this isn't actually necessary, considering that we
  * should be cd'd into the database directory.  Presently it is only
  * necessary to do it in "bootstrap" mode.	Maybe we should change
  * bootstrap mode to do the cd, and save a few cycles/bytes here.)
  */
 static char *
-filepath(char *filename)
+filepath(const char *filename)
 {
 	char	   *buf;
-	int			len;
 
 	/* Not an absolute path name? Then fill in with database path... */
 	if (*filename != '/')
 	{
-		len = strlen(DatabasePath) + strlen(filename) + 2;
-		buf = (char *) palloc(len);
+		buf = (char *) palloc(strlen(DatabasePath) + strlen(filename) + 2);
 		sprintf(buf, "%s/%s", DatabasePath, filename);
 	}
 	else
 	{
-		buf = (char *) palloc(strlen(filename) + 1);
-		strcpy(buf, filename);
+		buf = pstrdup(filename);
 	}
 
 #ifdef FILEDEBUG
@@ -742,21 +748,46 @@ PathNameOpenFile(FileName fileName, int fileFlags, int fileMode)
 File
 OpenTemporaryFile(void)
 {
-	char		tempfilename[64];
+	char		tempfilepath[128];
 	File		file;
 
 	/*
 	 * Generate a tempfile name that's unique within the current
-	 * transaction
+	 * transaction and database instance.
 	 */
-	snprintf(tempfilename, sizeof(tempfilename),
-			 "pg_sorttemp%d.%ld", MyProcPid, tempFileCounter++);
+	snprintf(tempfilepath, sizeof(tempfilepath),
+			 "%s/%s%d.%ld", PG_TEMP_FILES_DIR, PG_TEMP_FILE_PREFIX,
+			 MyProcPid, tempFileCounter++);
 
-	/* Open the file */
-	file = FileNameOpenFile(tempfilename,
-							O_RDWR | O_CREAT | O_TRUNC | PG_BINARY, 0600);
+	/*
+	 * Open the file.  Note: we don't use O_EXCL, in case there is an
+	 * orphaned temp file that can be reused.
+	 */
+	file = FileNameOpenFile(tempfilepath,
+							O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
+							0600);
 	if (file <= 0)
-		elog(ERROR, "Failed to create temporary file %s", tempfilename);
+	{
+		char   *dirpath;
+
+		/*
+		 * We might need to create the pg_tempfiles subdirectory, if
+		 * no one has yet done so.
+		 *
+		 * Don't check for error from mkdir; it could fail if someone else
+		 * just did the same thing.  If it doesn't work then we'll bomb out
+		 * on the second create attempt, instead.
+		 */
+		dirpath = filepath(PG_TEMP_FILES_DIR);
+		mkdir(dirpath, S_IRWXU);
+		pfree(dirpath);
+
+		file = FileNameOpenFile(tempfilepath,
+								O_RDWR | O_CREAT | O_TRUNC | PG_BINARY,
+								0600);
+		if (file <= 0)
+			elog(ERROR, "Failed to create temporary file %s", tempfilepath);
+	}
 
 	/* Mark it for deletion at close or EOXact */
 	VfdCache[file].fdstate |= FD_TEMPORARY;
@@ -1203,3 +1234,76 @@ AtEOXact_Files(void)
 	 */
 	tempFileCounter = 0;
 }
+
+
+/*
+ * Remove old temporary files
+ *
+ * This should be called during postmaster startup.  It will forcibly
+ * remove any leftover files created by OpenTemporaryFile.
+ */
+void
+RemovePgTempFiles(void)
+{
+	char 		db_path[MAXPGPATH];
+	char 		temp_path[MAXPGPATH];
+	char 		rm_path[MAXPGPATH];
+	DIR		   *db_dir;
+	DIR		   *temp_dir;
+	struct dirent  *db_de;
+	struct dirent  *temp_de;
+
+	/*
+	 * Cycle through pg_tempfiles for all databases
+	 * and remove old temp files.
+	 */
+	snprintf(db_path, sizeof(db_path), "%s/base", DataDir);
+	if ((db_dir = opendir(db_path)) != NULL)
+	{
+		while ((db_de = readdir(db_dir)) != NULL)
+		{
+			if (strcmp(db_de->d_name, ".") == 0 ||
+				strcmp(db_de->d_name, "..") == 0)
+				continue;
+
+			snprintf(temp_path, sizeof(temp_path),
+					 "%s/%s/%s",
+					 db_path, db_de->d_name,
+					 PG_TEMP_FILES_DIR);
+			if ((temp_dir = opendir(temp_path)) != NULL)
+			{
+				while ((temp_de = readdir(temp_dir)) != NULL)
+				{
+					if (strcmp(temp_de->d_name, ".") == 0 ||
+						strcmp(temp_de->d_name, "..") == 0)
+						continue;
+
+					snprintf(rm_path, sizeof(temp_path),
+							 "%s/%s/%s/%s",
+							 db_path, db_de->d_name,
+							 PG_TEMP_FILES_DIR,
+							 temp_de->d_name);
+
+					if (strncmp(temp_de->d_name,
+								PG_TEMP_FILE_PREFIX,
+								strlen(PG_TEMP_FILE_PREFIX)) == 0)
+					{
+						unlink(rm_path);
+					}
+					else
+					{
+						/*
+						 * would prefer to use elog here, but it's not
+						 * up and running during postmaster startup...
+						 */
+						fprintf(stderr,
+								"Unexpected file found in temporary-files directory: %s\n",
+								rm_path);
+					}
+				}
+				closedir(temp_dir);
+			}
+		}
+		closedir(db_dir);
+	}
+}
diff --git a/src/include/storage/fd.h b/src/include/storage/fd.h
index 6bb690c3f5713894e358126cd1cfab7f8b39266e..f3e06978a67ed5c4825851bf905d3e3078e3a398 100644
--- a/src/include/storage/fd.h
+++ b/src/include/storage/fd.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fd.h,v 1.29 2001/05/25 15:45:34 momjian Exp $
+ * $Id: fd.h,v 1.30 2001/06/11 04:12:29 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,6 +70,7 @@ extern int	BasicOpenFile(FileName fileName, int fileFlags, int fileMode);
 /* Miscellaneous support routines */
 extern void closeAllVfds(void);
 extern void AtEOXact_Files(void);
+extern void RemovePgTempFiles(void);
 extern int	pg_fsync(int fd);
 extern int	pg_fdatasync(int fd);