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