? src/Makefile.global
? src/int2arrayveceq.diff
? src/backend/postgres
? src/backend/catalog/postgres.bki
? src/backend/catalog/postgres.description
? src/backend/postmaster/pm
? src/backend/postmaster/syslogger.c
? src/backend/storage/ipc/.new.ipc.c
? src/backend/utils/adt/arrayfuncs-ap.c
? src/backend/utils/adt/misc-ap.c
? src/backend/utils/adt/misc.target
? src/backend/utils/error/elog-ap.c
? src/backend/utils/mb/conversion_procs/conversion_create.sql
? src/backend/utils/mb/conversion_procs/ascii_and_mic/libascii_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/cyrillic_and_mic/libcyrillic_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_cn_and_mic/libeuc_cn_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/libeuc_jp_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/euc_kr_and_mic/libeuc_kr_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/euc_tw_and_big5/libeuc_tw_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/latin2_and_win1250/liblatin2_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/latin_and_mic/liblatin_and_mic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_ascii/libutf8_and_ascii.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_big5/libutf8_and_big5.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/libutf8_and_cyrillic.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/libutf8_and_euc_cn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/libutf8_and_euc_jp.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/libutf8_and_euc_kr.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/libutf8_and_euc_tw.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gb18030/libutf8_and_gb18030.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_gbk/libutf8_and_gbk.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859/libutf8_and_iso8859.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/libutf8_and_iso8859_1.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_johab/libutf8_and_johab.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_sjis/libutf8_and_sjis.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_tcvn/libutf8_and_tcvn.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_uhc/libutf8_and_uhc.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1250/libutf8_and_win1250.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win1256/libutf8_and_win1256.so.0.0
? src/backend/utils/mb/conversion_procs/utf8_and_win874/libutf8_and_win874.so.0.0
? src/bin/initdb/initdb
? src/bin/initlocation/initlocation
? src/bin/ipcclean/ipcclean
? src/bin/pg_config/pg_config
? src/bin/pg_controldata/pg_controldata
? src/bin/pg_ctl/pg_ctl
? src/bin/pg_dump/pg_dump
? src/bin/pg_dump/pg_dumpall
? src/bin/pg_dump/pg_restore
? src/bin/pg_encoding/pg_encoding
? src/bin/pg_id/pg_id
? src/bin/pg_resetxlog/pg_resetxlog
? src/bin/psql/psql
? src/bin/scripts/clusterdb
? src/bin/scripts/createdb
? src/bin/scripts/createlang
? src/bin/scripts/createuser
? src/bin/scripts/dropdb
? src/bin/scripts/droplang
? src/bin/scripts/dropuser
? src/bin/scripts/vacuumdb
? src/include/pg_config.h
? src/include/stamp-h
? src/include/postmaster/syslogger.h
? src/interfaces/ecpg/compatlib/libecpg_compat.so.1.1
? src/interfaces/ecpg/ecpglib/libecpg.so.4.1
? src/interfaces/ecpg/ecpglib/libecpg.so.4.2
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.1.1
? src/interfaces/ecpg/pgtypeslib/libpgtypes.so.1.2
? src/interfaces/ecpg/preproc/ecpg
? src/interfaces/libpq/libpq.so.3.2
? src/interfaces/libpq/sav
? src/pl/plpgsql/src/libplpgsql.so.1.0
? src/pl/plpgsql/src/sav
? src/port/pg_config_paths.h
? src/timezone/zic
? src/tools/thread/thread_test.diff
Index: src/backend/postmaster/Makefile
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/Makefile,v
retrieving revision 1.15
diff -u -r1.15 Makefile
--- src/backend/postmaster/Makefile	29 May 2004 22:48:19 -0000	1.15
+++ src/backend/postmaster/Makefile	18 Jul 2004 22:13:57 -0000
@@ -12,7 +12,7 @@
 top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = postmaster.o bgwriter.o pgstat.o
+OBJS = postmaster.o bgwriter.o pgstat.o syslogger.o
 
 all: SUBSYS.o
 
Index: src/backend/postmaster/postmaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/postmaster/postmaster.c,v
retrieving revision 1.411
diff -u -r1.411 postmaster.c
--- src/backend/postmaster/postmaster.c	12 Jul 2004 19:14:56 -0000	1.411
+++ src/backend/postmaster/postmaster.c	18 Jul 2004 22:14:03 -0000
@@ -117,7 +117,7 @@
 #include "utils/ps_status.h"
 #include "bootstrap/bootstrap.h"
 #include "pgstat.h"
