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