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