]> granicus.if.org Git - postgresql/commitdiff
From: Magnus Hagander <mha@sollentuna.net>
authorMarc G. Fournier <scrappy@hub.org>
Tue, 12 Jan 1999 12:49:52 +0000 (12:49 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Tue, 12 Jan 1999 12:49:52 +0000 (12:49 +0000)
Here's another patch for the libpq backend areas. This patch removes all
usage of "FILE *" on the communications channel. It also cleans up the
comments and headers in the pqcomm.c file - a lot of things were either
missing or incorrect. Finally, it removes a couple of unused functions
(leftovers from the time of shared code between the libpq backend and
frontend).

src/backend/libpq/pqcomm.c
src/backend/libpq/pqcomprim.c
src/include/libpq/libpq.h
src/include/libpq/pqcomm.h

index 9fe835d8b7cbfc33b27c12a7a99fbfc7689fdd9e..e7da8d89a8cd590397651e6b0e4f656a184eba96 100644 (file)
@@ -5,19 +5,22 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: pqcomm.c,v 1.60 1999/01/11 03:56:06 scrappy Exp $
+ *  $Id: pqcomm.c,v 1.61 1999/01/12 12:49:51 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
 /*
  * INTERFACE ROUTINES
- *             pq_gettty               - return the name of the tty in the given buffer
+ *              pq_init                 - initialize libpq
  *             pq_getport              - return the PGPORT setting
  *             pq_close                - close input / output connections
  *             pq_flush                - flush pending output
  *             pq_getstr               - get a null terminated string from connection
- *             pq_getnchar             - get n characters from connection
+ *              pq_getchar              - get 1 character from connection
+ *              pq_peekchar             - peek at first character in connection
+ *             pq_getnchar             - get n characters from connection, and null-terminate
  *             pq_getint               - get an integer from connection
+ *              pq_putchar              - send 1 character to connection
  *             pq_putstr               - send a null terminated string to connection
  *             pq_putnchar             - send n characters to connection
  *             pq_putint               - send an integer to connection
  *                                        the length)
  *             pq_getinaddr    - initialize address from host and port number
  *             pq_getinserv    - initialize address from host and service name
- *             pq_connect              - create remote input / output connection
- *             pq_accept               - accept remote input / output connection
  *
+ *              StreamDoUnlink          - Shutdown UNIX socket connectioin
+ *              StreamServerPort        - Open sock stream
+ *              StreamConnection        - Create new connection with client
+ *              StreamClose             - Close a client/backend connection
+ * 
  * NOTES
- *             These functions are used by both frontend applications and
- *             the postgres backend.
+ *              Frontend is now completey in interfaces/libpq, and no 
+ *              functions from this file is used.
  *
  */
 #include "postgres.h"
 #endif
 #include "utils/trace.h"
 
-/* ----------------
- *             declarations
- * ----------------
- */
-static FILE    *Pfout,
-                       *Pfin,
-                       *Pfdebug;                       /* debugging libpq */
+extern FILE * debug_port; /* in util.c */
 
 /* --------------------------------
  *             pq_init - open portal file descriptors
@@ -86,15 +86,9 @@ static FILE  *Pfout,
 void
 pq_init(int fd)
 {
-       Pfin = fdopen(fd, "r");
-       Pfout = fdopen(dup(fd), "w");
-       if (!Pfin || !Pfout)
-               elog(FATAL, "pq_init: Couldn't initialize socket connection");
        PQnotifies_init();
        if (getenv("LIBPQ_DEBUG"))
-               Pfdebug = stderr;
-       else
-               Pfdebug = NULL;
+         debug_port = stderr;
 }
 
 /* -------------------------
@@ -102,19 +96,23 @@ pq_init(int fd)
  *
  *      get a character from the input file,
  *
- *      if Pfdebug is set, also echo the character fetched into Pfdebug
- *
- *      used for debugging libpq
  */
 
 int
 pq_getchar(void)
 {
-       int                     c;
-
-       c = getc(Pfin);
-       if (Pfdebug && c != EOF)
-               putc(c, Pfdebug);
+       char c;
+       char isDone = 0;
+
+       do {
+         if (recv(MyProcPort->sock,&c,1,MSG_WAITALL) != 1) {
+           if (errno != EINTR)
+             return EOF; /* Not interrupted, so something went wrong */
+         }
+         else
+           isDone = 1;
+       } while (!isDone);
+         
        return c;
 }
 
@@ -124,23 +122,23 @@ pq_getchar(void)
  */
 int
 pq_peekchar(void) {
-  char c = getc(Pfin);
-  ungetc(c,Pfin);
-  return c;
+       char c;
+       char isDone = 0;
+
+       do {
+         if (recv(MyProcPort->sock,&c,1,MSG_WAITALL | MSG_PEEK) != 1) {
+           if (errno != EINTR)
+             return EOF; /* Not interrupted, so something went wrong */
+         }
+         else
+           isDone = 1;
+       } while (!isDone);
+         
+       return c;
 }
   
 
 
-/* --------------------------------
- *             pq_gettty - return the name of the tty in the given buffer
- * --------------------------------
- */
-void
-pq_gettty(char *tp)
-{
-       strncpy(tp, ttyname(0), 19);
-}
-
 /* --------------------------------
  *             pq_getport - return the PGPORT setting
  * --------------------------------
@@ -162,16 +160,7 @@ pq_getport()
 void
 pq_close()
 {
-       if (Pfin)
-       {
-               fclose(Pfin);
-               Pfin = NULL;
-       }
-       if (Pfout)
-       {
-               fclose(Pfout);
-               Pfout = NULL;
-       }
+        close(MyProcPort->sock);
        PQnotifies_init();
 }
 
@@ -182,8 +171,7 @@ pq_close()
 void
 pq_flush()
 {
-       if (Pfout)
-               fflush(Pfout);
+  /* Not supported/required? */
 }
 
 /* --------------------------------
@@ -198,13 +186,7 @@ pq_getstr(char *s, int maxlen)
        char       *p;
 #endif
 
-       if (Pfin == (FILE *) NULL)
-       {
-/*             elog(DEBUG, "Input descriptor is null"); */
-               return EOF;
-       }
-
-       c = pqGetString(s, maxlen, Pfin);
+       c = pqGetString(s, maxlen);
 
 #ifdef MULTIBYTE
        p = (char*) pg_client_to_server((unsigned char *) s, maxlen);