-
+#include "postmaster/syslogger.h"
 
 /*
  * List of active backends (or child processes anyway; we don't actually
@@ -199,6 +199,7 @@
 static pid_t StartupPID = 0,
 			BgWriterPID = 0,
 			PgStatPID = 0;
+pid_t       SysLoggerPID = 0;
 
 /* Startup/shutdown state */
 #define			NoShutdown		0
@@ -849,6 +850,12 @@
 #endif
 
 	/*
+	 * start logging to file
+	 */ 
+
+    SysLoggerPID = SysLogger_Start();
+
+	/*
 	 * Reset whereToSendOutput from Debug (its starting state) to None.
 	 * This prevents ereport from sending log messages to stderr unless
 	 * the syslog/stderr switch permits.  We don't do this until the
@@ -1222,6 +1229,11 @@
 			StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
 			PgStatPID = pgstat_start();
 
+		/* If we have lost the system logger, try to start a new one */
+		if (SysLoggerPID == 0 &&
+			StartupPID == 0 && !FatalError && Shutdown == NoShutdown)
+			SysLoggerPID = SysLogger_Start();
+
 		/*
 		 * Touch the socket and lock file at least every ten minutes, to ensure
 		 * that they are not removed by overzealous /tmp-cleaning tasks.
@@ -1760,6 +1772,8 @@
 		SignalChildren(SIGHUP);
 		if (BgWriterPID != 0)
 			kill(BgWriterPID, SIGHUP);
+		if (SysLoggerPID != 0)
+			kill(SysLoggerPID, SIGHUP);
 		/* PgStatPID does not currently need SIGHUP */
 		load_hba();
 		load_ident();
@@ -1822,7 +1836,6 @@
 			if (PgStatPID != 0)
 				kill(PgStatPID, SIGQUIT);
 			break;
-
 		case SIGINT:
 			/*
 			 * Fast Shutdown:
@@ -1884,6 +1897,7 @@
 				kill(PgStatPID, SIGQUIT);
 			if (DLGetHead(BackendList))
 				SignalChildren(SIGQUIT);
+
 			ExitPostmaster(0);
 			break;
 	}
@@ -2020,6 +2034,15 @@
 			continue;
 		}
 
+		/* was it the system logger, try to start a new one */
+		if (SysLoggerPID != 0 && pid == SysLoggerPID)
+		{
+			if (exitstatus != 0)
+				LogChildExit(LOG, gettext("system logger process"),
+							 pid, exitstatus);
+			SysLoggerPID = SysLogger_Start();
+			continue;
+		}
 		/*
 		 * Else do standard backend child cleanup.
 		 */
@@ -2895,6 +2918,16 @@
 		PgstatCollectorMain(argc, argv);
 		proc_exit(0);
 	}
+	if (strcmp(argv[1], "-forklog") == 0)
+	{
+		/* Close the postmaster's sockets */
+		ClosePostmasterPorts();
+
+		/* Do not want to attach to shared memory */
+
+		SysLoggerMain(argc, argv);
+		proc_exit(0);
+	}
 
 	return 1;					/* shouldn't get here */
 }
@@ -2951,6 +2984,10 @@
 		if (Shutdown <= SmartShutdown)
 			SignalChildren(SIGUSR1);
 	}
+	if (CheckPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE) && SysLoggerPID != 0)
+	{
+	    kill(SysLoggerPID, SIGUSR1);
+	}
 
 	PG_SETMASK(&UnBlockSig);
 
Index: src/backend/utils/adt/misc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/adt/misc.c,v
retrieving revision 1.35
diff -u -r1.35 misc.c
--- src/backend/utils/adt/misc.c	2 Jul 2004 18:59:22 -0000	1.35
+++ src/backend/utils/adt/misc.c	18 Jul 2004 22:14:04 -0000
@@ -15,6 +15,7 @@
 #include "postgres.h"
 
 #include <sys/file.h>
+#include <unistd.h>
 #include <signal.h>
 #include <dirent.h>
 
@@ -26,6 +27,49 @@
 #include "funcapi.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_tablespace.h"
