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