1 /*-------------------------------------------------------------------------
4 * Communication functions between the Frontend and the Backend
6 * Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.43 1998/05/29 17:00:07 momjian Exp $
12 *-------------------------------------------------------------------------
16 * pq_gettty - return the name of the tty in the given buffer
17 * pq_getport - return the PGPORT setting
18 * pq_close - close input / output connections
19 * pq_flush - flush pending output
20 * pq_getstr - get a null terminated string from connection
21 * pq_getnchar - get n characters from connection
22 * pq_getint - get an integer from connection
23 * pq_putstr - send a null terminated string to connection
24 * pq_putnchar - send n characters to connection
25 * pq_putint - send an integer to connection
26 * pq_getinaddr - initialize address from host and port number
27 * pq_getinserv - initialize address from host and service name
28 * pq_connect - create remote input / output connection
29 * pq_accept - accept remote input / output connection
30 * pq_async_notify - receive notification from backend.
33 * These functions are used by both frontend applications and
34 * the postgres backend.
40 #if defined(HAVE_STRING_H)
48 #include <unistd.h> /* for ttyname() */
49 #include <sys/types.h>
51 #include <sys/socket.h>
54 #include <netinet/in.h>
55 #include <netinet/tcp.h>
56 #include <arpa/inet.h>
60 #define SOMAXCONN 5 /* from Linux listen(2) man page */
61 #endif /* SOMAXCONN */
64 #include "miscadmin.h"
65 #include "libpq/pqsignal.h"
66 #include "libpq/auth.h"
67 #include "libpq/libpq.h" /* where the declarations go */
68 #include "storage/ipc.h"
76 FILE *Pfdebug; /* debugging libpq */
77 int PQAsyncNotifyWaiting; /* for async. notification */
79 /* --------------------------------
80 * pq_init - open portal file descriptors
81 * --------------------------------
86 Pfin = fdopen(fd, "r");
87 Pfout = fdopen(dup(fd), "w");
89 elog(FATAL, "pq_init: Couldn't initialize socket connection");
91 if (getenv("LIBPQ_DEBUG"))
101 /* -------------------------
104 * get a character from the input file,
106 * if Pfdebug is set, also echo the character fetched into Pfdebug
108 * used for debugging libpq
116 if (Pfdebug && c != EOF)
121 /* --------------------------------
122 * pq_gettty - return the name of the tty in the given buffer
123 * --------------------------------
128 strncpy(tp, ttyname(0), 19);
131 /* --------------------------------
132 * pq_getport - return the PGPORT setting
133 * --------------------------------
138 char *envport = getenv("PGPORT");
141 return (atoi(envport));
142 return (atoi(DEF_PGPORT));
145 /* --------------------------------
146 * pq_close - close input / output connections
147 * --------------------------------
162 PQAsyncNotifyWaiting = 0;
167 /* --------------------------------
168 * pq_flush - flush pending output
169 * --------------------------------
178 /* --------------------------------
179 * pq_getstr - get a null terminated string from connection
180 * --------------------------------
183 pq_getstr(char *s, int maxlen)
187 if (Pfin == (FILE *) NULL)
189 /* elog(DEBUG, "Input descriptor is null"); */
193 while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c)
198 * If EOF reached let caller know.
199 * (This will only happen if we hit EOF before the string
200 * delimiter is reached.)
209 * USER FUNCTION - gets a newline-terminated string from the backend.
211 * Chiefly here so that applications can use "COPY <rel> to stdout"
212 * and read the output string. Returns a null-terminated string in s.
214 * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
215 * the terminating \n (like gets(3)).
218 * EOF if it is detected or invalid arguments are given
219 * 0 if EOL is reached (i.e., \n has been read)
220 * (this is required for backward-compatibility -- this
221 * routine used to always return EOF or 0, assuming that
222 * the line ended within maxlen bytes.)
226 PQgetline(char *s, int maxlen)
228 if (!Pfin || !s || maxlen <= 1)
231 if (fgets(s, maxlen - 1, Pfin) == NULL)
233 return feof(Pfin) ? EOF : 1;
251 * USER FUNCTION - sends a string to the backend.
253 * Chiefly here so that applications can use "COPY <rel> from stdin".
269 /* --------------------------------
270 * pq_getnchar - get n characters from connection
271 * --------------------------------
274 pq_getnchar(char *s, int off, int maxlen)
276 return pqGetNBytes(s + off, maxlen, Pfin);
279 /* --------------------------------
280 * pq_getint - get an integer from connection
281 * we receive an integer a byte at a type and reconstruct it so that
282 * machines with different ENDIAN representations can talk to each
284 * --------------------------------
296 * mjl: Seems inconsisten w/ return value of pq_putint (void). Also,
297 * EOF is a valid return value for an int! XXX
303 status = ((n = fgetc(Pfin)) == EOF);
306 status = pqGetShort(&n, Pfin);
309 status = pqGetLong(&n, Pfin);
312 fprintf(stderr, "** Unsupported size %d\n", b);
318 "FATAL: pq_getint failed: errno=%d\n", errno);
319 fputs(PQerrormsg, stderr);
320 pqdebug("%s", PQerrormsg);
327 /* --------------------------------
328 * pq_putstr - send a null terminated string to connection
329 * --------------------------------
334 if (pqPutString(s, Pfout))
337 "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno);
338 fputs(PQerrormsg, stderr);
339 pqdebug("%s", PQerrormsg);
343 /* --------------------------------
344 * pq_putnchar - send n characters to connection
345 * --------------------------------
348 pq_putnchar(char *s, int n)
350 if (pqPutNBytes(s, n, Pfout))
353 "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
355 fputs(PQerrormsg, stderr);
356 pqdebug("%s", PQerrormsg);
360 /* --------------------------------
361 * pq_putint - send an integer to connection
362 * we chop an integer into bytes and send individual bytes
363 * machines with different ENDIAN representations can still talk to each
365 * --------------------------------
368 pq_putint(int i, int b)
379 status = (fputc(i, Pfout) == EOF);
382 status = pqPutShort(i, Pfout);
385 status = pqPutLong(i, Pfout);
388 fprintf(stderr, "** Unsupported size %d\n", b);
394 "FATAL: pq_putint failed: errno=%d\n", errno);
395 fputs(PQerrormsg, stderr);
396 pqdebug("%s", PQerrormsg);
401 * pq_sendoob - send a string over the out-of-band channel
402 * pq_recvoob - receive a string over the oob channel
403 * NB: Fortunately, the out-of-band channel doesn't conflict with
404 * buffered I/O because it is separate from regular com. channel.
408 pq_sendoob(char *msg, int len)
410 int fd = fileno(Pfout);
412 return send(fd, msg, len, MSG_OOB);
416 pq_recvoob(char *msgPtr, int len)
418 int fd = fileno(Pfout);
420 return recv(fd, msgPtr, len, MSG_OOB);
423 /* --------------------------------
424 * pq_getinaddr - initialize address from host and port number
425 * --------------------------------
428 pq_getinaddr(struct sockaddr_in * sin,
434 MemSet((char *) sin, 0, sizeof(*sin));
438 if (*host >= '0' && *host <= '9')
439 sin->sin_addr.s_addr = inet_addr(host);
442 if (!(hs = gethostbyname(host)))
447 if (hs->h_addrtype != AF_INET)
450 "FATAL: pq_getinaddr: %s not on Internet\n",
452 fputs(PQerrormsg, stderr);
453 pqdebug("%s", PQerrormsg);
456 memmove((char *) &sin->sin_addr,
461 sin->sin_family = AF_INET;
462 sin->sin_port = htons(port);
466 /* --------------------------------
467 * pq_getinserv - initialize address from host and servive name
468 * --------------------------------
471 pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
475 if (*serv >= '0' && *serv <= '9')
476 return (pq_getinaddr(sin, host, atoi(serv)));
477 if (!(ss = getservbyname(serv, NULL)))
480 "FATAL: pq_getinserv: unknown service: %s\n",
482 fputs(PQerrormsg, stderr);
483 pqdebug("%s", PQerrormsg);
486 return (pq_getinaddr(sin, host, ntohs(ss->s_port)));
490 * register an out-of-band listener proc--at most one allowed.
491 * This is used for receiving async. notification from the backend.
494 pq_regoob(void (*fptr) ())
496 int fd = fileno(Pfout);
499 ioctl(fd, FIOSSAIOOWN, MyProcPid);
501 ioctl(fd, SIOCSPGRP, MyProcPid);
503 fcntl(fd, F_SETOWN, MyProcPid);
505 pqsignal(SIGURG, fptr);
511 pqsignal(SIGURG, SIG_DFL);
520 /* int len = sizeof(msg); */
523 if (pq_recvoob(msg, len) >= 0)
526 printf("received notification: %s\n", msg);
527 PQAsyncNotifyWaiting = 1;
528 /* PQappendNotify(msg+1); */
534 printf("SIGURG but no data: len = %d, err=%d\n", len, errno);
539 * Streams -- wrapper around Unix socket system calls
542 * Stream functions are used for vanilla TCP connection protocol.
546 * StreamServerPort -- open a sock stream "listening" port.
548 * This initializes the Postmaster's connection
551 * ASSUME: that this doesn't need to be non-blocking because
552 * the Postmaster uses select() to tell when the socket
555 * RETURNS: STATUS_OK or STATUS_ERROR
558 static char sock_path[MAXPGPATH + 1] = "";
561 * Shutdown routine for backend connection
562 * If a Unix socket is used for communication, explicitly close it.
567 Assert(sock_path[0]);
572 StreamServerPort(char *hostName, short portName, int *fdP)
581 family = ((hostName != NULL) ? AF_INET : AF_UNIX);
583 if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
586 "FATAL: StreamServerPort: socket() failed: errno=%d\n",
588 fputs(PQerrormsg, stderr);
589 pqdebug("%s", PQerrormsg);
590 return (STATUS_ERROR);
592 if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
596 "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n",
598 fputs(PQerrormsg, stderr);
599 pqdebug("%s", PQerrormsg);
600 return (STATUS_ERROR);
602 bzero(&saddr, sizeof(saddr));
603 saddr.sa.sa_family = family;
604 if (family == AF_UNIX)
606 len = UNIXSOCK_PATH(saddr.un, portName);
607 strcpy(sock_path, saddr.un.sun_path);
611 saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
612 saddr.in.sin_port = htons(portName);
613 len = sizeof(struct sockaddr_in);
615 err = bind(fd, &saddr.sa, len);
619 "FATAL: StreamServerPort: bind() failed: errno=%d\n",
621 pqdebug("%s", PQerrormsg);
622 strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
623 if (family == AF_UNIX)
624 strcat(PQerrormsg, "\tIf not, remove socket node (/tmp/.s.PGSQL.<portnumber>)and retry.\n");
626 strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
627 fputs(PQerrormsg, stderr);
628 return (STATUS_ERROR);
631 if (family == AF_UNIX)
632 on_exitpg(StreamDoUnlink, NULL);
634 listen(fd, SOMAXCONN);
637 * MS: I took this code from Dillon's version. It makes the listening
638 * port non-blocking. That is not necessary (and may tickle kernel
641 * fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY);
645 if (family == AF_UNIX)
647 chmod(sock_path, 0777);
653 * StreamConnection -- create a new connection with client using
656 * This one should be non-blocking.
658 * RETURNS: STATUS_OK or STATUS_ERROR
661 StreamConnection(int server_fd, Port *port)
665 int family = port->raddr.sa.sa_family;
667 /* accept connection (and fill in the client (remote) address) */
668 len = family == AF_INET ?
669 sizeof(struct sockaddr_in) : sizeof(struct sockaddr_un);
671 if ((port->sock = accept(server_fd,
672 (struct sockaddr *) & port->raddr,
675 elog(ERROR, "postmaster: StreamConnection: accept: %m");
676 return (STATUS_ERROR);
679 /* fill in the server (local) address */
681 if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
684 elog(ERROR, "postmaster: StreamConnection: getsockname: %m");
685 return (STATUS_ERROR);
687 if (family == AF_INET)
692 pe = getprotobyname("TCP");
695 elog(ERROR, "postmaster: getprotobyname failed");
696 return (STATUS_ERROR);
698 if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
699 &on, sizeof(on)) < 0)
701 elog(ERROR, "postmaster: setsockopt failed");
702 return (STATUS_ERROR);
706 /* reset to non-blocking */
707 fcntl(port->sock, F_SETFL, 1);
713 * StreamClose -- close a client/backend connection
716 StreamClose(int sock)
721 /* ---------------------------
722 * StreamOpen -- From client, initiate a connection with the
723 * server (Postmaster).
725 * RETURNS: STATUS_OK or STATUS_ERROR
727 * NOTE: connection is NOT established just because this
728 * routine exits. Local state is ok, but we haven't
729 * spoken to the postmaster yet.
730 * ---------------------------
733 StreamOpen(char *hostName, short portName, Port *port)
740 /* set up the server (remote) address */
741 MemSet((char *) &port->raddr, 0, sizeof(port->raddr));
744 if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET)
747 "FATAL: StreamOpen: unknown hostname: %s\n",
749 fputs(PQerrormsg, stderr);
750 pqdebug("%s", PQerrormsg);
751 return (STATUS_ERROR);
753 memmove((char *) &(port->raddr.in.sin_addr),
756 port->raddr.in.sin_family = AF_INET;
757 port->raddr.in.sin_port = htons(portName);
758 len = sizeof(struct sockaddr_in);
762 port->raddr.un.sun_family = AF_UNIX;
763 len = UNIXSOCK_PATH(port->raddr.un, portName);
765 /* connect to the server */
766 if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
769 "FATAL: StreamOpen: socket() failed: errno=%d\n",
771 fputs(PQerrormsg, stderr);
772 pqdebug("%s", PQerrormsg);
773 return (STATUS_ERROR);
775 err = connect(port->sock, &port->raddr.sa, len);
779 "FATAL: StreamOpen: connect() failed: errno=%d\n",
781 fputs(PQerrormsg, stderr);
782 pqdebug("%s", PQerrormsg);
783 return (STATUS_ERROR);
786 /* fill in the client address */
787 if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
790 "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
792 fputs(PQerrormsg, stderr);
793 pqdebug("%s", PQerrormsg);
794 return (STATUS_ERROR);