diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 61151ef6aadbc5fb8f1d172ea8fae6163ba69f35..a9e22ec40be7d47caa8b68116eefc04233b37106 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.65 1998/12/15 12:45:53 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.66 1999/01/11 03:56:05 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 #include <commands/copy.h>
 #include "commands/trigger.h"
 #include <storage/fd.h>
+#include <libpq/libpq.h>
 
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
@@ -67,11 +68,106 @@ static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
 static void CopyAttributeOut(FILE *fp, char *string, char *delim, int is_array);
 static int	CountTuples(Relation relation);
 
-extern FILE *Pfout,
-		   *Pfin;
-
 static int	lineno;
 
+/* 
+ * Internal communications functions
+ */
+inline void CopySendData(void *databuf, int datasize, FILE *fp);
+inline void CopySendString(char *str, FILE *fp);
+inline void CopySendChar(char c, FILE *fp);
+inline void CopyGetData(void *databuf, int datasize, FILE *fp);
+inline int CopyGetChar(FILE *fp);
+inline int CopyGetEof(FILE *fp);
+inline int CopyPeekChar(FILE *fp);
+inline void CopyDonePeek(FILE *fp, int c, int pickup);
+
+/*
+ * CopySendData sends output data either to the file
+ *  specified by fp or, if fp is NULL, using the standard
+ *  backend->frontend functions
+ *
+ * CopySendString does the same for null-terminated strings
+ * CopySendChar does the same for single characters
+ */
+inline void CopySendData(void *databuf, int datasize, FILE *fp) {
+  if (!fp)
+    pq_putnchar(databuf, datasize);
+  else
+    fwrite(databuf, datasize, 1, fp);
+}
+    
+inline void CopySendString(char *str, FILE *fp) {
+  CopySendData(str,strlen(str),fp);
+}
+
+inline void CopySendChar(char c, FILE *fp) {
+  CopySendData(&c,1,fp);
+}
+
+/*
+ * CopyGetData reads output data either from the file
+ *  specified by fp or, if fp is NULL, using the standard
+ *  backend->frontend functions
+ *
+ * CopyGetChar does the same for single characters
+ * CopyGetEof checks if it's EOF on the input
+ */
+inline void CopyGetData(void *databuf, int datasize, FILE *fp) {
+  if (!fp)
+    pq_getnchar(databuf, 0, datasize); 
+  else 
+    fread(databuf, datasize, 1, fp);
+}
+
+inline int CopyGetChar(FILE *fp) {
+  if (!fp) 
+    return pq_getchar();
+  else
+    return getc(fp);
+}
+
+inline int CopyGetEof(FILE *fp) {
+  if (!fp)
+    return 0; /* Never return EOF when talking to frontend ? */
+  else
+    return feof(fp);
+}
+
+/*
+ * CopyPeekChar reads a byte in "peekable" mode.
+ * after each call to CopyPeekChar, a call to CopyDonePeek _must_
+ * follow.
+ * CopyDonePeek will either take the peeked char off the steam 
+ * (if pickup is != 0) or leave it on the stream (if pickup == 0)
+ */
+inline int CopyPeekChar(FILE *fp) {
+  if (!fp) 
+    return pq_peekchar();
+  else
+    return getc(fp);
+}
+
+inline void CopyDonePeek(FILE *fp, int c, int pickup) {
+  if (!fp) {
+    if (pickup) {
+      /* We want to pick it up - just receive again into dummy buffer */
+      char c;
+      pq_getnchar(&c, 0, 1);
+    }
+    /* If we didn't want to pick it up, just leave it where it sits */
+  }
+  else {
+    if (!pickup) {
+      /* We don't want to pick it up - so put it back in there */
+      ungetc(c,fp);
+    }
+    /* If we wanted to pick it up, it's already there */
+  }
+}
+    
+
+
 /*
  *	 DoCopy executes a the SQL COPY statement.
  */
@@ -147,7 +243,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 				if (IsUnderPostmaster)
 				{
 					ReceiveCopyBegin();
-					fp = Pfin;
+					fp = NULL;
 				}
 				else
 					fp = stdin;
@@ -171,7 +267,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 				if (IsUnderPostmaster)
 				{
 					SendCopyBegin();
-					fp = Pfout;
+					fp = NULL;
 				}
 				else
 					fp = stdout;
