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