*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.28 1997/11/19 17:52:00 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>
#include <unistd.h> /* for ttyname() */
#include <sys/types.h>
+#include <sys/stat.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#endif /* SOMAXCONN */
#endif /* linux */
-#include <postgres.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
FILE *Pfout,
*Pfin;
FILE *Pfdebug; /* debugging libpq */
-int PQAsyncNotifyWaiting; /* for async. notification */
/* --------------------------------
* pq_init - open portal file descriptors
elog(FATAL, "pq_init: Couldn't initialize socket connection");
PQnotifies_init();
if (getenv("LIBPQ_DEBUG"))
- {
Pfdebug = stderr;
- }
else
- {
Pfdebug = NULL;
- }
}
/* -------------------------
fclose(Pfout);
Pfout = NULL;
}
- PQAsyncNotifyWaiting = 0;
PQnotifies_init();
- pq_unregoob();
}
/* --------------------------------
{
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"); */
*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
return (EOF);
if (fgets(s, maxlen - 1, Pfin) == NULL)
- {
return feof(Pfin) ? EOF : 1;
- }
else
{
for (; *s; s++)
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
}
/* --------------------------------
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);
}
}
-/* ---
- * 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
* --------------------------------
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, getpid());
-#elif defined(sco)
- ioctl(fd, SIOCSPGRP, getpid());
-#else
- fcntl(fd, F_SETOWN, getpid());
-#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
*
* RETURNS: STATUS_OK or STATUS_ERROR
*/
-static char sock_path[100] = "";
+static char sock_path[MAXPGPATH + 1] = "";
-static void
-do_unlink()
+/* do_unlink()
+ * Shutdown routine for backend connection
+ * If a Unix socket is used for communication, explicitly close it.
+ */
+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;
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);
/*
*/
*fdP = fd;
- if (family == AF_UNIX) atexit(do_unlink);
+ if (family == AF_UNIX)
+ chmod(sock_path, 0777);
return (STATUS_OK);
}
{
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 ?
(struct sockaddr *) & port->raddr,
&addrlen)) < 0)
{
- elog(WARN, "postmaster: StreamConnection: accept: %m");
+ elog(ERROR, "postmaster: StreamConnection: accept: %m");
return (STATUS_ERROR);
}
if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
&addrlen) < 0)
{
- elog(WARN, "postmaster: StreamConnection: getsockname: %m");
+ elog(ERROR, "postmaster: StreamConnection: getsockname: %m");
return (STATUS_ERROR);
}
if (family == AF_INET)
pe = getprotobyname("TCP");
if (pe == NULL)
{
- elog(WARN, "postmaster: getprotobyname failed");
+ elog(ERROR, "postmaster: getprotobyname failed");
return (STATUS_ERROR);
}
if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
&on, sizeof(on)) < 0)
{
- elog(WARN, "postmaster: setsockopt failed");
+ elog(ERROR, "postmaster: setsockopt failed");
return (STATUS_ERROR);
}
}
- port->mask = 1 << port->sock;
-
/* reset to non-blocking */
fcntl(port->sock, F_SETFL, 1);
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",
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,
}
/* 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",
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;
-
- if (type >= 1 && type <= LAST_AUTHENTICATION_TYPE)
- {
- result = authentication_type_name[type];
- }
-
- if (result == 0)
- {
- result = "<unknown authentication type>";
- }
+ unsigned char *p;
+ int len;
- return result;
+ p = pg_server_to_client(s, n);
+ len = strlen(p);
+ pq_putint(len, sizeof(int));
+ pq_putnchar(p, len);
}
+#endif