+#include "postmaster/syslogger.h"
+
+/*-----------------------
+ * some helper functions
+ */
+
+/*
+ * Return an absolute path. Argument may be absolute or 
+ * relative to the DataDir.
+ */
+static char *absClusterPath(text *arg)
+{
+	char *filename;
+	int len=VARSIZE(arg) - VARHDRSZ;
+
+	filename = palloc(len+1);
+	memcpy(filename, VARDATA(arg), len);
+	filename[len] = 0;
+
+	if (is_absolute_path(filename))
+	    return filename;
+	else
+	{
+	    char *absname = palloc(strlen(DataDir)+len+2);
+		sprintf(absname, "%s/%s", DataDir, filename);
+		pfree(filename);
+		return absname;
+	}
+}
+
+
+/*
+ * check for superuser, bark if not.
+ */
+static void
+requireSuperuser(void)
+{
+	if (!superuser())
+	    ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 (errmsg("only superuser may access generic file functions"))));
+}
+
 
 
 /*
@@ -73,10 +117,7 @@
 
 static int pg_signal_backend(int pid, int sig) 
 {
-	if (!superuser()) 
-		ereport(ERROR,
-				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-				 (errmsg("only superuser can signal other backends"))));
+    requireSuperuser();
 	
 	if (!IsBackendPid(pid))
 	{
@@ -109,18 +150,34 @@
 	PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT));
 }
 
+Datum
+pg_reload_conf(PG_FUNCTION_ARGS)
+{
+    requireSuperuser();
+
+	if (kill(PostmasterPid, SIGHUP))
+	{
+		ereport(WARNING,
+				(errmsg("failed to send signal to postmaster: %m")));
+
+		PG_RETURN_INT32(0);
+	}
+
+	PG_RETURN_INT32(1);
+}
+
 
 typedef struct 
 {
 	char *location;
 	DIR *dirdesc;
-} ts_db_fctx;
+} directory_fctx;
 
 Datum pg_tablespace_databases(PG_FUNCTION_ARGS)
 {
 	FuncCallContext *funcctx;
 	struct dirent *de;
-	ts_db_fctx *fctx;
+	directory_fctx *fctx;
 
 	if (SRF_IS_FIRSTCALL())
 	{
@@ -130,7 +187,7 @@
 		funcctx=SRF_FIRSTCALL_INIT();
 		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
 
-		fctx = palloc(sizeof(ts_db_fctx));
+		fctx = palloc(sizeof(directory_fctx));
 
 		/*
 		 * size = path length + tablespace dirname length
@@ -164,7 +221,7 @@
 	}
 
 	funcctx=SRF_PERCALL_SETUP();
-	fctx = (ts_db_fctx*) funcctx->user_fctx;
+	fctx = (directory_fctx*) funcctx->user_fctx;
 
 	if (!fctx->dirdesc)  /* not a tablespace */
 		SRF_RETURN_DONE(funcctx);
@@ -202,3 +259,396 @@
 	FreeDir(fctx->dirdesc);
 	SRF_RETURN_DONE(funcctx);
 }
