upload tizen2.0 source
[framework/uifw/xorg/lib/xtrans.git] / Xtranstli.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 <sys/un.h>
51 #include <stropts.h>
52 #include <poll.h>
53 #include <tiuser.h>
54
55 #include <netdir.h>
56 #include <netconfig.h>
57
58
59 /*
60  * This is the TLI implementation of the X Transport service layer
61  */
62
63 typedef struct _TLItrans2dev {
64     char        *transname;
65     char        *protofamily;
66     char        *devcotsname;
67     char        *devcltsname;
68     int family;
69 } TLItrans2dev;
70
71 static TLItrans2dev TLItrans2devtab[] = {
72         {"inet","inet","/dev/tcp","/dev/udp",AF_INET},
73         {"tcp","inet","/dev/tcp","/dev/udp",AF_INET},
74         {"tli","loopback","/dev/ticots","/dev/ticlts",AF_UNIX},
75 };
76
77 #define NUMTLIFAMILIES (sizeof(TLItrans2devtab)/sizeof(TLItrans2dev))
78
79 /*
80  * The local TLI connection, is a form of a local connection, so use a
81  * sockaddr_un for the address so that it will be treated just like the other
82  * local transports such as UNIX domain sockets, pts, and named.
83  */
84
85 #if defined(X11_t)
86 #define TLINODENAME     "TLI:xserver"
87 #endif
88
89 #if defined(XIM_t)
90 #define TLINODENAME     "TLI:xim"
91 #endif
92
93 #if defined(FS_t) || defined(FONT_t)
94 #define TLINODENAME     "TLI:fontserver"
95 #endif
96
97 #if defined(ICE_t)
98 #define TLINODENAME     "TLI:ICE"
99 #endif
100
101 #if defined(TEST_t)
102 #define TLINODENAME     "TLI:test"
103 #endif
104
105 #ifndef PORTBUFSIZE
106 #ifdef TRANS_SERVER
107 #define PORTBUFSIZE     64
108 #else
109 #ifdef TRANS_CLIENT
110 #define PORTBUFSIZE     64
111 #endif
112 #endif
113 #endif
114
115
116 /*
117  * These are some utility function used by the real interface function below.
118  */
119
120 static int
121 TRANS(TLISelectFamily)(char *family)
122
123 {
124     int     i;
125
126     prmsg(3,"TLISelectFamily(%s)\n", family);
127
128     for(i=0;i<NUMTLIFAMILIES;i++)
129     {
130         if( !strcmp(family,TLItrans2devtab[i].transname) )
131             return i;
132     }
133     return -1;
134 }
135
136
137 /*
138  * This function gets the local address of the transport and stores it in the
139  * XtransConnInfo structure for the connection.
140  */
141
142 static int
143 TRANS(TLIGetAddr)(XtransConnInfo ciptr)
144
145 {
146     Xtransaddr          sockname;
147     struct netbuf       netbuf;
148
149     prmsg(3,"TLIGetAddr(%x)\n", ciptr);
150
151     netbuf.buf=(char *)&sockname;
152     netbuf.len=sizeof(sockname);
153     netbuf.maxlen=sizeof(sockname);
154
155     if( t_getname(ciptr->fd,&netbuf,LOCALNAME) < 0 )
156     {
157         prmsg(1,"TLIGetAddr: t_getname(LOCALNAME) failed: %d\n",
158               errno);
159         return -1;
160     }
161
162     prmsg(4,"TLIGetAddr: got family %d len %d\n",
163           ((struct sockaddr *) &sockname)->sa_family ,netbuf.len);
164
165     /*
166      * Everything looks good: fill in the XtransConnInfo structure.
167      */
168
169     if( ciptr->addr )
170         free(ciptr->addr);
171
172     if( (ciptr->addr = malloc(netbuf.len)) == NULL )
173     {
174         prmsg(1, "TLIGetAddr: Can't allocate space for the addr\n");
175         return -1;
176     }
177
178     ciptr->family=((struct sockaddr *) &sockname)->sa_family;
179     ciptr->addrlen=netbuf.len;
180     memcpy(ciptr->addr,&sockname,ciptr->addrlen);
181
182     return 0;
183 }
184
185
186 /*
187  * This function gets the remote address of the socket and stores it in the
188  * XtransConnInfo structure for the connection.
189  */
190
191 static int
192 TRANS(TLIGetPeerAddr)(XtransConnInfo ciptr)
193
194 {
195     Xtransaddr          sockname;
196     struct netbuf       netbuf;
197
198     prmsg(3,"TLIGetPeerAddr(%x)\n", ciptr);
199
200     netbuf.buf=(char *)&sockname;
201     netbuf.len=sizeof(sockname);
202     netbuf.maxlen=sizeof(sockname);
203
204     if( t_getname(ciptr->fd,&netbuf,REMOTENAME) < 0 )
205     {
206         prmsg(1,"TLIGetPeerAddr: t_getname(REMOTENAME) failed: %d\n",
207               errno);
208         return -1;
209     }
210
211     prmsg(4,"TLIGetPeerAddr: got family %d len %d\n",
212           ((struct sockaddr *) &sockname)->sa_family ,netbuf.len);
213
214     /*
215      * Everything looks good: fill in the XtransConnInfo structure.
216      */
217
218     if( ciptr->peeraddr )
219         free(ciptr->peeraddr);
220
221     if( (ciptr->peeraddr = malloc(netbuf.len)) == NULL )
222     {
223         prmsg(1,
224               "TLIGetPeerAddr: Can't allocate space for the addr\n");
225         return -1;
226     }
227
228     ciptr->peeraddrlen=netbuf.len;
229     memcpy(ciptr->peeraddr,&sockname,ciptr->peeraddrlen);
230
231     return 0;
232 }
233
234
235 /*
236  * This function will establish a local name for the transport. This function
237  * do extra work for the local tli connection. It must create a sockaddr_un
238  * format address so that it will look like an AF_UNIX connection to the
239  * higher layer.
240  *
241  * This function will only be called by the OPENC?TSClient() functions since
242  * the local address is set up in the CreateListner() for the server ends.
243  */
244
245 static int
246 TRANS(TLITLIBindLocal)(int fd, int family, char *port)
247
248 {
249     struct sockaddr_un  *sunaddr=NULL;
250     struct t_bind       *req=NULL;
251
252     prmsg(2, "TLITLIBindLocal(%d,%d,%s)\n", fd, family, port);
253
254     if( family == AF_UNIX )
255     {
256         if( (req=(struct t_bind *)t_alloc(fd,T_BIND,0)) == NULL )
257         {
258             prmsg(1,
259                   "TLITLIBindLocal() failed to allocate a t_bind\n");
260             return -1;
261         }
262
263         if( (sunaddr=(struct sockaddr_un *)
264              malloc(sizeof(struct sockaddr_un))) == NULL )
265         {
266             prmsg(1,
267                   "TLITLIBindLocal: failed to allocate a sockaddr_un\n");
268             t_free((char *)req,T_BIND);
269             return -1;
270         }
271
272         sunaddr->sun_family=AF_UNIX;
273
274 #ifdef nuke
275         if( *port == '/' ) { /* A full pathname */
276             (void) strcpy(sunaddr->sun_path, port);
277         } else {
278             (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
279         }
280 #endif /*NUKE*/
281
282         (void) sprintf(sunaddr->sun_path,"%s%d",
283                        TLINODENAME, getpid()^time(NULL) );
284
285         prmsg(4, "TLITLIBindLocal: binding to %s\n",
286               sunaddr->sun_path);
287
288         req->addr.buf=(char *)sunaddr;
289         req->addr.len=sizeof(*sunaddr);
290         req->addr.maxlen=sizeof(*sunaddr);
291     }
292
293     if( t_bind(fd, req, NULL) < 0 )
294     {
295         prmsg(1,
296               "TLIBindLocal: Unable to bind TLI device to %s\n",
297               port);
298         if (sunaddr)
299             free((char *) sunaddr);
300         if (req)
301             t_free((char *)req,T_BIND);
302         return -1;
303     }
304     return 0;
305 }
306
307 static XtransConnInfo
308 TRANS(TLIOpen)(char *device)
309
310 {
311     XtransConnInfo      ciptr;
312
313     prmsg(3,"TLIOpen(%s)\n", device);
314
315     if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL )
316     {
317         prmsg(1, "TLIOpen: calloc failed\n");
318         return NULL;
319     }
320
321     if( (ciptr->fd=t_open( device, O_RDWR, NULL )) < 0 )
322     {
323         prmsg(1, "TLIOpen: t_open failed for %s\n", device);
324         free(ciptr);
325         return NULL;
326     }
327
328     return ciptr;
329 }
330
331
332 #ifdef TRANS_REOPEN
333
334 static XtransConnInfo
335 TRANS(TLIReopen)(char *device, int fd, char *port)
336
337 {
338     XtransConnInfo      ciptr;
339
340     prmsg(3,"TLIReopen(%s,%d, %s)\n", device, fd, port );
341
342     if (t_sync (fd) < 0)
343     {
344         prmsg(1, "TLIReopen: t_sync failed\n");
345         return NULL;
346     }
347
348     if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL )
349     {
350         prmsg(1, "TLIReopen: calloc failed\n");
351         return NULL;
352     }
353
354     ciptr->fd = fd;
355
356     return ciptr;
357 }
358
359 #endif /* TRANS_REOPEN */
360
361
362 static  int
363 TRANS(TLIAddrToNetbuf)(int tlifamily, char *host, char *port,
364                        struct netbuf *netbufp)
365
366 {
367     struct netconfig *netconfigp;
368     struct nd_hostserv  nd_hostserv;
369     struct nd_addrlist *nd_addrlistp = NULL;
370     void *handlep;
371     long lport;
372
373     prmsg(3,"TLIAddrToNetbuf(%d,%s,%s)\n", tlifamily, host, port );
374
375     if( (handlep=setnetconfig()) == NULL )
376         return -1;
377
378     lport = strtol (port, (char**)NULL, 10);
379     if (lport < 1024 || lport > USHRT_MAX)
380         return -1;
381
382     nd_hostserv.h_host = host;
383     if( port && *port ) {
384         nd_hostserv.h_serv = port;
385     } else {
386         nd_hostserv.h_serv = NULL;
387     }
388
389     while( (netconfigp=getnetconfig(handlep)) != NULL )
390     {
391         if( strcmp(netconfigp->nc_protofmly,
392                    TLItrans2devtab[tlifamily].protofamily) != 0 )
393             continue;
394         prmsg(5,"TLIAddrToNetbuf: Trying to resolve %s.%s for %s\n",
395               host, port, TLItrans2devtab[tlifamily].protofamily );
396         if( netdir_getbyname(netconfigp,&nd_hostserv, &nd_addrlistp) == 0 )
397         {
398             /* we have at least one address to use */
399
400             prmsg(5, "TLIAddrToNetbuf: found address for %s.%s\n", host, port);
401             prmsg(5, "TLIAddrToNetbuf: %s\n",taddr2uaddr(netconfigp,nd_addrlistp->n_addrs));
402
403             memcpy(netbufp->buf,nd_addrlistp->n_addrs->buf,
404                    nd_addrlistp->n_addrs->len);
405             netbufp->len=nd_addrlistp->n_addrs->len;
406             endnetconfig(handlep);
407             return 0;
408         }
409     }
410     endnetconfig(handlep);
411
412     return -1;
413 }
414
415 /*
416  * These functions are the interface supplied in the Xtransport structure
417  */
418
419 #ifdef TRANS_CLIENT
420
421 static XtransConnInfo
422 TRANS(TLIOpenCOTSClient)(Xtransport *thistrans, char *protocol,
423                          char *host, char *port)
424
425 {
426     XtransConnInfo      ciptr;
427     int                 i;
428
429     prmsg(2,"TLIOpenCOTSClient(%s,%s,%s)\n", protocol, host, port );
430
431     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
432     {
433         prmsg(1,"TLIOpenCOTSClient: Unable to determine device for %s\n",
434               thistrans->TransName);
435         return NULL;
436     }
437
438     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
439     {
440         prmsg(1,"TLIOpenCOTSClient: Unable to open device for %s\n",
441               thistrans->TransName);
442         return NULL;
443     }
444
445     if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
446     {
447         prmsg(1,
448               "TLIOpenCOTSClient: ...TLITLIBindLocal() failed: %d\n",
449               errno);
450         t_close(ciptr->fd);
451         free(ciptr);
452         return NULL;
453     }
454
455     if( TRANS(TLIGetAddr)(ciptr) < 0 )
456     {
457         prmsg(1,
458               "TLIOpenCOTSClient: ...TLIGetAddr() failed: %d\n",
459               errno);
460         t_close(ciptr->fd);
461         free(ciptr);
462         return NULL;
463     }
464
465     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
466     ciptr->index = i;
467
468     return ciptr;
469 }
470
471 #endif /* TRANS_CLIENT */
472
473
474 #ifdef TRANS_SERVER
475
476 static XtransConnInfo
477 TRANS(TLIOpenCOTSServer)(Xtransport *thistrans, char *protocol,
478                          char *host, char *port)
479
480 {
481     XtransConnInfo      ciptr;
482     int                 i;
483
484     prmsg(2,"TLIOpenCOTSServer(%s,%s,%s)\n", protocol, host, port );
485
486     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
487     {
488         prmsg(1,
489               "TLIOpenCOTSServer: Unable to determine device for %s\n",
490               thistrans->TransName);
491         return NULL;
492     }
493
494     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
495     {
496         prmsg(1,
497               "TLIOpenCOTSServer: Unable to open device for %s\n",
498               thistrans->TransName);
499         return NULL;
500     }
501
502     /* Set the family type */
503
504     ciptr->family = TLItrans2devtab[i].family;
505
506
507     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
508
509     ciptr->index = i;
510
511     return ciptr;
512 }
513
514 #endif /* TRANS_SERVER */
515
516
517 #ifdef TRANS_CLIENT
518
519 static XtransConnInfo
520 TRANS(TLIOpenCLTSClient)(Xtransport *thistrans, char *protocol,
521                          char *host, char *port)
522
523 {
524     XtransConnInfo      ciptr;
525     int                 i;
526
527     prmsg(2,"TLIOpenCLTSClient(%s,%s,%s)\n", protocol, host, port );
528
529     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
530     {
531         prmsg(1,
532               "TLIOpenCLTSClient: Unable to determine device for %s\n",
533               thistrans->TransName);
534         return NULL;
535     }
536
537     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
538     {
539         prmsg(1,
540               "TLIOpenCLTSClient: Unable to open device for %s\n",
541               thistrans->TransName);
542         return NULL;
543     }
544
545     if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
546     {
547         prmsg(1,
548               "TLIOpenCLTSClient: ...TLITLIBindLocal() failed: %d\n",
549               errno);
550         t_close(ciptr->fd);
551         free(ciptr);
552         return NULL;
553     }
554
555     if( TRANS(TLIGetAddr)(ciptr) < 0 )
556     {
557         prmsg(1,
558               "TLIOpenCLTSClient: ...TLIGetPeerAddr() failed: %d\n",
559               errno);
560         t_close(ciptr->fd);
561         free(ciptr);
562         return NULL;
563     }
564
565     return ciptr;
566 }
567
568 #endif /* TRANS_CLIENT */
569
570
571 #ifdef TRANS_SERVER
572
573 static XtransConnInfo
574 TRANS(TLIOpenCLTSServer)(Xtransport *thistrans, char *protocol,
575                          char *host, char *port)
576
577 {
578     XtransConnInfo      ciptr;
579     int                 i;
580
581     prmsg(2,"TLIOpenCLTSServer(%s,%s,%s)\n", protocol, host, port );
582
583     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
584     {
585         prmsg(1,
586               "TLIOpenCLTSServer: Unable to determine device for %s\n",
587               thistrans->TransName);
588         return NULL;
589     }
590
591     if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
592     {
593         prmsg(1,
594               "TLIOpenCLTSServer: Unable to open device for %s\n",
595               thistrans->TransName);
596         return NULL;
597     }
598
599     return ciptr;
600 }
601
602 #endif /* TRANS_SERVER */
603
604
605 #ifdef TRANS_REOPEN
606
607 static XtransConnInfo
608 TRANS(TLIReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
609
610 {
611     XtransConnInfo      ciptr;
612     int                 i;
613
614     prmsg(2,"TLIReopenCOTSServer(%d, %s)\n", fd, port);
615
616     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
617     {
618         prmsg(1,
619               "TLIReopenCOTSServer: Unable to determine device for %s\n",
620               thistrans->TransName);
621         return NULL;
622     }
623
624     if( (ciptr=TRANS(TLIReopen)(
625         TLItrans2devtab[i].devcotsname, fd, port)) == NULL )
626     {
627         prmsg(1,
628               "TLIReopenCOTSServer: Unable to open device for %s\n",
629               thistrans->TransName);
630         return NULL;
631     }
632
633     /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
634
635     ciptr->index = i;
636
637     return ciptr;
638 }
639
640
641 static XtransConnInfo
642 TRANS(TLIReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
643
644 {
645     XtransConnInfo      ciptr;
646     int                 i;
647
648     prmsg(2,"TLIReopenCLTSServer(%d, %s)\n", fd, port);
649
650     if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
651     {
652         prmsg(1,
653               "TLIReopenCLTSServer: Unable to determine device for %s\n",
654               thistrans->TransName);
655         return NULL;
656     }
657
658     if( (ciptr=TRANS(TLIReopen)(
659         TLItrans2devtab[i].devcltsname, fd, port)) == NULL )
660     {
661         prmsg(1,
662               "TLIReopenCLTSServer: Unable to open device for %s\n",
663               thistrans->TransName);
664         return NULL;
665     }
666
667     ciptr->index = i;
668
669     return ciptr;
670 }
671
672 #endif /* TRANS_REOPEN */
673
674
675 static int
676 TRANS(TLISetOption)(XtransConnInfo ciptr, int option, int arg)
677
678 {
679     prmsg(2,"TLISetOption(%d,%d,%d)\n", ciptr->fd, option, arg );
680
681     return -1;
682 }
683
684
685 #ifdef TRANS_SERVER
686
687 static int
688 TRANS(TLICreateListener)(XtransConnInfo ciptr, struct t_bind *req)
689
690 {
691     struct t_bind       *ret;
692
693     prmsg(2,"TLICreateListener(%x->%d,%x)\n", ciptr, ciptr->fd, req );
694
695     if( (ret=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
696     {
697         prmsg(1, "TLICreateListener: failed to allocate a t_bind\n");
698         t_free((char *)req,T_BIND);
699         return TRANS_CREATE_LISTENER_FAILED;
700     }
701
702     if( t_bind(ciptr->fd, req, ret) < 0 )
703     {
704         prmsg(1, "TLICreateListener: t_bind failed\n");
705         t_free((char *)req,T_BIND);
706         t_free((char *)ret,T_BIND);
707         return TRANS_CREATE_LISTENER_FAILED;
708     }
709
710     if( memcmp(req->addr.buf,ret->addr.buf,req->addr.len) != 0 )
711     {
712         prmsg(1, "TLICreateListener: unable to bind to %x\n",
713               req);
714         t_free((char *)req,T_BIND);
715         t_free((char *)ret,T_BIND);
716         return TRANS_ADDR_IN_USE;
717     }
718
719     /*
720      * Everything looks good: fill in the XtransConnInfo structure.
721      */
722
723     if( (ciptr->addr = malloc(ret->addr.len)) == NULL )
724     {
725         prmsg(1,
726               "TLICreateListener: Unable to allocate space for the address\n");
727         t_free((char *)req,T_BIND);
728         t_free((char *)ret, T_BIND);
729         return TRANS_CREATE_LISTENER_FAILED;
730     }
731
732     ciptr->addrlen=ret->addr.len;
733     memcpy(ciptr->addr,ret->addr.buf,ret->addr.len);
734
735     t_free((char *)req,T_BIND);
736     t_free((char *)ret, T_BIND);
737
738     return 0;
739 }
740
741
742 static int
743 TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
744
745 {
746     char    portbuf[PORTBUFSIZE];
747     struct t_bind       *req;
748     struct sockaddr_in  *sinaddr;
749     long                tmpport;
750
751     prmsg(2,"TLIINETCreateListener(%x->%d,%s)\n", ciptr,
752         ciptr->fd, port ? port : "NULL" );
753
754 #ifdef X11_t
755     /*
756      * X has a well known port, that is transport dependent. It is easier
757      * to handle it here, than try and come up with a transport independent
758      * representation that can be passed in and resolved the usual way.
759      *
760      * The port that is passed here is really a string containing the idisplay
761      * from ConnectDisplay().
762      */
763
764     if (is_numeric (port))
765     {
766         tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
767         sprintf(portbuf,"%u", tmpport);
768         port = portbuf;
769     }
770 #endif
771
772     if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
773     {
774         prmsg(1,
775             "TLIINETCreateListener: failed to allocate a t_bind\n");
776         return TRANS_CREATE_LISTENER_FAILED;
777     }
778
779     if( port && *port ) {
780         if(TRANS(TLIAddrToNetbuf)(ciptr->index,HOST_SELF,port,&(req->addr)) < 0)
781         {
782             prmsg(1,
783                   "TLIINETCreateListener: can't resolve name:HOST_SELF.%s\n",
784                   port);
785             t_free((char *)req,T_BIND);
786             return TRANS_CREATE_LISTENER_FAILED;
787         }
788     } else {
789         sinaddr=(struct sockaddr_in *) req->addr.buf;
790         sinaddr->sin_family=AF_INET;
791         sinaddr->sin_port=htons(0);
792         sinaddr->sin_addr.s_addr=0;
793     }
794
795     /* Set the qlen */
796
797     req->qlen=1;
798
799     return TRANS(TLICreateListener)(ciptr, req);
800 }
801
802
803 static int
804 TRANS(TLITLICreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
805
806 {
807     struct t_bind       *req;
808     struct sockaddr_un  *sunaddr;
809     int                 ret_value;
810
811     prmsg(2,"TLITLICreateListener(%x->%d,%s)\n", ciptr, ciptr->fd,
812         port ? port : "NULL");
813
814     if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,0)) == NULL )
815     {
816         prmsg(1,
817               "TLITLICreateListener: failed to allocate a t_bind\n");
818         return TRANS_CREATE_LISTENER_FAILED;
819     }
820
821     if( (sunaddr=(struct sockaddr_un *)
822          malloc(sizeof(struct sockaddr_un))) == NULL )
823     {
824         prmsg(1,
825               "TLITLICreateListener: failed to allocate a sockaddr_un\n");
826         t_free((char *)req,T_BIND);
827         return TRANS_CREATE_LISTENER_FAILED;
828     }
829
830     sunaddr->sun_family=AF_UNIX;
831     if( port && *port ) {
832         if( *port == '/' ) { /* A full pathname */
833             (void) strcpy(sunaddr->sun_path, port);
834         } else {
835             (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
836         }
837     } else {
838         (void) sprintf(sunaddr->sun_path,"%s%d", TLINODENAME, getpid());
839     }
840
841     req->addr.buf=(char *)sunaddr;
842     req->addr.len=sizeof(*sunaddr);
843     req->addr.maxlen=sizeof(*sunaddr);
844
845     /* Set the qlen */
846
847     req->qlen=1;
848
849     ret_value = TRANS(TLICreateListener)(ciptr, req);
850
851     free((char *) sunaddr);
852
853     return ret_value;
854 }
855
856
857 static XtransConnInfo
858 TRANS(TLIAccept)(XtransConnInfo ciptr, int *status)
859
860 {
861     struct t_call       *call;
862     XtransConnInfo      newciptr;
863     int i;
864
865     prmsg(2,"TLIAccept(%x->%d)\n", ciptr, ciptr->fd);
866
867     if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
868     {
869         prmsg(1, "TLIAccept() failed to allocate a t_call\n");
870         *status = TRANS_ACCEPT_BAD_MALLOC;
871         return NULL;
872     }
873
874     if( t_listen(ciptr->fd,call) < 0 )
875     {
876         extern char *t_errlist[];
877         extern int t_errno;
878         prmsg(1, "TLIAccept() t_listen() failed\n");
879         prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]);
880         t_free((char *)call,T_CALL);
881         *status = TRANS_ACCEPT_MISC_ERROR;
882         return NULL;
883     }
884
885     /*
886      * Now we need to set up the new endpoint for the incoming connection.
887      */
888
889     i=ciptr->index; /* Makes the next line more readable */
890
891     if( (newciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
892     {
893         prmsg(1, "TLIAccept() failed to open a new endpoint\n");
894         t_free((char *)call,T_CALL);
895         *status = TRANS_ACCEPT_MISC_ERROR;
896         return NULL;
897     }
898
899     if( TRANS(TLITLIBindLocal)(newciptr->fd,TLItrans2devtab[i].family,"") < 0 )
900     {
901         prmsg(1,
902               "TLIAccept: TRANS(TLITLIBindLocal)() failed: %d\n",
903               errno);
904         t_free((char *)call,T_CALL);
905         t_close(newciptr->fd);
906         free(newciptr);
907         *status = TRANS_ACCEPT_MISC_ERROR;
908         return NULL;
909     }
910
911
912     if( t_accept(ciptr->fd,newciptr->fd,call) < 0 )
913     {
914         extern char *t_errlist[];
915         extern int t_errno;
916         prmsg(1, "TLIAccept() t_accept() failed\n");
917         prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]);
918         if( t_errno == TLOOK )
919         {
920             int evtype = t_look(ciptr->fd);
921             prmsg(1, "TLIAccept() t_look() returned %d\n", evtype);
922             switch( evtype )
923             {
924                 case T_DISCONNECT:
925                     if( t_rcvdis(ciptr->fd, NULL) < 0 )
926                     {
927                         prmsg(1, "TLIAccept() t_rcvdis() failed\n");
928                         prmsg(1, "TLIAccept: %s\n", t_errlist[t_errno]);
929                     }
930                     break;
931                 default:
932                     break;
933             }
934         }
935         t_free((char *)call,T_CALL);
936         t_close(newciptr->fd);
937         free(newciptr);
938         *status = TRANS_ACCEPT_FAILED;
939         return NULL;
940     }
941
942     t_free((char *)call,T_CALL);
943
944     if( TRANS(TLIGetAddr)(newciptr) < 0 )
945     {
946         prmsg(1,
947               "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
948               errno);
949         t_close(newciptr->fd);
950         free(newciptr);
951         *status = TRANS_ACCEPT_MISC_ERROR;
952         return NULL;
953     }
954
955     if( TRANS(TLIGetPeerAddr)(newciptr) < 0 )
956     {
957         prmsg(1,
958               "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
959               errno);
960         t_close(newciptr->fd);
961         free(newciptr->addr);
962         free(newciptr);
963         *status = TRANS_ACCEPT_MISC_ERROR;
964         return NULL;
965     }
966
967     if( ioctl(newciptr->fd, I_POP,"timod") < 0 )
968     {
969         prmsg(1, "TLIAccept() ioctl(I_POP, \"timod\") failed %d\n",
970               errno);
971         t_close(newciptr->fd);
972         free(newciptr->addr);
973         free(newciptr);
974         *status = TRANS_ACCEPT_MISC_ERROR;
975         return NULL;
976     }
977
978     if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 )
979     {
980         prmsg(1, "TLIAccept() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
981               errno);
982         t_close(newciptr->fd);
983         free(newciptr->addr);
984         free(newciptr);
985         *status = TRANS_ACCEPT_MISC_ERROR;
986         return NULL;
987     }
988
989     *status = 0;
990
991     return newciptr;
992 }
993
994 #endif /* TRANS_SERVER */
995
996
997 #ifdef TRANS_CLIENT
998
999 static int
1000 TRANS(TLIConnect)(XtransConnInfo ciptr, struct t_call *sndcall )
1001
1002 {
1003     prmsg(2, "TLIConnect(%x->%d,%x)\n", ciptr, ciptr->fd, sndcall);
1004
1005     if( t_connect(ciptr->fd,sndcall,NULL) < 0 )
1006     {
1007         extern char *t_errlist[];
1008         extern int t_errno;
1009         prmsg(1, "TLIConnect() t_connect() failed\n");
1010         prmsg(1, "TLIConnect: %s\n", t_errlist[t_errno]);
1011         t_free((char *)sndcall,T_CALL);
1012         if (t_errno == TLOOK && t_look(ciptr->fd) == T_DISCONNECT)
1013         {
1014             t_rcvdis(ciptr->fd,NULL);
1015             return TRANS_TRY_CONNECT_AGAIN;
1016         }
1017         else
1018             return TRANS_CONNECT_FAILED;
1019     }
1020
1021     t_free((char *)sndcall,T_CALL);
1022
1023     /*
1024      * Sync up the address fields of ciptr.
1025      */
1026
1027     if( TRANS(TLIGetAddr)(ciptr) < 0 )
1028     {
1029         prmsg(1,
1030               "TLIConnect: ...TLIGetAddr() failed: %d\n",
1031               errno);
1032         return TRANS_CONNECT_FAILED;
1033     }
1034
1035     if( TRANS(TLIGetPeerAddr)(ciptr) < 0 )
1036     {
1037         prmsg(1,
1038               "TLIConnect: ...TLIGetPeerAddr() failed: %d\n",
1039               errno);
1040         return TRANS_CONNECT_FAILED;
1041     }
1042
1043     if( ioctl(ciptr->fd, I_POP,"timod") < 0 )
1044     {
1045         prmsg(1, "TLIConnect() ioctl(I_POP,\"timod\") failed %d\n",
1046               errno);
1047         return TRANS_CONNECT_FAILED;
1048     }
1049
1050     if( ioctl(ciptr->fd, I_PUSH,"tirdwr") < 0 )
1051     {
1052         prmsg(1, "TLIConnect() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
1053               errno);
1054         return TRANS_CONNECT_FAILED;
1055     }
1056
1057     return 0;
1058 }
1059
1060
1061 static int
1062 TRANS(TLIINETConnect)(XtransConnInfo ciptr, char *host, char *port)
1063
1064 {
1065     char        portbuf[PORTBUFSIZE];
1066     struct      t_call  *sndcall;
1067     long        tmpport;
1068
1069     prmsg(2, "TLIINETConnect(%s,%s)\n", host, port);
1070
1071 #ifdef X11_t
1072     /*
1073      * X has a well known port, that is transport dependant. It is easier
1074      * to handle it here, than try and come up with a transport independent
1075      * representation that can be passed in and resolved the usual way.
1076      *
1077      * The port that is passed here is really a string containing the idisplay
1078      * from ConnectDisplay().
1079      */
1080
1081     if (is_numeric (port))
1082     {
1083         tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
1084         sprintf(portbuf,"%u", tmpport );
1085         port = portbuf;
1086     }
1087 #endif
1088
1089     if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
1090     {
1091         prmsg(1, "TLIINETConnect() failed to allocate a t_call\n");
1092         return TRANS_CONNECT_FAILED;
1093     }
1094
1095     if( TRANS(TLIAddrToNetbuf)(ciptr->index, host, port, &(sndcall->addr) ) < 0 )
1096     {
1097         prmsg(1, "TLIINETConnect() unable to resolve name:%s.%s\n",
1098               host, port);
1099         t_free((char *)sndcall,T_CALL);
1100         return TRANS_CONNECT_FAILED;
1101     }
1102
1103     return TRANS(TLIConnect)(ciptr, sndcall );
1104 }
1105
1106
1107 static int
1108 TRANS(TLITLIConnect)(XtransConnInfo ciptr, char *host, char *port)
1109
1110 {
1111     struct t_call       *sndcall;
1112     struct sockaddr_un  *sunaddr;
1113     int                 ret_value;
1114
1115     prmsg(2, "TLITLIConnect(%s,%s)\n", host, port);
1116
1117     if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_OPT|T_UDATA)) == NULL )
1118     {
1119         prmsg(1, "TLITLIConnect() failed to allocate a t_call\n");
1120         return TRANS_CONNECT_FAILED;
1121     }
1122
1123     if( (sunaddr=(struct sockaddr_un *)
1124          malloc(sizeof(struct sockaddr_un))) == NULL )
1125     {
1126         prmsg(1,
1127               "TLITLIConnect: failed to allocate a sockaddr_un\n");
1128         t_free((char *)sndcall,T_CALL);
1129         return TRANS_CONNECT_FAILED;
1130     }
1131
1132     sunaddr->sun_family=AF_UNIX;
1133     if( *port == '/' ||
1134         strncmp (port, TLINODENAME, strlen (TLINODENAME)) == 0) {
1135         /* Use the port as is */
1136         (void) strcpy(sunaddr->sun_path, port);
1137     } else {
1138         (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
1139     }
1140
1141     sndcall->addr.buf=(char *)sunaddr;
1142     sndcall->addr.len=sizeof(*sunaddr);
1143     sndcall->addr.maxlen=sizeof(*sunaddr);
1144
1145     ret_value = TRANS(TLIConnect)(ciptr, sndcall );
1146
1147     free((char *) sunaddr);
1148
1149     return ret_value;
1150 }
1151
1152 #endif /* TRANS_CLIENT */
1153
1154
1155 static int
1156 TRANS(TLIBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend)
1157
1158 {
1159     int ret;
1160     struct pollfd filedes;
1161
1162     prmsg(2, "TLIByteReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend );
1163
1164     /*
1165      * This function should detect hangup conditions. Use poll to check
1166      * if no data is present. On SVR4, the M_HANGUP message sits on the
1167      * streams head, and ioctl(N_READ) keeps returning 0 because there is
1168      * no data available. The hangup goes undetected, and the client hangs.
1169      */
1170
1171     ret=ioctl(ciptr->fd, I_NREAD, (char *)pend);
1172
1173     if( ret != 0 )
1174         return ret; /* Data present or error */
1175
1176
1177     /* Zero data, or POLLHUP message */
1178
1179     filedes.fd=ciptr->fd;
1180     filedes.events=POLLIN;
1181
1182     ret=poll(&filedes, 1, 0);
1183
1184     if( ret == 0 ) {
1185         *pend=0;
1186         return 0; /* Really, no data */
1187         }
1188
1189     if( ret < 0 )
1190         return -1; /* just pass back the error */
1191
1192     if( filedes.revents & (POLLHUP|POLLERR) ) /* check for hangup */
1193         return -1;
1194
1195     /* Should only get here if data arrived after the first ioctl() */
1196     return ioctl(ciptr->fd, I_NREAD, (char *)pend);
1197 }
1198
1199
1200 static int
1201 TRANS(TLIRead)(XtransConnInfo ciptr, char *buf, int size)
1202
1203 {
1204     prmsg(2, "TLIRead(%d,%x,%d)\n", ciptr->fd, buf, size );
1205
1206     return read(ciptr->fd,buf,size);
1207 }
1208
1209
1210 static int
1211 TRANS(TLIWrite)(XtransConnInfo ciptr, char *buf, int size)
1212
1213 {
1214     prmsg(2, "TLIWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
1215
1216     return write(ciptr->fd,buf,size);
1217 }
1218
1219
1220 static int
1221 TRANS(TLIReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
1222
1223 {
1224     prmsg(2, "TLIReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
1225
1226     return READV(ciptr,buf,size);
1227 }
1228
1229
1230 static int
1231 TRANS(TLIWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
1232
1233 {
1234     prmsg(2, "TLIWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
1235
1236     return WRITEV(ciptr,buf,size);
1237 }
1238
1239
1240 static int
1241 TRANS(TLIDisconnect)(XtransConnInfo ciptr)
1242
1243 {
1244     prmsg(2, "TLIDisconnect(%x->%d)\n", ciptr, ciptr->fd);
1245
1246     /*
1247      * Restore the TLI modules so that the connection can be properly shutdown.
1248      * This avoids the situation where a connection goes into the TIME_WAIT
1249      * state, and the address remains unavailable for a while.
1250      */
1251     ioctl(ciptr->fd, I_POP,"tirdwr");
1252     ioctl(ciptr->fd, I_PUSH,"timod");
1253
1254     t_snddis(ciptr->fd,NULL);
1255
1256     return 0;
1257 }
1258
1259
1260 static int
1261 TRANS(TLIClose)(XtransConnInfo ciptr)
1262
1263 {
1264     prmsg(2, "TLIClose(%x->%d)\n", ciptr, ciptr->fd);
1265
1266     t_unbind(ciptr->fd);
1267
1268     return (t_close(ciptr->fd));
1269 }
1270
1271
1272 static int
1273 TRANS(TLICloseForCloning)(XtransConnInfo ciptr)
1274
1275 {
1276     /*
1277      * Don't unbind.
1278      */
1279
1280     prmsg(2, "TLICloseForCloning(%x->%d)\n", ciptr, ciptr->fd);
1281
1282     return (t_close(ciptr->fd));
1283 }
1284
1285
1286 Xtransport      TRANS(TLITCPFuncs) = {
1287         /* TLI Interface */
1288         "tcp",
1289         0,
1290 #ifdef TRANS_CLIENT
1291         TRANS(TLIOpenCOTSClient),
1292 #endif /* TRANS_CLIENT */
1293 #ifdef TRANS_SERVER
1294         NULL,
1295         TRANS(TLIOpenCOTSServer),
1296 #endif /* TRANS_SERVER */
1297 #ifdef TRANS_CLIENT
1298         TRANS(TLIOpenCLTSClient),
1299 #endif /* TRANS_CLIENT */
1300 #ifdef TRANS_SERVER
1301         TRANS(TLIOpenCLTSServer),
1302 #endif /* TRANS_SERVER */
1303 #ifdef TRANS_REOPEN
1304         TRANS(TLIReopenCOTSServer),
1305         TRANS(TLIReopenCLTSServer),
1306 #endif
1307         TRANS(TLISetOption),
1308 #ifdef TRANS_SERVER
1309         TRANS(TLIINETCreateListener),
1310         NULL,                                   /* ResetListener */
1311         TRANS(TLIAccept),
1312 #endif /* TRANS_SERVER */
1313 #ifdef TRANS_CLIENT
1314         TRANS(TLIINETConnect),
1315 #endif /* TRANS_CLIENT */
1316         TRANS(TLIBytesReadable),
1317         TRANS(TLIRead),
1318         TRANS(TLIWrite),
1319         TRANS(TLIReadv),
1320         TRANS(TLIWritev),
1321         TRANS(TLIDisconnect),
1322         TRANS(TLIClose),
1323         TRANS(TLICloseForCloning),
1324 };
1325
1326 #ifdef TRANS_SERVER
1327 static char * inet_aliases[] = { "tcp", NULL };
1328 #endif
1329 Xtransport      TRANS(TLIINETFuncs) = {
1330         /* TLI Interface */
1331         "inet",
1332         TRANS_ALIAS,
1333 #ifdef TRANS_CLIENT
1334         TRANS(TLIOpenCOTSClient),
1335 #endif /* TRANS_CLIENT */
1336 #ifdef TRANS_SERVER
1337         inet_aliases,
1338         TRANS(TLIOpenCOTSServer),
1339 #endif /* TRANS_SERVER */
1340 #ifdef TRANS_CLIENT
1341         TRANS(TLIOpenCLTSClient),
1342 #endif /* TRANS_CLIENT */
1343 #ifdef TRANS_SERVER
1344         TRANS(TLIOpenCLTSServer),
1345 #endif /* TRANS_SERVER */
1346 #ifdef TRANS_REOPEN
1347         TRANS(TLIReopenCOTSServer),
1348         TRANS(TLIReopenCLTSServer),
1349 #endif
1350         TRANS(TLISetOption),
1351 #ifdef TRANS_SERVER
1352         TRANS(TLIINETCreateListener),
1353         NULL,                                   /* ResetListener */
1354         TRANS(TLIAccept),
1355 #endif /* TRANS_SERVER */
1356 #ifdef TRANS_CLIENT
1357         TRANS(TLIINETConnect),
1358 #endif /* TRANS_CLIENT */
1359         TRANS(TLIBytesReadable),
1360         TRANS(TLIRead),
1361         TRANS(TLIWrite),
1362         TRANS(TLIReadv),
1363         TRANS(TLIWritev),
1364         TRANS(TLIDisconnect),
1365         TRANS(TLIClose),
1366         TRANS(TLICloseForCloning),
1367 };
1368
1369 Xtransport      TRANS(TLITLIFuncs) = {
1370         /* TLI Interface */
1371         "tli",
1372         0,
1373 #ifdef TRANS_CLIENT
1374         TRANS(TLIOpenCOTSClient),
1375 #endif /* TRANS_CLIENT */
1376 #ifdef TRANS_SERVER
1377         NULL,
1378         TRANS(TLIOpenCOTSServer),
1379 #endif /* TRANS_SERVER */
1380 #ifdef TRANS_CLIENT
1381         TRANS(TLIOpenCLTSClient),
1382 #endif /* TRANS_CLIENT */
1383 #ifdef TRANS_SERVER
1384         TRANS(TLIOpenCLTSServer),
1385 #endif /* TRANS_SERVER */
1386 #ifdef TRANS_REOPEN
1387         TRANS(TLIReopenCOTSServer),
1388         TRANS(TLIReopenCLTSServer),
1389 #endif
1390         TRANS(TLISetOption),
1391 #ifdef TRANS_SERVER
1392         TRANS(TLITLICreateListener),
1393         NULL,                                   /* ResetListener */
1394         TRANS(TLIAccept),
1395 #endif /* TRANS_SERVER */
1396 #ifdef TRANS_CLIENT
1397         TRANS(TLITLIConnect),
1398 #endif /* TRANS_CLIENT */
1399         TRANS(TLIBytesReadable),
1400         TRANS(TLIRead),
1401         TRANS(TLIWrite),
1402         TRANS(TLIReadv),
1403         TRANS(TLIWritev),
1404         TRANS(TLIDisconnect),
1405         TRANS(TLIClose),
1406         TRANS(TLICloseForCloning),
1407 };