]> granicus.if.org Git - postgresql/blob - src/backend/libpq/pqcomm.c
Mulitple inclusion of sys/socket.h
[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.8 1996/11/15 09:54:28 scrappy 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 <errno.h>
40 #include <fcntl.h>
41 #include <signal.h>
42 #ifndef WIN32
43 #include <unistd.h>             /* for ttyname() */
44 #include <sys/types.h>
45 #include <sys/socket.h>
46 #include <netdb.h>
47 #include <netinet/in.h>
48 #include <arpa/inet.h>
49 #else
50 #include <winsock.h>
51 #endif /* WIN32 */
52
53 #if defined(linux)
54 #ifndef SOMAXCONN
55 #define SOMAXCONN 5             /* from Linux listen(2) man page */
56 #endif /* SOMAXCONN */
57 #endif /* linux */
58
59 #include <postgres.h>
60
61 #include <libpq/pqsignal.h>     /* substitute for <signal.h> */
62 #include <libpq/auth.h>
63 #include <libpq/libpq.h>        /* where the declarations go */
64
65 /* ----------------
66  *      declarations
67  * ----------------
68  */
69 FILE *Pfout, *Pfin;
70 FILE *Pfdebug;    /* debugging libpq */
71 int PQAsyncNotifyWaiting;       /* for async. notification */
72
73 /* --------------------------------
74  *      pq_init - open portal file descriptors
75  * --------------------------------
76  */
77 void
78 pq_init(int fd)
79 {
80 #ifdef WIN32
81     int in, out;
82
83     in = _open_osfhandle(fd, _O_RDONLY);
84     out = _open_osfhandle(fd, _O_APPEND);
85     Pfin = fdopen(in, "rb");
86     Pfout = fdopen(out, "wb");
87 #else
88     Pfin = fdopen(fd, "r");
89     Pfout = fdopen(dup(fd), "w");
90 #endif /* WIN32 */
91     if (!Pfin || !Pfout)
92         elog(FATAL, "pq_init: Couldn't initialize socket connection");
93     PQnotifies_init();
94     if (getenv("LIBPQ_DEBUG")) {
95         Pfdebug = stderr;
96     }else {
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     (void) 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         fclose(Pfin);
154         Pfin = NULL;
155     }
156     if (Pfout) {
157         fclose(Pfout);
158         Pfout = NULL;
159     }
160     PQAsyncNotifyWaiting = 0;
161     PQnotifies_init();
162     pq_unregoob();
163 }
164
165 /* --------------------------------
166  *      pq_flush - flush pending output
167  * --------------------------------
168  */
169 void
170 pq_flush()
171 {
172     if (Pfout)
173         fflush(Pfout);
174 }
175
176 /* --------------------------------
177  *      pq_getstr - get a null terminated string from connection
178  * --------------------------------
179  */
180 int
181 pq_getstr(char *s, int maxlen)
182 {
183     int c = '\0';
184     
185     if (Pfin == (FILE *) NULL) {
186 /*      elog(DEBUG, "Input descriptor is null"); */
187         return(EOF);
188     }
189     
190     while (maxlen-- && (c = pq_getc(Pfin)) != EOF && c)
191         *s++ = c;
192     *s = '\0';
193     
194     /* -----------------
195      *     If EOF reached let caller know.
196      *     (This will only happen if we hit EOF before the string
197      *     delimiter is reached.)
198      * -----------------
199      */
200     if (c == EOF)
201         return(EOF);
202     return(!EOF);
203 }
204
205 /*
206  * USER FUNCTION - gets a newline-terminated string from the backend.
207  * 
208  * Chiefly here so that applications can use "COPY <rel> to stdout"
209  * and read the output string.  Returns a null-terminated string in s.
210  *
211  * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
212  * the terminating \n (like gets(3)).
213  *
214  * RETURNS:
215  *      EOF if it is detected or invalid arguments are given
216  *      0 if EOL is reached (i.e., \n has been read)
217  *              (this is required for backward-compatibility -- this
218  *               routine used to always return EOF or 0, assuming that
219  *               the line ended within maxlen bytes.)
220  *      1 in other cases
221  */
222 int
223 PQgetline(char *s, int maxlen)
224 {
225     int c = '\0';
226     
227     if (!Pfin || !s || maxlen <= 1)
228         return(EOF);
229     
230     for (; maxlen > 1 && (c = pq_getc(Pfin)) != '\n' && c != EOF; --maxlen) {
231         *s++ = c;
232     }
233     *s = '\0';
234     
235     if (c == EOF) {
236         return(EOF);            /* error -- reached EOF before \n */
237     } else if (c == '\n') {
238         return(0);              /* done with this line */
239     }
240     return(1);                  /* returning a full buffer */
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         (void) fputs(s, Pfout);
256         fflush(Pfout);
257     }
258     return(0);
259 }
260
261 /* --------------------------------
262  *      pq_getnchar - get n characters from connection
263  * --------------------------------
264  */
265 int
266 pq_getnchar(char *s, int off, int maxlen)
267 {
268     int c = '\0';
269     
270     if (Pfin == (FILE *) NULL) {
271 /*      elog(DEBUG, "Input descriptor is null"); */
272         return(EOF);
273     }
274     
275     s += off;
276     while (maxlen-- && (c = pq_getc(Pfin)) != EOF)
277         *s++ = c;
278     
279     /* -----------------
280      *     If EOF reached let caller know
281      * -----------------
282      */
283     if (c == EOF)
284         return(EOF);
285     return(!EOF);
286 }
287
288 /* --------------------------------
289  *      pq_getint - get an integer from connection
290  *   we receive an integer a byte at a type and reconstruct it so that
291  *   machines with different ENDIAN representations can talk to each
292  *   other
293  * --------------------------------
294  */
295 int
296 pq_getint(int b)
297 {
298     int n, c, p;
299     
300     if (Pfin == (FILE *) NULL) {
301 /*      elog(DEBUG, "pq_getint: Input descriptor is null"); */
302         return(EOF);
303     }
304     
305     n = p = 0;
306     while (b-- && (c = pq_getc(Pfin)) != EOF && p < 32) {
307         n |= (c & 0xff) << p;
308         p += 8;
309     }
310     
311     return(n);
312 }
313
314 /* --------------------------------
315  *      pq_putstr - send a null terminated string to connection
316  * --------------------------------
317  */
318 void
319 pq_putstr(char *s)
320 {
321     int status;
322     
323     if (Pfout) {
324         status = fputs(s, Pfout);
325         if (status == EOF) {
326             (void) sprintf(PQerrormsg,
327                            "FATAL: pq_putstr: fputs() failed: errno=%d\n",
328                            errno);
329             fputs(PQerrormsg, stderr);
330             pqdebug("%s", PQerrormsg);
331         }
332         status = fputc('\0', Pfout);
333         if (status == EOF) {
334             (void) sprintf(PQerrormsg,
335                            "FATAL: pq_putstr: fputc() failed: errno=%d\n",
336                            errno);
337             fputs(PQerrormsg, stderr);
338             pqdebug("%s", PQerrormsg);
339         }
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     int status;
351     
352     if (Pfout) {
353         while (n--) {
354             status = fputc(*s++, Pfout);
355             if (status == EOF) {
356                 (void) sprintf(PQerrormsg,
357                                "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
358                                errno);
359                 fputs(PQerrormsg, stderr);
360                 pqdebug("%s", PQerrormsg);
361             }
362         }
363     }
364 }
365
366 /* --------------------------------
367  *      pq_putint - send an integer to connection
368  *   we chop an integer into bytes and send individual bytes
369  *   machines with different ENDIAN representations can still talk to each
370  *   other
371  * --------------------------------
372  */
373 void
374 pq_putint(int i, int b)
375 {
376     int status;
377     
378     if (b > 4)
379         b = 4;
380     
381     if (Pfout) {
382         while (b--) {
383             status = fputc(i & 0xff, Pfout);
384             i >>= 8;
385             if (status == EOF) {
386                 (void) sprintf(PQerrormsg,
387                                "FATAL: pq_putint: fputc() failed: errno=%d\n",
388                                errno);
389                 fputs(PQerrormsg, stderr);
390                 pqdebug("%s", PQerrormsg);
391             }
392         }
393     }
394 }
395
396 /* ---
397  *     pq_sendoob - send a string over the out-of-band channel
398  *     pq_recvoob - receive a string over the oob channel
399  *  NB: Fortunately, the out-of-band channel doesn't conflict with
400  *      buffered I/O because it is separate from regular com. channel.
401  * ---
402  */
403 int
404 pq_sendoob(char *msg, int len)
405 {
406     int fd = fileno(Pfout);
407     
408     return(send(fd,msg,len,MSG_OOB));
409 }
410
411 int
412 pq_recvoob(char *msgPtr, int *lenPtr)
413 {
414     int fd = fileno(Pfout);
415     int len = 0;
416     
417     len = recv(fd,msgPtr+len,*lenPtr,MSG_OOB);
418     *lenPtr = len;
419     return(len);
420 }
421
422 /* --------------------------------
423  *      pq_getinaddr - initialize address from host and port number
424  * --------------------------------
425  */
426 int
427 pq_getinaddr(struct sockaddr_in *sin,
428              char *host,
429              int port)
430 {
431     struct hostent      *hs;
432     
433     memset((char *) sin, 0, sizeof(*sin));
434     
435     if (host) {
436         if (*host >= '0' && *host <= '9')
437             sin->sin_addr.s_addr = inet_addr(host);
438         else {
439             if (!(hs = gethostbyname(host))) {
440                 perror(host);
441                 return(1);
442             }
443             if (hs->h_addrtype != AF_INET) {
444                 (void) sprintf(PQerrormsg,
445                                "FATAL: pq_getinaddr: %s not on Internet\n",
446                                host);
447                 fputs(PQerrormsg, stderr);
448                 pqdebug("%s", PQerrormsg);
449                 return(1);
450             }
451             memmove((char *) &sin->sin_addr,
452                     hs->h_addr,
453                     hs->h_length);
454         }
455     }
456     sin->sin_family = AF_INET;
457     sin->sin_port = htons(port);
458     return(0);
459 }
460
461 /* --------------------------------
462  *      pq_getinserv - initialize address from host and servive name
463  * --------------------------------
464  */
465 int
466 pq_getinserv(struct sockaddr_in *sin, char *host, char *serv)
467 {
468     struct servent *ss;
469     
470     if (*serv >= '0' && *serv <= '9')
471         return(pq_getinaddr(sin, host, atoi(serv)));
472     if (!(ss = getservbyname(serv, NULL))) {
473         (void) 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 #ifdef WIN32
491     /* Who knows what to do here? */
492     return;
493 #else
494     int fd = fileno(Pfout);
495 #if defined(hpux)
496     ioctl(fd, FIOSSAIOOWN, getpid());
497 #else /* hpux */
498     fcntl(fd, F_SETOWN, getpid());
499 #endif /* hpux */
500     (void) signal(SIGURG,fptr);
501 #endif /* WIN32 */    
502 }
503
504 void
505 pq_unregoob()
506 {
507 #ifndef WIN32
508     signal(SIGURG,SIG_DFL);
509 #endif /* WIN32 */    
510 }
511
512
513 void
514 pq_async_notify()
515 {
516     char msg[20];
517     /*    int len = sizeof(msg);*/
518     int len = 20;
519     
520     if (pq_recvoob(msg,&len) >= 0) {
521         /* debugging */
522         printf("received notification: %s\n",msg);
523         PQAsyncNotifyWaiting = 1;
524         /*      PQappendNotify(msg+1);*/
525     } else {
526         extern int errno;
527         printf("SIGURG but no data: len = %d, err=%d\n",len,errno);
528     }
529 }
530
531 /*
532  * Streams -- wrapper around Unix socket system calls
533  *
534  *
535  *      Stream functions are used for vanilla TCP connection protocol.
536  */
537
538 /*
539  * StreamServerPort -- open a sock stream "listening" port.
540  *
541  * This initializes the Postmaster's connection
542  *      accepting port.  
543  *
544  * ASSUME: that this doesn't need to be non-blocking because
545  *      the Postmaster uses select() to tell when the socket
546  *      is ready.
547  *
548  * RETURNS: STATUS_OK or STATUS_ERROR
549  */
550 int
551 StreamServerPort(char *hostName, short portName, int *fdP)
552 {
553     struct sockaddr_in  sin;
554     int                 fd;
555     int                 one = 1;
556     
557 #ifdef WIN32
558     /* This is necessary to make it possible for a backend to use
559     ** stdio to read from the socket.
560     */
561     int optionvalue = SO_SYNCHRONOUS_NONALERT;
562
563     setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *)&optionvalue,
564                sizeof(optionvalue));
565 #endif /* WIN32 */
566
567     if (! hostName)
568         hostName = "localhost";
569     
570     memset((char *)&sin, 0, sizeof sin);
571     
572     if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
573         (void) sprintf(PQerrormsg,
574                        "FATAL: StreamServerPort: socket() failed: errno=%d\n",
575                        errno);
576         fputs(PQerrormsg, stderr);
577         pqdebug("%s", PQerrormsg);
578         return(STATUS_ERROR);
579     }
580
581     if((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
582                                                     sizeof(one))) == -1) {
583         (void) sprintf(PQerrormsg,
584             "FATAL: StreamServerPort: setsockopt (SO_REUSEADDR) failed: errno=%d\n",
585             errno);
586         fputs(PQerrormsg, stderr);
587         pqdebug("%s", PQerrormsg);
588         return(STATUS_ERROR);
589     }
590
591     sin.sin_family = AF_INET;
592     sin.sin_port = htons(portName);
593     
594     if (bind(fd, (struct sockaddr *)&sin, sizeof sin) < 0) {
595         (void) sprintf(PQerrormsg,
596                        "FATAL: StreamServerPort: bind() failed: errno=%d\n",
597                        errno);
598         pqdebug("%s", PQerrormsg);
599         (void) strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
600         (void) strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
601         fputs(PQerrormsg, stderr);
602         return(STATUS_ERROR);
603     }
604     
605     listen(fd, SOMAXCONN);
606     
607     /* MS: I took this code from Dillon's version.  It makes the 
608      * listening port non-blocking.  That is not necessary (and
609      * may tickle kernel bugs).
610      
611      (void) fcntl(fd, F_SETFD, 1);
612      (void) fcntl(fd, F_SETFL, FNDELAY);
613      */
614     
615     *fdP = fd;
616     return(STATUS_OK);
617 }
618
619 /*
620  * StreamConnection -- create a new connection with client using
621  *      server port.
622  *
623  * This one should be non-blocking.
624  * 
625  * RETURNS: STATUS_OK or STATUS_ERROR
626  */
627 int
628 StreamConnection(int server_fd, Port *port)
629 {
630     int addrlen;
631     
632     /* accept connection (and fill in the client (remote) address) */
633     addrlen = sizeof(struct sockaddr_in);
634     if ((port->sock = accept(server_fd,
635                              (struct sockaddr *) &port->raddr,
636                              &addrlen)) < 0) {
637         elog(WARN, "postmaster: StreamConnection: accept: %m");
638         return(STATUS_ERROR);
639     }
640     
641     /* fill in the server (local) address */
642     addrlen = sizeof(struct sockaddr_in);
643     if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
644                     &addrlen) < 0) {
645         elog(WARN, "postmaster: StreamConnection: getsockname: %m");
646         return(STATUS_ERROR);
647     }
648     
649     port->mask = 1 << port->sock;
650
651 #ifndef WIN32    
652     /* reset to non-blocking */
653     fcntl(port->sock, F_SETFL, 1);
654 #endif /* WIN32 */    
655     
656     return(STATUS_OK);
657 }
658
659 /* 
660  * StreamClose -- close a client/backend connection
661  */
662 void
663 StreamClose(int sock)
664 {
665     (void) close(sock); 
666 }
667
668 /* ---------------------------
669  * StreamOpen -- From client, initiate a connection with the 
670  *      server (Postmaster).
671  *
672  * RETURNS: STATUS_OK or STATUS_ERROR
673  *
674  * NOTE: connection is NOT established just because this
675  *      routine exits.  Local state is ok, but we haven't
676  *      spoken to the postmaster yet.
677  * ---------------------------
678  */
679 int
680 StreamOpen(char *hostName, short portName, Port *port)
681 {
682     struct hostent      *hp;
683     int                 laddrlen = sizeof(struct sockaddr_in);
684     extern int          errno;
685     
686     if (!hostName)
687         hostName = "localhost";
688     
689     /* set up the server (remote) address */
690     if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET) {
691         (void) sprintf(PQerrormsg,
692                        "FATAL: StreamOpen: unknown hostname: %s\n",
693                        hostName);
694         fputs(PQerrormsg, stderr);
695         pqdebug("%s", PQerrormsg);
696         return(STATUS_ERROR);
697     }
698     memset((char *) &port->raddr, 0, sizeof(port->raddr));
699     memmove((char *) &(port->raddr.sin_addr),
700             (char *) hp->h_addr, 
701             hp->h_length);
702     port->raddr.sin_family = AF_INET;
703     port->raddr.sin_port = htons(portName);
704     
705     /* connect to the server */
706     if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
707         (void) sprintf(PQerrormsg,
708                        "FATAL: StreamOpen: socket() failed: errno=%d\n",
709                        errno);
710         fputs(PQerrormsg, stderr);
711         pqdebug("%s", PQerrormsg);
712         return(STATUS_ERROR);
713     }
714     if (connect(port->sock, (struct sockaddr *)&port->raddr,
715                 sizeof(port->raddr)) < 0) {
716         (void) sprintf(PQerrormsg,
717                        "FATAL: StreamOpen: connect() failed: errno=%d\n",
718                        errno);
719         fputs(PQerrormsg, stderr);
720         pqdebug("%s", PQerrormsg);
721         return(STATUS_ERROR);
722     }
723     
724     /* fill in the client address */
725     if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
726                     &laddrlen) < 0) {
727         (void) sprintf(PQerrormsg,
728                        "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
729                        errno);
730         fputs(PQerrormsg, stderr);
731         pqdebug("%s", PQerrormsg);
732         return(STATUS_ERROR);
733     }
734     
735     return(STATUS_OK);
736 }