+
+
+
+/* ------------------------------------
+ * generic file handling functions
+ */
+
+Datum pg_file_length(PG_FUNCTION_ARGS)
+{
+    struct stat fst;
+	char *filename;
+    fst.st_size=0;
+
+	requireSuperuser();
+
+	filename = absClusterPath(PG_GETARG_TEXT_P(0));
+
+	if (stat(filename, &fst) < 0)
+	{
+		ereport(WARNING,
+				(errcode_for_file_access(),
+				 errmsg("could not stat file %s: %m", filename)));
+
+	    PG_RETURN_INT64(-1);
+	}
+  
+	PG_RETURN_INT64(fst.st_size);
+}
+
+
+Datum pg_file_read(PG_FUNCTION_ARGS)
+{
+	size_t size;
+	char *buf=0;
+	size_t nbytes;
+	int8 pos;
+	FILE *f;
+	char *filename;
+
+	requireSuperuser();
+
+	filename = absClusterPath(PG_GETARG_TEXT_P(0));
+	pos = PG_GETARG_INT64(1);
+	size = PG_GETARG_INT64(2);
+
+	f = fopen(filename, "r");
+	if (!f)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not open file %s for reading: %m", filename)));
+		PG_RETURN_NULL();
+	}
+
+	if (pos >= 0)
+	    fseek(f, pos, SEEK_SET);
+	else
+	    fseek(f, pos, SEEK_END);
+
+
+	buf = palloc(size + VARHDRSZ);
+
+	nbytes = fread(VARDATA(buf), 1, size, f);
+	if (nbytes < 0)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not read file %s: %m", filename)));
+		PG_RETURN_NULL();
+	}
+	VARATT_SIZEP(buf) = nbytes + VARHDRSZ;
+	fclose(f);
+
+	PG_RETURN_TEXT_P(buf);
+}
+
+
+Datum pg_file_write(PG_FUNCTION_ARGS)
+{
+	FILE *f;
+	char *filename;
+	text *data;
+	int8 count = 0;
+
+	requireSuperuser();
+
+	filename = absClusterPath(PG_GETARG_TEXT_P(0));
+	data = PG_GETARG_TEXT_P(1);
+
+	if (PG_ARGISNULL(2) || !PG_GETARG_BOOL(2))
+	{
+	    struct stat fst;
+		if (stat(filename, &fst) >= 0)
+		    ereport(ERROR,
+					(ERRCODE_DUPLICATE_FILE,
+					 errmsg("file %s exists", filename)));
+
+	    f = fopen(filename, "w");
+	}
+	else
+	    f = fopen(filename, "a");
+
+	if (!f)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could open file %s for writing: %m", filename)));
+	}
+
+	if (VARSIZE(data) != 0)
+	{
+		count = fwrite(VARDATA(data), 1, VARSIZE(data) - VARHDRSZ, f);
+
+		if (count != VARSIZE(data))
+		    ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("error writing file %s: %m", filename)));
+	}
+	fclose(f);
+
+	PG_RETURN_INT64(count);
+}
+
+
+Datum pg_file_rename(PG_FUNCTION_ARGS)
+{
+    char *fn1, *fn2, *fn3;
+	int rc;
+
+	requireSuperuser();
+
+	fn1=absClusterPath(PG_GETARG_TEXT_P(0));
+	fn2=absClusterPath(PG_GETARG_TEXT_P(1));
+	if (PG_ARGISNULL(2))
+	    fn3=0;
+	else
+	    fn3=absClusterPath(PG_GETARG_TEXT_P(2));
+
+    struct stat fst;
+	if (stat(fn1, &fst) < 0)
+	{
+		ereport(WARNING,
+				(errcode_for_file_access(),
+				 errmsg("could not stat file %s: %m", fn1)));
+
+	    PG_RETURN_BOOL(false);
+	}
+
+	if (fn3 && stat(fn2, &fst) < 0)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not stat file %s: %m", fn2)));
+
+	    PG_RETURN_BOOL(false);
+	}
+
+
+	rc = stat(fn3 ? fn3 : fn2, &fst);
+	if (rc >= 0 || errno != ENOENT)
+	{
+		ereport(ERROR,
+				(ERRCODE_DUPLICATE_FILE,
+				 errmsg("cannot rename: target file %s exists", fn3 ? fn3 : fn2)));
+	}
+	
+	if (fn3)
+	{
+	    if (rename(fn2, fn3) != 0)
+		{
+			ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("could not rename %s to %s: %m", fn2, fn3)));
+		}
+		if (rename(fn1, fn2) != 0)
+		{
+			ereport(WARNING,
+					(errcode_for_file_access(),
+					 errmsg("could not rename %s to %s: %m", fn1, fn2)));
+
+			if (rename(fn3, fn2) != 0)
+			{
+				ereport(ERROR,
+						(errcode_for_file_access(),
+						 errmsg("could not rename %s back to %s: %m", fn3, fn2)));
+			}
+			else
+			{
+				ereport(ERROR,
+						(ERRCODE_UNDEFINED_FILE,
+						 errmsg("renaming %s to %s was reverted", fn2, fn3)));
+
+			}
+		}
+	}
+	if (rename(fn1, fn2) != 0)
+	{
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errmsg("could not rename %s to %s: %m", fn1, fn2)));
+	}
+
+	PG_RETURN_BOOL(true);
+}
+
+
+Datum pg_file_unlink(PG_FUNCTION_ARGS)
+{
+    char *filename;
+
+	requireSuperuser();
+
+    filename = absClusterPath(PG_GETARG_TEXT_P(0));
+
+	if (unlink(filename) < 0)
+	{
+		ereport(WARNING,
+				(errcode_for_file_access(),
+				 errmsg("could not unlink file %s", filename)));
+
+		PG_RETURN_BOOL(false);
+	}
+	PG_RETURN_BOOL(true);
+}
+
+
+Datum pg_dir_ls(PG_FUNCTION_ARGS)
+{
+	FuncCallContext *funcctx;
+	struct dirent *de;
+	directory_fctx *fctx;
+
+	requireSuperuser();
+
+	if (SRF_IS_FIRSTCALL())
+	{
+		MemoryContext oldcontext;
+
+		funcctx=SRF_FIRSTCALL_INIT();
+		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+		fctx = palloc(sizeof(directory_fctx));
+		fctx->location = absClusterPath(PG_GETARG_TEXT_P(0));
+
+		fctx->dirdesc = AllocateDir(fctx->location);
+
+		if (!fctx->dirdesc)
+		    ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("%s is not browsable: %m", fctx->location)));
+
+		if (PG_ARGISNULL(1) || !PG_GETARG_BOOL(1))
+		{
+			pfree(fctx->location);
+			fctx->location = 0;
+		}
+		funcctx->user_fctx = fctx;
+		MemoryContextSwitchTo(oldcontext);
+	}
+
+	funcctx=SRF_PERCALL_SETUP();
+	fctx = (directory_fctx*) funcctx->user_fctx;
+
+	if (!fctx->dirdesc)  /* not a readable directory  */
+		SRF_RETURN_DONE(funcctx);
+
+	while ((de = readdir(fctx->dirdesc)) != NULL)
+	{
+	    char *name;
+		text *result;
+		int len;
+		if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+		    continue;
+		if (fctx->location)
+		{
+			char *path=palloc(strlen(fctx->location) + strlen(de->d_name) +2);
+			sprintf(path, "%s/%s", fctx->location, de->d_name);
+
+			name = path;
+		}
+		else
+		    name = de->d_name;
+
+
+		len = strlen(name);
+		result = palloc(len + VARHDRSZ);
+		VARATT_SIZEP(result) = len + VARHDRSZ;
+		memcpy(VARDATA(result), name, len);
+
+		SRF_RETURN_NEXT(funcctx, PointerGetDatum(result));
+	}
+
+	FreeDir(fctx->dirdesc);
+	SRF_RETURN_DONE(funcctx);
+}
+
+
+/*
+ * logfile handling functions
+ */
+
+
+Datum pg_logfile_rotate(PG_FUNCTION_ARGS)
+{
+    requireSuperuser();
+
+    PG_RETURN_BOOL(LogFileRotate());
+}
+
+
+Datum pg_logfiles_ls(PG_FUNCTION_ARGS)
+{
+	FuncCallContext *funcctx;
+	struct dirent *de;
+	directory_fctx *fctx;
+
+	requireSuperuser();
+
+	if (SRF_IS_FIRSTCALL())
+	{
+		MemoryContext oldcontext;
+		TupleDesc tupdesc;
+
+		funcctx=SRF_FIRSTCALL_INIT();
+		oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
+
+		fctx = palloc(sizeof(directory_fctx));
+
+		if (is_absolute_path(Log_directory))
+		    fctx->location = Log_directory;
+		else
+		{
+			fctx->location = palloc(strlen(DataDir) + strlen(Log_directory) +2);
+			sprintf(fctx->location, "%s/%s", DataDir, Log_directory);
+		}
+
+		tupdesc = CreateTemplateTupleDesc(3, false);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 1, "starttime",
+						   TIMESTAMPOID, -1, 0);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 2, "pid",
+						   INT4OID, -1, 0);
+		TupleDescInitEntry(tupdesc, (AttrNumber) 3, "filename",
+						   TEXTOID, -1, 0);
+
+		funcctx->attinmeta = TupleDescGetAttInMetadata(tupdesc);
+		
+		fctx->dirdesc = AllocateDir(fctx->location);
+
+		if (!fctx->dirdesc)
+		    ereport(ERROR,
+					(errcode_for_file_access(),
+					 errmsg("%s is not browsable: %m", fctx->location)));
+
+		funcctx->user_fctx = fctx;
+		MemoryContextSwitchTo(oldcontext);
+	}
+
+	funcctx=SRF_PERCALL_SETUP();
+	fctx = (directory_fctx*) funcctx->user_fctx;
+
+	if (!fctx->dirdesc)  /* not a readable directory  */
+		SRF_RETURN_DONE(funcctx);
+
+	while ((de = readdir(fctx->dirdesc)) != NULL)
+	{
+	    char *values[3];
+		HeapTuple tuple;
+		int year, month, day, hour, min, sec, pid, count;
+
+		// format: YYYY-MM-DD_HHMMSS_PPPPP.log
+		if (strlen(de->d_name) != 27)
+		    continue;
+
+		count = sscanf(de->d_name, "%04d-%02d-%02d_%02d%02d%02d_%05d.log", &year, &month, &day, &hour, &min, &sec, &pid);
+		if (count != 7)
+		    continue;
+
+		values[0] = palloc(30);
+		values[1] = palloc(30);
+		values[2] = palloc(strlen(de->d_name) + strlen(fctx->location) + 2);
+
+		sprintf(values[0], "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
+		sprintf(values[1], "%d", pid);
+		sprintf(values[2], "%s/%s", fctx->location, de->d_name);
+
+		tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
+
+		SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple));
+	}
+
+	FreeDir(fctx->dirdesc);
+	SRF_RETURN_DONE(funcctx);
+}
Index: src/backend/utils/error/elog.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/error/elog.c,v
retrieving revision 1.142
diff -u -r1.142 elog.c
--- src/backend/utils/error/elog.c	24 Jun 2004 21:03:13 -0000	1.142
+++ src/backend/utils/error/elog.c	18 Jul 2004 22:14:07 -0000
@@ -84,6 +84,9 @@
 static void write_eventlog(int level, const char *line);
 #endif
 
