]> granicus.if.org Git - postgresql/blobdiff - src/backend/libpq/pqcomm.c
From: t-ishii@sra.co.jp
[postgresql] / src / backend / libpq / pqcomm.c
index 8014ae14f82b42bd9f62ab2f0aba2f29bf9ad15b..56f0fd658e99a40969c90891c09e56c3fda7f14c 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.34 1998/01/25 05:13:18 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.50 1998/07/26 04:30:28 scrappy Exp $
  *
  *-------------------------------------------------------------------------
  */
  *             pq_putstr               - send a null terminated string to connection
  *             pq_putnchar             - send n characters to connection
  *             pq_putint               - send an integer to connection
+ *             pq_putncharlen          - send n characters to connection
+ *                                       (also send an int header indicating
+ *                                        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
- *             pq_async_notify - receive notification from backend.
  *
  * NOTES
  *             These functions are used by both frontend applications and
  *             the postgres backend.
  *
  */
+#include "postgres.h"
+
 #include <stdio.h>
+#if defined(HAVE_STRING_H)
 #include <string.h>
+#else
+#include <strings.h>
+#endif
 #include <signal.h>
 #include <errno.h>
 #include <fcntl.h>
 #endif                                                 /* SOMAXCONN */
 #endif                                                 /* linux */
 
-#include <postgres.h>
-
-#include <miscadmin.h>
-#include <libpq/pqsignal.h>
-#include <libpq/auth.h>
-#include <libpq/libpq.h>               /* where the declarations go */
-#include <storage/ipc.h>
+#include "miscadmin.h"
+#include "libpq/pqsignal.h"
+#include "libpq/auth.h"
+#include "libpq/libpq.h"               /* where the declarations go */
+#include "storage/ipc.h"
+#ifdef MULTIBYTE
+#include "mb/pg_wchar.h"
+#endif
 
 /* ----------------
  *             declarations
@@ -69,7 +78,6 @@
 FILE      *Pfout,
                   *Pfin;
 FILE      *Pfdebug;                    /* debugging libpq */
-int                    PQAsyncNotifyWaiting;           /* for async. notification */
 
 /* --------------------------------
  *             pq_init - open portal file descriptors
@@ -84,13 +92,9 @@ pq_init(int fd)
                elog(FATAL, "pq_init: Couldn't initialize socket connection");
        PQnotifies_init();
        if (getenv("LIBPQ_DEBUG"))
-       {
                Pfdebug = stderr;
-       }
        else
-       {
                Pfdebug = NULL;
-       }
 }
 
 /* -------------------------
@@ -154,9 +158,7 @@ pq_close()
                fclose(Pfout);
                Pfout = NULL;
        }
-       PQAsyncNotifyWaiting = 0;
        PQnotifies_init();
-       pq_unregoob();
 }
 
 /* --------------------------------
@@ -179,6 +181,14 @@ pq_getstr(char *s, int maxlen)
 {
        int                     c = '\0';
 
+#ifdef MULTIBYTE
+       unsigned char *p, *ps;
+       int len;
+
+       ps = s;
+       len = maxlen;
+#endif
+
        if (Pfin == (FILE *) NULL)
        {
 /*             elog(DEBUG, "Input descriptor is null"); */
@@ -189,6 +199,13 @@ pq_getstr(char *s, int maxlen)
                *s++ = c;
        *s = '\0';
 
+#ifdef MULTIBYTE
+       p = pg_client_to_server(ps, len);
+       if (ps != p) {  /* actual conversion has been done? */
+         strcpy(ps, p);
+       }
+#endif
+       
        /* -----------------
         *         If EOF reached let caller know.
         *         (This will only happen if we hit EOF before the string
@@ -224,9 +241,7 @@ PQgetline(char *s, int maxlen)
                return (EOF);
 
        if (fgets(s, maxlen - 1, Pfin) == NULL)
-       {
                return feof(Pfin) ? EOF : 1;
-       }
        else
        {
                for (; *s; s++)
@@ -269,28 +284,6 @@ int
 pq_getnchar(char *s, int off, int maxlen)
 {
        return pqGetNBytes(s + off, maxlen, Pfin);
-
-#if 0
-       int                     c = '\0';
-
-       if (Pfin == (FILE *) NULL)
-       {
-/*             elog(DEBUG, "Input descriptor is null"); */
-               return (EOF);
-       }
-
-       s += off;
-       while (maxlen-- && (c = pq_getc(Pfin)) != EOF)
-               *s++ = c;
-
-       /* -----------------
-        *         If EOF reached let caller know
-        * -----------------
-        */
-       if (c == EOF)
-               return (EOF);
-       return (!EOF);
-#endif
 }
 
 /* --------------------------------
@@ -348,7 +341,14 @@ pq_getint(int b)
 void
 pq_putstr(char *s)
 {
+#ifdef MULTIBYTE
+        unsigned char *p;
+
+        p = pg_server_to_client(s, strlen(s));
+       if (pqPutString(p, Pfout))
+#else
        if (pqPutString(s, Pfout))
+#endif
        {
                sprintf(PQerrormsg,
                                "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno);
@@ -414,32 +414,6 @@ pq_putint(int i, int b)
        }
 }
 
-/* ---
- *        pq_sendoob - send a string over the out-of-band channel
- *        pq_recvoob - receive a string over the oob channel
- *     NB: Fortunately, the out-of-band channel doesn't conflict with
- *             buffered I/O because it is separate from regular com. channel.
- * ---
- */
-int
-pq_sendoob(char *msg, int len)
-{
-       int                     fd = fileno(Pfout);
-
-       return (send(fd, msg, len, MSG_OOB));
-}
-
-int
-pq_recvoob(char *msgPtr, int *lenPtr)
-{
-       int                     fd = fileno(Pfout);
-       int                     len = 0;
-
-       len = recv(fd, msgPtr + len, *lenPtr, MSG_OOB);
-       *lenPtr = len;
-       return (len);
-}
-
 /* --------------------------------
  *             pq_getinaddr - initialize address from host and port number
  * --------------------------------
@@ -506,55 +480,6 @@ pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
        return (pq_getinaddr(sin, host, ntohs(ss->s_port)));
 }
 
-/*
- * register an out-of-band listener proc--at most one allowed.
- * This is used for receiving async. notification from the backend.
- */
-void
-pq_regoob(void (*fptr) ())
-{
-       int                     fd = fileno(Pfout);
-
-#if defined(hpux)
-       ioctl(fd, FIOSSAIOOWN, MyProcPid);
-#elif defined(sco)
-       ioctl(fd, SIOCSPGRP, MyProcPid);
-#else
-       fcntl(fd, F_SETOWN, MyProcPid);
-#endif                                                 /* hpux */
-       pqsignal(SIGURG, fptr);
-}
-
-void
-pq_unregoob()
-{
-       pqsignal(SIGURG, SIG_DFL);
-}
-
-
-void
-pq_async_notify()
-{
-       char            msg[20];
-
-       /* int len = sizeof(msg); */
-       int                     len = 20;
-
-       if (pq_recvoob(msg, &len) >= 0)
-       {
-               /* debugging */
-               printf("received notification: %s\n", msg);
-               PQAsyncNotifyWaiting = 1;
-               /* PQappendNotify(msg+1); */
-       }
-       else
-       {
-               extern int      errno;
-
-               printf("SIGURG but no data: len = %d, err=%d\n", len, errno);
-       }
-}
-
 /*
  * Streams -- wrapper around Unix socket system calls
  *
@@ -575,27 +500,23 @@ pq_async_notify()
  * RETURNS: STATUS_OK or STATUS_ERROR
  */
 
