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.49 1998/07/18 18:34:03 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_putncharlen - send n characters to connection
27 * (also send an int header indicating
29 * pq_getinaddr - initialize address from host and port number
30 * pq_getinserv - initialize address from host and service name
31 * pq_connect - create remote input / output connection
32 * pq_accept - accept remote input / output connection
35 * These functions are used by both frontend applications and
36 * the postgres backend.
42 #if defined(HAVE_STRING_H)
50 #include <unistd.h> /* for ttyname() */
51 #include <sys/types.h>
53 #include <sys/socket.h>
55 #include <netinet/in.h>
56 #include <netinet/tcp.h>
57 #include <arpa/inet.h>
61 #define SOMAXCONN 5 /* from Linux listen(2) man page */
62 #endif /* SOMAXCONN */
65 #include "miscadmin.h"
66 #include "libpq/pqsignal.h"
67 #include "libpq/auth.h"
68 #include "libpq/libpq.h" /* where the declarations go */
69 #include "storage/ipc.h"
71 #include "commands/variable.h"
80 FILE *Pfdebug; /* debugging libpq */
82 /* --------------------------------
83 * pq_init - open portal file descriptors
84 * --------------------------------
89 Pfin = fdopen(fd, "r");
90 Pfout = fdopen(dup(fd), "w");
92 elog(FATAL, "pq_init: Couldn't initialize socket connection");
94 if (getenv("LIBPQ_DEBUG"))
100 /* -------------------------
103 * get a character from the input file,
105 * if Pfdebug is set, also echo the character fetched into Pfdebug
107 * used for debugging libpq
115 if (Pfdebug && c != EOF)
120 /* --------------------------------
121 * pq_gettty - return the name of the tty in the given buffer
122 * --------------------------------
127 strncpy(tp, ttyname(0), 19);
130 /* --------------------------------
131 * pq_getport - return the PGPORT setting
132 * --------------------------------
137 char *envport = getenv("PGPORT");
140 return (atoi(envport));
141 return (atoi(DEF_PGPORT));
144 /* --------------------------------
145 * pq_close - close input / output connections
146 * --------------------------------
164 /* --------------------------------
165 * pq_flush - flush pending output
166 * --------------------------------
175 /* --------------------------------
176 * pq_getstr - get a null terminated string from connection
177 * --------------------------------
180 pq_getstr(char *s, int maxlen)
185 unsigned char *p, *ps;
192 if (Pfin == (FILE *) NULL)
194 /* elog(DEBUG, "Input descriptor is null"); */
198 while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c)
203 p = pg_client_to_server(ps, len);
204 if (ps != p) { /* actual conversion has been done? */
210 * If EOF reached let caller know.
211 * (This will only happen if we hit EOF before the string
212 * delimiter is reached.)
221 * USER FUNCTION - gets a newline-terminated string from the backend.
223 * Chiefly here so that applications can use "COPY <rel> to stdout"
224 * and read the output string. Returns a null-terminated string in s.
226 * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
227 * the terminating \n (like gets(3)).
230 * EOF if it is detected or invalid arguments are given
231 * 0 if EOL is reached (i.e., \n has been read)
232 * (this is required for backward-compatibility -- this
233 * routine used to always return EOF or 0, assuming that
234 * the line ended within maxlen bytes.)
238 PQgetline(char *s, int maxlen)
240 if (!Pfin || !s || maxlen <= 1)
243 if (fgets(s, maxlen - 1, Pfin) == NULL)
244 return feof(Pfin) ? EOF : 1;
261 * USER FUNCTION - sends a string to the backend.
263 * Chiefly here so that applications can use "COPY <rel> from stdin".
279 /* --------------------------------
280 * pq_getnchar - get n characters from connection
281 * --------------------------------
284 pq_getnchar(char *s, int off, int maxlen)
286 return pqGetNBytes(s + off, maxlen, Pfin);
289 /* --------------------------------
290 * pq_getint - get an integer from connection
291 * we receive an integer a byte at a type and reconstruct it so that
292 * machines with different ENDIAN representations can talk to each
294 * --------------------------------
306 * mjl: Seems inconsisten w/ return value of pq_putint (void). Also,
307 * EOF is a valid return value for an int! XXX
313 status = ((n = fgetc(Pfin)) == EOF);
316 status = pqGetShort(&n, Pfin);
319 status = pqGetLong(&n, Pfin);
322 fprintf(stderr, "** Unsupported size %d\n", b);
328 "FATAL: pq_getint failed: errno=%d\n", errno);
329 fputs(PQerrormsg, stderr);
330 pqdebug("%s", PQerrormsg);
337 /* --------------------------------
338 * pq_putstr - send a null terminated string to connection
339 * --------------------------------
347 p = pg_server_to_client(s, strlen(s));
348 if (pqPutString(p, Pfout))
350 if (pqPutString(s, Pfout))
354 "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno);
355 fputs(PQerrormsg, stderr);
356 pqdebug("%s", PQerrormsg);
360 /* --------------------------------
361 * pq_putnchar - send n characters to connection
362 * --------------------------------
365 pq_putnchar(char *s, int n)
367 if (pqPutNBytes(s, n, Pfout))
370 "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
372 fputs(PQerrormsg, stderr);
373 pqdebug("%s", PQerrormsg);
377 /* --------------------------------
378 * pq_putint - send an integer to connection
379 * we chop an integer into bytes and send individual bytes
380 * machines with different ENDIAN representations can still talk to each
382 * --------------------------------
385 pq_putint(int i, int b)
396 status = (fputc(i, Pfout) == EOF);
399 status = pqPutShort(i, Pfout);
402 status = pqPutLong(i, Pfout);
405 fprintf(stderr, "** Unsupported size %d\n", b);
411 "FATAL: pq_putint failed: errno=%d\n", errno);
412 fputs(PQerrormsg, stderr);
413 pqdebug("%s", PQerrormsg);
417 /* --------------------------------
418 * pq_getinaddr - initialize address from host and port number
419 * --------------------------------
422 pq_getinaddr(struct sockaddr_in * sin,
428 MemSet((char *) sin, 0, sizeof(*sin));
432 if (*host >= '0' && *host <= '9')
433 sin->sin_addr.s_addr = inet_addr(host);
436 if (!(hs = gethostbyname(host)))
441 if (hs->h_addrtype != AF_INET)
444 "FATAL: pq_getinaddr: %s not on Internet\n",
446 fputs(PQerrormsg, stderr);
447 pqdebug("%s", PQerrormsg);
450 memmove((char *) &sin->sin_addr,
455 sin->sin_family = AF_INET;
456 sin->sin_port = htons(port);
460 /* --------------------------------
461 * pq_getinserv - initialize address from host and servive name
462 * --------------------------------
465 pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
469 if (*serv >= '0' && *serv <= '9')
470 return (pq_getinaddr(sin, host, atoi(serv)));
471 if (!(ss = getservbyname(serv, NULL)))
474 "FATAL: pq_getinserv: unknown service: %s\n",
476 fputs(PQerrormsg, stderr);
477 pqdebug("%s", PQerrormsg);
480 return (pq_getinaddr(sin, host, ntohs(ss->s_port)));
484 * Streams -- wrapper around Unix socket system calls
487 * Stream functions are used for vanilla TCP connection protocol.
491 * StreamServerPort -- open a sock stream "listening" port.
493 * This initializes the Postmaster's connection
496 * ASSUME: that this doesn't need to be non-blocking because
497 * the Postmaster uses select() to tell when the socket
500 * RETURNS: STATUS_OK or STATUS_ERROR
503 static char sock_path[MAXPGPATH + 1] = "";
506 * Shutdown routine for backend connection
507 * If a Unix socket is used for communication, explicitly close it.
512 Assert(sock_path[0]);
517 StreamServerPort(char *hostName, short portName, int *fdP)
526 family = ((hostName != NULL) ? AF_INET : AF_UNIX);
528 if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
531 "FATAL: StreamServerPort: socket() failed: errno=%d\n",
533 fputs(PQerrormsg, stderr);
534 pqdebug("%s", PQerrormsg);
535 return (STATUS_ERROR);
537 if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
541 "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n",
543 fputs(PQerrormsg, stderr);
544 pqdebug("%s", PQerrormsg);
545 return (STATUS_ERROR);
547 MemSet((char *) &saddr, 0, sizeof(saddr));
548 saddr.sa.sa_family = family;
549 if (family == AF_UNIX)
551 len = UNIXSOCK_PATH(saddr.un, portName);
552 strcpy(sock_path, saddr.un.sun_path);
556 saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
557 saddr.in.sin_port = htons(portName);
558 len = sizeof(struct sockaddr_in);
560 err = bind(fd, &saddr.sa, len);
564 "FATAL: StreamServerPort: bind() failed: errno=%d\n",
566 pqdebug("%s", PQerrormsg);
567 strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
568 if (family == AF_UNIX)
569 strcat(PQerrormsg, "\tIf not, remove socket node (/tmp/.s.PGSQL.<portnumber>)and retry.\n");
571 strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
572 fputs(PQerrormsg, stderr);
573 return (STATUS_ERROR);
576 if (family == AF_UNIX)
577 on_proc_exit(StreamDoUnlink, NULL);
579 listen(fd, SOMAXCONN);
582 * MS: I took this code from Dillon's version. It makes the listening
583 * port non-blocking. That is not necessary (and may tickle kernel
586 * fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY);
590 if (family == AF_UNIX)
591 chmod(sock_path, 0777);
596 * StreamConnection -- create a new connection with client using
599 * This one should be non-blocking.
601 * RETURNS: STATUS_OK or STATUS_ERROR
604 StreamConnection(int server_fd, Port *port)
608 int family = port->raddr.sa.sa_family;
610 /* accept connection (and fill in the client (remote) address) */
611 len = family == AF_INET ?
612 sizeof(struct sockaddr_in) : sizeof(struct sockaddr_un);
614 if ((port->sock = accept(server_fd,
615 (struct sockaddr *) & port->raddr,
618 elog(ERROR, "postmaster: StreamConnection: accept: %m");
619 return (STATUS_ERROR);
622 /* fill in the server (local) address */
624 if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
627 elog(ERROR, "postmaster: StreamConnection: getsockname: %m");
628 return (STATUS_ERROR);
630 if (family == AF_INET)
635 pe = getprotobyname("TCP");
638 elog(ERROR, "postmaster: getprotobyname failed");
639 return (STATUS_ERROR);
641 if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
642 &on, sizeof(on)) < 0)
644 elog(ERROR, "postmaster: setsockopt failed");
645 return (STATUS_ERROR);
649 /* reset to non-blocking */
650 fcntl(port->sock, F_SETFL, 1);
656 * StreamClose -- close a client/backend connection
659 StreamClose(int sock)
664 /* ---------------------------
665 * StreamOpen -- From client, initiate a connection with the
666 * server (Postmaster).
668 * RETURNS: STATUS_OK or STATUS_ERROR
670 * NOTE: connection is NOT established just because this
671 * routine exits. Local state is ok, but we haven't
672 * spoken to the postmaster yet.
673 * ---------------------------
676 StreamOpen(char *hostName, short portName, Port *port)
683 /* set up the server (remote) address */
684 MemSet((char *) &port->raddr, 0, sizeof(port->raddr));
687 if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET)
690 "FATAL: StreamOpen: unknown hostname: %s\n",
692 fputs(PQerrormsg, stderr);
693 pqdebug("%s", PQerrormsg);
694 return (STATUS_ERROR);
696 memmove((char *) &(port->raddr.in.sin_addr),
699 port->raddr.in.sin_family = AF_INET;
700 port->raddr.in.sin_port = htons(portName);
701 len = sizeof(struct sockaddr_in);
705 port->raddr.un.sun_family = AF_UNIX;
706 len = UNIXSOCK_PATH(port->raddr.un, portName);
708 /* connect to the server */
709 if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
712 "FATAL: StreamOpen: socket() failed: errno=%d\n",
714 fputs(PQerrormsg, stderr);
715 pqdebug("%s", PQerrormsg);
716 return (STATUS_ERROR);
718 err = connect(port->sock, &port->raddr.sa, len);
722 "FATAL: StreamOpen: connect() failed: errno=%d\n",
724 fputs(PQerrormsg, stderr);
725 pqdebug("%s", PQerrormsg);
726 return (STATUS_ERROR);
729 /* fill in the client address */
730 if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
733 "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
735 fputs(PQerrormsg, stderr);
736 pqdebug("%s", PQerrormsg);
737 return (STATUS_ERROR);
745 pq_putncharlen(char *s, int n)
750 p = pg_server_to_client(s, n);
752 pq_putint(len, sizeof(int));