master
ブランチ master
ShaderPlayground / deps / xlibre / include / X11 / Xtrans / Xtranslcl.c
31.8 KB、1462行 生 Blame 履歴
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# include <stropts.h>
82#include <sys/wait.h>
83#include <sys/types.h>
84
85/*
86 * The local transports should be treated the same as a UNIX domain socket
87 * wrt authentication, etc. Because of this, we will use struct sockaddr_un
88 * for the address format. This will simplify the code in other places like
89 * The X Server.
90 */
91
92#include <sys/socket.h>
93#ifndef X_NO_SYS_UN
94#include <sys/un.h>
95#endif
96
97
98/* Types of local connections supported:
99 * - PTS
100 * - named pipes
101 */
102#if defined(SVR4) || defined(__SVR4)
103# define LOCAL_TRANS_NAMED
104#endif
105
106static int TRANS(LocalClose)(XtransConnInfo ciptr);
107
108/*
109 * These functions actually implement the local connection mechanisms.
110 */
111
112/* Type Not Supported */
113
114static int
115TRANS(OpenFail)(XtransConnInfo ciptr _X_UNUSED, const char *port _X_UNUSED)
116
117{
118 return -1;
119}
120
121#ifdef TRANS_REOPEN
122
123static int
124TRANS(ReopenFail)(XtransConnInfo ciptr _X_UNUSED, int fd _X_UNUSED,
125 const char *port _X_UNUSED)
126
127{
128 return 0;
129}
130
131#endif /* TRANS_REOPEN */
132
133#if XTRANS_SEND_FDS
134static int
135TRANS(LocalRecvFdInvalid)(XtransConnInfo ciptr)
136{
137 errno = EINVAL;
138 return -1;
139}
140
141static int
142TRANS(LocalSendFdInvalid)(XtransConnInfo ciptr, int fd, int do_close)
143{
144 errno = EINVAL;
145 return -1;
146}
147#endif
148
149
150static int
151TRANS(FillAddrInfo)(XtransConnInfo ciptr,
152 const char *sun_path, const char *peer_sun_path)
153
154{
155 struct sockaddr_un *sunaddr;
156 struct sockaddr_un *p_sunaddr;
157
158 ciptr->family = AF_UNIX;
159 ciptr->addrlen = sizeof (struct sockaddr_un);
160
161 if ((sunaddr = malloc (ciptr->addrlen)) == NULL)
162 {
163 prmsg(1,"FillAddrInfo: failed to allocate memory for addr\n");
164 return 0;
165 }
166
167 sunaddr->sun_family = AF_UNIX;
168
169 if (strlen(sun_path) > sizeof(sunaddr->sun_path) - 1) {
170 prmsg(1, "FillAddrInfo: path too long\n");
171 free((char *) sunaddr);
172 return 0;
173 }
174 strcpy (sunaddr->sun_path, sun_path);
175#if defined(BSD44SOCKETS)
176 sunaddr->sun_len = strlen (sunaddr->sun_path);
177#endif
178
179 ciptr->addr = (char *) sunaddr;
180
181 ciptr->peeraddrlen = sizeof (struct sockaddr_un);
182
183 if ((p_sunaddr = malloc (ciptr->peeraddrlen)) == NULL)
184 {
185 prmsg(1,
186 "FillAddrInfo: failed to allocate memory for peer addr\n");
187 free (sunaddr);
188 ciptr->addr = NULL;
189
190 return 0;
191 }
192
193 p_sunaddr->sun_family = AF_UNIX;
194
195 if (strlen(peer_sun_path) > sizeof(p_sunaddr->sun_path) - 1) {
196 prmsg(1, "FillAddrInfo: peer path too long\n");
197 free((char *) p_sunaddr);
198 return 0;
199 }
200 strcpy (p_sunaddr->sun_path, peer_sun_path);
201#if defined(BSD44SOCKETS)
202 p_sunaddr->sun_len = strlen (p_sunaddr->sun_path);
203#endif
204
205 ciptr->peeraddr = (char *) p_sunaddr;
206
207 return 1;
208}
209
210
211
212
213#ifndef X11_t
214#define X_STREAMS_DIR "/dev/X"
215#else
216#define X_STREAMS_DIR "/tmp/.X11-pipe"
217#endif
218
219#define DEV_PTMX "/dev/ptmx"
220
221#if defined(X11_t)
222
223#define NAMEDNODENAME "/tmp/.X11-pipe/X"
224#endif
225#if defined(XIM_t)
226#define NAMEDNODENAME "/tmp/.XIM-pipe/XIM"
227#endif
228#if defined(FS_t) || defined (FONT_t)
229#define NAMEDNODENAME "/tmp/.font-pipe/fs"
230#endif
231#if defined(ICE_t)
232#define NAMEDNODENAME "/tmp/.ICE-pipe/"
233#endif
234
235
236
237
238
239#ifdef LOCAL_TRANS_NAMED
240
241/* NAMED */
242
243#ifdef TRANS_CLIENT
244
245static int
246TRANS(NAMEDOpenClient)(XtransConnInfo ciptr, const char *port)
247
248{
249#ifdef NAMEDNODENAME
250 int fd;
251 char server_path[64];
252 struct stat filestat;
253#endif
254
255 prmsg(2,"NAMEDOpenClient(%s)\n", port);
256
257#if !defined(NAMEDNODENAME)
258 prmsg(1,"NAMEDOpenClient: Protocol is not supported by a NAMED connection\n");
259 return -1;
260#else
261 if ( port && *port ) {
262 if( *port == '/' ) { /* A full pathname */
263 (void) snprintf(server_path, sizeof(server_path), "%s", port);
264 } else {
265 (void) snprintf(server_path, sizeof(server_path), "%s%s", NAMEDNODENAME, port);
266 }
267 } else {
268 (void) snprintf(server_path, sizeof(server_path), "%s%ld", NAMEDNODENAME, (long)getpid());
269 }
270
271 if ((fd = open(server_path, O_RDWR)) < 0) {
272 prmsg(1,"NAMEDOpenClient: Cannot open %s for NAMED connection\n", server_path);
273 return -1;
274 }
275
276 if (fstat(fd, &filestat) < 0 ) {
277 prmsg(1,"NAMEDOpenClient: Cannot stat %s for NAMED connection\n", server_path);
278 (void) close(fd);
279 return -1;
280 }
281
282 if ((filestat.st_mode & S_IFMT) != S_IFIFO) {
283 prmsg(1,"NAMEDOpenClient: Device %s is not a FIFO\n", server_path);
284 /* Is this really a failure? */
285 (void) close(fd);
286 return -1;
287 }
288
289
290 if (isastream(fd) <= 0) {
291 prmsg(1,"NAMEDOpenClient: %s is not a streams device\n", server_path);
292 (void) close(fd);
293 return -1;
294 }
295
296 /*
297 * Everything looks good: fill in the XtransConnInfo structure.
298 */
299
300 if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
301 {
302 prmsg(1,"NAMEDOpenClient: failed to fill in addr info\n");
303 close(fd);
304 return -1;
305 }
306
307 return(fd);
308
309#endif /* !NAMEDNODENAME */
310}
311
312#endif /* TRANS_CLIENT */
313
314
315#ifdef TRANS_SERVER
316
317
318#ifdef NAMEDNODENAME
319static int
320TRANS(NAMEDOpenPipe)(const char *server_path)
321{
322 int fd, pipefd[2];
323 struct stat sbuf;
324 int mode;
325
326 prmsg(2,"NAMEDOpenPipe(%s)\n", server_path);
327
328#ifdef HAS_STICKY_DIR_BIT
329 mode = 01777;
330#else
331 mode = 0777;
332#endif
333 if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
334 prmsg (1, "NAMEDOpenPipe: mkdir(%s) failed, errno = %d\n",
335 X_STREAMS_DIR, errno);
336 return(-1);
337 }
338
339 if(stat(server_path, &sbuf) != 0) {
340 if (errno == ENOENT) {
341 if ((fd = creat(server_path, (mode_t)0666)) == -1) {
342 prmsg(1, "NAMEDOpenPipe: Can't open %s\n", server_path);
343 return(-1);
344 }
345 if (fchmod(fd, (mode_t)0666) < 0) {
346 prmsg(1, "NAMEDOpenPipe: Can't chmod %s\n", server_path);
347 close(fd);
348 return(-1);
349 }
350 close(fd);
351 } else {
352 prmsg(1, "NAMEDOpenPipe: stat on %s failed\n", server_path);
353 return(-1);
354 }
355 }
356
357 if( pipe(pipefd) != 0) {
358 prmsg(1, "NAMEDOpenPipe: pipe() failed, errno=%d\n",errno);
359 return(-1);
360 }
361
362 if( ioctl(pipefd[0], I_PUSH, "connld") != 0) {
363 prmsg(1, "NAMEDOpenPipe: ioctl(I_PUSH,\"connld\") failed, errno=%d\n",errno);
364 close(pipefd[0]);
365 close(pipefd[1]);
366 return(-1);
367 }
368
369 if( fattach(pipefd[0], server_path) != 0) {
370 prmsg(1, "NAMEDOpenPipe: fattach(%s) failed, errno=%d\n", server_path,errno);
371 close(pipefd[0]);
372 close(pipefd[1]);
373 return(-1);
374 }
375
376 return(pipefd[1]);
377}
378#endif
379
380static int
381TRANS(NAMEDOpenServer)(XtransConnInfo ciptr, const char *port)
382{
383#ifdef NAMEDNODENAME
384 int fd;
385 char server_path[64];
386#endif
387
388 prmsg(2,"NAMEDOpenServer(%s)\n", port);
389
390#if !defined(NAMEDNODENAME)
391 prmsg(1,"NAMEDOpenServer: Protocol is not supported by a NAMED connection\n");
392 return -1;
393#else
394 if ( port && *port ) {
395 if( *port == '/' ) { /* A full pathname */
396 (void) snprintf(server_path, sizeof(server_path), "%s", port);
397 } else {
398 (void) snprintf(server_path, sizeof(server_path), "%s%s",
399 NAMEDNODENAME, port);
400 }
401 } else {
402 (void) snprintf(server_path, sizeof(server_path), "%s%ld",
403 NAMEDNODENAME, (long)getpid());
404 }
405
406 fd = TRANS(NAMEDOpenPipe)(server_path);
407 if (fd < 0) {
408 return -1;
409 }
410
411 /*
412 * Everything looks good: fill in the XtransConnInfo structure.
413 */
414
415 if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
416 {
417 prmsg(1,"NAMEDOpenServer: failed to fill in addr info\n");
418 TRANS(LocalClose)(ciptr);
419 return -1;
420 }
421
422 return fd;
423
424#endif /* !NAMEDNODENAME */
425}
426
427static int
428TRANS(NAMEDResetListener) (XtransConnInfo ciptr)
429
430{
431 struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr;
432 struct stat statb;
433
434 prmsg(2,"NAMEDResetListener(%p, %d)\n", (void *) ciptr, ciptr->fd);
435
436 if (ciptr->fd != -1) {
437 /*
438 * see if the pipe has disappeared
439 */
440
441 if (stat (sockname->sun_path, &statb) == -1 ||
442 (statb.st_mode & S_IFMT) != S_IFIFO) {
443 prmsg(3, "Pipe %s trashed, recreating\n", sockname->sun_path);
444 TRANS(LocalClose)(ciptr);
445 ciptr->fd = TRANS(NAMEDOpenPipe)(sockname->sun_path);
446 if (ciptr->fd >= 0)
447 return TRANS_RESET_NEW_FD;
448 else
449 return TRANS_CREATE_LISTENER_FAILED;
450 }
451 }
452 return TRANS_RESET_NOOP;
453}
454
455static int
456TRANS(NAMEDAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
457
458{
459 struct strrecvfd str;
460
461 prmsg(2,"NAMEDAccept(%p->%d)\n", (void *) ciptr, ciptr->fd);
462
463 if( ioctl(ciptr->fd, I_RECVFD, &str ) < 0 ) {
464 prmsg(1, "NAMEDAccept: ioctl(I_RECVFD) failed, errno=%d\n", errno);
465 *status = TRANS_ACCEPT_MISC_ERROR;
466 return(-1);
467 }
468
469 /*
470 * Everything looks good: fill in the XtransConnInfo structure.
471 */
472 newciptr->family=ciptr->family;
473 newciptr->addrlen=ciptr->addrlen;
474 if( (newciptr->addr = malloc(newciptr->addrlen)) == NULL ) {
475 prmsg(1,
476 "NAMEDAccept: failed to allocate memory for pipe addr\n");
477 close(str.fd);
478 *status = TRANS_ACCEPT_BAD_MALLOC;
479 return -1;
480 }
481
482 memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
483
484 newciptr->peeraddrlen=newciptr->addrlen;
485 if( (newciptr->peeraddr = malloc(newciptr->peeraddrlen)) == NULL ) {
486 prmsg(1,
487 "NAMEDAccept: failed to allocate memory for peer addr\n");
488 free(newciptr->addr);
489 close(str.fd);
490 *status = TRANS_ACCEPT_BAD_MALLOC;
491 return -1;
492 }
493
494 memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
495
496 *status = 0;
497
498 return str.fd;
499}
500
501#endif /* TRANS_SERVER */
502
503#endif /* LOCAL_TRANS_NAMED */
504
505
506
507
508
509
510
511
512
513
514#ifdef TRANS_REOPEN
515
516#ifdef LOCAL_TRANS_NAMED
517
518static int
519TRANS(NAMEDReopenServer)(XtransConnInfo ciptr, int fd _X_UNUSED, const char *port)
520
521{
522#ifdef NAMEDNODENAME
523 char server_path[64];
524#endif
525
526 prmsg(2,"NAMEDReopenServer(%s)\n", port);
527
528#if !defined(NAMEDNODENAME)
529 prmsg(1,"NAMEDReopenServer: Protocol is not supported by a NAMED connection\n");
530 return 0;
531#else
532 if ( port && *port ) {
533 if( *port == '/' ) { /* A full pathname */
534 snprintf(server_path, sizeof(server_path),"%s", port);
535 } else {
536 snprintf(server_path, sizeof(server_path), "%s%s",
537 NAMEDNODENAME, port);
538 }
539 } else {
540 snprintf(server_path, sizeof(server_path), "%s%ld",
541 NAMEDNODENAME, (long)getpid());
542 }
543
544 if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
545 {
546 prmsg(1,"NAMEDReopenServer: failed to fill in addr info\n");
547 return 0;
548 }
549
550 return 1;
551
552#endif /* !NAMEDNODENAME */
553}
554
555#endif /* LOCAL_TRANS_NAMED */
556
557
558
559#endif /* TRANS_REOPEN */
560
561
562
563/*
564 * This table contains all of the entry points for the different local
565 * connection mechanisms.
566 */
567
568typedef struct _LOCALtrans2dev {
569 const char *transname;
570
571#ifdef TRANS_CLIENT
572
573 int (*devcotsopenclient)(
574 XtransConnInfo, const char * /*port*/
575);
576
577#endif /* TRANS_CLIENT */
578
579#ifdef TRANS_SERVER
580
581 int (*devcotsopenserver)(
582 XtransConnInfo, const char * /*port*/
583);
584
585#endif /* TRANS_SERVER */
586
587#ifdef TRANS_CLIENT
588
589 int (*devcltsopenclient)(
590 XtransConnInfo, const char * /*port*/
591);
592
593#endif /* TRANS_CLIENT */
594
595#ifdef TRANS_SERVER
596
597 int (*devcltsopenserver)(
598 XtransConnInfo, const char * /*port*/
599);
600
601#endif /* TRANS_SERVER */
602
603#ifdef TRANS_REOPEN
604
605 int (*devcotsreopenserver)(
606 XtransConnInfo,
607 int, /* fd */
608 const char * /* port */
609);
610
611 int (*devcltsreopenserver)(
612 XtransConnInfo,
613 int, /* fd */
614 const char * /* port */
615);
616
617#endif /* TRANS_REOPEN */
618
619#ifdef TRANS_SERVER
620
621 int (*devreset)(
622 XtransConnInfo /* ciptr */
623);
624
625 int (*devaccept)(
626 XtransConnInfo, XtransConnInfo, int *
627);
628
629#endif /* TRANS_SERVER */
630
631} LOCALtrans2dev;
632
633static LOCALtrans2dev LOCALtrans2devtab[] = {
634{"",
635#ifdef TRANS_CLIENT
636 TRANS(NAMEDOpenClient),
637#endif /* TRANS_CLIENT */
638#ifdef TRANS_SERVER
639 TRANS(NAMEDOpenServer),
640#endif /* TRANS_SERVER */
641#ifdef TRANS_CLIENT
642 TRANS(OpenFail),
643#endif /* TRANS_CLIENT */
644#ifdef TRANS_SERVER
645 TRANS(OpenFail),
646#endif /* TRANS_SERVER */
647#ifdef TRANS_REOPEN
648 TRANS(NAMEDReopenServer),
649 TRANS(ReopenFail),
650#endif
651#ifdef TRANS_SERVER
652 TRANS(NAMEDResetListener),
653 TRANS(NAMEDAccept)
654#endif /* TRANS_SERVER */
655},
656
657{"local",
658#ifdef TRANS_CLIENT
659 TRANS(NAMEDOpenClient),
660#endif /* TRANS_CLIENT */
661#ifdef TRANS_SERVER
662 TRANS(NAMEDOpenServer),
663#endif /* TRANS_SERVER */
664#ifdef TRANS_CLIENT
665 TRANS(OpenFail),
666#endif /* TRANS_CLIENT */
667#ifdef TRANS_SERVER
668 TRANS(OpenFail),
669#endif /* TRANS_SERVER */
670#ifdef TRANS_REOPEN
671 TRANS(NAMEDReopenServer),
672 TRANS(ReopenFail),
673#endif
674#ifdef TRANS_SERVER
675 TRANS(NAMEDResetListener),
676 TRANS(NAMEDAccept)
677#endif /* TRANS_SERVER */
678},
679
680#ifdef LOCAL_TRANS_NAMED
681{"named",
682#ifdef TRANS_CLIENT
683 TRANS(NAMEDOpenClient),
684#endif /* TRANS_CLIENT */
685#ifdef TRANS_SERVER
686 TRANS(NAMEDOpenServer),
687#endif /* TRANS_SERVER */
688#ifdef TRANS_CLIENT
689 TRANS(OpenFail),
690#endif /* TRANS_CLIENT */
691#ifdef TRANS_SERVER
692 TRANS(OpenFail),
693#endif /* TRANS_SERVER */
694#ifdef TRANS_REOPEN
695 TRANS(NAMEDReopenServer),
696 TRANS(ReopenFail),
697#endif
698#ifdef TRANS_SERVER
699 TRANS(NAMEDResetListener),
700 TRANS(NAMEDAccept)
701#endif /* TRANS_SERVER */
702},
703
704{"pipe",
705#ifdef TRANS_CLIENT
706 TRANS(NAMEDOpenClient),
707#endif /* TRANS_CLIENT */
708#ifdef TRANS_SERVER
709 TRANS(NAMEDOpenServer),
710#endif /* TRANS_SERVER */
711#ifdef TRANS_CLIENT
712 TRANS(OpenFail),
713#endif /* TRANS_CLIENT */
714#ifdef TRANS_SERVER
715 TRANS(OpenFail),
716#endif /* TRANS_SERVER */
717#ifdef TRANS_REOPEN
718 TRANS(NAMEDReopenServer),
719 TRANS(ReopenFail),
720#endif
721#ifdef TRANS_SERVER
722 TRANS(NAMEDResetListener),
723 TRANS(NAMEDAccept)
724#endif /* TRANS_SERVER */
725},
726#endif /* LOCAL_TRANS_NAMED */
727
728
729};
730
731#define NUMTRANSPORTS (sizeof(LOCALtrans2devtab)/sizeof(LOCALtrans2dev))
732
733static const char *XLOCAL=NULL;
734static char *workingXLOCAL=NULL;
735static char *freeXLOCAL=NULL;
736
737#define DEF_XLOCAL "UNIX:NAMED"
738
739static void
740TRANS(LocalInitTransports)(const char *protocol)
741
742{
743 prmsg(3,"LocalInitTransports(%s)\n", protocol);
744
745 if( strcmp(protocol,"local") && strcmp(protocol,"LOCAL") )
746 {
747 workingXLOCAL = freeXLOCAL = strdup (protocol);
748 }
749 else {
750 XLOCAL = getenv("XLOCAL");
751 if(XLOCAL==NULL)
752 XLOCAL=DEF_XLOCAL;
753 workingXLOCAL = freeXLOCAL = strdup (XLOCAL);
754 }
755}
756
757static void
758TRANS(LocalEndTransports)(void)
759
760{
761 prmsg(3,"LocalEndTransports()\n");
762 free(freeXLOCAL);
763 freeXLOCAL = NULL;
764}
765
766#define TYPEBUFSIZE 32
767
768#ifdef TRANS_CLIENT
769
770static LOCALtrans2dev *
771TRANS(LocalGetNextTransport)(void)
772
773{
774 char *typetocheck;
775 prmsg(3,"LocalGetNextTransport()\n");
776
777 while(1)
778 {
779 if( workingXLOCAL == NULL || *workingXLOCAL == '\0' )
780 return NULL;
781
782 typetocheck=workingXLOCAL;
783 workingXLOCAL=strchr(workingXLOCAL,':');
784 if(workingXLOCAL && *workingXLOCAL)
785 *workingXLOCAL++='\0';
786
787 for (unsigned int i = 0; i < NUMTRANSPORTS; i++)
788 {
789#ifndef HAVE_STRCASECMP
790 int j;
791 char typebuf[TYPEBUFSIZE];
792 /*
793 * This is equivalent to a case insensitive strcmp(),
794 * but should be more portable.
795 */
796 strncpy(typebuf,typetocheck,TYPEBUFSIZE);
797 for(j=0;j<TYPEBUFSIZE;j++)
798 if (isupper(typebuf[j]))
799 typebuf[j]=tolower(typebuf[j]);
800
801 /* Now, see if they match */
802 if(!strcmp(LOCALtrans2devtab[i].transname,typebuf))
803#else
804 if(!strcasecmp(LOCALtrans2devtab[i].transname,typetocheck))
805#endif
806 return &LOCALtrans2devtab[i];
807 }
808 }
809#if 0
810 /*NOTREACHED*/
811 return NULL;
812#endif
813}
814
815#ifdef NEED_UTSNAME
816#include <sys/utsname.h>
817#endif
818
819/*
820 * Make sure 'host' is really local.
821 */
822
823static int
824HostReallyLocal (const char *host)
825
826{
827 /*
828 * The 'host' passed to this function may have been generated
829 * by either uname() or gethostname(). We try both if possible.
830 */
831
832#ifdef NEED_UTSNAME
833 struct utsname name;
834#endif
835 char buf[256];
836
837#ifdef NEED_UTSNAME
838 if (uname (&name) >= 0 && strcmp (host, name.nodename) == 0)
839 return (1);
840#endif
841
842 buf[0] = '\0';
843 (void) gethostname (buf, 256);
844 buf[255] = '\0';
845
846 if (strcmp (host, buf) == 0)
847 return (1);
848
849 return (0);
850}
851
852
853static XtransConnInfo
854TRANS(LocalOpenClient)(int type, const char *protocol,
855 const char *host, const char *port)
856
857{
858 LOCALtrans2dev *transptr;
859 XtransConnInfo ciptr;
860 int index;
861
862 prmsg(3,"LocalOpenClient()\n");
863
864 /*
865 * Make sure 'host' is really local. If not, we return failure.
866 * The reason we make this check is because a process may advertise
867 * a "local" address for which it can accept connections, but if a
868 * process on a remote machine tries to connect to this address,
869 * we know for sure it will fail.
870 */
871
872 if (strcmp (host, "unix") != 0 && !HostReallyLocal (host))
873 {
874 prmsg (1,
875 "LocalOpenClient: Cannot connect to non-local host %s\n",
876 host);
877 return NULL;
878 }
879
880
881#if defined(X11_t)
882 /*
883 * X has a well known port, that is transport dependent. It is easier
884 * to handle it here, than try and come up with a transport independent
885 * representation that can be passed in and resolved the usual way.
886 *
887 * The port that is passed here is really a string containing the idisplay
888 * from ConnectDisplay(). Since that is what we want for the local transports,
889 * we don't have to do anything special.
890 */
891#endif /* X11_t */
892
893 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL )
894 {
895 prmsg(1,"LocalOpenClient: calloc(1,%lu) failed\n",
896 sizeof(struct _XtransConnInfo));
897 return NULL;
898 }
899
900 ciptr->fd = -1;
901
902 TRANS(LocalInitTransports)(protocol);
903
904 index = 0;
905 for(transptr=TRANS(LocalGetNextTransport)();
906 transptr!=NULL;transptr=TRANS(LocalGetNextTransport)(), index++)
907 {
908 switch( type )
909 {
910 case XTRANS_OPEN_COTS_CLIENT:
911 ciptr->fd=transptr->devcotsopenclient(ciptr,port);
912 break;
913 case XTRANS_OPEN_COTS_SERVER:
914 prmsg(1,
915 "LocalOpenClient: Should not be opening a server with this function\n");
916 break;
917 default:
918 prmsg(1,
919 "LocalOpenClient: Unknown Open type %d\n",
920 type);
921 }
922 if( ciptr->fd >= 0 )
923 break;
924 }
925
926 TRANS(LocalEndTransports)();
927
928 if( ciptr->fd < 0 )
929 {
930 free(ciptr);
931 return NULL;
932 }
933
934 ciptr->priv=(char *)transptr;
935 ciptr->index = index;
936
937 return ciptr;
938}
939
940#endif /* TRANS_CLIENT */
941
942
943#ifdef TRANS_SERVER
944
945static XtransConnInfo
946TRANS(LocalOpenServer)(int type, const char *protocol,
947 const char *host _X_UNUSED, const char *port)
948
949{
950 XtransConnInfo ciptr;
951
952 prmsg(2,"LocalOpenServer(%d,%s,%s)\n", type, protocol, port);
953
954#if defined(X11_t)
955 /*
956 * For X11, the port will be in the format xserverN where N is the
957 * display number. All of the local connections just need to know
958 * the display number because they don't do any name resolution on
959 * the port. This just truncates port to the display portion.
960 */
961#endif /* X11_t */
962
963 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL )
964 {
965 prmsg(1,"LocalOpenServer: calloc(1,%lu) failed\n",
966 sizeof(struct _XtransConnInfo));
967 return NULL;
968 }
969
970 for (unsigned int i = 1; i < NUMTRANSPORTS; i++)
971 {
972 if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 )
973 continue;
974 switch( type )
975 {
976 case XTRANS_OPEN_COTS_CLIENT:
977 prmsg(1,
978 "LocalOpenServer: Should not be opening a client with this function\n");
979 break;
980 case XTRANS_OPEN_COTS_SERVER:
981 ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port);
982 break;
983 default:
984 prmsg(1,"LocalOpenServer: Unknown Open type %d\n",
985 type );
986 }
987 if( ciptr->fd >= 0 ) {
988 ciptr->priv=(char *)&LOCALtrans2devtab[i];
989 ciptr->index=i;
990 ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
991 return ciptr;
992 }
993 }
994
995 free(ciptr);
996 return NULL;
997}
998
999#endif /* TRANS_SERVER */
1000
1001
1002#ifdef TRANS_REOPEN
1003
1004static XtransConnInfo
1005TRANS(LocalReopenServer)(int type, int index, int fd, const char *port)
1006
1007{
1008 XtransConnInfo ciptr;
1009 int stat = 0;
1010
1011 prmsg(2,"LocalReopenServer(%d,%d,%d)\n", type, index, fd);
1012
1013 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL )
1014 {
1015 prmsg(1,"LocalReopenServer: calloc(1,%lu) failed\n",
1016 sizeof(struct _XtransConnInfo));
1017 return NULL;
1018 }
1019
1020 ciptr->fd = fd;
1021
1022 switch( type )
1023 {
1024 case XTRANS_OPEN_COTS_SERVER:
1025 stat = LOCALtrans2devtab[index].devcotsreopenserver(ciptr,fd,port);
1026 break;
1027 default:
1028 prmsg(1,"LocalReopenServer: Unknown Open type %d\n",
1029 type );
1030 }
1031
1032 if( stat > 0 ) {
1033 ciptr->priv=(char *)&LOCALtrans2devtab[index];
1034 ciptr->index=index;
1035 ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
1036 return ciptr;
1037 }
1038
1039 free(ciptr);
1040 return NULL;
1041}
1042
1043#endif /* TRANS_REOPEN */
1044
1045
1046
1047/*
1048 * This is the Local implementation of the X Transport service layer
1049 */
1050
1051#ifdef TRANS_CLIENT
1052
1053static XtransConnInfo
1054TRANS(LocalOpenCOTSClient)(Xtransport *thistrans _X_UNUSED, const char *protocol,
1055 const char *host, const char *port)
1056
1057{
1058 prmsg(2,"LocalOpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
1059
1060 return TRANS(LocalOpenClient)(XTRANS_OPEN_COTS_CLIENT, protocol, host, port);
1061}
1062
1063#endif /* TRANS_CLIENT */
1064
1065
1066#ifdef TRANS_SERVER
1067
1068static XtransConnInfo
1069TRANS(LocalOpenCOTSServer)(Xtransport *thistrans, const char *protocol,
1070 const char *host, const char *port)
1071
1072{
1073 char *typetocheck = NULL;
1074 int found = 0;
1075
1076 prmsg(2,"LocalOpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
1077
1078 /* Check if this local type is in the XLOCAL list */
1079 TRANS(LocalInitTransports)("local");
1080 typetocheck = workingXLOCAL;
1081 while (typetocheck && !found) {
1082#ifndef HAVE_STRCASECMP
1083 int j;
1084 char typebuf[TYPEBUFSIZE];
1085#endif
1086
1087 workingXLOCAL = strchr(workingXLOCAL, ':');
1088 if (workingXLOCAL && *workingXLOCAL)
1089 *workingXLOCAL++ = '\0';
1090#ifndef HAVE_STRCASECMP
1091 strncpy(typebuf, typetocheck, TYPEBUFSIZE);
1092 for (j = 0; j < TYPEBUFSIZE; j++)
1093 if (isupper(typebuf[j]))
1094 typebuf[j] = tolower(typebuf[j]);
1095 if (!strcmp(thistrans->TransName, typebuf))
1096#else
1097 if (!strcasecmp(thistrans->TransName, typetocheck))
1098#endif
1099 found = 1;
1100 typetocheck = workingXLOCAL;
1101 }
1102 TRANS(LocalEndTransports)();
1103
1104 if (!found) {
1105 prmsg(3,"LocalOpenCOTSServer: disabling %s\n",thistrans->TransName);
1106 thistrans->flags |= TRANS_DISABLED;
1107 return NULL;
1108 }
1109
1110 return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port);
1111}
1112
1113#endif /* TRANS_SERVER */
1114
1115#ifdef TRANS_REOPEN
1116
1117static XtransConnInfo
1118TRANS(LocalReopenCOTSServer)(Xtransport *thistrans, int fd, const char *port)
1119
1120{
1121 unsigned int index;
1122
1123 prmsg(2,"LocalReopenCOTSServer(%d,%s)\n", fd, port);
1124
1125 for(index=1;index<NUMTRANSPORTS;index++)
1126 {
1127 if( strcmp(thistrans->TransName,
1128 LOCALtrans2devtab[index].transname) == 0 )
1129 break;
1130 }
1131
1132 if (index >= NUMTRANSPORTS)
1133 {
1134 return (NULL);
1135 }
1136
1137 return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER,
1138 index, fd, port);
1139}
1140
1141#endif /* TRANS_REOPEN */
1142
1143
1144
1145static int
1146TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg)
1147
1148{
1149 prmsg(2,"LocalSetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
1150
1151 return -1;
1152}
1153
1154
1155#ifdef TRANS_SERVER
1156
1157static int
1158TRANS(LocalCreateListener)(XtransConnInfo ciptr, const char *port,
1159 unsigned int flags _X_UNUSED)
1160
1161{
1162 prmsg(2,"LocalCreateListener(%p->%d,%s)\n", (void *) ciptr, ciptr->fd, port);
1163
1164 return 0;
1165}
1166
1167static int
1168TRANS(LocalResetListener)(XtransConnInfo ciptr)
1169
1170{
1171 LOCALtrans2dev *transptr;
1172
1173 prmsg(2,"LocalResetListener(%p)\n", (void *) ciptr);
1174
1175 transptr=(LOCALtrans2dev *)ciptr->priv;
1176 if (transptr->devreset != NULL) {
1177 return transptr->devreset(ciptr);
1178 }
1179 return TRANS_RESET_NOOP;
1180}
1181
1182
1183static XtransConnInfo
1184TRANS(LocalAccept)(XtransConnInfo ciptr, int *status)
1185
1186{
1187 XtransConnInfo newciptr;
1188 LOCALtrans2dev *transptr;
1189
1190 prmsg(2,"LocalAccept(%p->%d)\n", (void *) ciptr, ciptr->fd);
1191
1192 transptr=(LOCALtrans2dev *)ciptr->priv;
1193
1194 if( (newciptr = calloc(1,sizeof(struct _XtransConnInfo)))==NULL )
1195 {
1196 prmsg(1,"LocalAccept: calloc(1,%lu) failed\n",
1197 sizeof(struct _XtransConnInfo));
1198 *status = TRANS_ACCEPT_BAD_MALLOC;
1199 return NULL;
1200 }
1201
1202 newciptr->fd=transptr->devaccept(ciptr,newciptr,status);
1203
1204 if( newciptr->fd < 0 )
1205 {
1206 free(newciptr);
1207 return NULL;
1208 }
1209
1210 newciptr->priv=(char *)transptr;
1211 newciptr->index = ciptr->index;
1212
1213 *status = 0;
1214
1215 return newciptr;
1216}
1217
1218#endif /* TRANS_SERVER */
1219
1220
1221#ifdef TRANS_CLIENT
1222
1223static int
1224TRANS(LocalConnect)(XtransConnInfo ciptr,
1225 const char *host _X_UNUSED, const char *port)
1226
1227{
1228 prmsg(2,"LocalConnect(%p->%d,%s)\n", (void *) ciptr, ciptr->fd, port);
1229
1230 return 0;
1231}
1232
1233#endif /* TRANS_CLIENT */
1234
1235
1236static int
1237TRANS(LocalBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend )
1238
1239{
1240 prmsg(2,"LocalBytesReadable(%p->%d,%p)\n",
1241 (void *) ciptr, ciptr->fd, (void *) pend);
1242
1243 return ioctl(ciptr->fd, FIONREAD, (char *)pend);
1244}
1245
1246static int
1247TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size)
1248
1249{
1250 prmsg(2,"LocalRead(%d,%p,%d)\n", ciptr->fd, (void *) buf, size );
1251
1252 return read(ciptr->fd,buf,size);
1253}
1254
1255static int
1256TRANS(LocalWrite)(XtransConnInfo ciptr, const char *buf, int size)
1257
1258{
1259 prmsg(2,"LocalWrite(%d,%p,%d)\n", ciptr->fd, (const void *) buf, size );
1260
1261 return write(ciptr->fd,buf,size);
1262}
1263
1264static int
1265TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
1266
1267{
1268 prmsg(2,"LocalReadv(%d,%p,%d)\n", ciptr->fd, (void *) buf, size );
1269
1270 return READV(ciptr,buf,size);
1271}
1272
1273static int
1274TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
1275
1276{
1277 prmsg(2,"LocalWritev(%d,%p,%d)\n", ciptr->fd, (const void *) buf, size );
1278
1279 return WRITEV(ciptr,buf,size);
1280}
1281
1282static int
1283TRANS(LocalDisconnect)(XtransConnInfo ciptr)
1284
1285{
1286 prmsg(2,"LocalDisconnect(%p->%d)\n", (void *) ciptr, ciptr->fd);
1287
1288 return 0;
1289}
1290
1291static int
1292TRANS(LocalClose)(XtransConnInfo ciptr)
1293
1294{
1295 struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr;
1296 int ret;
1297
1298 prmsg(2,"LocalClose(%p->%d)\n", (void *) ciptr, ciptr->fd );
1299
1300 ret=close(ciptr->fd);
1301
1302 if(ciptr->flags
1303 && sockname
1304 && sockname->sun_family == AF_UNIX
1305 && sockname->sun_path[0] )
1306 {
1307 if (!(ciptr->flags & TRANS_NOUNLINK))
1308 unlink(sockname->sun_path);
1309 }
1310
1311 return ret;
1312}
1313
1314static int
1315TRANS(LocalCloseForCloning)(XtransConnInfo ciptr)
1316
1317{
1318 int ret;
1319
1320 prmsg(2,"LocalCloseForCloning(%p->%d)\n", (void *) ciptr, ciptr->fd );
1321
1322 /* Don't unlink path */
1323
1324 ret=close(ciptr->fd);
1325
1326 return ret;
1327}
1328
1329
1330/*
1331 * MakeAllCOTSServerListeners() will go through the entire Xtransports[]
1332 * array defined in Xtrans.c and try to OpenCOTSServer() for each entry.
1333 * We will add duplicate entries to that table so that the OpenCOTSServer()
1334 * function will get called once for each type of local transport.
1335 *
1336 * The TransName is in lowercase, so it will never match during a normal
1337 * call to SelectTransport() in Xtrans.c.
1338 */
1339
1340#ifdef TRANS_SERVER
1341static const char * local_aliases[] = {
1342 "named",
1343 "pipe", /* compatibility with Solaris Xlib */
1344 NULL };
1345#endif
1346
1347static Xtransport TRANS(LocalFuncs) = {
1348 /* Local Interface */
1349 "local",
1350 TRANS_ALIAS | TRANS_LOCAL,
1351#ifdef TRANS_CLIENT
1352 TRANS(LocalOpenCOTSClient),
1353#endif /* TRANS_CLIENT */
1354#ifdef TRANS_SERVER
1355 local_aliases,
1356 TRANS(LocalOpenCOTSServer),
1357#endif /* TRANS_SERVER */
1358#ifdef TRANS_REOPEN
1359 TRANS(LocalReopenCOTSServer),
1360#endif
1361 TRANS(LocalSetOption),
1362#ifdef TRANS_SERVER
1363 TRANS(LocalCreateListener),
1364 TRANS(LocalResetListener),
1365 TRANS(LocalAccept),
1366#endif /* TRANS_SERVER */
1367#ifdef TRANS_CLIENT
1368 TRANS(LocalConnect),
1369#endif /* TRANS_CLIENT */
1370 TRANS(LocalBytesReadable),
1371 TRANS(LocalRead),
1372 TRANS(LocalWrite),
1373 TRANS(LocalReadv),
1374 TRANS(LocalWritev),
1375#if XTRANS_SEND_FDS
1376 TRANS(LocalSendFdInvalid),
1377 TRANS(LocalRecvFdInvalid),
1378#endif
1379 TRANS(LocalDisconnect),
1380 TRANS(LocalClose),
1381 TRANS(LocalCloseForCloning),
1382};
1383
1384
1385#ifdef LOCAL_TRANS_NAMED
1386
1387static Xtransport TRANS(NAMEDFuncs) = {
1388 /* Local Interface */
1389 "named",
1390 TRANS_LOCAL,
1391#ifdef TRANS_CLIENT
1392 TRANS(LocalOpenCOTSClient),
1393#endif /* TRANS_CLIENT */
1394#ifdef TRANS_SERVER
1395 NULL,
1396 TRANS(LocalOpenCOTSServer),
1397#endif /* TRANS_SERVER */
1398#ifdef TRANS_REOPEN
1399 TRANS(LocalReopenCOTSServer),
1400#endif
1401 TRANS(LocalSetOption),
1402#ifdef TRANS_SERVER
1403 TRANS(LocalCreateListener),
1404 TRANS(LocalResetListener),
1405 TRANS(LocalAccept),
1406#endif /* TRANS_SERVER */
1407#ifdef TRANS_CLIENT
1408 TRANS(LocalConnect),
1409#endif /* TRANS_CLIENT */
1410 TRANS(LocalBytesReadable),
1411 TRANS(LocalRead),
1412 TRANS(LocalWrite),
1413 TRANS(LocalReadv),
1414 TRANS(LocalWritev),
1415#if XTRANS_SEND_FDS
1416 TRANS(LocalSendFdInvalid),
1417 TRANS(LocalRecvFdInvalid),
1418#endif
1419 TRANS(LocalDisconnect),
1420 TRANS(LocalClose),
1421 TRANS(LocalCloseForCloning),
1422};
1423
1424static Xtransport TRANS(PIPEFuncs) = {
1425 /* Local Interface */
1426 "pipe",
1427 TRANS_ALIAS | TRANS_LOCAL,
1428#ifdef TRANS_CLIENT
1429 TRANS(LocalOpenCOTSClient),
1430#endif /* TRANS_CLIENT */
1431#ifdef TRANS_SERVER
1432 NULL,
1433 TRANS(LocalOpenCOTSServer),
1434#endif /* TRANS_SERVER */
1435#ifdef TRANS_REOPEN
1436 TRANS(LocalReopenCOTSServer),
1437#endif
1438 TRANS(LocalSetOption),
1439#ifdef TRANS_SERVER
1440 TRANS(LocalCreateListener),
1441 TRANS(LocalResetListener),
1442 TRANS(LocalAccept),
1443#endif /* TRANS_SERVER */
1444#ifdef TRANS_CLIENT
1445 TRANS(LocalConnect),
1446#endif /* TRANS_CLIENT */
1447 TRANS(LocalBytesReadable),
1448 TRANS(LocalRead),
1449 TRANS(LocalWrite),
1450 TRANS(LocalReadv),
1451 TRANS(LocalWritev),
1452#if XTRANS_SEND_FDS
1453 TRANS(LocalSendFdInvalid),
1454 TRANS(LocalRecvFdInvalid),
1455#endif
1456 TRANS(LocalDisconnect),
1457 TRANS(LocalClose),
1458 TRANS(LocalCloseForCloning),
1459};
1460#endif /* LOCAL_TRANS_NAMED */
1461
1462