ca04e7f0328fc45967aa4d75ce48ea2595dc22fd
[framework/uifw/xorg/lib/xtrans.git] / Xtranslcl.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 /*
51  *
52  * The connection code/ideas in lib/X and server/os for SVR4/Intel 
53  * environments was contributed by the following companies/groups:
54  *
55  *      MetroLink Inc
56  *      NCR
57  *      Pittsburgh Powercomputing Corporation (PPc)/Quarterdeck Office Systems
58  *      SGCS
59  *      Unix System Laboratories (USL) / Novell
60  *      XFree86
61  *
62  * The goal is to have common connection code among all SVR4/Intel vendors.
63  *
64  * ALL THE ABOVE COMPANIES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 
65  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, 
66  * IN NO EVENT SHALL THESE COMPANIES * BE LIABLE FOR ANY SPECIAL, INDIRECT 
67  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 
68  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
69  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 
70  * OR PERFORMANCE OF THIS SOFTWARE.
71  */
72
73 #include <errno.h>
74 #include <ctype.h>
75 #include <sys/signal.h>
76 #include <sys/ioctl.h>
77 #include <sys/stat.h>
78 #if defined(SVR4) || defined(__SVR4)
79 #include <sys/filio.h>
80 #endif
81 #ifdef sun
82 # include <stropts.h>
83 #else
84 # include <sys/stropts.h>
85 #endif
86 #include <sys/wait.h>
87 #include <sys/types.h>
88
89 /*
90  * The local transports should be treated the same as a UNIX domain socket
91  * wrt authentication, etc. Because of this, we will use struct sockaddr_un
92  * for the address format. This will simplify the code in other places like
93  * The X Server.
94  */
95
96 #include <sys/socket.h>
97 #ifndef X_NO_SYS_UN
98 #include <sys/un.h>
99 #endif
100
101
102 /* Types of local connections supported:
103  *  - PTS
104  *  - named pipes
105  *  - SCO
106  */
107 #if !defined(sun)
108 # define LOCAL_TRANS_PTS
109 #endif
110 #if defined(SVR4) || defined(__SVR4)
111 # define LOCAL_TRANS_NAMED
112 #endif
113 #if defined(__SCO__) || defined(__UNIXWARE__)
114 # define LOCAL_TRANS_SCO
115 #endif
116
117 static int TRANS(LocalClose)(XtransConnInfo ciptr);
118
119 /*
120  * These functions actually implement the local connection mechanisms.
121  */
122
123 /* Type Not Supported */
124
125 static int
126 TRANS(OpenFail)(XtransConnInfo ciptr, char *port)
127
128 {
129     return -1;
130 }
131
132 #ifdef TRANS_REOPEN
133
134 static int
135 TRANS(ReopenFail)(XtransConnInfo ciptr, int fd, char *port)
136
137 {
138     return 0;
139 }
140
141 #endif /* TRANS_REOPEN */
142
143
144 \f
145 static int
146 TRANS(FillAddrInfo)(XtransConnInfo ciptr, char *sun_path, char *peer_sun_path)
147
148 {
149     struct sockaddr_un  *sunaddr;
150     struct sockaddr_un  *p_sunaddr;
151
152     ciptr->family = AF_UNIX;
153     ciptr->addrlen = sizeof (struct sockaddr_un);
154
155     if ((sunaddr = (struct sockaddr_un *) xalloc (ciptr->addrlen)) == NULL)
156     {
157         PRMSG(1,"FillAddrInfo: failed to allocate memory for addr\n", 0, 0, 0);
158         return 0;
159     }
160
161     sunaddr->sun_family = AF_UNIX;
162
163     if (strlen(sun_path) > sizeof(sunaddr->sun_path) - 1) {
164         PRMSG(1, "FillAddrInfo: path too long\n", 0, 0, 0);
165         xfree((char *) sunaddr);
166         return 0;
167     }
168     strcpy (sunaddr->sun_path, sun_path);
169 #if defined(BSD44SOCKETS) 
170     sunaddr->sun_len = strlen (sunaddr->sun_path);
171 #endif
172
173     ciptr->addr = (char *) sunaddr;
174
175     ciptr->peeraddrlen = sizeof (struct sockaddr_un);
176
177     if ((p_sunaddr = (struct sockaddr_un *) xalloc (
178         ciptr->peeraddrlen)) == NULL)
179     {
180         PRMSG(1,
181            "FillAddrInfo: failed to allocate memory for peer addr\n",
182                                                                         0,0,0);
183         xfree ((char *) sunaddr);
184         ciptr->addr = NULL;
185
186         return 0;
187     }
188
189     p_sunaddr->sun_family = AF_UNIX;
190
191     if (strlen(peer_sun_path) > sizeof(p_sunaddr->sun_path) - 1) {
192         PRMSG(1, "FillAddrInfo: peer path too long\n", 0, 0, 0);
193         xfree((char *) p_sunaddr);
194         return 0;
195     }
196     strcpy (p_sunaddr->sun_path, peer_sun_path);
197 #if defined(BSD44SOCKETS) 
198     p_sunaddr->sun_len = strlen (p_sunaddr->sun_path);
199 #endif
200
201     ciptr->peeraddr = (char *) p_sunaddr;
202
203     return 1;
204 }
205
206
207 \f
208 #ifdef LOCAL_TRANS_PTS
209 /* PTS */
210
211 #if defined(SYSV) && !defined(__SCO__) 
212 #define SIGNAL_T int
213 #else
214 #define SIGNAL_T void
215 #endif /* SYSV */
216
217 typedef SIGNAL_T (*PFV)();
218
219 extern PFV signal();
220
221 extern char *ptsname(
222     int
223 );
224
225 static void _dummy(int sig)
226
227 {
228 }
229 #endif /* LOCAL_TRANS_PTS */
230
231 #ifndef sun
232 #define X_STREAMS_DIR   "/dev/X"
233 #define DEV_SPX         "/dev/spx"
234 #else
235 #ifndef X11_t
236 #define X_STREAMS_DIR   "/dev/X"
237 #else
238 #define X_STREAMS_DIR   "/tmp/.X11-pipe"
239 #endif
240 #endif
241
242 #define DEV_PTMX        "/dev/ptmx"
243
244 #if defined(X11_t)
245
246 #define PTSNODENAME "/dev/X/server."
247 #ifdef sun
248 #define NAMEDNODENAME "/tmp/.X11-pipe/X"
249 #else
250 #define NAMEDNODENAME "/dev/X/Nserver."
251
252 #define SCORNODENAME    "/dev/X%1sR"
253 #define SCOSNODENAME    "/dev/X%1sS"
254 #endif /* !sun */
255 #endif
256 #if defined(XIM_t)
257 #ifdef sun
258 #define NAMEDNODENAME "/tmp/.XIM-pipe/XIM"
259 #else
260 #define PTSNODENAME     "/dev/X/XIM."
261 #define NAMEDNODENAME   "/dev/X/NXIM."
262 #define SCORNODENAME    "/dev/XIM.%sR"
263 #define SCOSNODENAME    "/dev/XIM.%sS"
264 #endif
265 #endif
266 #if defined(FS_t) || defined (FONT_t)
267 #ifdef sun
268 #define NAMEDNODENAME   "/tmp/.font-pipe/fs"
269 #else
270 /*
271  * USL has already defined something here. We need to check with them
272  * and see if their choice is usable here.
273  */
274 #define PTSNODENAME     "/dev/X/fontserver."
275 #define NAMEDNODENAME   "/dev/X/Nfontserver."
276 #define SCORNODENAME    "/dev/fontserver.%sR"
277 #define SCOSNODENAME    "/dev/fontserver.%sS"
278 #endif
279 #endif
280 #if defined(ICE_t)
281 #ifdef sun
282 #define NAMEDNODENAME   "/tmp/.ICE-pipe/"
283 #else
284 #define PTSNODENAME     "/dev/X/ICE."
285 #define NAMEDNODENAME   "/dev/X/NICE."
286 #define SCORNODENAME    "/dev/ICE.%sR"
287 #define SCOSNODENAME    "/dev/ICE.%sS"
288 #endif
289 #endif
290 #if defined(TEST_t)
291 #ifdef sun
292 #define NAMEDNODENAME   "/tmp/.Test-unix/test"
293 #endif
294 #define PTSNODENAME     "/dev/X/transtest."
295 #define NAMEDNODENAME   "/dev/X/Ntranstest."
296 #define SCORNODENAME    "/dev/transtest.%sR"
297 #define SCOSNODENAME    "/dev/transtest.%sS"
298 #endif
299
300
301 \f
302 #ifdef LOCAL_TRANS_PTS
303 #ifdef TRANS_CLIENT
304
305 static int
306 TRANS(PTSOpenClient)(XtransConnInfo ciptr, char *port)
307
308 {
309 #ifdef PTSNODENAME
310     int                 fd,server,exitval,alarm_time,ret;
311     char                server_path[64];
312     char                *slave, namelen;
313     char                buf[20]; /* MAX_PATH_LEN?? */
314     PFV                 savef;
315     pid_t               saved_pid;
316 #endif
317
318     PRMSG(2,"PTSOpenClient(%s)\n", port, 0,0 );
319
320 #if !defined(PTSNODENAME)
321     PRMSG(1,"PTSOpenClient: Protocol is not supported by a pts connection\n", 0,0,0);
322     return -1;
323 #else
324     if (port && *port ) {
325         if( *port == '/' ) { /* A full pathname */
326                 (void) sprintf(server_path, "%s", port);
327             } else {
328                 (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
329             }
330     } else {
331         (void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
332     }
333
334
335     /*
336      * Open the node the on which the server is listening.
337      */
338
339     if ((server = open (server_path, O_RDWR)) < 0) {
340         PRMSG(1,"PTSOpenClient: failed to open %s\n", server_path, 0,0);
341         return -1;
342     }
343
344
345     /*
346      * Open the streams based pipe that will be this connection.
347      */
348
349     if ((fd = open(DEV_PTMX, O_RDWR)) < 0) {
350         PRMSG(1,"PTSOpenClient: failed to open %s\n", DEV_PTMX, 0,0);
351         close(server);
352         return(-1);
353     }
354
355     (void) grantpt(fd);
356     (void) unlockpt(fd);
357
358     slave = ptsname(fd); /* get name */
359
360     if( slave == NULL ) {
361         PRMSG(1,"PTSOpenClient: failed to get ptsname()\n", 0,0,0);
362         close(fd);
363         close(server);
364         return -1;
365     }
366
367     /*
368      * This is neccesary for the case where a program is setuid to non-root.
369      * grantpt() calls /usr/lib/pt_chmod which is set-uid root. This program will
370      * set the owner of the pt device incorrectly if the uid is not restored
371      * before it is called. The problem is that once it gets restored, it
372      * cannot be changed back to its original condition, hence the fork().
373      */
374
375     if(!(saved_pid=fork())) {
376         uid_t       saved_euid;
377
378         saved_euid = geteuid();
379         /** sets the euid to the actual/real uid **/
380         if (setuid( getuid() ) == -1) {
381                 exit(1);
382         }
383         if( chown( slave, saved_euid, -1 ) < 0 ) {
384                 exit( 1 );
385                 }
386
387         exit( 0 );
388     }
389
390     waitpid(saved_pid, &exitval, 0);
391     if (WIFEXITED(exitval) && WEXITSTATUS(exitval) != 0) {
392         close(fd);
393         close(server);
394         PRMSG(1, "PTSOpenClient: cannot set the owner of %s\n",
395               slave, 0, 0);
396         return(-1);
397     }
398     if (chmod(slave, 0666) < 0) {
399         close(fd);
400         close(server);
401         PRMSG(1,"PTSOpenClient: Cannot chmod %s\n", slave, 0,0);
402         return(-1);
403     }
404
405     /*
406      * write slave name to server
407      */
408
409     namelen = strlen(slave);
410     buf[0] = namelen;
411     (void) sprintf(&buf[1], slave);
412     (void) write(server, buf, namelen+1);
413     (void) close(server);
414
415     /*
416      * wait for server to respond
417      */
418
419     savef = signal(SIGALRM, _dummy);
420     alarm_time = alarm (30); /* CONNECT_TIMEOUT */
421
422     ret = read(fd, buf, 1);
423
424     (void) alarm(alarm_time);
425     (void) signal(SIGALRM, savef);
426
427     if (ret != 1) {
428         PRMSG(1,
429         "PTSOpenClient: failed to get acknoledgement from server\n", 0, 0, 0);
430         (void) close(fd);
431         fd = -1;
432     }
433
434     /*
435      * Everything looks good: fill in the XtransConnInfo structure.
436      */
437
438     if (TRANS(FillAddrInfo) (ciptr, slave, server_path) == 0)
439     {
440         PRMSG(1,"PTSOpenClient: failed to fill in addr info\n", 0, 0, 0);
441         close(fd);
442         return -1;
443     }
444
445     return(fd);
446
447 #endif /* !PTSNODENAME */
448 }
449
450 #endif /* TRANS_CLIENT */
451
452
453 #ifdef TRANS_SERVER
454
455 static int
456 TRANS(PTSOpenServer)(XtransConnInfo ciptr, char *port)
457
458 {
459 #ifdef PTSNODENAME
460     int fd, server;
461     char server_path[64], *slave;
462     int mode;
463 #endif
464
465     PRMSG(2,"PTSOpenServer(%s)\n", port, 0,0 );
466
467 #if !defined(PTSNODENAME)
468     PRMSG(1,"PTSOpenServer: Protocol is not supported by a pts connection\n", 0,0,0);
469     return -1;
470 #else
471     if (port && *port ) {
472         if( *port == '/' ) { /* A full pathname */
473                 (void) sprintf(server_path, "%s", port);
474             } else {
475                 (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
476             }
477     } else {
478         (void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
479     }
480
481 #ifdef HAS_STICKY_DIR_BIT
482     mode = 01777;
483 #else
484     mode = 0777;
485 #endif
486     if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
487         PRMSG (1, "PTSOpenServer: mkdir(%s) failed, errno = %d\n",
488                X_STREAMS_DIR, errno, 0);
489         return(-1);
490     }
491
492 #if 0
493     if( (fd=open(server_path, O_RDWR)) >= 0 ) {
494         /*
495          * This doesn't prevent the server from starting up, and doesn't
496          * prevent clients from trying to connect to the in-use PTS (which
497          * is often in use by something other than another server).
498          */
499         PRMSG(1, "PTSOpenServer: A server is already running on port %s\n", port, 0,0 );
500         PRMSG(1, "PTSOpenServer: Remove %s if this is incorrect.\n", server_path, 0,0 );
501         close(fd);
502         return(-1);
503     }
504 #else
505     /* Just remove the old path (which is what happens with UNIXCONN) */
506 #endif
507
508     unlink(server_path);
509
510     if( (fd=open(DEV_PTMX, O_RDWR)) < 0) {
511         PRMSG(1, "PTSOpenServer: Unable to open %s\n", DEV_PTMX, 0,0 );
512         return(-1);
513     }
514
515     grantpt(fd);
516     unlockpt(fd);
517
518     if( (slave=ptsname(fd)) == NULL) {
519         PRMSG(1, "PTSOpenServer: Unable to get slave device name\n", 0,0,0 );
520         close(fd);
521         return(-1);
522     }
523
524     if( link(slave,server_path) < 0 ) {
525         PRMSG(1, "PTSOpenServer: Unable to link %s to %s\n", slave, server_path,0 );
526         close(fd);
527         return(-1);
528     }
529
530     if( chmod(server_path, 0666) < 0 ) {
531         PRMSG(1, "PTSOpenServer: Unable to chmod %s to 0666\n", server_path,0,0 );
532         close(fd);
533         return(-1);
534     }
535
536     if( (server=open(server_path, O_RDWR)) < 0 ) {
537         PRMSG(1, "PTSOpenServer: Unable to open server device %s\n", server_path,0,0 );
538         close(fd);
539         return(-1);
540     }
541
542     close(server);
543
544     /*
545      * Everything looks good: fill in the XtransConnInfo structure.
546      */
547
548     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
549     {
550         PRMSG(1,"PTSOpenServer: failed to fill in addr info\n", 0, 0, 0);
551         close(fd);
552         return -1;
553     }
554
555     return fd;
556
557 #endif /* !PTSNODENAME */
558 }
559
560 static int
561 TRANS(PTSAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
562
563 {
564     int                 newfd;
565     int                 in;
566     unsigned char       length;
567     char                buf[256];
568     struct sockaddr_un  *sunaddr;
569
570     PRMSG(2,"PTSAccept(%x->%d)\n",ciptr,ciptr->fd,0);
571
572     if( (in=read(ciptr->fd,&length,1)) <= 0 ){
573         if( !in ) {
574                 PRMSG(2,
575                 "PTSAccept: Incoming connection closed\n",0,0,0);
576                 }
577         else {
578                 PRMSG(1,
579         "PTSAccept: Error reading incoming connection. errno=%d \n",
580                                                                 errno,0,0);
581                 }
582         *status = TRANS_ACCEPT_MISC_ERROR;
583         return -1;
584     }
585
586     if( (in=read(ciptr->fd,buf,length)) <= 0 ){
587         if( !in ) {
588                 PRMSG(2,
589                 "PTSAccept: Incoming connection closed\n",0,0,0);
590                 }
591         else {
592                 PRMSG(1,
593 "PTSAccept: Error reading device name for new connection. errno=%d \n",
594                                                                 errno,0,0);
595                 }
596         *status = TRANS_ACCEPT_MISC_ERROR;
597         return -1;
598     }
599
600     buf[length] = '\0';
601
602     if( (newfd=open(buf,O_RDWR)) < 0 ) {
603         PRMSG(1, "PTSAccept: Failed to open %s\n",buf,0,0);
604         *status = TRANS_ACCEPT_MISC_ERROR;
605         return -1;
606     }
607
608     write(newfd,"1",1);
609
610     /*
611      * Everything looks good: fill in the XtransConnInfo structure.
612      */
613
614     newciptr->addrlen=ciptr->addrlen;
615     if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
616         PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
617                                                                         0,0,0);
618         close(newfd);
619         *status = TRANS_ACCEPT_BAD_MALLOC;
620         return -1;
621     }
622
623     memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
624
625     newciptr->peeraddrlen=sizeof(struct sockaddr_un);
626     if( (sunaddr=(struct sockaddr_un *)xalloc(newciptr->peeraddrlen)) == NULL ) {
627         PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
628                                                                         0,0,0);
629         xfree(newciptr->addr);
630         close(newfd);
631         *status = TRANS_ACCEPT_BAD_MALLOC;
632         return -1;
633     }
634
635     sunaddr->sun_family=AF_UNIX;
636     strcpy(sunaddr->sun_path,buf);
637 #if defined(BSD44SOCKETS) 
638     sunaddr->sun_len=strlen(sunaddr->sun_path);
639 #endif
640
641     newciptr->peeraddr=(char *)sunaddr;
642
643     *status = 0;
644
645     return newfd;
646 }
647
648 #endif /* TRANS_SERVER */
649 #endif /* LOCAL_TRANS_PTS */
650
651 \f
652 #ifdef LOCAL_TRANS_NAMED
653
654 /* NAMED */
655
656 #ifdef TRANS_CLIENT
657
658 static int
659 TRANS(NAMEDOpenClient)(XtransConnInfo ciptr, char *port)
660
661 {
662 #ifdef NAMEDNODENAME
663     int                 fd;
664     char                server_path[64];
665     struct stat         filestat;
666 # ifndef sun    
667     extern int          isastream(int);
668 # endif
669 #endif
670
671     PRMSG(2,"NAMEDOpenClient(%s)\n", port, 0,0 );
672
673 #if !defined(NAMEDNODENAME)
674     PRMSG(1,"NAMEDOpenClient: Protocol is not supported by a NAMED connection\n", 0,0,0);
675     return -1;
676 #else
677     if ( port && *port ) {
678         if( *port == '/' ) { /* A full pathname */
679                 (void) snprintf(server_path, sizeof(server_path), "%s", port);
680             } else {
681                 (void) snprintf(server_path, sizeof(server_path), "%s%s", NAMEDNODENAME, port);
682             }
683     } else {
684         (void) snprintf(server_path, sizeof(server_path), "%s%ld", NAMEDNODENAME, (long)getpid());
685     }
686
687     if ((fd = open(server_path, O_RDWR)) < 0) {
688         PRMSG(1,"NAMEDOpenClient: Cannot open %s for NAMED connection\n", server_path, 0,0 );
689         return -1;
690     }
691
692     if (fstat(fd, &filestat) < 0 ) {
693         PRMSG(1,"NAMEDOpenClient: Cannot stat %s for NAMED connection\n", server_path, 0,0 );
694         (void) close(fd);
695         return -1;
696     }
697
698     if ((filestat.st_mode & S_IFMT) != S_IFIFO) {
699         PRMSG(1,"NAMEDOpenClient: Device %s is not a FIFO\n", server_path, 0,0 );
700         /* Is this really a failure? */
701         (void) close(fd);       
702         return -1;
703     }
704
705
706     if (isastream(fd) <= 0) {
707         PRMSG(1,"NAMEDOpenClient: %s is not a streams device\n", server_path, 0,0 );
708         (void) close(fd);
709         return -1;
710     }
711
712     /*
713      * Everything looks good: fill in the XtransConnInfo structure.
714      */
715
716     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
717     {
718         PRMSG(1,"NAMEDOpenClient: failed to fill in addr info\n",
719                                                                 0,0,0);
720         close(fd);
721         return -1;
722     }
723
724     return(fd);
725
726 #endif /* !NAMEDNODENAME */
727 }
728
729 #endif /* TRANS_CLIENT */
730
731
732 #ifdef TRANS_SERVER
733
734
735 #ifdef NAMEDNODENAME
736 static int
737 TRANS(NAMEDOpenPipe)(const char *server_path)
738 {
739     PRMSG(2,"NAMEDOpenPipe(%s)\n", server_path, 0,0 );
740
741     int                 fd, pipefd[2];
742     struct stat         sbuf;
743     int                 mode;
744     
745 #if defined(sun) && defined(X11_t)
746     mode = 0775;        /* Solaris requires uid or gid 0 to create X11 pipes */
747 #else    
748 #ifdef HAS_STICKY_DIR_BIT
749     mode = 01777;
750 #else
751     mode = 0777;
752 #endif
753 #endif
754     if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
755         PRMSG (1, "NAMEDOpenPipe: mkdir(%s) failed, errno = %d\n",
756                X_STREAMS_DIR, errno, 0);
757         return(-1);
758     }
759
760     if(stat(server_path, &sbuf) != 0) {
761         if (errno == ENOENT) {
762             if ((fd = creat(server_path, (mode_t)0666)) == -1) {
763                 PRMSG(1, "NAMEDOpenPipe: Can't open %s\n", server_path, 0,0 );
764                 return(-1);
765             }
766             close(fd);
767             if (chmod(server_path, (mode_t)0666) < 0) {
768                 PRMSG(1, "NAMEDOpenPipe: Can't open %s\n", server_path, 0,0 );
769                 return(-1);
770             }
771         } else {
772             PRMSG(1, "NAMEDOpenPipe: stat on %s failed\n", server_path, 0,0 );
773             return(-1);
774         }
775     }
776
777     if( pipe(pipefd) != 0) {
778         PRMSG(1, "NAMEDOpenPipe: pipe() failed, errno=%d\n",errno, 0,0 );
779         return(-1);
780     }
781
782     if( ioctl(pipefd[0], I_PUSH, "connld") != 0) {
783         PRMSG(1, "NAMEDOpenPipe: ioctl(I_PUSH,\"connld\") failed, errno=%d\n",errno, 0,0 );
784         close(pipefd[0]);
785         close(pipefd[1]);
786         return(-1);
787     }
788
789     if( fattach(pipefd[0], server_path) != 0) {
790         PRMSG(1, "NAMEDOpenPipe: fattach(%s) failed, errno=%d\n", server_path,errno, 0 );
791         close(pipefd[0]);
792         close(pipefd[1]);
793         return(-1);
794     }
795
796     return(pipefd[1]);
797 }
798 #endif
799
800 static int
801 TRANS(NAMEDOpenServer)(XtransConnInfo ciptr, char *port)
802 {
803 #ifdef NAMEDNODENAME
804     int                 fd;
805     char                server_path[64];
806 #endif
807
808     PRMSG(2,"NAMEDOpenServer(%s)\n", port, 0,0 );
809
810 #if !defined(NAMEDNODENAME)
811     PRMSG(1,"NAMEDOpenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
812     return -1;
813 #else
814     if ( port && *port ) {
815         if( *port == '/' ) { /* A full pathname */
816             (void) snprintf(server_path, sizeof(server_path), "%s", port);
817         } else {
818             (void) snprintf(server_path, sizeof(server_path), "%s%s",
819                             NAMEDNODENAME, port);
820         }
821     } else {
822         (void) snprintf(server_path, sizeof(server_path), "%s%ld",
823                        NAMEDNODENAME, (long)getpid());
824     }
825
826     fd = TRANS(NAMEDOpenPipe)(server_path);
827     if (fd < 0) {
828         return -1;
829     }
830     
831     /*
832      * Everything looks good: fill in the XtransConnInfo structure.
833      */
834
835     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
836     {
837         PRMSG(1,"NAMEDOpenServer: failed to fill in addr info\n", 0,0,0);
838         TRANS(LocalClose)(ciptr);
839         return -1;
840     }
841
842     return fd;
843
844 #endif /* !NAMEDNODENAME */
845 }
846
847 static int
848 TRANS(NAMEDResetListener) (XtransConnInfo ciptr)
849
850 {
851   int status = TRANS_RESET_NOOP;
852   struct sockaddr_un      *sockname=(struct sockaddr_un *) ciptr->addr;
853   struct stat     statb;
854   
855   PRMSG(2,"NAMEDResetListener(%p, %d)\n", ciptr, ciptr->fd, 0 );
856   
857   if (ciptr->fd != -1) {
858     /*
859      * see if the pipe has disappeared
860      */
861
862     if (stat (sockname->sun_path, &statb) == -1 ||
863         (statb.st_mode & S_IFMT) != S_IFIFO) {
864       PRMSG(3, "Pipe %s trashed, recreating\n", sockname->sun_path, 0, 0);
865       TRANS(LocalClose)(ciptr);
866       ciptr->fd = TRANS(NAMEDOpenPipe)(sockname->sun_path);
867       if (ciptr->fd >= 0)
868           return TRANS_RESET_NEW_FD;
869       else
870           return TRANS_CREATE_LISTENER_FAILED;
871     }
872   }
873   return TRANS_RESET_NOOP;
874 }
875
876 static int
877 TRANS(NAMEDAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
878
879 {
880     struct strrecvfd str;
881
882     PRMSG(2,"NAMEDAccept(%x->%d)\n", ciptr, ciptr->fd, 0 );
883
884     if( ioctl(ciptr->fd, I_RECVFD, &str ) < 0 ) {
885         PRMSG(1, "NAMEDAccept: ioctl(I_RECVFD) failed, errno=%d\n", errno, 0,0 );
886         *status = TRANS_ACCEPT_MISC_ERROR;
887         return(-1);
888     }
889
890     /*
891      * Everything looks good: fill in the XtransConnInfo structure.
892      */
893     newciptr->family=ciptr->family;
894     newciptr->addrlen=ciptr->addrlen;
895     if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
896         PRMSG(1,
897               "NAMEDAccept: failed to allocate memory for pipe addr\n",
898                                                                         0,0,0);
899         close(str.fd);
900         *status = TRANS_ACCEPT_BAD_MALLOC;
901         return -1;
902     }
903
904     memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
905
906     newciptr->peeraddrlen=newciptr->addrlen;
907     if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
908         PRMSG(1,
909         "NAMEDAccept: failed to allocate memory for peer addr\n",
910                                                                         0,0,0);
911         xfree(newciptr->addr);
912         close(str.fd);
913         *status = TRANS_ACCEPT_BAD_MALLOC;
914         return -1;
915     }
916
917     memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
918
919     *status = 0;
920
921     return str.fd;
922 }
923
924 #endif /* TRANS_SERVER */
925
926 #endif /* LOCAL_TRANS_NAMED */
927
928
929 \f
930 #if defined(LOCAL_TRANS_SCO)
931
932 /*
933  * connect_spipe is used by the SCO connection type.
934  */
935 static int
936 connect_spipe(int fd1, int fd2)
937 {
938     long temp;
939     struct strfdinsert sbuf;
940
941     sbuf.databuf.maxlen = -1;
942     sbuf.databuf.len = -1;
943     sbuf.databuf.buf = NULL;
944     sbuf.ctlbuf.maxlen = sizeof(long);
945     sbuf.ctlbuf.len = sizeof(long);
946     sbuf.ctlbuf.buf = (caddr_t)&temp;
947     sbuf.offset = 0;
948     sbuf.fildes = fd2;
949     sbuf.flags = 0;
950
951     if( ioctl(fd1, I_FDINSERT, &sbuf) < 0 )
952         return(-1);
953
954     return(0);
955 }
956
957 /*
958  * named_spipe is used by the SCO connection type.
959  */
960
961 static int
962 named_spipe(int fd, char *path)
963
964 {
965     int oldUmask, ret;
966     struct stat sbuf;
967
968     oldUmask = umask(0);
969
970     (void) fstat(fd, &sbuf);
971     ret = mknod(path, 0020666, sbuf.st_rdev);
972
973     umask(oldUmask);
974
975     if (ret < 0) {
976         ret = -1;
977     } else {
978         ret = fd;
979     }
980
981     return(ret);
982 }
983
984 #endif /* defined(LOCAL_TRANS_SCO) */
985
986
987
988 \f
989 #ifdef LOCAL_TRANS_SCO
990 /* SCO */
991
992 /*
993  * 2002-11-09 (jkj@sco.com)
994  *
995  * This code has been modified to match what is in the actual SCO X server.
996  * This greatly helps inter-operability between X11R6 and X11R5 (the native
997  * SCO server). Mainly, it relies on streams nodes existing in /dev, not
998  * creating them or unlinking them, which breaks the native X server.
999  *
1000  * However, this is only for the X protocol. For all other protocols, we
1001  * do in fact create the nodes, as only X11R6 will use them, and this makes
1002  * it possible to have both types of clients running, otherwise we get all
1003  * kinds of nasty errors on startup for anything that doesnt use the X
1004  * protocol (like SM, when KDE starts up).
1005  */
1006
1007 #ifdef TRANS_CLIENT
1008
1009 static int
1010 TRANS(SCOOpenClient)(XtransConnInfo ciptr, char *port)
1011 {
1012 #ifdef SCORNODENAME
1013     int                 fd, server, fl, ret;
1014     char                server_path[64];
1015     struct strbuf       ctlbuf;
1016     unsigned long       alarm_time;
1017     void                (*savef)();
1018     long                temp;
1019     extern int  getmsg(), putmsg();
1020 #endif
1021
1022     PRMSG(2,"SCOOpenClient(%s)\n", port, 0,0 );
1023     if (!port || !port[0])
1024         port = "0";
1025
1026 #if !defined(SCORNODENAME)
1027     PRMSG(2,"SCOOpenClient: Protocol is not supported by a SCO connection\n", 0,0,0);
1028     return -1;
1029 #else
1030     (void) sprintf(server_path, SCORNODENAME, port);
1031
1032     if ((server = open(server_path, O_RDWR)) < 0) {
1033         PRMSG(1,"SCOOpenClient: failed to open %s\n", server_path, 0,0 );
1034         return -1;
1035     }
1036
1037     if ((fd = open(DEV_SPX, O_RDWR)) < 0) {
1038         PRMSG(1,"SCOOpenClient: failed to open %s\n", DEV_SPX, 0,0 );
1039         close(server);
1040         return -1;
1041     }
1042
1043     (void) write(server, &server, 1);
1044     ctlbuf.len = 0;
1045     ctlbuf.maxlen = sizeof(long);
1046     ctlbuf.buf = (caddr_t)&temp;
1047     fl = 0;
1048
1049     savef = signal(SIGALRM, _dummy);
1050     alarm_time = alarm(10);
1051
1052     ret = getmsg(server, &ctlbuf, 0, &fl);
1053
1054     (void) alarm(alarm_time);
1055     (void) signal(SIGALRM, savef);
1056
1057     if (ret < 0) {
1058         PRMSG(1,"SCOOpenClient: error from getmsg\n", 0,0,0 );
1059         close(fd);
1060         close(server);
1061         return -1;
1062     }
1063
1064     /* The msg we got via getmsg is the result of an
1065      * I_FDINSERT, so if we do a putmsg with whatever
1066      * we recieved, we're doing another I_FDINSERT ...
1067      */
1068     (void) putmsg(fd, &ctlbuf, 0, 0);
1069     (void) fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NDELAY);
1070
1071     (void) close(server);
1072
1073     /*
1074      * Everything looks good: fill in the XtransConnInfo structure.
1075      */
1076
1077 #if defined(X11_t) && defined(__SCO__)
1078     ciptr->flags |= TRANS_NOUNLINK;
1079 #endif
1080     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
1081     {
1082         PRMSG(1,"SCOOpenClient: failed to fill addr info\n", 0, 0, 0);
1083         close(fd);
1084         return -1;
1085     }
1086
1087     return(fd);
1088
1089 #endif  /* !SCORNODENAME */
1090 }
1091
1092 #endif /* TRANS_CLIENT */
1093
1094
1095 #ifdef TRANS_SERVER
1096
1097 static int
1098 TRANS(SCOOpenServer)(XtransConnInfo ciptr, char *port)
1099 {
1100 #ifdef SCORNODENAME
1101     char                serverR_path[64];
1102     char                serverS_path[64];
1103     struct flock        mylock;
1104     int                 fdr = -1;
1105     int                 fds = -1;
1106 #endif
1107
1108     PRMSG(2,"SCOOpenServer(%s)\n", port, 0,0 );
1109     if (!port || !port[0])
1110         port = "0";
1111
1112 #if !defined(SCORNODENAME)
1113     PRMSG(1,"SCOOpenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
1114     return -1;
1115 #else
1116     (void) sprintf(serverR_path, SCORNODENAME, port);
1117     (void) sprintf(serverS_path, SCOSNODENAME, port);
1118
1119 #if !defined(X11_t) || !defined(__SCO__)
1120     unlink(serverR_path);
1121     unlink(serverS_path);
1122
1123     if ((fds = open(DEV_SPX, O_RDWR)) < 0 ||
1124         (fdr = open(DEV_SPX, O_RDWR)) < 0 ) {
1125         PRMSG(1,"SCOOpenServer: failed to open %s\n", DEV_SPX, 0,0 );
1126         if (fds >= 0)
1127                 close(fds);
1128         if (fdr >= 0)
1129                 close(fdr);
1130         return -1;
1131     }
1132
1133     if (named_spipe (fds, serverS_path) == -1) {
1134         PRMSG(1,"SCOOpenServer: failed to create %s\n", serverS_path, 0, 0);
1135         close (fdr);
1136         close (fds);
1137         return -1;
1138     }
1139
1140     if (named_spipe (fdr, serverR_path) == -1) {
1141         PRMSG(1,"SCOOpenServer: failed to create %s\n", serverR_path, 0, 0);
1142         close (fdr);
1143         close (fds);
1144         return -1;
1145     }
1146 #else /* X11_t */
1147
1148     fds = open (serverS_path, O_RDWR | O_NDELAY);
1149     if (fds < 0) {
1150         PRMSG(1,"SCOOpenServer: failed to open %s\n", serverS_path, 0, 0);
1151         return -1;
1152     }
1153
1154     /*
1155      * Lock the connection device for the duration of the server.
1156      * This resolves multiple server starts especially on SMP machines.
1157      */
1158     mylock.l_type       = F_WRLCK;
1159     mylock.l_whence     = 0;
1160     mylock.l_start      = 0;
1161     mylock.l_len        = 0;
1162     if (fcntl (fds, F_SETLK, &mylock) < 0) {
1163         PRMSG(1,"SCOOpenServer: failed to lock %s\n", serverS_path, 0, 0);
1164         close (fds);
1165         return -1;
1166     }
1167
1168     fdr = open (serverR_path, O_RDWR | O_NDELAY);
1169     if (fdr < 0) {
1170         PRMSG(1,"SCOOpenServer: failed to open %s\n", serverR_path, 0, 0);
1171         close (fds);
1172         return -1;
1173     }
1174 #endif /* X11_t */
1175
1176     if (connect_spipe(fds, fdr)) {
1177         PRMSG(1,"SCOOpenServer: ioctl(I_FDINSERT) failed on %s\n",
1178               serverS_path, 0, 0);
1179         close (fdr);
1180         close (fds);
1181         return -1;
1182     }
1183
1184     /*
1185      * Everything looks good: fill in the XtransConnInfo structure.
1186      */
1187
1188 #if defined(X11_t) && defined(__SCO__)
1189     ciptr->flags |= TRANS_NOUNLINK;
1190 #endif
1191     if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0) {
1192         PRMSG(1,"SCOOpenServer: failed to fill in addr info\n", 0,0,0);
1193         close(fds);
1194         close(fdr);
1195         return -1;
1196     }
1197
1198     return(fds);
1199
1200 #endif /* !SCORNODENAME */
1201 }
1202
1203 static int
1204 TRANS(SCOAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
1205 {
1206     char                c;
1207     int                 fd;
1208
1209     PRMSG(2,"SCOAccept(%d)\n", ciptr->fd, 0,0 );
1210
1211     if (read(ciptr->fd, &c, 1) < 0) {
1212         PRMSG(1,"SCOAccept: can't read from client\n",0,0,0);
1213         *status = TRANS_ACCEPT_MISC_ERROR;
1214         return(-1);
1215     }
1216
1217     if( (fd = open(DEV_SPX, O_RDWR)) < 0 ) {
1218         PRMSG(1,"SCOAccept: can't open \"%s\"\n",DEV_SPX, 0,0 );
1219         *status = TRANS_ACCEPT_MISC_ERROR;
1220         return(-1);
1221     }
1222
1223     if (connect_spipe (ciptr->fd, fd) < 0) {
1224         PRMSG(1,"SCOAccept: ioctl(I_FDINSERT) failed\n", 0, 0, 0);
1225         close (fd);
1226         *status = TRANS_ACCEPT_MISC_ERROR;
1227         return -1;
1228     }
1229
1230     /*
1231      * Everything looks good: fill in the XtransConnInfo structure.
1232      */
1233
1234     newciptr->addrlen=ciptr->addrlen;
1235     if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
1236         PRMSG(1,
1237               "SCOAccept: failed to allocate memory for peer addr\n",
1238               0,0,0);
1239         close(fd);
1240         *status = TRANS_ACCEPT_BAD_MALLOC;
1241         return -1;
1242     }
1243
1244     memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
1245 #if defined(__SCO__)
1246     newciptr->flags |= TRANS_NOUNLINK;
1247 #endif
1248
1249     newciptr->peeraddrlen=newciptr->addrlen;
1250     if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
1251         PRMSG(1,
1252               "SCOAccept: failed to allocate memory for peer addr\n",
1253               0,0,0);
1254         xfree(newciptr->addr);
1255         close(fd);
1256         *status = TRANS_ACCEPT_BAD_MALLOC;
1257         return -1;
1258     }
1259
1260     memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
1261
1262     *status = 0;
1263
1264     return(fd);
1265 }
1266
1267 #endif /* TRANS_SERVER */
1268 #endif /* LOCAL_TRANS_SCO */
1269
1270
1271 \f
1272 #ifdef TRANS_REOPEN
1273 #ifdef LOCAL_TRANS_PTS
1274
1275 static int
1276 TRANS(PTSReopenServer)(XtransConnInfo ciptr, int fd, char *port)
1277
1278 {
1279 #ifdef PTSNODENAME
1280     char server_path[64];
1281 #endif
1282
1283     PRMSG(2,"PTSReopenServer(%d,%s)\n", fd, port, 0 );
1284
1285 #if !defined(PTSNODENAME)
1286     PRMSG(1,"PTSReopenServer: Protocol is not supported by a pts connection\n", 0,0,0);
1287     return 0;
1288 #else
1289     if (port && *port ) {
1290         if( *port == '/' ) { /* A full pathname */
1291                 (void) sprintf(server_path, "%s", port);
1292             } else {
1293                 (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
1294             }
1295     } else {
1296         (void) sprintf(server_path, "%s%ld", PTSNODENAME, (long)getpid());
1297     }
1298
1299     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
1300     {
1301         PRMSG(1,"PTSReopenServer: failed to fill in addr info\n",
1302                                                                 0,0,0);
1303         return 0;
1304     }
1305
1306     return 1;
1307
1308 #endif /* !PTSNODENAME */
1309 }
1310
1311 #endif /* LOCAL_TRANS_PTS */
1312
1313 #ifdef LOCAL_TRANS_NAMED
1314
1315 static int
1316 TRANS(NAMEDReopenServer)(XtransConnInfo ciptr, int fd, char *port)
1317
1318 {
1319 #ifdef NAMEDNODENAME
1320     char server_path[64];
1321 #endif
1322
1323     PRMSG(2,"NAMEDReopenServer(%s)\n", port, 0,0 );
1324
1325 #if !defined(NAMEDNODENAME)
1326     PRMSG(1,"NAMEDReopenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
1327     return 0;
1328 #else
1329     if ( port && *port ) {
1330         if( *port == '/' ) { /* A full pathname */
1331             (void) sprintf(server_path, "%s", port);
1332         } else {
1333             (void) sprintf(server_path, "%s%s", NAMEDNODENAME, port);
1334         }
1335     } else {
1336         (void) sprintf(server_path, "%s%ld", NAMEDNODENAME, (long)getpid());
1337     }
1338
1339     if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
1340     {
1341         PRMSG(1,"NAMEDReopenServer: failed to fill in addr info\n",
1342                                                                 0,0,0);
1343         return 0;
1344     }
1345
1346     return 1;
1347
1348 #endif /* !NAMEDNODENAME */
1349 }
1350
1351 #endif /* LOCAL_TRANS_NAMED */
1352
1353
1354 #ifdef LOCAL_TRANS_SCO
1355 static int
1356 TRANS(SCOReopenServer)(XtransConnInfo ciptr, int fd, char *port)
1357
1358 {
1359 #ifdef SCORNODENAME
1360     char serverR_path[64], serverS_path[64];
1361 #endif
1362
1363     PRMSG(2,"SCOReopenServer(%s)\n", port, 0,0 );
1364     if (!port || !port[0])
1365       port = "0";
1366
1367 #if !defined(SCORNODENAME)
1368     PRMSG(2,"SCOReopenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
1369     return 0;
1370 #else
1371     (void) sprintf(serverR_path, SCORNODENAME, port);
1372     (void) sprintf(serverS_path, SCOSNODENAME, port);
1373
1374 #if defined(X11_t) && defined(__SCO__)
1375     ciptr->flags |= TRANS_NOUNLINK;
1376 #endif
1377     if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0)
1378     {
1379         PRMSG(1, "SCOReopenServer: failed to fill in addr info\n", 0,0,0);
1380         return 0;
1381     }
1382
1383     return 1;
1384
1385 #endif /* SCORNODENAME */
1386 }
1387
1388 #endif /* LOCAL_TRANS_SCO */
1389
1390 #endif /* TRANS_REOPEN */
1391
1392
1393 \f
1394 /*
1395  * This table contains all of the entry points for the different local
1396  * connection mechanisms.
1397  */
1398
1399 typedef struct _LOCALtrans2dev {
1400     char        *transname;
1401
1402 #ifdef TRANS_CLIENT
1403
1404     int (*devcotsopenclient)(
1405         XtransConnInfo, char * /*port*/
1406 );
1407
1408 #endif /* TRANS_CLIENT */
1409
1410 #ifdef TRANS_SERVER
1411
1412     int (*devcotsopenserver)(
1413         XtransConnInfo, char * /*port*/
1414 );
1415
1416 #endif /* TRANS_SERVER */
1417
1418 #ifdef TRANS_CLIENT
1419
1420     int (*devcltsopenclient)(
1421         XtransConnInfo, char * /*port*/
1422 );
1423
1424 #endif /* TRANS_CLIENT */
1425
1426 #ifdef TRANS_SERVER
1427
1428     int (*devcltsopenserver)(
1429         XtransConnInfo, char * /*port*/
1430 );
1431
1432 #endif /* TRANS_SERVER */
1433
1434 #ifdef TRANS_REOPEN
1435
1436     int (*devcotsreopenserver)(
1437         XtransConnInfo,
1438         int,    /* fd */
1439         char *  /* port */
1440 );
1441
1442     int (*devcltsreopenserver)(
1443         XtransConnInfo,
1444         int,    /* fd */
1445         char *  /* port */
1446 );
1447
1448 #endif /* TRANS_REOPEN */
1449
1450 #ifdef TRANS_SERVER
1451
1452     int (*devreset)(
1453         XtransConnInfo /* ciptr */
1454 );
1455
1456     int (*devaccept)(
1457         XtransConnInfo, XtransConnInfo, int *
1458 );
1459
1460 #endif /* TRANS_SERVER */
1461
1462 } LOCALtrans2dev;
1463
1464 static LOCALtrans2dev LOCALtrans2devtab[] = {
1465 #ifdef LOCAL_TRANS_PTS
1466 {"",
1467 #ifdef TRANS_CLIENT
1468      TRANS(PTSOpenClient),
1469 #endif /* TRANS_CLIENT */
1470 #ifdef TRANS_SERVER
1471      TRANS(PTSOpenServer),
1472 #endif /* TRANS_SERVER */
1473 #ifdef TRANS_CLIENT
1474      TRANS(OpenFail),
1475 #endif /* TRANS_CLIENT */
1476 #ifdef TRANS_SERVER
1477      TRANS(OpenFail),
1478 #endif /* TRANS_SERVER */
1479 #ifdef TRANS_REOPEN
1480      TRANS(PTSReopenServer),
1481      TRANS(ReopenFail),
1482 #endif
1483 #ifdef TRANS_SERVER
1484      NULL,              /* ResetListener */
1485      TRANS(PTSAccept)
1486 #endif /* TRANS_SERVER */
1487 },
1488
1489 {"local",
1490 #ifdef TRANS_CLIENT
1491      TRANS(PTSOpenClient),
1492 #endif /* TRANS_CLIENT */
1493 #ifdef TRANS_SERVER
1494      TRANS(PTSOpenServer),
1495 #endif /* TRANS_SERVER */
1496 #ifdef TRANS_CLIENT
1497      TRANS(OpenFail),
1498 #endif /* TRANS_CLIENT */
1499 #ifdef TRANS_SERVER
1500      TRANS(OpenFail),
1501 #endif /* TRANS_SERVER */
1502 #ifdef TRANS_REOPEN
1503      TRANS(PTSReopenServer),
1504      TRANS(ReopenFail),
1505 #endif
1506 #ifdef TRANS_SERVER
1507      NULL,              /* ResetListener */
1508      TRANS(PTSAccept)
1509 #endif /* TRANS_SERVER */
1510 },
1511
1512 {"pts",
1513 #ifdef TRANS_CLIENT
1514      TRANS(PTSOpenClient),
1515 #endif /* TRANS_CLIENT */
1516 #ifdef TRANS_SERVER
1517      TRANS(PTSOpenServer),
1518 #endif /* TRANS_SERVER */
1519 #ifdef TRANS_CLIENT
1520      TRANS(OpenFail),
1521 #endif /* TRANS_CLIENT */
1522 #ifdef TRANS_SERVER
1523      TRANS(OpenFail),
1524 #endif /* TRANS_SERVER */
1525 #ifdef TRANS_REOPEN
1526      TRANS(PTSReopenServer),
1527      TRANS(ReopenFail),
1528 #endif
1529 #ifdef TRANS_SERVER
1530      NULL,              /* ResetListener */
1531      TRANS(PTSAccept)
1532 #endif /* TRANS_SERVER */
1533 },
1534 #else /* !LOCAL_TRANS_PTS */
1535 {"",
1536 #ifdef TRANS_CLIENT
1537      TRANS(NAMEDOpenClient),
1538 #endif /* TRANS_CLIENT */
1539 #ifdef TRANS_SERVER
1540      TRANS(NAMEDOpenServer),
1541 #endif /* TRANS_SERVER */
1542 #ifdef TRANS_CLIENT
1543      TRANS(OpenFail),
1544 #endif /* TRANS_CLIENT */
1545 #ifdef TRANS_SERVER
1546      TRANS(OpenFail),
1547 #endif /* TRANS_SERVER */
1548 #ifdef TRANS_REOPEN
1549      TRANS(NAMEDReopenServer),
1550      TRANS(ReopenFail),
1551 #endif
1552 #ifdef TRANS_SERVER
1553      TRANS(NAMEDResetListener),
1554      TRANS(NAMEDAccept)
1555 #endif /* TRANS_SERVER */
1556 },
1557
1558 {"local",
1559 #ifdef TRANS_CLIENT
1560      TRANS(NAMEDOpenClient),
1561 #endif /* TRANS_CLIENT */
1562 #ifdef TRANS_SERVER
1563      TRANS(NAMEDOpenServer),
1564 #endif /* TRANS_SERVER */
1565 #ifdef TRANS_CLIENT
1566      TRANS(OpenFail),
1567 #endif /* TRANS_CLIENT */
1568 #ifdef TRANS_SERVER
1569      TRANS(OpenFail),
1570 #endif /* TRANS_SERVER */
1571 #ifdef TRANS_REOPEN
1572      TRANS(NAMEDReopenServer),
1573      TRANS(ReopenFail),
1574 #endif
1575 #ifdef TRANS_SERVER
1576      TRANS(NAMEDResetListener),
1577      TRANS(NAMEDAccept)
1578 #endif /* TRANS_SERVER */
1579 },
1580 #endif /* !LOCAL_TRANS_PTS */
1581
1582 #ifdef LOCAL_TRANS_NAMED
1583 {"named",
1584 #ifdef TRANS_CLIENT
1585      TRANS(NAMEDOpenClient),
1586 #endif /* TRANS_CLIENT */
1587 #ifdef TRANS_SERVER
1588      TRANS(NAMEDOpenServer),
1589 #endif /* TRANS_SERVER */
1590 #ifdef TRANS_CLIENT
1591      TRANS(OpenFail),
1592 #endif /* TRANS_CLIENT */
1593 #ifdef TRANS_SERVER
1594      TRANS(OpenFail),
1595 #endif /* TRANS_SERVER */
1596 #ifdef TRANS_REOPEN
1597      TRANS(NAMEDReopenServer),
1598      TRANS(ReopenFail),
1599 #endif
1600 #ifdef TRANS_SERVER
1601      TRANS(NAMEDResetListener),
1602      TRANS(NAMEDAccept)
1603 #endif /* TRANS_SERVER */
1604 },
1605
1606 #ifdef sun /* Alias "pipe" to named, since that's what Solaris called it */
1607 {"pipe",
1608 #ifdef TRANS_CLIENT
1609      TRANS(NAMEDOpenClient),
1610 #endif /* TRANS_CLIENT */
1611 #ifdef TRANS_SERVER
1612      TRANS(NAMEDOpenServer),
1613 #endif /* TRANS_SERVER */
1614 #ifdef TRANS_CLIENT
1615      TRANS(OpenFail),
1616 #endif /* TRANS_CLIENT */
1617 #ifdef TRANS_SERVER
1618      TRANS(OpenFail),
1619 #endif /* TRANS_SERVER */
1620 #ifdef TRANS_REOPEN
1621      TRANS(NAMEDReopenServer),
1622      TRANS(ReopenFail),
1623 #endif
1624 #ifdef TRANS_SERVER
1625      TRANS(NAMEDResetListener),
1626      TRANS(NAMEDAccept)
1627 #endif /* TRANS_SERVER */
1628 },
1629 #endif /* sun */
1630 #endif /* LOCAL_TRANS_NAMED */
1631
1632
1633 #ifdef LOCAL_TRANS_SCO
1634 {"sco",
1635 #ifdef TRANS_CLIENT
1636      TRANS(SCOOpenClient),
1637 #endif /* TRANS_CLIENT */
1638 #ifdef TRANS_SERVER
1639      TRANS(SCOOpenServer),
1640 #endif /* TRANS_SERVER */
1641 #ifdef TRANS_CLIENT
1642      TRANS(OpenFail),
1643 #endif /* TRANS_CLIENT */
1644 #ifdef TRANS_SERVER
1645      TRANS(OpenFail),
1646 #endif /* TRANS_SERVER */
1647 #ifdef TRANS_REOPEN
1648      TRANS(SCOReopenServer),
1649      TRANS(ReopenFail),
1650 #endif
1651 #ifdef TRANS_SERVER
1652      NULL,              /* ResetListener */
1653      TRANS(SCOAccept)
1654 #endif /* TRANS_SERVER */
1655 },
1656 #endif /* LOCAL_TRANS_SCO */
1657 };
1658
1659 #define NUMTRANSPORTS   (sizeof(LOCALtrans2devtab)/sizeof(LOCALtrans2dev))
1660
1661 static  char    *XLOCAL=NULL;
1662 static  char    *workingXLOCAL=NULL;
1663 static  char    *freeXLOCAL=NULL;
1664
1665 #if defined(__SCO__)
1666 #define DEF_XLOCAL "SCO:UNIX:PTS"
1667 #elif defined(__UNIXWARE__)
1668 #define DEF_XLOCAL "UNIX:PTS:NAMED:SCO"
1669 #elif defined(sun)
1670 #define DEF_XLOCAL "UNIX:NAMED"
1671 #else
1672 #define DEF_XLOCAL "UNIX:PTS:NAMED:SCO"
1673 #endif
1674
1675 static void
1676 TRANS(LocalInitTransports)(char *protocol)
1677
1678 {
1679     PRMSG(3,"LocalInitTransports(%s)\n", protocol, 0,0 );
1680
1681     if( strcmp(protocol,"local") && strcmp(protocol,"LOCAL") )
1682     {
1683         workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (protocol) + 1);
1684         if (workingXLOCAL)
1685             strcpy (workingXLOCAL, protocol);
1686     }
1687     else {
1688         XLOCAL=(char *)getenv("XLOCAL");
1689         if(XLOCAL==NULL)
1690             XLOCAL=DEF_XLOCAL;
1691         workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (XLOCAL) + 1);
1692         if (workingXLOCAL)
1693             strcpy (workingXLOCAL, XLOCAL);
1694     }
1695 }
1696
1697 static void
1698 TRANS(LocalEndTransports)(void)
1699
1700 {
1701     PRMSG(3,"LocalEndTransports()\n", 0,0,0 );
1702     xfree(freeXLOCAL);
1703 }
1704
1705 #define TYPEBUFSIZE     32
1706
1707 #ifdef TRANS_CLIENT
1708
1709 static LOCALtrans2dev *
1710 TRANS(LocalGetNextTransport)(void)
1711
1712 {
1713     int i,j;
1714     char        *typetocheck;
1715     char        typebuf[TYPEBUFSIZE];
1716     PRMSG(3,"LocalGetNextTransport()\n", 0,0,0 );
1717
1718     while(1)
1719     {
1720         if( workingXLOCAL == NULL || *workingXLOCAL == '\0' )
1721             return NULL;
1722
1723         typetocheck=workingXLOCAL;
1724         workingXLOCAL=strchr(workingXLOCAL,':');
1725         if(workingXLOCAL && *workingXLOCAL)
1726             *workingXLOCAL++='\0';
1727
1728         for(i=0;i<NUMTRANSPORTS;i++)
1729         {
1730             /*
1731              * This is equivalent to a case insensitive strcmp(),
1732              * but should be more portable.
1733              */
1734             strncpy(typebuf,typetocheck,TYPEBUFSIZE);
1735             for(j=0;j<TYPEBUFSIZE;j++)
1736                 if (isupper(typebuf[j]))
1737                     typebuf[j]=tolower(typebuf[j]);
1738
1739             /* Now, see if they match */
1740             if(!strcmp(LOCALtrans2devtab[i].transname,typebuf))
1741                 return &LOCALtrans2devtab[i];
1742         }
1743     }
1744 #if 0
1745     /*NOTREACHED*/
1746     return NULL;
1747 #endif
1748 }
1749
1750 #ifdef NEED_UTSNAME
1751 #include <sys/utsname.h>
1752 #endif
1753
1754 /*
1755  * Make sure 'host' is really local.
1756  */
1757
1758 static int
1759 HostReallyLocal (char *host)
1760
1761 {
1762     /*
1763      * The 'host' passed to this function may have been generated
1764      * by either uname() or gethostname().  We try both if possible.
1765      */
1766
1767 #ifdef NEED_UTSNAME
1768     struct utsname name;
1769 #endif
1770     char buf[256];
1771
1772 #ifdef NEED_UTSNAME
1773     if (uname (&name) >= 0 && strcmp (host, name.nodename) == 0)
1774         return (1);
1775 #endif
1776
1777     buf[0] = '\0';
1778     (void) gethostname (buf, 256);
1779     buf[255] = '\0';
1780
1781     if (strcmp (host, buf) == 0)
1782         return (1);
1783
1784     return (0);
1785 }
1786
1787
1788 static XtransConnInfo
1789 TRANS(LocalOpenClient)(int type, char *protocol, char *host, char *port)
1790
1791 {
1792     LOCALtrans2dev *transptr;
1793     XtransConnInfo ciptr;
1794     int index;
1795
1796     PRMSG(3,"LocalOpenClient()\n", 0,0,0 );
1797
1798     /*
1799      * Make sure 'host' is really local.  If not, we return failure.
1800      * The reason we make this check is because a process may advertise
1801      * a "local" address for which it can accept connections, but if a
1802      * process on a remote machine tries to connect to this address,
1803      * we know for sure it will fail.
1804      */
1805
1806     if (strcmp (host, "unix") != 0 && !HostReallyLocal (host))
1807     {
1808         PRMSG (1,
1809            "LocalOpenClient: Cannot connect to non-local host %s\n",
1810                host, 0, 0);
1811         return NULL;
1812     }
1813
1814
1815 #if defined(X11_t)
1816     /*
1817      * X has a well known port, that is transport dependant. It is easier
1818      * to handle it here, than try and come up with a transport independent
1819      * representation that can be passed in and resolved the usual way.
1820      *
1821      * The port that is passed here is really a string containing the idisplay
1822      * from ConnectDisplay(). Since that is what we want for the local transports,
1823      * we don't have to do anything special.
1824      */
1825 #endif /* X11_t */
1826
1827     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
1828     {
1829         PRMSG(1,"LocalOpenClient: calloc(1,%d) failed\n",
1830               sizeof(struct _XtransConnInfo),0,0 );
1831         return NULL;
1832     }
1833
1834     ciptr->fd = -1;
1835
1836     TRANS(LocalInitTransports)(protocol);
1837
1838     index = 0;
1839     for(transptr=TRANS(LocalGetNextTransport)();
1840         transptr!=NULL;transptr=TRANS(LocalGetNextTransport)(), index++)
1841     {
1842         switch( type )
1843         {
1844         case XTRANS_OPEN_COTS_CLIENT:
1845             ciptr->fd=transptr->devcotsopenclient(ciptr,port);
1846             break;
1847         case XTRANS_OPEN_CLTS_CLIENT:
1848             ciptr->fd=transptr->devcltsopenclient(ciptr,port);
1849             break;
1850         case XTRANS_OPEN_COTS_SERVER:
1851         case XTRANS_OPEN_CLTS_SERVER:
1852             PRMSG(1,
1853                   "LocalOpenClient: Should not be opening a server with this function\n",
1854                   0,0,0);
1855             break;
1856         default:
1857             PRMSG(1,
1858                   "LocalOpenClient: Unknown Open type %d\n",
1859                   type, 0,0 );
1860         }
1861         if( ciptr->fd >= 0 )
1862             break;
1863     }
1864
1865     TRANS(LocalEndTransports)();
1866
1867     if( ciptr->fd < 0 )
1868     {
1869         xfree(ciptr);
1870         return NULL;
1871     }
1872
1873     ciptr->priv=(char *)transptr;
1874     ciptr->index = index;
1875
1876     return ciptr;
1877 }
1878
1879 #endif /* TRANS_CLIENT */
1880
1881
1882 #ifdef TRANS_SERVER
1883
1884 static XtransConnInfo
1885 TRANS(LocalOpenServer)(int type, char *protocol, char *host, char *port)
1886
1887 {
1888     int i;
1889     XtransConnInfo ciptr;
1890
1891     PRMSG(2,"LocalOpenServer(%d,%s,%s)\n", type, protocol, port);
1892
1893 #if defined(X11_t)
1894     /*
1895      * For X11, the port will be in the format xserverN where N is the
1896      * display number. All of the local connections just need to know
1897      * the display number because they don't do any name resolution on
1898      * the port. This just truncates port to the display portion.
1899      */
1900 #endif /* X11_t */
1901
1902     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
1903     {
1904         PRMSG(1,"LocalOpenServer: calloc(1,%d) failed\n",
1905               sizeof(struct _XtransConnInfo),0,0 );
1906         return NULL;
1907     }
1908
1909     for(i=1;i<NUMTRANSPORTS;i++)
1910     {
1911         if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 )
1912             continue;
1913         switch( type )
1914         {
1915         case XTRANS_OPEN_COTS_CLIENT:
1916         case XTRANS_OPEN_CLTS_CLIENT:
1917             PRMSG(1,
1918                   "LocalOpenServer: Should not be opening a client with this function\n",
1919                   0,0,0);
1920             break;
1921         case XTRANS_OPEN_COTS_SERVER:
1922             ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port);
1923             break;
1924         case XTRANS_OPEN_CLTS_SERVER:
1925             ciptr->fd=LOCALtrans2devtab[i].devcltsopenserver(ciptr,port);
1926             break;
1927         default:
1928             PRMSG(1,"LocalOpenServer: Unknown Open type %d\n",
1929                   type ,0,0);
1930         }
1931         if( ciptr->fd >= 0 ) {
1932             ciptr->priv=(char *)&LOCALtrans2devtab[i];
1933             ciptr->index=i;
1934             ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
1935             return ciptr;
1936         }
1937     }
1938
1939     xfree(ciptr);
1940     return NULL;
1941 }
1942
1943 #endif /* TRANS_SERVER */
1944
1945
1946 #ifdef TRANS_REOPEN
1947
1948 static XtransConnInfo
1949 TRANS(LocalReopenServer)(int type, int index, int fd, char *port)
1950
1951 {
1952     XtransConnInfo ciptr;
1953     int stat = 0;
1954
1955     PRMSG(2,"LocalReopenServer(%d,%d,%d)\n", type, index, fd);
1956
1957     if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
1958     {
1959         PRMSG(1,"LocalReopenServer: calloc(1,%d) failed\n",
1960               sizeof(struct _XtransConnInfo),0,0 );
1961         return NULL;
1962     }
1963
1964     ciptr->fd = fd;
1965
1966     switch( type )
1967     {
1968     case XTRANS_OPEN_COTS_SERVER:
1969         stat = LOCALtrans2devtab[index].devcotsreopenserver(ciptr,fd,port);
1970         break;
1971     case XTRANS_OPEN_CLTS_SERVER:
1972         stat = LOCALtrans2devtab[index].devcltsreopenserver(ciptr,fd,port);
1973         break;
1974     default:
1975         PRMSG(1,"LocalReopenServer: Unknown Open type %d\n",
1976           type ,0,0);
1977     }
1978
1979     if( stat > 0 ) {
1980         ciptr->priv=(char *)&LOCALtrans2devtab[index];
1981         ciptr->index=index;
1982         ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
1983         return ciptr;
1984     }
1985
1986     xfree(ciptr);
1987     return NULL;
1988 }
1989
1990 #endif /* TRANS_REOPEN */
1991
1992
1993 \f
1994 /*
1995  * This is the Local implementation of the X Transport service layer
1996  */
1997
1998 #ifdef TRANS_CLIENT
1999
2000 static XtransConnInfo
2001 TRANS(LocalOpenCOTSClient)(Xtransport *thistrans, char *protocol, 
2002                            char *host, char *port)
2003
2004 {
2005     PRMSG(2,"LocalOpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
2006
2007     return TRANS(LocalOpenClient)(XTRANS_OPEN_COTS_CLIENT, protocol, host, port);
2008 }
2009
2010 #endif /* TRANS_CLIENT */
2011
2012
2013 #ifdef TRANS_SERVER
2014
2015 static XtransConnInfo
2016 TRANS(LocalOpenCOTSServer)(Xtransport *thistrans, char *protocol, 
2017                            char *host, char *port)
2018
2019 {
2020     char *typetocheck = NULL;
2021     int found = 0;
2022     char typebuf[TYPEBUFSIZE];
2023
2024     PRMSG(2,"LocalOpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
2025
2026     /* Check if this local type is in the XLOCAL list */
2027     TRANS(LocalInitTransports)("local");
2028     typetocheck = workingXLOCAL;
2029     while (typetocheck && !found) {
2030         int j;
2031
2032         workingXLOCAL = strchr(workingXLOCAL, ':');
2033         if (workingXLOCAL && *workingXLOCAL)
2034             *workingXLOCAL++ = '\0';
2035         strncpy(typebuf, typetocheck, TYPEBUFSIZE);
2036         for (j = 0; j < TYPEBUFSIZE; j++)
2037             if (isupper(typebuf[j]))
2038                 typebuf[j] = tolower(typebuf[j]);
2039         if (!strcmp(thistrans->TransName, typebuf))
2040             found = 1;
2041         typetocheck = workingXLOCAL;
2042     }
2043     TRANS(LocalEndTransports)();
2044
2045     if (!found) {
2046         PRMSG(3,"LocalOpenCOTSServer: disabling %s\n",thistrans->TransName,0,0);
2047         thistrans->flags |= TRANS_DISABLED;
2048         return NULL;
2049     }
2050
2051     return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port);
2052 }
2053
2054 #endif /* TRANS_SERVER */
2055
2056
2057 #ifdef TRANS_CLIENT
2058
2059 static XtransConnInfo
2060 TRANS(LocalOpenCLTSClient)(Xtransport *thistrans, char *protocol, 
2061                            char *host, char *port)
2062
2063 {
2064     PRMSG(2,"LocalOpenCLTSClient(%s,%s,%s)\n",protocol,host,port);
2065
2066     return TRANS(LocalOpenClient)(XTRANS_OPEN_CLTS_CLIENT, protocol, host, port);
2067 }
2068
2069 #endif /* TRANS_CLIENT */
2070
2071
2072 #ifdef TRANS_SERVER
2073
2074 static XtransConnInfo
2075 TRANS(LocalOpenCLTSServer)(Xtransport *thistrans, char *protocol, 
2076                            char *host, char *port)
2077
2078 {
2079     PRMSG(2,"LocalOpenCLTSServer(%s,%s,%s)\n",protocol,host,port);
2080
2081     return TRANS(LocalOpenServer)(XTRANS_OPEN_CLTS_SERVER, protocol, host, port);
2082 }
2083
2084 #endif /* TRANS_SERVER */
2085
2086
2087 #ifdef TRANS_REOPEN
2088
2089 static XtransConnInfo
2090 TRANS(LocalReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
2091
2092 {
2093     int index;
2094
2095     PRMSG(2,"LocalReopenCOTSServer(%d,%s)\n", fd, port, 0);
2096
2097     for(index=1;index<NUMTRANSPORTS;index++)
2098     {
2099         if( strcmp(thistrans->TransName,
2100             LOCALtrans2devtab[index].transname) == 0 )
2101             break;
2102     }
2103
2104     if (index >= NUMTRANSPORTS)
2105     {
2106         return (NULL);
2107     }
2108
2109     return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER,
2110         index, fd, port);
2111 }
2112
2113 static XtransConnInfo
2114 TRANS(LocalReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
2115
2116 {
2117     int index;
2118
2119     PRMSG(2,"LocalReopenCLTSServer(%d,%s)\n", fd, port, 0);
2120
2121     for(index=1;index<NUMTRANSPORTS;index++)
2122     {
2123         if( strcmp(thistrans->TransName,
2124             LOCALtrans2devtab[index].transname) == 0 )
2125             break;
2126     }
2127
2128     if (index >= NUMTRANSPORTS)
2129     {
2130         return (NULL);
2131     }
2132
2133     return TRANS(LocalReopenServer)(XTRANS_OPEN_CLTS_SERVER,
2134         index, fd, port);
2135 }
2136
2137 #endif /* TRANS_REOPEN */
2138
2139
2140
2141 static int
2142 TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg)
2143
2144 {
2145     PRMSG(2,"LocalSetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
2146
2147     return -1;
2148 }
2149
2150
2151 #ifdef TRANS_SERVER
2152
2153 static int
2154 TRANS(LocalCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
2155
2156 {
2157     PRMSG(2,"LocalCreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port);
2158
2159     return 0;
2160 }
2161
2162 static int
2163 TRANS(LocalResetListener)(XtransConnInfo ciptr)
2164
2165 {
2166     LOCALtrans2dev      *transptr;
2167     
2168     PRMSG(2,"LocalResetListener(%x)\n",ciptr,0,0);
2169
2170     transptr=(LOCALtrans2dev *)ciptr->priv;
2171     if (transptr->devreset != NULL) {
2172         return transptr->devreset(ciptr);
2173     }
2174     return TRANS_RESET_NOOP;
2175 }
2176
2177
2178 static XtransConnInfo
2179 TRANS(LocalAccept)(XtransConnInfo ciptr, int *status)
2180
2181 {
2182     XtransConnInfo      newciptr;
2183     LOCALtrans2dev      *transptr;
2184
2185     PRMSG(2,"LocalAccept(%x->%d)\n", ciptr, ciptr->fd,0);
2186
2187     transptr=(LOCALtrans2dev *)ciptr->priv;
2188
2189     if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL )
2190     {
2191         PRMSG(1,"LocalAccept: calloc(1,%d) failed\n",
2192               sizeof(struct _XtransConnInfo),0,0 );
2193         *status = TRANS_ACCEPT_BAD_MALLOC;
2194         return NULL;
2195     }
2196
2197     newciptr->fd=transptr->devaccept(ciptr,newciptr,status);
2198
2199     if( newciptr->fd < 0 )
2200     {
2201         xfree(newciptr);
2202         return NULL;
2203     }
2204
2205     newciptr->priv=(char *)transptr;
2206     newciptr->index = ciptr->index;
2207
2208     *status = 0;
2209
2210     return newciptr;
2211 }
2212
2213 #endif /* TRANS_SERVER */
2214
2215
2216 #ifdef TRANS_CLIENT
2217
2218 static int
2219 TRANS(LocalConnect)(XtransConnInfo ciptr, char *host, char *port)
2220
2221 {
2222     PRMSG(2,"LocalConnect(%x->%d,%s)\n", ciptr, ciptr->fd, port);
2223
2224     return 0;
2225 }
2226
2227 #endif /* TRANS_CLIENT */
2228
2229
2230 static int
2231 TRANS(LocalBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend )
2232
2233 {
2234     PRMSG(2,"LocalBytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend);
2235
2236 #if defined(SCO325)
2237     return ioctl(ciptr->fd, I_NREAD, (char *)pend);
2238 #else
2239     return ioctl(ciptr->fd, FIONREAD, (char *)pend);
2240 #endif
2241 }
2242
2243 static int
2244 TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size)
2245
2246 {
2247     PRMSG(2,"LocalRead(%d,%x,%d)\n", ciptr->fd, buf, size );
2248
2249     return read(ciptr->fd,buf,size);
2250 }
2251
2252 static int
2253 TRANS(LocalWrite)(XtransConnInfo ciptr, char *buf, int size)
2254
2255 {
2256     PRMSG(2,"LocalWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
2257
2258     return write(ciptr->fd,buf,size);
2259 }
2260
2261 static int
2262 TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
2263
2264 {
2265     PRMSG(2,"LocalReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
2266
2267     return READV(ciptr,buf,size);
2268 }
2269
2270 static int
2271 TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
2272
2273 {
2274     PRMSG(2,"LocalWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
2275
2276     return WRITEV(ciptr,buf,size);
2277 }
2278
2279 static int
2280 TRANS(LocalDisconnect)(XtransConnInfo ciptr)
2281
2282 {
2283     PRMSG(2,"LocalDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
2284
2285     return 0;
2286 }
2287
2288 static int
2289 TRANS(LocalClose)(XtransConnInfo ciptr)
2290
2291 {
2292     struct sockaddr_un      *sockname=(struct sockaddr_un *) ciptr->addr;
2293     int ret;
2294
2295     PRMSG(2,"LocalClose(%x->%d)\n", ciptr, ciptr->fd ,0);
2296
2297     ret=close(ciptr->fd);
2298
2299     if(ciptr->flags
2300        && sockname
2301        && sockname->sun_family == AF_UNIX
2302        && sockname->sun_path[0] )
2303     {
2304         if (!(ciptr->flags & TRANS_NOUNLINK))
2305             unlink(sockname->sun_path);
2306     }
2307
2308     return ret;
2309 }
2310
2311 static int
2312 TRANS(LocalCloseForCloning)(XtransConnInfo ciptr)
2313
2314 {
2315     int ret;
2316
2317     PRMSG(2,"LocalCloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0);
2318
2319     /* Don't unlink path */
2320
2321     ret=close(ciptr->fd);
2322
2323     return ret;
2324 }
2325
2326
2327 /*
2328  * MakeAllCOTSServerListeners() will go through the entire Xtransports[]
2329  * array defined in Xtrans.c and try to OpenCOTSServer() for each entry.
2330  * We will add duplicate entries to that table so that the OpenCOTSServer()
2331  * function will get called once for each type of local transport. 
2332  *
2333  * The TransName is in lowercase, so it will never match during a normal
2334  * call to SelectTransport() in Xtrans.c.
2335  */
2336
2337 #ifdef TRANS_SERVER
2338 static char * local_aliases[] = {
2339 # ifdef LOCAL_TRANS_PTS
2340                                   "pts",
2341 # endif
2342                                   "named",
2343 # ifdef sun
2344                                   "pipe", /* compatibility with Solaris Xlib */
2345 # endif                           
2346 # ifdef LOCAL_TRANS_SCO                           
2347                                   "sco",
2348 # endif
2349                                   NULL };
2350 #endif
2351
2352 Xtransport      TRANS(LocalFuncs) = {
2353         /* Local Interface */
2354         "local",
2355         TRANS_ALIAS | TRANS_LOCAL,
2356 #ifdef TRANS_CLIENT
2357         TRANS(LocalOpenCOTSClient),
2358 #endif /* TRANS_CLIENT */
2359 #ifdef TRANS_SERVER
2360         local_aliases,
2361         TRANS(LocalOpenCOTSServer),
2362 #endif /* TRANS_SERVER */
2363 #ifdef TRANS_CLIENT
2364         TRANS(LocalOpenCLTSClient),
2365 #endif /* TRANS_CLIENT */
2366 #ifdef TRANS_SERVER
2367         TRANS(LocalOpenCLTSServer),
2368 #endif /* TRANS_SERVER */
2369 #ifdef TRANS_REOPEN
2370         TRANS(LocalReopenCOTSServer),
2371         TRANS(LocalReopenCLTSServer),
2372 #endif
2373         TRANS(LocalSetOption),
2374 #ifdef TRANS_SERVER
2375         TRANS(LocalCreateListener),
2376         TRANS(LocalResetListener),
2377         TRANS(LocalAccept),
2378 #endif /* TRANS_SERVER */
2379 #ifdef TRANS_CLIENT
2380         TRANS(LocalConnect),
2381 #endif /* TRANS_CLIENT */
2382         TRANS(LocalBytesReadable),
2383         TRANS(LocalRead),
2384         TRANS(LocalWrite),
2385         TRANS(LocalReadv),
2386         TRANS(LocalWritev),
2387         TRANS(LocalDisconnect),
2388         TRANS(LocalClose),
2389         TRANS(LocalCloseForCloning),
2390 };
2391
2392 #ifdef LOCAL_TRANS_PTS
2393
2394 Xtransport      TRANS(PTSFuncs) = {
2395         /* Local Interface */
2396         "pts",
2397         TRANS_LOCAL,
2398 #ifdef TRANS_CLIENT
2399         TRANS(LocalOpenCOTSClient),
2400 #endif /* TRANS_CLIENT */
2401 #ifdef TRANS_SERVER
2402         NULL,
2403         TRANS(LocalOpenCOTSServer),
2404 #endif /* TRANS_SERVER */
2405 #ifdef TRANS_CLIENT
2406         TRANS(LocalOpenCLTSClient),
2407 #endif /* TRANS_CLIENT */
2408 #ifdef TRANS_SERVER
2409         TRANS(LocalOpenCLTSServer),
2410 #endif /* TRANS_SERVER */
2411 #ifdef TRANS_REOPEN
2412         TRANS(LocalReopenCOTSServer),
2413         TRANS(LocalReopenCLTSServer),
2414 #endif
2415         TRANS(LocalSetOption),
2416 #ifdef TRANS_SERVER
2417         TRANS(LocalCreateListener),
2418         TRANS(LocalResetListener),
2419         TRANS(LocalAccept),
2420 #endif /* TRANS_SERVER */
2421 #ifdef TRANS_CLIENT
2422         TRANS(LocalConnect),
2423 #endif /* TRANS_CLIENT */
2424         TRANS(LocalBytesReadable),
2425         TRANS(LocalRead),
2426         TRANS(LocalWrite),
2427         TRANS(LocalReadv),
2428         TRANS(LocalWritev),
2429         TRANS(LocalDisconnect),
2430         TRANS(LocalClose),
2431         TRANS(LocalCloseForCloning),
2432 };
2433
2434 #endif /* LOCAL_TRANS_PTS */
2435
2436 #ifdef LOCAL_TRANS_NAMED
2437
2438 Xtransport      TRANS(NAMEDFuncs) = {
2439         /* Local Interface */
2440         "named",
2441         TRANS_LOCAL,
2442 #ifdef TRANS_CLIENT
2443         TRANS(LocalOpenCOTSClient),
2444 #endif /* TRANS_CLIENT */
2445 #ifdef TRANS_SERVER
2446         NULL,
2447         TRANS(LocalOpenCOTSServer),
2448 #endif /* TRANS_SERVER */
2449 #ifdef TRANS_CLIENT
2450         TRANS(LocalOpenCLTSClient),
2451 #endif /* TRANS_CLIENT */
2452 #ifdef TRANS_SERVER
2453         TRANS(LocalOpenCLTSServer),
2454 #endif /* TRANS_SERVER */
2455 #ifdef TRANS_REOPEN
2456         TRANS(LocalReopenCOTSServer),
2457         TRANS(LocalReopenCLTSServer),
2458 #endif
2459         TRANS(LocalSetOption),
2460 #ifdef TRANS_SERVER
2461         TRANS(LocalCreateListener),
2462         TRANS(LocalResetListener),
2463         TRANS(LocalAccept),
2464 #endif /* TRANS_SERVER */
2465 #ifdef TRANS_CLIENT
2466         TRANS(LocalConnect),
2467 #endif /* TRANS_CLIENT */
2468         TRANS(LocalBytesReadable),
2469         TRANS(LocalRead),
2470         TRANS(LocalWrite),
2471         TRANS(LocalReadv),
2472         TRANS(LocalWritev),
2473         TRANS(LocalDisconnect),
2474         TRANS(LocalClose),
2475         TRANS(LocalCloseForCloning),
2476 };
2477
2478 #ifdef sun
2479 Xtransport      TRANS(PIPEFuncs) = {
2480         /* Local Interface */
2481         "pipe",
2482         TRANS_ALIAS | TRANS_LOCAL,
2483 #ifdef TRANS_CLIENT
2484         TRANS(LocalOpenCOTSClient),
2485 #endif /* TRANS_CLIENT */
2486 #ifdef TRANS_SERVER
2487         NULL,
2488         TRANS(LocalOpenCOTSServer),
2489 #endif /* TRANS_SERVER */
2490 #ifdef TRANS_CLIENT
2491         TRANS(LocalOpenCLTSClient),
2492 #endif /* TRANS_CLIENT */
2493 #ifdef TRANS_SERVER
2494         TRANS(LocalOpenCLTSServer),
2495 #endif /* TRANS_SERVER */
2496 #ifdef TRANS_REOPEN
2497         TRANS(LocalReopenCOTSServer),
2498         TRANS(LocalReopenCLTSServer),
2499 #endif
2500         TRANS(LocalSetOption),
2501 #ifdef TRANS_SERVER
2502         TRANS(LocalCreateListener),
2503         TRANS(LocalResetListener),
2504         TRANS(LocalAccept),
2505 #endif /* TRANS_SERVER */
2506 #ifdef TRANS_CLIENT
2507         TRANS(LocalConnect),
2508 #endif /* TRANS_CLIENT */
2509         TRANS(LocalBytesReadable),
2510         TRANS(LocalRead),
2511         TRANS(LocalWrite),
2512         TRANS(LocalReadv),
2513         TRANS(LocalWritev),
2514         TRANS(LocalDisconnect),
2515         TRANS(LocalClose),
2516         TRANS(LocalCloseForCloning),
2517 };
2518 #endif /* sun */
2519 #endif /* LOCAL_TRANS_NAMED */
2520
2521
2522 #ifdef LOCAL_TRANS_SCO
2523 Xtransport      TRANS(SCOFuncs) = {
2524         /* Local Interface */
2525         "sco",
2526         TRANS_LOCAL,
2527 #ifdef TRANS_CLIENT
2528         TRANS(LocalOpenCOTSClient),
2529 #endif /* TRANS_CLIENT */
2530 #ifdef TRANS_SERVER
2531         NULL,
2532         TRANS(LocalOpenCOTSServer),
2533 #endif /* TRANS_SERVER */
2534 #ifdef TRANS_CLIENT
2535         TRANS(LocalOpenCLTSClient),
2536 #endif /* TRANS_CLIENT */
2537 #ifdef TRANS_SERVER
2538         TRANS(LocalOpenCLTSServer),
2539 #endif /* TRANS_SERVER */
2540 #ifdef TRANS_REOPEN
2541         TRANS(LocalReopenCOTSServer),
2542         TRANS(LocalReopenCLTSServer),
2543 #endif
2544         TRANS(LocalSetOption),
2545 #ifdef TRANS_SERVER
2546         TRANS(LocalCreateListener),
2547         TRANS(LocalResetListener),
2548         TRANS(LocalAccept),
2549 #endif /* TRANS_SERVER */
2550 #ifdef TRANS_CLIENT
2551         TRANS(LocalConnect),
2552 #endif /* TRANS_CLIENT */
2553         TRANS(LocalBytesReadable),
2554         TRANS(LocalRead),
2555         TRANS(LocalWrite),
2556         TRANS(LocalReadv),
2557         TRANS(LocalWritev),
2558         TRANS(LocalDisconnect),
2559         TRANS(LocalClose),
2560         TRANS(LocalCloseForCloning),
2561 };
2562 #endif /* LOCAL_TRANS_SCO */