Xtranslcl.c revision 47a4502c
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", 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", 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",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",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", 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", 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", ciptr, ciptr->fd, pend); 1241 1242 return ioctl(ciptr->fd, FIONREAD, (char *)pend); 1243} 1244 1245static int 1246TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size) 1247 1248{ 1249 prmsg(2,"LocalRead(%d,%p,%d)\n", ciptr->fd, buf, size ); 1250 1251 return read(ciptr->fd,buf,size); 1252} 1253 1254static int 1255TRANS(LocalWrite)(XtransConnInfo ciptr, char *buf, int size) 1256 1257{ 1258 prmsg(2,"LocalWrite(%d,%p,%d)\n", ciptr->fd, buf, size ); 1259 1260 return write(ciptr->fd,buf,size); 1261} 1262 1263static int 1264TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size) 1265 1266{ 1267 prmsg(2,"LocalReadv(%d,%p,%d)\n", ciptr->fd, buf, size ); 1268 1269 return READV(ciptr,buf,size); 1270} 1271 1272static int 1273TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size) 1274 1275{ 1276 prmsg(2,"LocalWritev(%d,%p,%d)\n", ciptr->fd, buf, size ); 1277 1278 return WRITEV(ciptr,buf,size); 1279} 1280 1281static int 1282TRANS(LocalDisconnect)(XtransConnInfo ciptr) 1283 1284{ 1285 prmsg(2,"LocalDisconnect(%p->%d)\n", ciptr, ciptr->fd); 1286 1287 return 0; 1288} 1289 1290static int 1291TRANS(LocalClose)(XtransConnInfo ciptr) 1292 1293{ 1294 struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr; 1295 int ret; 1296 1297 prmsg(2,"LocalClose(%p->%d)\n", ciptr, ciptr->fd ); 1298 1299 ret=close(ciptr->fd); 1300 1301 if(ciptr->flags 1302 && sockname 1303 && sockname->sun_family == AF_UNIX 1304 && sockname->sun_path[0] ) 1305 { 1306 if (!(ciptr->flags & TRANS_NOUNLINK)) 1307 unlink(sockname->sun_path); 1308 } 1309 1310 return ret; 1311} 1312 1313static int 1314TRANS(LocalCloseForCloning)(XtransConnInfo ciptr) 1315 1316{ 1317 int ret; 1318 1319 prmsg(2,"LocalCloseForCloning(%p->%d)\n", ciptr, ciptr->fd ); 1320 1321 /* Don't unlink path */ 1322 1323 ret=close(ciptr->fd); 1324 1325 return ret; 1326} 1327 1328 1329/* 1330 * MakeAllCOTSServerListeners() will go through the entire Xtransports[] 1331 * array defined in Xtrans.c and try to OpenCOTSServer() for each entry. 1332 * We will add duplicate entries to that table so that the OpenCOTSServer() 1333 * function will get called once for each type of local transport. 1334 * 1335 * The TransName is in lowercase, so it will never match during a normal 1336 * call to SelectTransport() in Xtrans.c. 1337 */ 1338 1339#ifdef TRANS_SERVER 1340static const char * local_aliases[] = { 1341 "named", 1342 "pipe", /* compatibility with Solaris Xlib */ 1343 NULL }; 1344#endif 1345 1346Xtransport TRANS(LocalFuncs) = { 1347 /* Local Interface */ 1348 "local", 1349 TRANS_ALIAS | TRANS_LOCAL, 1350#ifdef TRANS_CLIENT 1351 TRANS(LocalOpenCOTSClient), 1352#endif /* TRANS_CLIENT */ 1353#ifdef TRANS_SERVER 1354 local_aliases, 1355 TRANS(LocalOpenCOTSServer), 1356#endif /* TRANS_SERVER */ 1357#ifdef TRANS_REOPEN 1358 TRANS(LocalReopenCOTSServer), 1359#endif 1360 TRANS(LocalSetOption), 1361#ifdef TRANS_SERVER 1362 TRANS(LocalCreateListener), 1363 TRANS(LocalResetListener), 1364 TRANS(LocalAccept), 1365#endif /* TRANS_SERVER */ 1366#ifdef TRANS_CLIENT 1367 TRANS(LocalConnect), 1368#endif /* TRANS_CLIENT */ 1369 TRANS(LocalBytesReadable), 1370 TRANS(LocalRead), 1371 TRANS(LocalWrite), 1372 TRANS(LocalReadv), 1373 TRANS(LocalWritev), 1374#if XTRANS_SEND_FDS 1375 TRANS(LocalSendFdInvalid), 1376 TRANS(LocalRecvFdInvalid), 1377#endif 1378 TRANS(LocalDisconnect), 1379 TRANS(LocalClose), 1380 TRANS(LocalCloseForCloning), 1381}; 1382 1383 1384#ifdef LOCAL_TRANS_NAMED 1385 1386Xtransport TRANS(NAMEDFuncs) = { 1387 /* Local Interface */ 1388 "named", 1389 TRANS_LOCAL, 1390#ifdef TRANS_CLIENT 1391 TRANS(LocalOpenCOTSClient), 1392#endif /* TRANS_CLIENT */ 1393#ifdef TRANS_SERVER 1394 NULL, 1395 TRANS(LocalOpenCOTSServer), 1396#endif /* TRANS_SERVER */ 1397#ifdef TRANS_REOPEN 1398 TRANS(LocalReopenCOTSServer), 1399#endif 1400 TRANS(LocalSetOption), 1401#ifdef TRANS_SERVER 1402 TRANS(LocalCreateListener), 1403 TRANS(LocalResetListener), 1404 TRANS(LocalAccept), 1405#endif /* TRANS_SERVER */ 1406#ifdef TRANS_CLIENT 1407 TRANS(LocalConnect), 1408#endif /* TRANS_CLIENT */ 1409 TRANS(LocalBytesReadable), 1410 TRANS(LocalRead), 1411 TRANS(LocalWrite), 1412 TRANS(LocalReadv), 1413 TRANS(LocalWritev), 1414#if XTRANS_SEND_FDS 1415 TRANS(LocalSendFdInvalid), 1416 TRANS(LocalRecvFdInvalid), 1417#endif 1418 TRANS(LocalDisconnect), 1419 TRANS(LocalClose), 1420 TRANS(LocalCloseForCloning), 1421}; 1422 1423Xtransport TRANS(PIPEFuncs) = { 1424 /* Local Interface */ 1425 "pipe", 1426 TRANS_ALIAS | TRANS_LOCAL, 1427#ifdef TRANS_CLIENT 1428 TRANS(LocalOpenCOTSClient), 1429#endif /* TRANS_CLIENT */ 1430#ifdef TRANS_SERVER 1431 NULL, 1432 TRANS(LocalOpenCOTSServer), 1433#endif /* TRANS_SERVER */ 1434#ifdef TRANS_REOPEN 1435 TRANS(LocalReopenCOTSServer), 1436#endif 1437 TRANS(LocalSetOption), 1438#ifdef TRANS_SERVER 1439 TRANS(LocalCreateListener), 1440 TRANS(LocalResetListener), 1441 TRANS(LocalAccept), 1442#endif /* TRANS_SERVER */ 1443#ifdef TRANS_CLIENT 1444 TRANS(LocalConnect), 1445#endif /* TRANS_CLIENT */ 1446 TRANS(LocalBytesReadable), 1447 TRANS(LocalRead), 1448 TRANS(LocalWrite), 1449 TRANS(LocalReadv), 1450 TRANS(LocalWritev), 1451#if XTRANS_SEND_FDS 1452 TRANS(LocalSendFdInvalid), 1453 TRANS(LocalRecvFdInvalid), 1454#endif 1455 TRANS(LocalDisconnect), 1456 TRANS(LocalClose), 1457 TRANS(LocalCloseForCloning), 1458}; 1459#endif /* LOCAL_TRANS_NAMED */ 1460 1461 1462