-static char sock_path[MAXPGPATH+1] = "";
+static char sock_path[MAXPGPATH + 1] = "";
 
 /* do_unlink()
  * Shutdown routine for backend connection
  * If a Unix socket is used for communication, explicitly close it.
  */
-static void
-do_unlink()
+void
+StreamDoUnlink()
 {
-       if (sock_path[0])
-               unlink(sock_path);
+       Assert(sock_path[0]);
+       unlink(sock_path);
 }
 
 int
 StreamServerPort(char *hostName, short portName, int *fdP)
 {
-       union
-       {
-               struct sockaddr_in in;
-               struct sockaddr_un un;
-       }                       saddr;
+       SockAddr        saddr;
        int                     fd,
                                err,
                                family;
@@ -623,36 +544,38 @@ StreamServerPort(char *hostName, short portName, int *fdP)
                pqdebug("%s", PQerrormsg);
                return (STATUS_ERROR);
        }
-       bzero(&saddr, sizeof(saddr));
+       MemSet((char *) &saddr, 0, sizeof(saddr));
+       saddr.sa.sa_family = family;
        if (family == AF_UNIX)
        {
-               saddr.un.sun_family = family;
                len = UNIXSOCK_PATH(saddr.un, portName);
                strcpy(sock_path, saddr.un.sun_path);
        }
        else
        {
-               saddr.in.sin_family = family;
                saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
                saddr.in.sin_port = htons(portName);
-               len = sizeof saddr.in;
+               len = sizeof(struct sockaddr_in);
        }