+extern FILE *realStdErr;
+extern pid_t SysLoggerPID;
+
 /*
  * ErrorData holds the data accumulated during any one ereport() cycle.
  * Any non-NULL pointers must point to palloc'd data in ErrorContext.
@@ -1451,10 +1454,27 @@
 		write_eventlog(eventlog_level, buf.data);
 	}
 #endif   /* WIN32 */
-	/* Write to stderr, if enabled */
-	if ((Log_destination & LOG_DESTINATION_STDERR) || whereToSendOutput == Debug)
+	
+	/*
+	 * Write to stderr. If Log_destination is file or stderr
+	 * if file is target, the logger process will handle this
+	 */
+	if ((Log_destination & (LOG_DESTINATION_STDERR | LOG_DESTINATION_FILE)) 
+		|| whereToSendOutput == Debug)
 	{
-		fprintf(stderr, "%s", buf.data);
+	    if (SysLoggerPID == MyProcPid && realStdErr != 0)
+		{
+		    /*
+			 * If realStdErr is not null in the SysLogger process,
+			 * there's something really wrong because stderr is probably
+			 * redirected to the pipe. To avoid circular writes, we
+			 * write to realStdErr which is hopefully the stderr the postmaster
+			 * was started with.
+			 */
+		    fprintf(realStdErr, "%s", buf.data);
+		}
+		else
+		    fprintf(stderr, "%s", buf.data) ;
 	}
 
 	pfree(buf.data);
