Xtranslcl.c revision af928962
1/*
2
3Copyright 1993, 1994, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from 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
117static int TRANS(LocalClose)(XtransConnInfo ciptr);
118
119/*
120 * These functions actually implement the local connection mechanisms.
121 */
122
123/* Type Not Supported */
124
125static int
126TRANS(OpenFail)(XtransConnInfo ciptr, char *port)
127
128{
129    return -1;
130}
131
132#ifdef TRANS_REOPEN
133
134static int
135TRANS(ReopenFail)(XtransConnInfo ciptr, int fd, char *port)
136
137{
138    return 0;
139}
140
141#endif /* TRANS_REOPEN */
142
143
144
145static int
146TRANS(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
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
217typedef SIGNAL_T (*PFV)();
218
219extern PFV signal();
220
221extern char *ptsname(
222    int
223);
224
225static 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
302#ifdef LOCAL_TRANS_PTS
303#ifdef TRANS_CLIENT
304
305static int
306TRANS(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
455static int
456TRANS(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
560static int
561TRANS(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
652#ifdef LOCAL_TRANS_NAMED
653
654/* NAMED */
655
656#ifdef TRANS_CLIENT
657
658static int
659TRANS(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
736static int
737TRANS(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
800static int
801TRANS(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
847static int
848TRANS(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
876static int
877TRANS(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
930#if defined(LOCAL_TRANS_SCO)
931
932/*
933 * connect_spipe is used by the SCO connection type.
934 */
935static int
936connect_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
961static int
962named_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
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
1009static int
1010TRANS(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
1097static int
1098TRANS(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
1203static int
1204TRANS(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
1272#ifdef TRANS_REOPEN
1273#ifdef LOCAL_TRANS_PTS
1274
1275static int
1276TRANS(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
1315static int
1316TRANS(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
1355static int
1356TRANS(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
1394/*
1395 * This table contains all of the entry points for the different local
1396 * connection mechanisms.
1397 */
1398
1399typedef 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
1464static 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
1661static	char	*XLOCAL=NULL;
1662static	char	*workingXLOCAL=NULL;
1663static	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
1675static void
1676TRANS(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
1697static void
1698TRANS(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
1709static LOCALtrans2dev *
1710TRANS(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
1758static int
1759HostReallyLocal (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
1788static XtransConnInfo
1789TRANS(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
1884static XtransConnInfo
1885TRANS(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
1948static XtransConnInfo
1949TRANS(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
1994/*
1995 * This is the Local implementation of the X Transport service layer
1996 */
1997
1998#ifdef TRANS_CLIENT
1999
2000static XtransConnInfo
2001TRANS(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
2015static XtransConnInfo
2016TRANS(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
2059static XtransConnInfo
2060TRANS(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
2074static XtransConnInfo
2075TRANS(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
2089static XtransConnInfo
2090TRANS(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
2113static XtransConnInfo
2114TRANS(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
2141static int
2142TRANS(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
2153static int
2154TRANS(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
2162static int
2163TRANS(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
2178static XtransConnInfo
2179TRANS(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
2218static int
2219TRANS(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
2230static int
2231TRANS(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
2243static int
2244TRANS(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
2252static int
2253TRANS(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
2261static int
2262TRANS(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
2270static int
2271TRANS(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
2279static int
2280TRANS(LocalDisconnect)(XtransConnInfo ciptr)
2281
2282{
2283    PRMSG(2,"LocalDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
2284
2285    return 0;
2286}
2287
2288static int
2289TRANS(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
2311static int
2312TRANS(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
2338static 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
2352Xtransport	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
2394Xtransport	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
2438Xtransport	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
2479Xtransport	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
2523Xtransport	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 */
2563