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