Index: src/backend/utils/misc/guc.c
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/guc.c,v
retrieving revision 1.219
diff -u -r1.219 guc.c
--- src/backend/utils/misc/guc.c	12 Jul 2004 02:22:51 -0000	1.219
+++ src/backend/utils/misc/guc.c	18 Jul 2004 22:14:16 -0000
@@ -44,6 +44,7 @@
 #include "parser/parse_expr.h"
 #include "parser/parse_relation.h"
 #include "postmaster/bgwriter.h"
+#include "postmaster/syslogger.h"
 #include "postmaster/postmaster.h"
 #include "storage/bufmgr.h"
 #include "storage/fd.h"
@@ -1282,6 +1283,23 @@
 		BLCKSZ, BLCKSZ, BLCKSZ, NULL, NULL
 	},
 
+	{
+	  {"log_rotation_age", PGC_SIGHUP, LOGGING_WHERE,
+	   gettext_noop("Automatic logfile rotation will occur after n minutes"),
+	   NULL
+	  },
+	  &Log_RotationAge,
+	  24*60, 0, INT_MAX, NULL, NULL
+	},
+	{
+	  {"log_rotation_size", PGC_SIGHUP, LOGGING_WHERE,
+	   gettext_noop("Automatic logfile rotation will occur if this size is reached (in kb)"),
+	   NULL
+	  },
+	  &Log_RotationSize,
+	  10*1024, 0, INT_MAX, NULL, NULL
+	},
+
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
@@ -1615,13 +1633,23 @@
 	{
 		{"log_destination", PGC_POSTMASTER, LOGGING_WHERE,
 		 gettext_noop("Sets the target for log output."),
-		 gettext_noop("Valid values are combinations of stderr, syslog "
+		 gettext_noop("Valid values are combinations of stderr, file, syslog "
 					  "and eventlog, depending on platform."),
 		 GUC_LIST_INPUT
 		},
 		&log_destination_string,
 		"stderr", assign_log_destination, NULL
 	},
+	{
+		{"log_directory", PGC_SIGHUP, LOGGING_WHERE,
+		 gettext_noop("Sets the target directory for log output."),
+		 gettext_noop("May be specified as relative to the cluster directory "
+					  "or as absolute path."),
+		 GUC_LIST_INPUT | GUC_REPORT
+		},
+		&Log_directory,
+		"pg_log", NULL, NULL
+	},
 
 #ifdef HAVE_SYSLOG
 	{
@@ -5067,6 +5095,8 @@
 	
 		if (pg_strcasecmp(tok,"stderr") == 0)
 			newlogdest |= LOG_DESTINATION_STDERR;
+		else if (pg_strcasecmp(tok,"file") == 0)
+			newlogdest |= LOG_DESTINATION_FILE;
 #ifdef HAVE_SYSLOG
 		else if (pg_strcasecmp(tok,"syslog") == 0)
 			newlogdest |= LOG_DESTINATION_SYSLOG;
Index: src/backend/utils/misc/postgresql.conf.sample
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/backend/utils/misc/postgresql.conf.sample,v
retrieving revision 1.115
diff -u -r1.115 postgresql.conf.sample
--- src/backend/utils/misc/postgresql.conf.sample	11 Jul 2004 21:48:25 -0000	1.115
+++ src/backend/utils/misc/postgresql.conf.sample	18 Jul 2004 22:14:17 -0000
@@ -157,9 +157,16 @@
 
 # - Where to Log -
 
-#log_destination = 'stderr'	# Valid values are combinations of stderr,
-                                # syslog and eventlog, depending on
-                                # platform.
+#log_destination = 'stderr' # Valid values are combinations of stderr, file,
+                            # syslog and eventlog, depending on platform.
+#log_directory = 'pg_log'   # subdirectory where logfiles are written 
+                            # if 'file' log_destination is used.
+                            # May be specified absolute or relative to PGDATA
+#log_rotation_age = 1440    # Automatic rotation of logfiles will happen if 
+                            # specified age in minutes is reached. 0 to disable.
+#log_rotation_size = 10240  # Automatic rotation of logfiles will happen if 
+                            # specified size in kb is reached. 0 to disable.
+
 #syslog_facility = 'LOCAL0'
 #syslog_ident = 'postgres'
 
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/catalog/pg_proc.h,v
retrieving revision 1.342
diff -u -r1.342 pg_proc.h
--- src/include/catalog/pg_proc.h	12 Jul 2004 20:23:53 -0000	1.342
+++ src/include/catalog/pg_proc.h	18 Jul 2004 22:14:32 -0000
@@ -2819,6 +2819,8 @@
 DESCR("Terminate a backend process");
 DATA(insert OID = 2172 ( pg_cancel_backend              PGNSP PGUID 12 f f t f s 1 23 "23" _null_ pg_cancel_backend - _null_ ));
 DESCR("Cancel running query on a backend process");
+DATA(insert OID = 2173 ( pg_reload_conf                PGNSP PGUID 12 f f t f s 1 23 "" _null_ pg_reload_conf - _null_ ));
+DESCR("Reload postgresql.conf");
 
 DATA(insert OID = 1946 (  encode						PGNSP PGUID 12 f f t f i 2 25 "17 25" _null_  binary_encode - _null_ ));
 DESCR("Convert bytea value into some ascii-only text string");
@@ -3607,6 +3609,25 @@
 DATA(insert OID = 2556 ( pg_tablespace_databases	PGNSP PGUID 12 f f t t s 1 26 "26" _null_ pg_tablespace_databases - _null_));
 DESCR("returns database oids in a tablespace");
 
+DATA(insert OID = 2557( pg_file_length		           PGNSP PGUID 12 f f t f v 1 20 "25" _null_ pg_file_length - _null_ ));
+DESCR("length of generic file");
+DATA(insert OID = 2558( pg_file_read		           PGNSP PGUID 12 f f t f v 3 25 "25 20 20" _null_ pg_file_read - _null_ ));
+DESCR("read contents of generic file");
+DATA(insert OID = 2559( pg_file_write		           PGNSP PGUID 12 f f t f v 3 20 "25 25 16" _null_ pg_file_write - _null_ ));
+DESCR("write generic file");
+DATA(insert OID = 2560( pg_file_rename                PGNSP PGUID 12 f f t f v 2 16 "25 25" _null_ pg_file_rename - _null_ ));
+DESCR("rename generic file");
+DATA(insert OID = 2561( pg_file_rename                PGNSP PGUID 12 f f t f v 33 16 "25 25 25" _null_ pg_file_rename - _null_ ));
+DESCR("rename generic file");
+DATA(insert OID = 2562( pg_file_unlink		           PGNSP PGUID 12 f f t f v 1 16 "25" _null_ pg_file_unlink - _null_ ));
+DESCR("remove generic file");
+DATA(insert OID = 2563( pg_dir_ls		               PGNSP PGUID 12 f f t t v 2 25 "25 16" _null_ pg_dir_ls - _null_ ));
+DESCR("list generic directory");
+
+DATA(insert OID = 2564( pg_logfile_rotate		       PGNSP PGUID 12 f f t f v 0 16 "" _null_ pg_logfile_rotate - _null_ ));
+DESCR("rotate log file");
+DATA(insert OID = 2565( pg_logfiles_ls		           PGNSP PGUID 12 f f t t v 0 2249 "" _null_ pg_logfiles_ls - _null_ ));
+DESCR("list all available log files");
 
 /*
  * Symbolic values for provolatile column: these indicate whether the result
Index: src/include/storage/pmsignal.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/storage/pmsignal.h,v
retrieving revision 1.8
diff -u -r1.8 pmsignal.h
--- src/include/storage/pmsignal.h	29 May 2004 22:48:23 -0000	1.8
+++ src/include/storage/pmsignal.h	18 Jul 2004 22:14:33 -0000
@@ -24,6 +24,7 @@
 {
 	PMSIGNAL_PASSWORD_CHANGE,	/* pg_pwd file has changed */
 	PMSIGNAL_WAKEN_CHILDREN,	/* send a SIGUSR1 signal to all backends */
+	PMSIGNAL_ROTATE_LOGFILE,	/* send SIGUSR1 to syslogger to rotate logfile */
 
 	NUM_PMSIGNALS				/* Must be last value of enum! */
 } PMSignalReason;
Index: src/include/utils/builtins.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/builtins.h,v
retrieving revision 1.246
diff -u -r1.246 builtins.h
--- src/include/utils/builtins.h	12 Jul 2004 20:23:59 -0000	1.246
+++ src/include/utils/builtins.h	18 Jul 2004 22:14:35 -0000
@@ -362,8 +362,20 @@
 extern Datum current_database(PG_FUNCTION_ARGS);
 extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
 extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
+extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
 extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
 
+extern Datum pg_logfile_rotate(PG_FUNCTION_ARGS);
+extern Datum pg_logfiles_ls(PG_FUNCTION_ARGS);
+
+extern Datum pg_file_length(PG_FUNCTION_ARGS);
+extern Datum pg_file_read(PG_FUNCTION_ARGS);
+extern Datum pg_file_write(PG_FUNCTION_ARGS);
+extern Datum pg_file_rename(PG_FUNCTION_ARGS);
+extern Datum pg_file_unlink(PG_FUNCTION_ARGS);
+
+extern Datum pg_dir_ls(PG_FUNCTION_ARGS);
+
 /* not_in.c */
 extern Datum int4notin(PG_FUNCTION_ARGS);
 extern Datum oidnotin(PG_FUNCTION_ARGS);
Index: src/include/utils/elog.h
===================================================================
RCS file: /projects/cvsroot/pgsql-server/src/include/utils/elog.h,v
retrieving revision 1.70
diff -u -r1.70 elog.h
--- src/include/utils/elog.h	6 Jul 2004 19:51:59 -0000	1.70
+++ src/include/utils/elog.h	18 Jul 2004 22:14:36 -0000
@@ -185,10 +185,10 @@
 #define LOG_DESTINATION_STDERR   1
 #define LOG_DESTINATION_SYSLOG   2
 #define LOG_DESTINATION_EVENTLOG 4
+#define LOG_DESTINATION_FILE     8
 
 /* Other exported functions */
 extern void DebugFileOpen(void);
-
 /*
  * Write errors to stderr (or by equal means when stderr is
  * not available). Used before ereport/elog can be used
