From 3b3ffc8d97d97067eefea66b8df95fc963d8b0be Mon Sep 17 00:00:00 2001
From: "Marc G. Fournier" <scrappy@hub.org>
Date: Mon, 11 Jan 1999 03:56:11 +0000
Subject: [PATCH] From: Magnus Hagander <mha@sollentuna.net>

Here is a first patch to cleanup the backend side of libpq.
This patch removes all external dependencies on the "Pfin" and "Pfout" that
are declared in pqcomm.h. These variables are also changed to "static" to
make sure.
Almost all the change is in the handler of the "copy" command - most other
areas of the backend already used the correct functions.
This change will make the way for cleanup of the internal stuff there - now
that all the functions accessing the file descriptors are confined to a
single directory.
---
 src/backend/commands/copy.c    | 205 +++++++++++++++++++++++++--------
 src/backend/libpq/pqcomm.c     |  27 +++--
 src/backend/utils/error/elog.c |  11 +-
 src/include/libpq/libpq-be.h   |   4 +-
 src/include/libpq/libpq.h      |   4 +-
 5 files changed, 179 insertions(+), 72 deletions(-)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 61151ef6aad..a9e22ec40be 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 b4bab9c8991..9fe835d8b7c 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 e965cd2ad38..4e68c1e24a8 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 bad77383c98..4c65e7769b8 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 ef7ec5d2cfd..4fca9623aa9 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);
-- 
GitLab