@@ -199,9 +295,9 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
 		}
 		else if (!from && !binary)
 		{
-			fputs("\\.\n", fp);
+		        CopySendData("\\.\n",3,fp);
 			if (IsUnderPostmaster)
-				fflush(Pfout);
+			        pq_flush();
 		}
 	}
 }
@@ -269,7 +365,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 		/* XXX expensive */
 
 		ntuples = CountTuples(rel);
-		fwrite(&ntuples, sizeof(int32), 1, fp);
+		CopySendData(&ntuples, sizeof(int32), fp);
 	}
 
 	while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
@@ -277,8 +373,8 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 
 		if (oids && !binary)
 		{
-			fputs(oidout(tuple->t_data->t_oid), fp);
-			fputc(delim[0], fp);
+		        CopySendString(oidout(tuple->t_data->t_oid),fp);
+			CopySendChar(delim[0],fp);
 		}
 
 		for (i = 0; i < attr_count; i++)
@@ -294,10 +390,10 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 					pfree(string);
 				}
 				else
-					fputs("\\N", fp);	/* null indicator */
+					CopySendString("\\N", fp);	/* null indicator */
 
 				if (i == attr_count - 1)
-					fputc('\n', fp);
+					CopySendChar('\n', fp);
 				else
 				{
 
@@ -305,7 +401,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 					 * when copying out, only use the first char of the
 					 * delim string
 					 */
-					fputc(delim[0], fp);
+					CopySendChar(delim[0], fp);
 				}
 			}
 			else
@@ -332,24 +428,24 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 			}
 
 			length = tuple->t_len - tuple->t_data->t_hoff;
-			fwrite(&length, sizeof(int32), 1, fp);
+			CopySendData(&length, sizeof(int32), fp);
 			if (oids)
-				fwrite((char *) &tuple->t_data->t_oid, sizeof(int32), 1, fp);
+				CopySendData((char *) &tuple->t_data->t_oid, sizeof(int32), fp);
 
-			fwrite(&null_ct, sizeof(int32), 1, fp);
+			CopySendData(&null_ct, sizeof(int32), fp);
 			if (null_ct > 0)
 			{
 				for (i = 0; i < attr_count; i++)
 				{
 					if (nulls[i] == 'n')
 					{
-						fwrite(&i, sizeof(int32), 1, fp);
+						CopySendData(&i, sizeof(int32), fp);
 						nulls[i] = ' ';
 					}
 				}
 			}
-			fwrite((char *) tuple->t_data + tuple->t_data->t_hoff, 
-					length, 1, fp);
+			CopySendData((char *) tuple->t_data + tuple->t_data->t_hoff, 
+					length, fp);
 		}
 	}
 
@@ -527,7 +623,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 		in_functions = NULL;
 		elements = NULL;
 		typmod = NULL;
-		fread(&ntuples, sizeof(int32), 1, fp);
+		CopyGetData(&ntuples, sizeof(int32), fp);
 		if (ntuples != 0)
 			reading_to_eof = false;
 	}
@@ -544,10 +640,12 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 		index_nulls[i] = ' ';
 		byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
 	}
