]> granicus.if.org Git - postgresql/blob - src/backend/libpq/pqcomm.c
Remove fork()/exec() and only do fork(). Small cleanups.
[postgresql] / src / backend / libpq / pqcomm.c
1  /*-------------------------------------------------------------------------
2  *
3  * pqcomm.c--
4  *        Communication functions between the Frontend and the Backend
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.43 1998/05/29 17:00:07 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 /*
15  * INTERFACE ROUTINES
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.
31  *
32  * NOTES
33  *              These functions are used by both frontend applications and
34  *              the postgres backend.
35  *
36  */
37 #include "postgres.h"
38
39 #include <stdio.h>
40 #if defined(HAVE_STRING_H)
41 #include <string.h>
42 #else
43 #include <strings.h>
44 #endif
45 #include <signal.h>
46 #include <errno.h>
47 #include <fcntl.h>
48 #include <unistd.h>                             /* for ttyname() */
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <sys/socket.h>
52 #include <sys/un.h>
53 #include <netdb.h>
54 #include <netinet/in.h>
55 #include <netinet/tcp.h>
56 #include <arpa/inet.h>
57
58 #if defined(linux)
59 #ifndef SOMAXCONN
60 #define SOMAXCONN 5                             /* from Linux listen(2) man page */
61 #endif                                                  /* SOMAXCONN */
62 #endif                                                  /* linux */
63
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"
69
70 /* ----------------
71  *              declarations
72  * ----------------
73  */
74 FILE       *Pfout,
75                    *Pfin;
76 FILE       *Pfdebug;                    /* debugging libpq */
77 int                     PQAsyncNotifyWaiting;           /* for async. notification */
78
79 /* --------------------------------
80  *              pq_init - open portal file descriptors
81  * --------------------------------
82  */
83 void
84 pq_init(int fd)
85 {
86         Pfin = fdopen(fd, "r");
87         Pfout = fdopen(dup(fd), "w");
88         if (!Pfin || !Pfout)
89                 elog(FATAL, "pq_init: Couldn't initialize socket connection");
90         PQnotifies_init();
91         if (getenv("LIBPQ_DEBUG"))
92         {
93                 Pfdebug = stderr;
94         }
95         else
96         {
97                 Pfdebug = NULL;
98         }
99 }
100
101 /* -------------------------
102  *       pq_getc(File* fin)
103  *
104  *       get a character from the input file,
105  *
106  *       if Pfdebug is set, also echo the character fetched into Pfdebug
107  *
108  *       used for debugging libpq
109  */
110 static int
111 pq_getc(FILE *fin)
112 {
113         int                     c;
114
115         c = getc(fin);
116         if (Pfdebug && c != EOF)
117                 putc(c, Pfdebug);
118         return c;
119 }
120
121 /* --------------------------------
122  *              pq_gettty - return the name of the tty in the given buffer
123  * --------------------------------
124  */
125 void
126 pq_gettty(char *tp)
127 {
128         strncpy(tp, ttyname(0), 19);
129 }
130
131 /* --------------------------------
132  *              pq_getport - return the PGPORT setting
133  * --------------------------------
134  */
135 int
136 pq_getport()
137 {
138         char       *envport = getenv("PGPORT");
139
140         if (envport)
141                 return (atoi(envport));
142         return (atoi(DEF_PGPORT));
143 }
144
145 /* --------------------------------
146  *              pq_close - close input / output connections
147  * --------------------------------
148  */
149 void
150 pq_close()
151 {
152         if (Pfin)
153         {
154                 fclose(Pfin);
155                 Pfin = NULL;
156         }
157         if (Pfout)
158         {
159                 fclose(Pfout);
160                 Pfout = NULL;
161         }
162         PQAsyncNotifyWaiting = 0;
163         PQnotifies_init();
164         pq_unregoob();
165 }
166
167 /* --------------------------------
168  *              pq_flush - flush pending output
169  * --------------------------------
170  */
171 void
172 pq_flush()
173 {
174         if (Pfout)
175                 fflush(Pfout);
176 }
177
178 /* --------------------------------
179  *              pq_getstr - get a null terminated string from connection
180  * --------------------------------
181  */
182 int
183 pq_getstr(char *s, int maxlen)
184 {
185         int                     c = '\0';
186
187         if (Pfin == (FILE *) NULL)
188         {
189 /*              elog(DEBUG, "Input descriptor is null"); */
190                 return (EOF);
191         }
192
193         while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c)
194                 *s++ = c;
195         *s = '\0';
196
197         /* -----------------
198          *         If EOF reached let caller know.
199          *         (This will only happen if we hit EOF before the string
200          *         delimiter is reached.)
201          * -----------------
202          */
203         if (c == EOF)
204                 return (EOF);
205         return (!EOF);
206 }
207
208 /*
209  * USER FUNCTION - gets a newline-terminated string from the backend.
210  *
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.
213  *
214  * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
215  * the terminating \n (like gets(3)).
216  *
217  * RETURNS:
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.)
223  *              1 in other cases
224  */
225 int
226 PQgetline(char *s, int maxlen)
227 {
228         if (!Pfin || !s || maxlen <= 1)
229                 return (EOF);
230
231         if (fgets(s, maxlen - 1, Pfin) == NULL)
232         {
233                 return feof(Pfin) ? EOF : 1;
234         }
235         else
236         {
237                 for (; *s; s++)
238                 {
239                         if (*s == '\n')
240                         {
241                                 *s = '\0';
242                                 break;
243                         }
244                 }
245         }
246
247         return 0;
248 }
249
250 /*
251  * USER FUNCTION - sends a string to the backend.
252  *
253  * Chiefly here so that applications can use "COPY <rel> from stdin".
254  *
255  * RETURNS:
256  *              0 in all cases.
257  */
258 int
259 PQputline(char *s)
260 {
261         if (Pfout)
262         {
263                 fputs(s, Pfout);
264                 fflush(Pfout);
265         }
266         return (0);
267 }
268
269 /* --------------------------------
270  *              pq_getnchar - get n characters from connection
271  * --------------------------------
272  */
273 int
274 pq_getnchar(char *s, int off, int maxlen)
275 {
276         return pqGetNBytes(s + off, maxlen, Pfin);
277 }
278
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
283  *       other
284  * --------------------------------
285  */
286 int
287 pq_getint(int b)
288 {
289         int                     n,
290                                 status = 1;
291
292         if (!Pfin)
293                 return EOF;
294
295         /*
296          * mjl: Seems inconsisten w/ return value of pq_putint (void). Also,
297          * EOF is a valid return value for an int! XXX
298          */
299
300         switch (b)
301         {
302                 case 1:
303                         status = ((n = fgetc(Pfin)) == EOF);
304                         break;
305                 case 2:
306                         status = pqGetShort(&n, Pfin);
307                         break;
308                 case 4:
309                         status = pqGetLong(&n, Pfin);
310                         break;
311                 default:
312                         fprintf(stderr, "** Unsupported size %d\n", b);
313         }
314
315         if (status)
316         {
317                 sprintf(PQerrormsg,
318                                 "FATAL: pq_getint failed: errno=%d\n", errno);
319                 fputs(PQerrormsg, stderr);
320                 pqdebug("%s", PQerrormsg);
321                 n = 0;
322         }
323
324         return n;
325 }
326
327 /* --------------------------------
328  *              pq_putstr - send a null terminated string to connection
329  * --------------------------------
330  */
331 void
332 pq_putstr(char *s)
333 {
334         if (pqPutString(s, Pfout))
335         {
336                 sprintf(PQerrormsg,
337                                 "FATAL: pq_putstr: fputs() failed: errno=%d\n", errno);
338                 fputs(PQerrormsg, stderr);
339                 pqdebug("%s", PQerrormsg);
340         }
341 }
342
343 /* --------------------------------
344  *              pq_putnchar - send n characters to connection
345  * --------------------------------
346  */
347 void
348 pq_putnchar(char *s, int n)
349 {
350         if (pqPutNBytes(s, n, Pfout))
351         {
352                 sprintf(PQerrormsg,
353                                 "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
354                                 errno);
355                 fputs(PQerrormsg, stderr);
356                 pqdebug("%s", PQerrormsg);
357         }
358 }
359
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
364  *       other
365  * --------------------------------
366  */
367 void
368 pq_putint(int i, int b)
369 {
370         int                     status;
371
372         if (!Pfout)
373                 return;
374
375         status = 1;
376         switch (b)
377         {
378                 case 1:
379                         status = (fputc(i, Pfout) == EOF);
380                         break;
381                 case 2:
382                         status = pqPutShort(i, Pfout);
383                         break;
384                 case 4:
385                         status = pqPutLong(i, Pfout);
386                         break;
387                 default:
388                         fprintf(stderr, "** Unsupported size %d\n", b);
389         }
390
391         if (status)
392         {
393                 sprintf(PQerrormsg,
394                                 "FATAL: pq_putint failed: errno=%d\n", errno);
395                 fputs(PQerrormsg, stderr);
396                 pqdebug("%s", PQerrormsg);
397         }
398 }
399
400 /* ---
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.
405  * ---
406  */
407 int
408 pq_sendoob(char *msg, int len)
409 {
410         int                     fd = fileno(Pfout);
411
412         return send(fd, msg, len, MSG_OOB);
413 }
414
415 int
416 pq_recvoob(char *msgPtr, int len)
417 {
418         int                     fd = fileno(Pfout);
419
420         return recv(fd, msgPtr, len, MSG_OOB);
421 }
422
423 /* --------------------------------
424  *              pq_getinaddr - initialize address from host and port number
425  * --------------------------------
426  */
427 int
428 pq_getinaddr(struct sockaddr_in * sin,
429                          char *host,
430                          int port)
431 {
432         struct hostent *hs;
433
434         MemSet((char *) sin, 0, sizeof(*sin));
435
436         if (host)
437         {
438                 if (*host >= '0' && *host <= '9')
439                         sin->sin_addr.s_addr = inet_addr(host);
440                 else
441                 {
442                         if (!(hs = gethostbyname(host)))
443                         {
444                                 perror(host);
445                                 return (1);
446                         }
447                         if (hs->h_addrtype != AF_INET)
448                         {
449                                 sprintf(PQerrormsg,
450                                                 "FATAL: pq_getinaddr: %s not on Internet\n",
451                                                 host);
452                                 fputs(PQerrormsg, stderr);
453                                 pqdebug("%s", PQerrormsg);
454                                 return (1);
455                         }
456                         memmove((char *) &sin->sin_addr,
457                                         hs->h_addr,
458                                         hs->h_length);
459                 }
460         }
461         sin->sin_family = AF_INET;
462         sin->sin_port = htons(port);
463         return (0);
464 }
465
466 /* --------------------------------
467  *              pq_getinserv - initialize address from host and servive name
468  * --------------------------------
469  */
470 int
471 pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
472 {
473         struct servent *ss;
474
475         if (*serv >= '0' && *serv <= '9')
476                 return (pq_getinaddr(sin, host, atoi(serv)));
477         if (!(ss = getservbyname(serv, NULL)))
478         {
479                 sprintf(PQerrormsg,
480                                 "FATAL: pq_getinserv: unknown service: %s\n",
481                                 serv);
482                 fputs(PQerrormsg, stderr);
483                 pqdebug("%s", PQerrormsg);
484                 return (1);
485         }
486         return (pq_getinaddr(sin, host, ntohs(ss->s_port)));
487 }
488
489 /*
490  * register an out-of-band listener proc--at most one allowed.
491  * This is used for receiving async. notification from the backend.
492  */
493 void
494 pq_regoob(void (*fptr) ())
495 {
496         int                     fd = fileno(Pfout);
497
498 #if defined(hpux)
499         ioctl(fd, FIOSSAIOOWN, MyProcPid);
500 #elif defined(sco)
501         ioctl(fd, SIOCSPGRP, MyProcPid);
502 #else
503         fcntl(fd, F_SETOWN, MyProcPid);
504 #endif                                                  /* hpux */
505         pqsignal(SIGURG, fptr);
506 }
507
508 void
509 pq_unregoob()
510 {
511         pqsignal(SIGURG, SIG_DFL);
512 }
513
514
515 void
516 pq_async_notify()
517 {
518         char            msg[20];
519
520         /* int len = sizeof(msg); */
521         int                     len = 20;
522
523         if (pq_recvoob(msg, len) >= 0)
524         {
525                 /* debugging */
526                 printf("received notification: %s\n", msg);
527                 PQAsyncNotifyWaiting = 1;
528                 /* PQappendNotify(msg+1); */
529         }
530         else
531         {
532                 extern int      errno;
533
534                 printf("SIGURG but no data: len = %d, err=%d\n", len, errno);
535         }
536 }
537
538 /*
539  * Streams -- wrapper around Unix socket system calls
540  *
541  *
542  *              Stream functions are used for vanilla TCP connection protocol.
543  */
544
545 /*
546  * StreamServerPort -- open a sock stream "listening" port.
547  *
548  * This initializes the Postmaster's connection
549  *              accepting port.
550  *
551  * ASSUME: that this doesn't need to be non-blocking because
552  *              the Postmaster uses select() to tell when the socket
553  *              is ready.
554  *
555  * RETURNS: STATUS_OK or STATUS_ERROR
556  */
557
558 static char sock_path[MAXPGPATH + 1] = "";
559
560 /* do_unlink()
561  * Shutdown routine for backend connection
562  * If a Unix socket is used for communication, explicitly close it.
563  */
564 void
565 StreamDoUnlink()
566 {
567         Assert(sock_path[0]);
568         unlink(sock_path);
569 }
570
571 int
572 StreamServerPort(char *hostName, short portName, int *fdP)
573 {
574         SockAddr        saddr;
575         int                     fd,
576                                 err,
577                                 family;
578         size_t          len;
579         int                     one = 1;
580
581         family = ((hostName != NULL) ? AF_INET : AF_UNIX);
582
583         if ((fd = socket(family, SOCK_STREAM, 0)) < 0)
584         {
585                 sprintf(PQerrormsg,
586                                 "FATAL: StreamServerPort: socket() failed: errno=%d\n",
587                                 errno);
588                 fputs(PQerrormsg, stderr);
589                 pqdebug("%s", PQerrormsg);
590                 return (STATUS_ERROR);
591         }
592         if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
593                                         sizeof(one))) == -1)
594         {
595                 sprintf(PQerrormsg,
596                                 "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n",
597                                 errno);
598                 fputs(PQerrormsg, stderr);
599                 pqdebug("%s", PQerrormsg);
600                 return (STATUS_ERROR);
601         }
602         bzero(&saddr, sizeof(saddr));
603         saddr.sa.sa_family = family;
604         if (family == AF_UNIX)
605         {
606                 len = UNIXSOCK_PATH(saddr.un, portName);
607                 strcpy(sock_path, saddr.un.sun_path);
608         }
609         else
610         {
611                 saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
612                 saddr.in.sin_port = htons(portName);
613                 len = sizeof(struct sockaddr_in);
614         }
615         err = bind(fd, &saddr.sa, len);
616         if (err < 0)
617         {
618                 sprintf(PQerrormsg,
619                                 "FATAL: StreamServerPort: bind() failed: errno=%d\n",
620                                 errno);
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");
625                 else
626                         strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
627                 fputs(PQerrormsg, stderr);
628                 return (STATUS_ERROR);
629         }
630
631         if (family == AF_UNIX)
632                 on_exitpg(StreamDoUnlink, NULL);
633
634         listen(fd, SOMAXCONN);
635
636         /*
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
639          * bugs).
640          *
641          * fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY);
642          */
643
644         *fdP = fd;
645         if (family == AF_UNIX)
646         {
647                 chmod(sock_path, 0777);
648         }
649         return (STATUS_OK);
650 }
651
652 /*
653  * StreamConnection -- create a new connection with client using
654  *              server port.
655  *
656  * This one should be non-blocking.
657  *
658  * RETURNS: STATUS_OK or STATUS_ERROR
659  */
660 int
661 StreamConnection(int server_fd, Port *port)
662 {
663         int                     len,
664                                 addrlen;
665         int                     family = port->raddr.sa.sa_family;
666
667         /* accept connection (and fill in the client (remote) address) */
668         len = family == AF_INET ?
669                 sizeof(struct sockaddr_in) : sizeof(struct sockaddr_un);
670         addrlen = len;
671         if ((port->sock = accept(server_fd,
672                                                          (struct sockaddr *) & port->raddr,
673                                                          &addrlen)) < 0)
674         {
675                 elog(ERROR, "postmaster: StreamConnection: accept: %m");
676                 return (STATUS_ERROR);
677         }
678
679         /* fill in the server (local) address */
680         addrlen = len;
681         if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
682                                         &addrlen) < 0)
683         {
684                 elog(ERROR, "postmaster: StreamConnection: getsockname: %m");
685                 return (STATUS_ERROR);
686         }
687         if (family == AF_INET)
688         {
689                 struct protoent *pe;
690                 int                     on = 1;
691
692                 pe = getprotobyname("TCP");
693                 if (pe == NULL)
694                 {
695                         elog(ERROR, "postmaster: getprotobyname failed");
696                         return (STATUS_ERROR);
697                 }
698                 if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY,
699                                            &on, sizeof(on)) < 0)
700                 {
701                         elog(ERROR, "postmaster: setsockopt failed");
702                         return (STATUS_ERROR);
703                 }
704         }
705
706         /* reset to non-blocking */
707         fcntl(port->sock, F_SETFL, 1);
708
709         return (STATUS_OK);
710 }
711
712 /*
713  * StreamClose -- close a client/backend connection
714  */
715 void
716 StreamClose(int sock)
717 {
718         close(sock);
719 }
720
721 /* ---------------------------
722  * StreamOpen -- From client, initiate a connection with the
723  *              server (Postmaster).
724  *
725  * RETURNS: STATUS_OK or STATUS_ERROR
726  *
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  * ---------------------------
731  */
732 int
733 StreamOpen(char *hostName, short portName, Port *port)
734 {
735         int                     len,
736                                 err;
737         struct hostent *hp;
738         extern int      errno;
739
740         /* set up the server (remote) address */
741         MemSet((char *) &port->raddr, 0, sizeof(port->raddr));
742         if (hostName)
743         {
744                 if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET)
745                 {
746                         sprintf(PQerrormsg,
747                                         "FATAL: StreamOpen: unknown hostname: %s\n",
748                                         hostName);
749                         fputs(PQerrormsg, stderr);
750                         pqdebug("%s", PQerrormsg);
751                         return (STATUS_ERROR);
752                 }
753                 memmove((char *) &(port->raddr.in.sin_addr),
754                                 (char *) hp->h_addr,
755                                 hp->h_length);
756                 port->raddr.in.sin_family = AF_INET;
757                 port->raddr.in.sin_port = htons(portName);
758                 len = sizeof(struct sockaddr_in);
759         }
760         else
761         {
762                 port->raddr.un.sun_family = AF_UNIX;
763                 len = UNIXSOCK_PATH(port->raddr.un, portName);
764         }
765         /* connect to the server */
766         if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
767         {
768                 sprintf(PQerrormsg,
769                                 "FATAL: StreamOpen: socket() failed: errno=%d\n",
770                                 errno);
771                 fputs(PQerrormsg, stderr);
772                 pqdebug("%s", PQerrormsg);
773                 return (STATUS_ERROR);
774         }
775         err = connect(port->sock, &port->raddr.sa, len);
776         if (err < 0)
777         {
778                 sprintf(PQerrormsg,
779                                 "FATAL: StreamOpen: connect() failed: errno=%d\n",
780                                 errno);
781                 fputs(PQerrormsg, stderr);
782                 pqdebug("%s", PQerrormsg);
783                 return (STATUS_ERROR);
784         }
785
786         /* fill in the client address */
787         if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
788         {
789                 sprintf(PQerrormsg,
790                                 "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
791                                 errno);
792                 fputs(PQerrormsg, stderr);
793                 pqdebug("%s", PQerrormsg);
794                 return (STATUS_ERROR);
795         }
796
797         return (STATUS_OK);
798 }