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