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