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