upload tizen2.0 source
[framework/uifw/xorg/lib/xtrans.git] / Xtrans.c
1 /*
2
3 Copyright 1993, 1994, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26
27  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
28  *
29  * All Rights Reserved
30  *
31  * Permission to use, copy, modify, and distribute this software and its
32  * documentation for any purpose and without fee is hereby granted, provided
33  * that the above copyright notice appear in all copies and that both that
34  * copyright notice and this permission notice appear in supporting
35  * documentation, and that the name NCR not be used in advertising
36  * or publicity pertaining to distribution of the software without specific,
37  * written prior permission.  NCR makes no representations about the
38  * suitability of this software for any purpose.  It is provided "as is"
39  * without express or implied warranty.
40  *
41  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
42  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
43  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
44  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
45  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
46  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
47  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
48  */
49
50 #include <ctype.h>
51
52 /*
53  * The transport table contains a definition for every transport (protocol)
54  * family. All operations that can be made on the transport go through this
55  * table.
56  *
57  * Each transport is assigned a unique transport id.
58  *
59  * New transports can be added by adding an entry in this table.
60  * For compatiblity, the transport ids should never be renumbered.
61  * Always add to the end of the list.
62  */
63
64 #define TRANS_TLI_INET_INDEX            1
65 #define TRANS_TLI_TCP_INDEX             2
66 #define TRANS_TLI_TLI_INDEX             3
67 #define TRANS_SOCKET_UNIX_INDEX         4
68 #define TRANS_SOCKET_LOCAL_INDEX        5
69 #define TRANS_SOCKET_INET_INDEX         6
70 #define TRANS_SOCKET_TCP_INDEX          7
71 #define TRANS_DNET_INDEX                8
72 #define TRANS_LOCAL_LOCAL_INDEX         9
73 #define TRANS_LOCAL_PTS_INDEX           10
74 #define TRANS_LOCAL_NAMED_INDEX         11
75 /* 12 used to be ISC, but that's gone. */
76 #define TRANS_LOCAL_SCO_INDEX           13
77 #define TRANS_SOCKET_INET6_INDEX        14
78 #define TRANS_LOCAL_PIPE_INDEX          15
79
80
81 static
82 Xtransport_table Xtransports[] = {
83 #if defined(STREAMSCONN)
84     { &TRANS(TLITCPFuncs),      TRANS_TLI_TCP_INDEX },
85     { &TRANS(TLIINETFuncs),     TRANS_TLI_INET_INDEX },
86     { &TRANS(TLITLIFuncs),      TRANS_TLI_TLI_INDEX },
87 #endif /* STREAMSCONN */
88 #if defined(TCPCONN)
89     { &TRANS(SocketTCPFuncs),   TRANS_SOCKET_TCP_INDEX },
90 #if defined(IPv6) && defined(AF_INET6)
91     { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX },
92 #endif /* IPv6 */
93     { &TRANS(SocketINETFuncs),  TRANS_SOCKET_INET_INDEX },
94 #endif /* TCPCONN */
95 #if defined(UNIXCONN)
96 #if !defined(LOCALCONN)
97     { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
98 #endif /* !LOCALCONN */
99     { &TRANS(SocketUNIXFuncs),  TRANS_SOCKET_UNIX_INDEX },
100 #endif /* UNIXCONN */
101 #if defined(LOCALCONN)
102     { &TRANS(LocalFuncs),       TRANS_LOCAL_LOCAL_INDEX },
103 #ifndef sun
104     { &TRANS(PTSFuncs),         TRANS_LOCAL_PTS_INDEX },
105 #endif /* sun */
106 #if defined(SVR4) || defined(__SVR4)
107     { &TRANS(NAMEDFuncs),       TRANS_LOCAL_NAMED_INDEX },
108 #endif
109 #ifdef sun
110     { &TRANS(PIPEFuncs),        TRANS_LOCAL_PIPE_INDEX },
111 #endif /* sun */
112 #if defined(__SCO__) || defined(__UNIXWARE__)
113     { &TRANS(SCOFuncs),         TRANS_LOCAL_SCO_INDEX },
114 #endif /* __SCO__ || __UNIXWARE__ */
115 #endif /* LOCALCONN */
116 };
117
118 #define NUMTRANS        (sizeof(Xtransports)/sizeof(Xtransport_table))
119
120
121 #ifdef WIN32
122 #define ioctl ioctlsocket
123 #endif
124
125
126 \f
127 /*
128  * These are a few utility function used by the public interface functions.
129  */
130
131 void
132 TRANS(FreeConnInfo) (XtransConnInfo ciptr)
133
134 {
135     prmsg (3,"FreeConnInfo(%p)\n", ciptr);
136
137     if (ciptr->addr)
138         free (ciptr->addr);
139
140     if (ciptr->peeraddr)
141         free (ciptr->peeraddr);
142
143     if (ciptr->port)
144         free (ciptr->port);
145
146     free (ciptr);
147 }
148
149
150 #define PROTOBUFSIZE    20
151
152 static Xtransport *
153 TRANS(SelectTransport) (const char *protocol)
154
155 {
156     char        protobuf[PROTOBUFSIZE];
157     int         i;
158
159     prmsg (3,"SelectTransport(%s)\n", protocol);
160
161     /*
162      * Force Protocol to be lowercase as a way of doing
163      * a case insensitive match.
164      */
165
166     strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
167     protobuf[PROTOBUFSIZE-1] = '\0';
168
169     for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
170         if (isupper (protobuf[i]))
171             protobuf[i] = tolower (protobuf[i]);
172
173     /* Look at all of the configured protocols */
174
175     for (i = 0; i < NUMTRANS; i++)
176     {
177         if (!strcmp (protobuf, Xtransports[i].transport->TransName))
178             return Xtransports[i].transport;
179     }
180
181     return NULL;
182 }
183
184 #ifndef TEST_t
185 static
186 #endif /* TEST_t */
187 int
188 TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
189
190 {
191     /*
192      * For the font library, the address is a string formatted
193      * as "protocol/host:port[/catalogue]".  Note that the catologue
194      * is optional.  At this time, the catologue info is ignored, but
195      * we have to parse it anyways.
196      *
197      * Other than fontlib, the address is a string formatted
198      * as "protocol/host:port".
199      *
200      * If the protocol part is missing, then assume TCP.
201      * If the protocol part and host part are missing, then assume local.
202      * If a "::" is found then assume DNET.
203      */
204
205     char        *mybuf, *tmpptr;
206     const char  *_protocol;
207     char        *_host, *_port;
208     char        hostnamebuf[256];
209     int         _host_len;
210
211     prmsg (3,"ParseAddress(%s)\n", address);
212
213     /* Copy the string so it can be changed */
214
215     tmpptr = mybuf = strdup (address);
216
217     /* Parse the string to get each component */
218
219     /* Get the protocol part */
220
221     _protocol = mybuf;
222
223
224    if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
225       ((mybuf = strrchr (tmpptr,':')) == NULL) )
226    {
227         /* address is in a bad format */
228         *protocol = NULL;
229         *host = NULL;
230         *port = NULL;
231         free (tmpptr);
232         return 0;
233     }
234
235     if (*mybuf == ':')
236     {
237         /*
238          * If there is a hostname, then assume tcp, otherwise
239          * it must be local.
240          */
241         if (mybuf == tmpptr)
242         {
243             /* There is neither a protocol or host specified */
244             _protocol = "local";
245         }
246         else
247         {
248             /* There is a hostname specified */
249             _protocol = "tcp";
250             mybuf = tmpptr;     /* reset to the begining of the host ptr */
251         }
252     }
253     else
254     {
255         /* *mybuf == '/' */
256
257         *mybuf ++= '\0'; /* put a null at the end of the protocol */
258
259         if (strlen(_protocol) == 0)
260         {
261             /*
262              * If there is a hostname, then assume tcp, otherwise
263              * it must be local.
264              */
265             if (*mybuf != ':')
266                 _protocol = "tcp";
267             else
268                 _protocol = "local";
269         }
270     }
271
272     /* Get the host part */
273
274     _host = mybuf;
275
276     if ((mybuf = strrchr (mybuf,':')) == NULL)
277     {
278         *protocol = NULL;
279         *host = NULL;
280         *port = NULL;
281         free (tmpptr);
282         return 0;
283     }
284
285     *mybuf ++= '\0';
286
287     _host_len = strlen(_host);
288     if (_host_len == 0)
289     {
290         TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
291         _host = hostnamebuf;
292     }
293 #if defined(IPv6) && defined(AF_INET6)
294     /* hostname in IPv6 [numeric_addr]:0 form? */
295     else if ( (_host_len > 3) &&
296       ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
297       && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
298         struct sockaddr_in6 sin6;
299
300         *(_host + _host_len - 1) = '\0';
301
302         /* Verify address is valid IPv6 numeric form */
303         if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
304             /* It is. Use it as such. */
305             _host++;
306             _protocol = "inet6";
307         } else {
308             /* It's not, restore it just in case some other code can use it. */
309             *(_host + _host_len - 1) = ']';
310         }
311     }
312 #endif
313
314
315     /* Get the port */
316
317     _port = mybuf;
318
319 #if defined(FONT_t) || defined(FS_t)
320     /*
321      * Is there an optional catalogue list?
322      */
323
324     if ((mybuf = strchr (mybuf,'/')) != NULL)
325         *mybuf ++= '\0';
326
327     /*
328      * The rest, if any, is the (currently unused) catalogue list.
329      *
330      * _catalogue = mybuf;
331      */
332 #endif
333
334 #ifdef HAVE_LAUNCHD
335     /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
336     if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
337       _protocol="local";
338       _host="";
339       _port=address+6;
340     }
341 #endif
342
343     /*
344      * Now that we have all of the components, allocate new
345      * string space for them.
346      */
347
348     if ((*protocol = strdup (_protocol)) == NULL)
349     {
350         /* Malloc failed */
351         *port = NULL;
352         *host = NULL;
353         *protocol = NULL;
354         free (tmpptr);
355         return 0;
356     }
357
358     if ((*host = strdup (_host)) == NULL)
359     {
360         /* Malloc failed */
361         *port = NULL;
362         *host = NULL;
363         free (*protocol);
364         *protocol = NULL;
365         free (tmpptr);
366         return 0;
367     }
368
369     if ((*port = strdup (_port)) == NULL)
370     {
371         /* Malloc failed */
372         *port = NULL;
373         free (*host);
374         *host = NULL;
375         free (*protocol);
376         *protocol = NULL;
377         free (tmpptr);
378         return 0;
379     }
380
381     free (tmpptr);
382
383     return 1;
384 }
385
386
387 /*
388  * TRANS(Open) does all of the real work opening a connection. The only
389  * funny part about this is the type parameter which is used to decide which
390  * type of open to perform.
391  */
392
393 static XtransConnInfo
394 TRANS(Open) (int type, char *address)
395
396 {
397     char                *protocol = NULL, *host = NULL, *port = NULL;
398     XtransConnInfo      ciptr = NULL;
399     Xtransport          *thistrans;
400
401     prmsg (2,"Open(%d,%s)\n", type, address);
402
403 #if defined(WIN32) && defined(TCPCONN)
404     if (TRANS(WSAStartup)())
405     {
406         prmsg (1,"Open: WSAStartup failed\n");
407         return NULL;
408     }
409 #endif
410
411     /* Parse the Address */
412
413     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
414     {
415         prmsg (1,"Open: Unable to Parse address %s\n", address);
416         return NULL;
417     }
418
419     /* Determine the transport type */
420
421     if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
422     {
423         prmsg (1,"Open: Unable to find transport for %s\n",
424                protocol);
425
426         free (protocol);
427         free (host);
428         free (port);
429         return NULL;
430     }
431
432     /* Open the transport */
433
434     switch (type)
435     {
436     case XTRANS_OPEN_COTS_CLIENT:
437 #ifdef TRANS_CLIENT
438         ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
439 #endif /* TRANS_CLIENT */
440         break;
441     case XTRANS_OPEN_COTS_SERVER:
442 #ifdef TRANS_SERVER
443         ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
444 #endif /* TRANS_SERVER */
445         break;
446     case XTRANS_OPEN_CLTS_CLIENT:
447 #ifdef TRANS_CLIENT
448         ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
449 #endif /* TRANS_CLIENT */
450         break;
451     case XTRANS_OPEN_CLTS_SERVER:
452 #ifdef TRANS_SERVER
453         ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
454 #endif /* TRANS_SERVER */
455         break;
456     default:
457         prmsg (1,"Open: Unknown Open type %d\n", type);
458     }
459
460     if (ciptr == NULL)
461     {
462         if (!(thistrans->flags & TRANS_DISABLED))
463         {
464             prmsg (1,"Open: transport open failed for %s/%s:%s\n",
465                    protocol, host, port);
466         }
467         free (protocol);
468         free (host);
469         free (port);
470         return NULL;
471     }
472
473     ciptr->transptr = thistrans;
474     ciptr->port = port;                 /* We need this for TRANS(Reopen) */
475
476     free (protocol);
477     free (host);
478
479     return ciptr;
480 }
481
482
483 #ifdef TRANS_REOPEN
484
485 /*
486  * We might want to create an XtransConnInfo object based on a previously
487  * opened connection.  For example, the font server may clone itself and
488  * pass file descriptors to the parent.
489  */
490
491 static XtransConnInfo
492 TRANS(Reopen) (int type, int trans_id, int fd, char *port)
493
494 {
495     XtransConnInfo      ciptr = NULL;
496     Xtransport          *thistrans = NULL;
497     char                *save_port;
498     int                 i;
499
500     prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
501
502     /* Determine the transport type */
503
504     for (i = 0; i < NUMTRANS; i++)
505         if (Xtransports[i].transport_id == trans_id)
506         {
507             thistrans = Xtransports[i].transport;
508             break;
509         }
510
511     if (thistrans == NULL)
512     {
513         prmsg (1,"Reopen: Unable to find transport id %d\n",
514                trans_id);
515
516         return NULL;
517     }
518
519     if ((save_port = strdup (port)) == NULL)
520     {
521         prmsg (1,"Reopen: Unable to malloc port string\n");
522
523         return NULL;
524     }
525
526     /* Get a new XtransConnInfo object */
527
528     switch (type)
529     {
530     case XTRANS_OPEN_COTS_SERVER:
531         ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
532         break;
533     case XTRANS_OPEN_CLTS_SERVER:
534         ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
535         break;
536     default:
537         prmsg (1,"Reopen: Bad Open type %d\n", type);
538     }
539
540     if (ciptr == NULL)
541     {
542         prmsg (1,"Reopen: transport open failed\n");
543         free (save_port);
544         return NULL;
545     }
546
547     ciptr->transptr = thistrans;
548     ciptr->port = save_port;
549
550     return ciptr;
551 }
552
553 #endif /* TRANS_REOPEN */
554
555
556 \f
557 /*
558  * These are the public interfaces to this Transport interface.
559  * These are the only functions that should have knowledge of the transport
560  * table.
561  */
562
563 #ifdef TRANS_CLIENT
564
565 XtransConnInfo
566 TRANS(OpenCOTSClient) (char *address)
567
568 {
569     prmsg (2,"OpenCOTSClient(%s)\n", address);
570     return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
571 }
572
573 #endif /* TRANS_CLIENT */
574
575
576 #ifdef TRANS_SERVER
577
578 XtransConnInfo
579 TRANS(OpenCOTSServer) (char *address)
580
581 {
582     prmsg (2,"OpenCOTSServer(%s)\n", address);
583     return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
584 }
585
586 #endif /* TRANS_SERVER */
587
588
589 #ifdef TRANS_CLIENT
590
591 XtransConnInfo
592 TRANS(OpenCLTSClient) (char *address)
593
594 {
595     prmsg (2,"OpenCLTSClient(%s)\n", address);
596     return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
597 }
598
599 #endif /* TRANS_CLIENT */
600
601
602 #ifdef TRANS_SERVER
603
604 XtransConnInfo
605 TRANS(OpenCLTSServer) (char *address)
606
607 {
608     prmsg (2,"OpenCLTSServer(%s)\n", address);
609     return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
610 }
611
612 #endif /* TRANS_SERVER */
613
614
615 #ifdef TRANS_REOPEN
616
617 XtransConnInfo
618 TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
619
620 {
621     prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
622     return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
623 }
624
625 XtransConnInfo
626 TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
627
628 {
629     prmsg (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
630     return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
631 }
632
633
634 int
635 TRANS(GetReopenInfo) (XtransConnInfo ciptr,
636                       int *trans_id, int *fd, char **port)
637
638 {
639     int i;
640
641     for (i = 0; i < NUMTRANS; i++)
642         if (Xtransports[i].transport == ciptr->transptr)
643         {
644             *trans_id = Xtransports[i].transport_id;
645             *fd = ciptr->fd;
646
647             if ((*port = strdup (ciptr->port)) == NULL)
648                 return 0;
649             else
650                 return 1;
651         }
652
653     return 0;
654 }
655
656 #endif /* TRANS_REOPEN */
657
658
659 int
660 TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
661
662 {
663     int fd = ciptr->fd;
664     int ret = 0;
665
666     prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
667
668     /*
669      * For now, all transport type use the same stuff for setting options.
670      * As long as this is true, we can put the common code here. Once a more
671      * complicated transport such as shared memory or an OSI implementation
672      * that uses the session and application libraries is implemented, this
673      * code may have to move to a transport dependent function.
674      *
675      * ret = ciptr->transptr->SetOption (ciptr, option, arg);
676      */
677
678     switch (option)
679     {
680     case TRANS_NONBLOCKING:
681         switch (arg)
682         {
683         case 0:
684             /* Set to blocking mode */
685             break;
686         case 1: /* Set to non-blocking mode */
687
688 #if defined(O_NONBLOCK) && !defined(SCO325)
689             ret = fcntl (fd, F_GETFL, 0);
690             if (ret != -1)
691                 ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
692 #else
693 #ifdef FIOSNBIO
694         {
695             int arg;
696             arg = 1;
697             ret = ioctl (fd, FIOSNBIO, &arg);
698         }
699 #else
700 #if defined(WIN32)
701         {
702 #ifdef WIN32
703             u_long arg;
704 #else
705             int arg;
706 #endif
707             arg = 1;
708 /* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
709  * eventually with EWOULDBLOCK */
710             ret = ioctl (fd, FIONBIO, &arg);
711         }
712 #else
713             ret = fcntl (fd, F_GETFL, 0);
714 #ifdef FNDELAY
715             ret = fcntl (fd, F_SETFL, ret | FNDELAY);
716 #else
717             ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
718 #endif
719 #endif /* AIXV3  || uniosu */
720 #endif /* FIOSNBIO */
721 #endif /* O_NONBLOCK */
722             break;
723         default:
724             /* Unknown option */
725             break;
726         }
727         break;
728     case TRANS_CLOSEONEXEC:
729 #ifdef F_SETFD
730 #ifdef FD_CLOEXEC
731         ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
732 #else
733         ret = fcntl (fd, F_SETFD, 1);
734 #endif /* FD_CLOEXEC */
735 #endif /* F_SETFD */
736         break;
737     }
738
739     return ret;
740 }
741
742 #ifdef TRANS_SERVER
743
744 int
745 TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
746
747 {
748     return ciptr->transptr->CreateListener (ciptr, port, flags);
749 }
750
751 int
752 TRANS(NoListen) (const char * protocol)
753
754 {
755    Xtransport *trans;
756    int i = 0, ret = 0;
757
758    if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
759    {
760         prmsg (1,"TransNoListen: unable to find transport: %s\n",
761                protocol);
762
763         return -1;
764    }
765    if (trans->flags & TRANS_ALIAS) {
766        if (trans->nolisten)
767            while (trans->nolisten[i]) {
768                ret |= TRANS(NoListen)(trans->nolisten[i]);
769                i++;
770        }
771    }
772
773    trans->flags |= TRANS_NOLISTEN;
774    return ret;
775 }
776
777 int
778 TRANS(ResetListener) (XtransConnInfo ciptr)
779
780 {
781     if (ciptr->transptr->ResetListener)
782         return ciptr->transptr->ResetListener (ciptr);
783     else
784         return TRANS_RESET_NOOP;
785 }
786
787
788 XtransConnInfo
789 TRANS(Accept) (XtransConnInfo ciptr, int *status)
790
791 {
792     XtransConnInfo      newciptr;
793
794     prmsg (2,"Accept(%d)\n", ciptr->fd);
795
796     newciptr = ciptr->transptr->Accept (ciptr, status);
797
798     if (newciptr)
799         newciptr->transptr = ciptr->transptr;
800
801     return newciptr;
802 }
803
804 #endif /* TRANS_SERVER */
805
806
807 #ifdef TRANS_CLIENT
808
809 int
810 TRANS(Connect) (XtransConnInfo ciptr, char *address)
811
812 {
813     char        *protocol;
814     char        *host;
815     char        *port;
816     int         ret;
817
818     prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address);
819
820     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
821     {
822         prmsg (1,"Connect: Unable to Parse address %s\n",
823                address);
824         return -1;
825     }
826
827 #ifdef HAVE_LAUNCHD
828     if (!host) host=strdup("");
829 #endif
830
831     if (!port || !*port)
832     {
833         prmsg (1,"Connect: Missing port specification in %s\n",
834               address);
835         if (protocol) free (protocol);
836         if (host) free (host);
837         return -1;
838     }
839
840     ret = ciptr->transptr->Connect (ciptr, host, port);
841
842     if (protocol) free (protocol);
843     if (host) free (host);
844     if (port) free (port);
845
846     return ret;
847 }
848
849 #endif /* TRANS_CLIENT */
850
851
852 int
853 TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
854
855 {
856     return ciptr->transptr->BytesReadable (ciptr, pend);
857 }
858
859 int
860 TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
861
862 {
863     return ciptr->transptr->Read (ciptr, buf, size);
864 }
865
866 int
867 TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
868
869 {
870     return ciptr->transptr->Write (ciptr, buf, size);
871 }
872
873 int
874 TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
875
876 {
877     return ciptr->transptr->Readv (ciptr, buf, size);
878 }
879
880 int
881 TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
882
883 {
884     return ciptr->transptr->Writev (ciptr, buf, size);
885 }
886
887 int
888 TRANS(Disconnect) (XtransConnInfo ciptr)
889
890 {
891     return ciptr->transptr->Disconnect (ciptr);
892 }
893
894 int
895 TRANS(Close) (XtransConnInfo ciptr)
896
897 {
898     int ret;
899
900     prmsg (2,"Close(%d)\n", ciptr->fd);
901
902     ret = ciptr->transptr->Close (ciptr);
903
904     TRANS(FreeConnInfo) (ciptr);
905
906     return ret;
907 }
908
909 int
910 TRANS(CloseForCloning) (XtransConnInfo ciptr)
911
912 {
913     int ret;
914
915     prmsg (2,"CloseForCloning(%d)\n", ciptr->fd);
916
917     ret = ciptr->transptr->CloseForCloning (ciptr);
918
919     TRANS(FreeConnInfo) (ciptr);
920
921     return ret;
922 }
923
924 int
925 TRANS(IsLocal) (XtransConnInfo ciptr)
926
927 {
928     return (ciptr->family == AF_UNIX);
929 }
930
931
932 int
933 TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
934                   Xtransaddr **addrp)
935
936 {
937     prmsg (2,"GetMyAddr(%d)\n", ciptr->fd);
938
939     *familyp = ciptr->family;
940     *addrlenp = ciptr->addrlen;
941
942     if ((*addrp = malloc (ciptr->addrlen)) == NULL)
943     {
944         prmsg (1,"GetMyAddr: malloc failed\n");
945         return -1;
946     }
947     memcpy(*addrp, ciptr->addr, ciptr->addrlen);
948
949     return 0;
950 }
951
952 int
953 TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
954                     Xtransaddr **addrp)
955
956 {
957     prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd);
958
959     *familyp = ciptr->family;
960     *addrlenp = ciptr->peeraddrlen;
961
962     if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL)
963     {
964         prmsg (1,"GetPeerAddr: malloc failed\n");
965         return -1;
966     }
967     memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
968
969     return 0;
970 }
971
972
973 int
974 TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
975
976 {
977     return ciptr->fd;
978 }
979
980 \f
981 /*
982  * These functions are really utility functions, but they require knowledge
983  * of the internal data structures, so they have to be part of the Transport
984  * Independant API.
985  */
986
987 #ifdef TRANS_SERVER
988
989 static int
990 complete_network_count (void)
991
992 {
993     int count = 0;
994     int found_local = 0;
995     int i;
996
997     /*
998      * For a complete network, we only need one LOCALCONN transport to work
999      */
1000
1001     for (i = 0; i < NUMTRANS; i++)
1002     {
1003         if (Xtransports[i].transport->flags & TRANS_ALIAS
1004          || Xtransports[i].transport->flags & TRANS_NOLISTEN)
1005             continue;
1006
1007         if (Xtransports[i].transport->flags & TRANS_LOCAL)
1008             found_local = 1;
1009         else
1010             count++;
1011     }
1012
1013     return (count + found_local);
1014 }
1015
1016
1017 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
1018 extern int xquartz_launchd_fd;
1019 #endif
1020
1021 int
1022 TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
1023                                    XtransConnInfo **ciptrs_ret)
1024
1025 {
1026     char                buffer[256]; /* ??? What size ?? */
1027     XtransConnInfo      ciptr, temp_ciptrs[NUMTRANS];
1028     int                 status, i, j;
1029
1030 #if defined(IPv6) && defined(AF_INET6)
1031     int         ipv6_succ = 0;
1032 #endif
1033     prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n",
1034            port ? port : "NULL", ciptrs_ret);
1035
1036     *count_ret = 0;
1037
1038 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
1039     fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
1040     if(xquartz_launchd_fd != -1) {
1041         if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
1042                                            xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
1043             fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
1044         else
1045             temp_ciptrs[(*count_ret)++] = ciptr;
1046     }
1047 #endif
1048
1049     for (i = 0; i < NUMTRANS; i++)
1050     {
1051         Xtransport *trans = Xtransports[i].transport;
1052         unsigned int flags = 0;
1053
1054         if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
1055             continue;
1056
1057         snprintf(buffer, sizeof(buffer), "%s/:%s",
1058                  trans->TransName, port ? port : "");
1059
1060         prmsg (5,"MakeAllCOTSServerListeners: opening %s\n",
1061                buffer);
1062
1063         if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
1064         {
1065             if (trans->flags & TRANS_DISABLED)
1066                 continue;
1067
1068             prmsg (1,
1069           "MakeAllCOTSServerListeners: failed to open listener for %s\n",
1070                   trans->TransName);
1071             continue;
1072         }
1073 #if defined(IPv6) && defined(AF_INET6)
1074                 if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
1075                      && ipv6_succ))
1076                     flags |= ADDR_IN_USE_ALLOWED;
1077 #endif
1078
1079         if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
1080         {
1081             if (status == TRANS_ADDR_IN_USE)
1082             {
1083                 /*
1084                  * We failed to bind to the specified address because the
1085                  * address is in use.  It must be that a server is already
1086                  * running at this address, and this function should fail.
1087                  */
1088
1089                 prmsg (1,
1090                 "MakeAllCOTSServerListeners: server already running\n");
1091
1092                 for (j = 0; j < *count_ret; j++)
1093                     TRANS(Close) (temp_ciptrs[j]);
1094
1095                 *count_ret = 0;
1096                 *ciptrs_ret = NULL;
1097                 *partial = 0;
1098                 return -1;
1099             }
1100             else
1101             {
1102                 prmsg (1,
1103         "MakeAllCOTSServerListeners: failed to create listener for %s\n",
1104                   trans->TransName);
1105
1106                 continue;
1107             }
1108         }
1109
1110 #if defined(IPv6) && defined(AF_INET6)
1111         if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
1112             ipv6_succ = 1;
1113 #endif
1114
1115         prmsg (5,
1116               "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
1117               trans->TransName, ciptr->fd);
1118
1119         temp_ciptrs[*count_ret] = ciptr;
1120         (*count_ret)++;
1121     }
1122
1123     *partial = (*count_ret < complete_network_count());
1124
1125     prmsg (5,
1126      "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
1127         *partial, *count_ret, complete_network_count());
1128
1129     if (*count_ret > 0)
1130     {
1131         if ((*ciptrs_ret = malloc (
1132             *count_ret * sizeof (XtransConnInfo))) == NULL)
1133         {
1134             return -1;
1135         }
1136
1137         for (i = 0; i < *count_ret; i++)
1138         {
1139             (*ciptrs_ret)[i] = temp_ciptrs[i];
1140         }
1141     }
1142     else
1143         *ciptrs_ret = NULL;
1144
1145     return 0;
1146 }
1147
1148 int
1149 TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
1150                                    XtransConnInfo **ciptrs_ret)
1151
1152 {
1153     char                buffer[256]; /* ??? What size ?? */
1154     XtransConnInfo      ciptr, temp_ciptrs[NUMTRANS];
1155     int                 status, i, j;
1156
1157     prmsg (2,"MakeAllCLTSServerListeners(%s,%p)\n",
1158         port ? port : "NULL", ciptrs_ret);
1159
1160     *count_ret = 0;
1161
1162     for (i = 0; i < NUMTRANS; i++)
1163     {
1164         Xtransport *trans = Xtransports[i].transport;
1165
1166         if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
1167             continue;
1168
1169         snprintf(buffer, sizeof(buffer), "%s/:%s",
1170                  trans->TransName, port ? port : "");
1171
1172         prmsg (5,"MakeAllCLTSServerListeners: opening %s\n",
1173             buffer);
1174
1175         if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
1176         {
1177             prmsg (1,
1178         "MakeAllCLTSServerListeners: failed to open listener for %s\n",
1179                   trans->TransName);
1180             continue;
1181         }
1182
1183         if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
1184         {
1185             if (status == TRANS_ADDR_IN_USE)
1186             {
1187                 /*
1188                  * We failed to bind to the specified address because the
1189                  * address is in use.  It must be that a server is already
1190                  * running at this address, and this function should fail.
1191                  */
1192
1193                 prmsg (1,
1194                 "MakeAllCLTSServerListeners: server already running\n");
1195
1196                 for (j = 0; j < *count_ret; j++)
1197                     TRANS(Close) (temp_ciptrs[j]);
1198
1199                 *count_ret = 0;
1200                 *ciptrs_ret = NULL;
1201                 *partial = 0;
1202                 return -1;
1203             }
1204             else
1205             {
1206                 prmsg (1,
1207         "MakeAllCLTSServerListeners: failed to create listener for %s\n",
1208                   trans->TransName);
1209
1210                 continue;
1211             }
1212         }
1213
1214         prmsg (5,
1215         "MakeAllCLTSServerListeners: opened listener for %s, %d\n",
1216               trans->TransName, ciptr->fd);
1217         temp_ciptrs[*count_ret] = ciptr;
1218         (*count_ret)++;
1219     }
1220
1221     *partial = (*count_ret < complete_network_count());
1222
1223     prmsg (5,
1224      "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
1225         *partial, *count_ret, complete_network_count());
1226
1227     if (*count_ret > 0)
1228     {
1229         if ((*ciptrs_ret = malloc (
1230             *count_ret * sizeof (XtransConnInfo))) == NULL)
1231         {
1232             return -1;
1233         }
1234
1235         for (i = 0; i < *count_ret; i++)
1236         {
1237             (*ciptrs_ret)[i] = temp_ciptrs[i];
1238         }
1239     }
1240     else
1241         *ciptrs_ret = NULL;
1242
1243     return 0;
1244 }
1245
1246 #endif /* TRANS_SERVER */
1247
1248
1249 \f
1250 /*
1251  * These routines are not part of the X Transport Interface, but they
1252  * may be used by it.
1253  */
1254
1255
1256 #if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
1257
1258 /*
1259  * emulate readv
1260  */
1261
1262 static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
1263
1264 {
1265     int i, len, total;
1266     char *base;
1267
1268     ESET(0);
1269     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
1270         len = iov->iov_len;
1271         base = iov->iov_base;
1272         while (len > 0) {
1273             register int nbytes;
1274             nbytes = TRANS(Read) (ciptr, base, len);
1275             if (nbytes < 0 && total == 0)  return -1;
1276             if (nbytes <= 0)  return total;
1277             ESET(0);
1278             len   -= nbytes;
1279             total += nbytes;
1280             base  += nbytes;
1281         }
1282     }
1283     return total;
1284 }
1285
1286 #endif /* SYSV && __i386__ || WIN32 || __sxg__ */
1287
1288 #if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
1289
1290 /*
1291  * emulate writev
1292  */
1293
1294 static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
1295
1296 {
1297     int i, len, total;
1298     char *base;
1299
1300     ESET(0);
1301     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
1302         len = iov->iov_len;
1303         base = iov->iov_base;
1304         while (len > 0) {
1305             register int nbytes;
1306             nbytes = TRANS(Write) (ciptr, base, len);
1307             if (nbytes < 0 && total == 0)  return -1;
1308             if (nbytes <= 0)  return total;
1309             ESET(0);
1310             len   -= nbytes;
1311             total += nbytes;
1312             base  += nbytes;
1313         }
1314     }
1315     return total;
1316 }
1317
1318 #endif /* SYSV && __i386__ || WIN32 || __sxg__ */
1319
1320
1321 #if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__)
1322 #ifndef NEED_UTSNAME
1323 #define NEED_UTSNAME
1324 #endif
1325 #include <sys/utsname.h>
1326 #endif
1327
1328 /*
1329  * TRANS(GetHostname) - similar to gethostname but allows special processing.
1330  */
1331
1332 int TRANS(GetHostname) (char *buf, int maxlen)
1333
1334 {
1335     int len;
1336
1337 #ifdef NEED_UTSNAME
1338     struct utsname name;
1339
1340     uname (&name);
1341     len = strlen (name.nodename);
1342     if (len >= maxlen) len = maxlen - 1;
1343     strncpy (buf, name.nodename, len);
1344     buf[len] = '\0';
1345 #else
1346     buf[0] = '\0';
1347     (void) gethostname (buf, maxlen);
1348     buf [maxlen - 1] = '\0';
1349     len = strlen(buf);
1350 #endif /* NEED_UTSNAME */
1351     return len;
1352 }