@@ -215,73 +197,16 @@ pq_getstr(char *s, int maxlen)
        return c;
 }
 
-/*
- * USER FUNCTION - gets a newline-terminated string from the backend.
- *
- * Chiefly here so that applications can use "COPY <rel> to stdout"
- * and read the output string. Returns a null-terminated string in s.
- *
- * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
- * the terminating \n (like gets(3)).
- *
- * RETURNS:
- *             EOF if it is detected or invalid arguments are given
- *             0 if EOL is reached (i.e., \n has been read)
- *                             (this is required for backward-compatibility -- this
- *                              routine used to always return EOF or 0, assuming that
- *                              the line ended within maxlen bytes.)
- *             1 in other cases
- */
-int
-PQgetline(char *s, int maxlen)
-{
-       if (!Pfin || !s || maxlen <= 1)
-               return EOF;
-
-       if (fgets(s, maxlen - 1, Pfin) == NULL)
-               return feof(Pfin) ? EOF : 1;
-       else
-       {
-               for (; *s; s++)
-               {
-                       if (*s == '\n')
-                       {
-                               *s = '\0';
-                               break;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-/*
- * USER FUNCTION - sends a string to the backend.
- *
- * Chiefly here so that applications can use "COPY <rel> from stdin".
- *
- * RETURNS:
- *             0 in all cases.
- */
-int
-PQputline(char *s)
-{
-       if (Pfout)
-       {
-               fputs(s, Pfout);
-               fflush(Pfout);
-       }
-       return 0;
-}
-
 /* --------------------------------
- *             pq_getnchar - get n characters from connection
+ *             pq_getnchar - get n characters from connection, and null terminate
  * --------------------------------
  */
 int
 pq_getnchar(char *s, int off, int maxlen)
 {
-       return pqGetNBytes(s + off, maxlen, Pfin);
+        int r = pqGetNBytes(s + off, maxlen);
+       s[off+maxlen] = '\0';
+       return r;
 }
 
 /* --------------------------------
@@ -297,9 +222,6 @@ pq_getint(int b)
        int                     n,
                                status = 1;
 
-       if (!Pfin)
-               return EOF;
-
        /*
         * mjl: Seems inconsisten w/ return value of pq_putint (void). Also,
         * EOF is a valid return value for an int! XXX
@@ -308,13 +230,13 @@ pq_getint(int b)
        switch (b)
        {
                case 1:
-                       status = ((n = fgetc(Pfin)) == EOF);
+                       status = ((n = pq_getchar()) == EOF);
                        break;
                case 2:
-                       status = pqGetShort(&n, Pfin);
+                       status = pqGetShort(&n);
                        break;
                case 4:
-                       status = pqGetLong(&n, Pfin);
+                       status = pqGetLong(&n);
                        break;
                default:
                        fprintf(stderr, "** Unsupported size %d\n", b);
@@ -343,9 +265,9 @@ pq_putstr(char *s)
        unsigned char *p;
 
        p = pg_server_to_client(s, strlen(s));
-       if (pqPutString(p, Pfout))
+       if (pqPutString(p))
 #else
-       if                      (pqPutString(s, Pfout))
+       if (pqPutString(s))
 #endif
        {
                snprintf(PQerrormsg, ERROR_MSG_LENGTH,
@@ -362,10 +284,10 @@ pq_putstr(char *s)
 void
 pq_putnchar(char *s, int n)
 {
-       if (pqPutNBytes(s, n, Pfout))
+       if (pqPutNBytes(s, n))
        {
                snprintf(PQerrormsg, ERROR_MSG_LENGTH,
-                               "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
+                               "FATAL: pq_putnchar: pqPutNBytes() failed: errno=%d\n",
                                errno);
                fputs(PQerrormsg, stderr);
                pqdebug("%s", PQerrormsg);
@@ -384,20 +306,17 @@ pq_putint(int i, int b)
 {
        int                     status;
 
-       if (!Pfout)
-               return;
-
        status = 1;
        switch (b)
        {
                case 1:
-                       status = (fputc(i, Pfout) == EOF);
+                       status = (pq_putchar(i) == EOF);
                        break;
                case 2:
-                       status = pqPutShort(i, Pfout);
+                       status = pqPutShort(i);
                        break;
                case 4:
-                       status = pqPutLong(i, Pfout);
+                       status = pqPutLong(i);
                        break;
                default:
                        fprintf(stderr, "** Unsupported size %d\n", b);
@@ -485,6 +404,19 @@ pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
  *             Stream functions are used for vanilla TCP connection protocol.
  */
 
+static char sock_path[MAXPGPATH + 1] = "";
+
+/* StreamDoUnlink()
+ * Shutdown routine for backend connection
+ * If a Unix socket is used for communication, explicitly close it.
+ */
+void
+StreamDoUnlink()
+{
+       Assert(sock_path[0]);
+       unlink(sock_path);
+}
+
 /*
  * StreamServerPort -- open a sock stream "listening" port.
  *
@@ -498,19 +430,6 @@ pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
  * RETURNS: STATUS_OK or STATUS_ERROR
  */
 
-static char sock_path[MAXPGPATH + 1] = "";
-
-/* do_unlink()
- * Shutdown routine for backend connection
- * If a Unix socket is used for communication, explicitly close it.
- */
-void
-StreamDoUnlink()
-{
-       Assert(sock_path[0]);
-       unlink(sock_path);
-}
-
 int
 StreamServerPort(char *hostName, short portName, int *fdP)
 {
@@ -707,81 +626,6 @@ StreamClose(int sock)
        close(sock);
 }
 
-/* ---------------------------
- * StreamOpen -- From client, initiate a connection with the
- *             server (Postmaster).
- *
- * RETURNS: STATUS_OK or STATUS_ERROR
- *
- * NOTE: connection is NOT established just because this
- *             routine exits.  Local state is ok, but we haven't
- *             spoken to the postmaster yet.
- * ---------------------------
- */
-int
-StreamOpen(char *hostName, short portName, Port *port)
-{
-       SOCKET_SIZE_TYPE        len;
-       int                     err;
-       struct hostent *hp;
-       extern int      errno;
-
-       /* set up the server (remote) address */
-       MemSet((char *) &port->raddr, 0, sizeof(port->raddr));
-       if (hostName)
-       {
-               if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET)
-               {
-                       snprintf(PQerrormsg, ERROR_MSG_LENGTH,
-                                       "FATAL: StreamOpen: unknown hostname: %s\n", hostName);
-                       fputs(PQerrormsg, stderr);
-                       pqdebug("%s", PQerrormsg);
-                       return STATUS_ERROR;
-               }
-               memmove((char *) &(port->raddr.in.sin_addr),
-                               (char *) hp->h_addr,
-                               hp->h_length);
-               port->raddr.in.sin_family = AF_INET;
-               port->raddr.in.sin_port = htons(portName);
-               len = sizeof(struct sockaddr_in);
-       }
-       else
-       {
-               port->raddr.un.sun_family = AF_UNIX;
-               len = UNIXSOCK_PATH(port->raddr.un, portName);
-       }
-       /* connect to the server */
-       if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
-       {
-               snprintf(PQerrormsg, ERROR_MSG_LENGTH,
-                               "FATAL: StreamOpen: socket() failed: errno=%d\n", errno);
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-       err = connect(port->sock, &port->raddr.sa, len);
-       if (err < 0)
-       {
-               snprintf(PQerrormsg, ERROR_MSG_LENGTH,
-                               "FATAL: StreamOpen: connect() failed: errno=%d\n", errno);
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-
-       /* fill in the client address */
-       if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
-       {
-               snprintf(PQerrormsg, ERROR_MSG_LENGTH,
-                               "FATAL: StreamOpen: getsockname() failed: errno=%d\n", errno);
-               fputs(PQerrormsg, stderr);
-               pqdebug("%s", PQerrormsg);
-               return STATUS_ERROR;
-       }
-
-       return STATUS_OK;
-}
-
 #ifdef MULTIBYTE
 void
 pq_putncharlen(char *s, int n)
@@ -798,3 +642,24 @@ pq_putncharlen(char *s, int n)
 #endif
 
 
+/* 
+ * Act like the stdio putc() function. Write one character
+ * to the stream. Return this character, or EOF on error.
+ */
+int pq_putchar(char c) 
+{
+  char isDone = 0;
+
+  do {
+    if (send(MyProcPort->sock, &c, 1, 0) != 1) {
+      if (errno != EINTR) 
+       return EOF; /* Anything other than interrupt is error! */
+    }
+    else
+      isDone = 1; /* Done if we sent one char */
+  } while (!isDone);
+  return c;
+}
+
+
+
index 17c0a2fba5bc2639bbc125af55f13d7a201d84f3..8c08adb3fd4cde11f06a86e501a33a48ca0c8516 100644 (file)
@@ -4,7 +4,9 @@
 #include <netinet/in.h>
 
 #include "postgres.h"
+#include "miscadmin.h"
 #include "libpq/pqcomm.h"
+#include "libpq/libpq.h"
 
 
 /*
@@ -69,7 +71,7 @@
 
 /* --------------------------------------------------------------------- */
 int
-pqPutShort(int integer, FILE *f)
+pqPutShort(int integer)
 {
        uint16          n;
 
@@ -79,15 +81,12 @@ pqPutShort(int integer, FILE *f)
        n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_s(integer) : htons((uint16) integer));
 #endif
 
-       if (fwrite(&n, 2, 1, f) != 1)
-               return EOF;
-
-       return 0;
+       return pqPutNBytes((char *)&n, 2); /* 0 on success, EOF otherwise */
 }
 
 /* --------------------------------------------------------------------- */
 int
-pqPutLong(int integer, FILE *f)
+pqPutLong(int integer)
 {
        uint32          n;
 
@@ -97,20 +96,17 @@ pqPutLong(int integer, FILE *f)
        n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_l(integer) : htonl((uint32) integer));
 #endif
 
-       if (fwrite(&n, 4, 1, f) != 1)
-               return EOF;
-
-       return 0;
+        return pqPutNBytes((char *)&n,4);
 }
 
 /* --------------------------------------------------------------------- */
 int
-pqGetShort(int *result, FILE *f)
+pqGetShort(int *result)
 {
        uint16          n;
 
-       if (fread(&n, 2, 1, f) != 1)
-               return EOF;
+       if (pqGetNBytes((char *)&n,2) != 0)
+         return EOF;
 
 #ifdef FRONTEND
        *result = (int) ntohs(n);
@@ -123,12 +119,12 @@ pqGetShort(int *result, FILE *f)
 
 /* --------------------------------------------------------------------- */
 int
-pqGetLong(int *result, FILE *f)
+pqGetLong(int *result)
 {
        uint32          n;
 
-       if (fread(&n, 4, 1, f) != 1)
-               return EOF;
+       if (pqGetNBytes((char *)&n, 4) != 0)
+         return EOF;
 
 #ifdef FRONTEND
        *result = (int) ntohl(n);
@@ -145,47 +141,59 @@ pqGetLong(int *result, FILE *f)
                Return 0 if ok.
 */
 int
-pqGetNBytes(char *s, size_t len, FILE *f)
+pqGetNBytes(char *s, size_t len)
 {
-       int                     cnt;
-
-       if (f == NULL)
-               return EOF;
-
-       cnt = fread(s, 1, len, f);
-       s[cnt] = '\0';
-
-       return (cnt == len) ? 0 : EOF;
+       int bytesDone = 0;
+
+       do {
+         int r = recv(MyProcPort->sock, s+bytesDone, len-bytesDone, MSG_WAITALL);
+         if (r == 0 || r == -1) {
+           if (errno != EINTR)
+             return EOF; /* All other than signal-interrupted is error */
+           continue; /* Otherwise, try again */
+         }
+         
+         /* r contains number of bytes received */
+         bytesDone += r;
+
+       } while (bytesDone < len);
+       /* Zero-termination now in pq_getnchar() instead */
+       return 0;
 }
 
 /* --------------------------------------------------------------------- */
 int
-pqPutNBytes(const char *s, size_t len, FILE *f)
+pqPutNBytes(const char *s, size_t len)
 {
-       if (f == NULL)
-               return EOF;
-
-       if (fwrite(s, 1, len, f) != len)
-               return EOF;
+        int bytesDone = 0;
+
+       do {
+         int r = send(MyProcPort->sock, s+bytesDone, len-bytesDone, 0);
+         if (r == 0 || r == -1) {
+           if (errno != EINTR)
+             return EOF; /* Only signal interruption allowed */
+           continue; /* If interruped and read nothing, just try again */
+         }
+         
+         /* r contains number of bytes sent so far */
+         bytesDone += r;
+       } while (bytesDone < len);
 
        return 0;
 }
 
 /* --------------------------------------------------------------------- */
 int
-pqGetString(char *s, size_t len, FILE *f)
+pqGetString(char *s, size_t len)
 {
        int                     c;
 
-       if (f == NULL)
-               return EOF;
-
        /*
         * Keep on reading until we get the terminating '\0' and discard those
         * bytes we don't have room for.
         */
 
-       while ((c = getc(f)) != EOF && c != '\0')
+       while ((c = pq_getchar()) != EOF && c != '\0')
                if (len > 1)
                {
                        *s++ = c;
@@ -202,33 +210,8 @@ pqGetString(char *s, size_t len, FILE *f)
 
 /* --------------------------------------------------------------------- */
 int
-pqPutString(const char *s, FILE *f)
-{
-       if (f == NULL)
-               return 0;
-
-       if (fputs(s, f) == EOF)
-               return EOF;
-
-       fputc('\0', f);                         /* important to send an ending \0 since
-                                                                * backend expects it */
-
-       return 0;
-}
-
-/* --------------------------------------------------------------------- */
-int
-pqGetByte(FILE *f)
+pqPutString(const char *s)
 {
-       return getc(f);
+  return pqPutNBytes(s,strlen(s)+1);
 }
 
-/* --------------------------------------------------------------------- */
-int
-pqPutByte(int c, FILE *f)
-{
-       if (!f)
-               return 0;
-
-       return (putc(c, f) == c) ? 0 : EOF;
-}
index 4fca9623aa934900814e6b4b0e7fa64cfbaa3e6a..a315521eb3594ce5d901208a77b4c0e04bb50db7 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: libpq.h,v 1.22 1999/01/11 03:56:11 scrappy Exp $
+ * $Id: libpq.h,v 1.23 1999/01/12 12:49:52 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -262,6 +262,7 @@ 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 int  pq_putchar(char c);
 extern void pq_putstr(char *s);
 extern void pq_putnchar(char *s, int n);
 extern void pq_putint(int i, int b);
index 0f36e8e93ebf6706a3cd0f7c5485a8e51c0f512d..15c123e4b8d501d096c4f871f37456fef00ff397 100644 (file)
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqcomm.h,v 1.29 1998/09/01 04:36:31 momjian Exp $
+ * $Id: pqcomm.h,v 1.30 1999/01/12 12:49:52 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -152,7 +152,7 @@ typedef struct CancelRequestPacket
 }                      CancelRequestPacket;
 
 
-/* in pqcompriv.c */
+/* in pqcomprim.c */
 int                    pqGetShort(int *, FILE *);
 int                    pqGetLong(int *, FILE *);
 int                    pqGetNBytes(char *, size_t, FILE *);