+	values = (Datum *) palloc(sizeof(Datum) * attr_count);
 
 	lineno = 0;
 	while (!done)
 	{
+	  values = (Datum *) palloc(sizeof(Datum) * attr_count);
 		if (!binary)
 		{
 #ifdef COPY_PATCH
@@ -608,29 +706,29 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
 		}
 		else
 		{						/* binary */
-			fread(&len, sizeof(int32), 1, fp);
-			if (feof(fp))
+			CopyGetData(&len, sizeof(int32), fp);
+			if (CopyGetEof(fp))
 				done = 1;
 			else
 			{
 				if (oids)
 				{
-					fread(&loaded_oid, sizeof(int32), 1, fp);
+					CopyGetData(&loaded_oid, sizeof(int32), fp);
 					if (loaded_oid < BootstrapObjectIdData)
 						elog(ERROR, "COPY BINARY: Invalid Oid line: %d", lineno);
 				}
-				fread(&null_ct, sizeof(int32), 1, fp);
+				CopyGetData(&null_ct, sizeof(int32), fp);
 				if (null_ct > 0)
 				{
 					for (i = 0; i < null_ct; i++)
 					{
-						fread(&null_id, sizeof(int32), 1, fp);
+						CopyGetData(&null_id, sizeof(int32), fp);
 						nulls[null_id] = 'n';
 					}
 				}
 
 				string = (char *) palloc(len);
-				fread(string, len, 1, fp);
+				CopyGetData(string, len, fp);
 
 				ptr = string;
 
@@ -979,7 +1077,7 @@ CopyReadNewline(FILE *fp, int *newline)
 	if (!*newline)
 	{
 		elog(NOTICE, "CopyReadNewline: line %d - extra fields ignored", lineno);
-		while (!feof(fp) && (getc(fp) != '\n'));
+		while (!CopyGetEof(fp) && (CopyGetChar(fp) != '\n'));
 	}
 	*newline = 0;
 }
@@ -1028,19 +1126,19 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
 #endif
 
 	*isnull = (bool) false;		/* set default */
-	if (feof(fp))
+	if (CopyGetEof(fp))
 		return NULL;
 
 	while (!done)
 	{
-		c = getc(fp);
+		c = CopyGetChar(fp);
 
-		if (feof(fp))
+		if (CopyGetEof(fp))
 			return NULL;
 		else if (c == '\\')
 		{
-			c = getc(fp);
-			if (feof(fp))
+			c = CopyGetChar(fp);
+			if (CopyGetEof(fp))
 				return NULL;
 			switch (c)
 			{
@@ -1056,25 +1154,30 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
 						int			val;
 
 						val = VALUE(c);
-						c = getc(fp);
+						c = CopyPeekChar(fp);
 						if (ISOCTAL(c))
 						{
 							val = (val << 3) + VALUE(c);
-							c = getc(fp);
-							if (ISOCTAL(c))
+							CopyDonePeek(fp, c, 1); /* Pick up the character! */
+							c = CopyPeekChar(fp);
+							if (ISOCTAL(c)) {
+							        CopyDonePeek(fp,c,1); /* pick up! */
 								val = (val << 3) + VALUE(c);
+							}
 							else
 							{
-								if (feof(fp))
+							        if (CopyGetEof(fp)) {
+								        CopyDonePeek(fp,c,1); /* pick up */
 									return NULL;
-								ungetc(c, fp);
+								}
+								CopyDonePeek(fp,c,0); /* Return to stream! */
 							}
 						}
 						else
 						{
-							if (feof(fp))
+							if (CopyGetEof(fp))
 								return NULL;
-							ungetc(c, fp);
+							CopyDonePeek(fp,c,0); /* Return to stream! */
 						}
 						c = val & 0377;
 					}
@@ -1102,7 +1205,7 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
 					*isnull = (bool) true;
 					break;
 				case '.':
-					c = getc(fp);
+					c = CopyGetChar(fp);
 					if (c != '\n')
 						elog(ERROR, "CopyReadAttribute - end of record marker corrupted. line: %d", lineno);
 					return NULL;
@@ -1125,8 +1228,8 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
 		mblen--;
 		for (j = 0; j < mblen; j++)
 		{
-			c = getc(fp);
-			if (feof(fp))
+			c = CopyGetChar(fp);
+			if (CopyGetEof(fp))
 				return NULL;
 			attribute[i++] = c;
 		}
@@ -1171,29 +1274,29 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim, int is_array)
 	{
 		if (c == delim[0] || c == '\n' ||
 			(c == '\\' && !is_array))
-			fputc('\\', fp);
+			CopySendChar('\\', fp);
 		else if (c == '\\' && is_array)
 		{
 			if (*(string + 1) == '\\')
 			{
 				/* translate \\ to \\\\ */
-				fputc('\\', fp);
-				fputc('\\', fp);
-				fputc('\\', fp);
+				CopySendChar('\\', fp);
+				CopySendChar('\\', fp);
+				CopySendChar('\\', fp);
 				string++;
 			}
 			else if (*(string + 1) == '"')
 			{
 				/* translate \" to \\\" */
-				fputc('\\', fp);
-				fputc('\\', fp);
+				CopySendChar('\\', fp);
+				CopySendChar('\\', fp);
 			}
 		}
 #ifdef MULTIBYTE
 		for (i = 0; i < mblen; i++)
-			fputc(*(string + i), fp);
+			CopySendChar(*(string + i), fp);
 #else
-		fputc(*string, fp);
+		CopySendChar(*string, fp);
 #endif
 	}
 }
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index b4bab9c8991b1bf86da8f373e95064c809ebcf28..9fe835d8b7cbfc33b27c12a7a99fbfc7689fdd9e 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: pqcomm.c,v 1.59 1998/12/14 06:50:27 scrappy Exp $
+ *  $Id: pqcomm.c,v 1.60 1999/01/11 03:56:06 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,7 +75,7 @@
  *		declarations
  * ----------------
  */
-FILE	*Pfout,
+static FILE	*Pfout,
 			*Pfin,
 			*Pfdebug;			/* debugging libpq */
 
@@ -98,7 +98,7 @@ pq_init(int fd)
 }
 
 /* -------------------------
- *	 pq_getc(File* fin)
+ *	 pq_getchar()
  *
  *	 get a character from the input file,
  *
@@ -107,20 +107,29 @@ pq_init(int fd)
  *	 used for debugging libpq
  */
 
-#if 0							/* not used anymore */
-
-static int
-pq_getc(FILE *fin)
+int
+pq_getchar(void)
 {
 	int			c;
 
-	c = getc(fin);
+	c = getc(Pfin);
 	if (Pfdebug && c != EOF)
 		putc(c, Pfdebug);
 	return c;
 }
 
-#endif
+/*
+ * --------------------------------
+ *              pq_peekchar - get 1 character from connection, but leave it in the stream
+ */
+int
+pq_peekchar(void) {
+  char c = getc(Pfin);
+  ungetc(c,Pfin);
+  return c;
+}
+  
+
 
 /* --------------------------------
  *		pq_gettty - return the name of the tty in the given buffer
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index e965cd2ad38d64e985a24da3f7d0e15a97f9fcb1..4e68c1e24a8177e2438f9e3c97bccdad7f45a345 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.36 1999/01/01 04:48:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.37 1999/01/11 03:56:07 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -67,11 +67,6 @@ elog(int lev, const char *fmt,...)
 	extern int	errno,
 				sys_nerr;
 
-#ifndef PG_STANDALONE
-	extern FILE *Pfout;
-
-#endif
-
 #ifdef USE_SYSLOG
 	int			log_level;
 
@@ -190,7 +185,7 @@ elog(int lev, const char *fmt,...)
 
 #ifndef PG_STANDALONE
 	/* Send IPC message to the front-end program */
-	if (Pfout != NULL && lev > DEBUG)
+	if (IsUnderPostmaster && lev > DEBUG)
 	{
 		/* notices are not exactly errors, handle it differently */
 		if (lev == NOTICE)
@@ -201,7 +196,7 @@ elog(int lev, const char *fmt,...)
 		pq_putstr(line + TIMESTAMP_SIZE);		/* don't show timestamps */
 		pq_flush();
 	}
-	if (Pfout == NULL)
+	if (!IsUnderPostmaster)
 	{
 
 		/*
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index bad77383c9873bdc2f22a05f71ead928a6872689..4c65e7769b8ec6300c03e8e459cbb3e1ed5652e0 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq-be.h,v 1.12 1998/09/01 04:36:27 momjian Exp $
+ * $Id: libpq-be.h,v 1.13 1999/01/11 03:56:11 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -131,8 +131,6 @@ typedef struct Port
 } Port;
 
 
-extern FILE *Pfout,
-		   *Pfin;
 extern ProtocolVersion FrontendProtocol;
 
 
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index ef7ec5d2cfda11f3fb8c5b5284a7f2c3759bf925..4fca9623aa934900814e6b4b0e7fa64cfbaa3e6a 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq.h,v 1.21 1998/09/01 04:36:29 momjian Exp $
+ * $Id: libpq.h,v 1.22 1999/01/11 03:56:11 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -258,6 +258,8 @@ extern void pq_flush(void);
 extern int	pq_getstr(char *s, int maxlen);
 extern int	PQgetline(char *s, int maxlen);
 extern int	PQputline(char *s);
+extern int      pq_getchar(void);
+extern int      pq_peekchar(void);
 extern int	pq_getnchar(char *s, int off, int maxlen);
 extern int	pq_getint(int b);
 extern void pq_putstr(char *s);