-       err = bind(fd, (struct sockaddr *) & saddr, len);
+       err = bind(fd, &saddr.sa, len);
        if (err < 0)
        {
-         sprintf(PQerrormsg,
-                 "FATAL: StreamServerPort: bind() failed: errno=%d\n",
-                 errno);
-         pqdebug("%s", PQerrormsg);
-         strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
-         if (family == AF_UNIX)
-           strcat(PQerrormsg, "\tIf not, remove socket node (/tmp/.s.PGSQL.<portnr>)and retry.\n");
-         else
-           strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
-         fputs(PQerrormsg, stderr);
-         return (STATUS_ERROR);
+               sprintf(PQerrormsg,
+                               "FATAL: StreamServerPort: bind() failed: errno=%d\n",
+                               errno);
+               pqdebug("%s", PQerrormsg);
+               strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
+               if (family == AF_UNIX)
+                       strcat(PQerrormsg, "\tIf not, remove socket node (/tmp/.s.PGSQL.<portnumber>)and retry.\n");
+               else
+                       strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
+               fputs(PQerrormsg, stderr);
+               return (STATUS_ERROR);
        }
 
+       if (family == AF_UNIX)
+               on_proc_exit(StreamDoUnlink, NULL);
+
        listen(fd, SOMAXCONN);
 
        /*
@@ -665,10 +588,7 @@ StreamServerPort(char *hostName, short portName, int *fdP)
 
        *fdP = fd;
        if (family == AF_UNIX)
-         {
-           chmod(sock_path, 0777);
-           atexit(do_unlink);
-         }
+               chmod(sock_path, 0777);
        return (STATUS_OK);
 }
 
@@ -685,7 +605,7 @@ StreamConnection(int server_fd, Port *port)
 {
        int                     len,
                                addrlen;
-       int                     family = port->raddr.in.sin_family;
+       int                     family = port->raddr.sa.sa_family;
 
        /* accept connection (and fill in the client (remote) address) */
        len = family == AF_INET ?
@@ -726,8 +646,6 @@ StreamConnection(int server_fd, Port *port)
                }
        }
 
-       port->mask = 1 << port->sock;
-
        /* reset to non-blocking */
        fcntl(port->sock, F_SETFL, 1);
 
@@ -788,7 +706,7 @@ StreamOpen(char *hostName, short portName, Port *port)
                len = UNIXSOCK_PATH(port->raddr.un, portName);
        }
        /* connect to the server */
-       if ((port->sock = socket(port->raddr.in.sin_family, SOCK_STREAM, 0)) < 0)
+       if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
        {
                sprintf(PQerrormsg,
                                "FATAL: StreamOpen: socket() failed: errno=%d\n",
@@ -797,7 +715,7 @@ StreamOpen(char *hostName, short portName, Port *port)
                pqdebug("%s", PQerrormsg);
                return (STATUS_ERROR);
        }
-       err = connect(port->sock, (struct sockaddr *) & port->raddr, len);
+       err = connect(port->sock, &port->raddr.sa, len);
        if (err < 0)
        {
                sprintf(PQerrormsg,
@@ -809,8 +727,7 @@ StreamOpen(char *hostName, short portName, Port *port)
        }
 
        /* fill in the client address */
-       if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
-                                       &len) < 0)
+       if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
        {
                sprintf(PQerrormsg,
                                "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
@@ -823,31 +740,16 @@ StreamOpen(char *hostName, short portName, Port *port)
        return (STATUS_OK);
 }
 
-static char *authentication_type_name[] = {
-       0, 0, 0, 0, 0, 0, 0,
-       "the default authentication type",
-       0, 0,
-       "Kerberos v4",
-       "Kerberos v5",
-       "host-based authentication",
-       "unauthenication",
-       "plaintext password authentication"
-};
-
-char      *
-name_of_authentication_type(int type)
+#ifdef MULTIBYTE
+void
+pq_putncharlen(char *s, int n)
 {
-       char       *result = 0;
+  unsigned char *p;
+  int len;
 
-       if (type >= 1 && type <= LAST_AUTHENTICATION_TYPE)
-       {
-               result = authentication_type_name[type];
-       }
-
-       if (result == 0)
-       {
-               result = "<unknown authentication type>";
-       }
-
-       return result;
+  p = pg_server_to_client(s, n);
+  len = strlen(p);
+  pq_putint(len, sizeof(int));
+  pq_putnchar(p, len);
 }
+#endif