Xtranslcl.c revision e45ace2b
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=(char *)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 int i; 775 char *typetocheck; 776 prmsg(3,"LocalGetNextTransport()\n"); 777 778 while(1) 779 { 780 if( workingXLOCAL == NULL || *workingXLOCAL == '\0' ) 781 return NULL; 782 783 typetocheck=workingXLOCAL; 784 workingXLOCAL=strchr(workingXLOCAL,':'); 785 if(workingXLOCAL && *workingXLOCAL) 786 *workingXLOCAL++='\0'; 787 788 for(i=0;i<NUMTRANSPORTS;i++) 789 { 790#ifndef HAVE_STRCASECMP 791 int j; 792 char typebuf[TYPEBUFSIZE]; 793 /* 794 * This is equivalent to a case insensitive strcmp(), 795 * but should be more portable. 796 */ 797 strncpy(typebuf,typetocheck,TYPEBUFSIZE); 798 for(j=0;j<TYPEBUFSIZE;j++) 799 if (isupper(typebuf[j])) 800 typebuf[j]=tolower(typebuf[j]); 801 802 /* Now, see if they match */ 803 if(!strcmp(LOCALtrans2devtab[i].transname,typebuf)) 804#else 805 if(!strcasecmp(LOCALtrans2devtab[i].transname,typetocheck)) 806#endif 807 return &LOCALtrans2devtab[i]; 808 } 809 } 810#if 0 811 /*NOTREACHED*/ 812 return NULL; 813#endif 814} 815 816#ifdef NEED_UTSNAME 817#include <sys/utsname.h> 818#endif 819 820/* 821 * Make sure 'host' is really local. 822 */ 823 824static int 825HostReallyLocal (const char *host) 826 827{ 828 /* 829 * The 'host' passed to this function may have been generated 830 * by either uname() or gethostname(). We try both if possible. 831 */ 832 833#ifdef NEED_UTSNAME 834 struct utsname name; 835#endif 836 char buf[256]; 837 838#ifdef NEED_UTSNAME 839 if (uname (&name) >= 0 && strcmp (host, name.nodename) == 0) 840 return (1); 841#endif 842 843 buf[0] = '\0'; 844 (void) gethostname (buf, 256); 845 buf[255] = '\0'; 846 847 if (strcmp (host, buf) == 0) 848 return (1); 849 850 return (0); 851} 852 853 854static XtransConnInfo 855TRANS(LocalOpenClient)(int type, const char *protocol, 856 const char *host, const char *port) 857 858{ 859 LOCALtrans2dev *transptr; 860 XtransConnInfo ciptr; 861 int index; 862 863 prmsg(3,"LocalOpenClient()\n"); 864 865 /* 866 * Make sure 'host' is really local. If not, we return failure. 867 * The reason we make this check is because a process may advertise 868 * a "local" address for which it can accept connections, but if a 869 * process on a remote machine tries to connect to this address, 870 * we know for sure it will fail. 871 */ 872 873 if (strcmp (host, "unix") != 0 && !HostReallyLocal (host)) 874 { 875 prmsg (1, 876 "LocalOpenClient: Cannot connect to non-local host %s\n", 877 host); 878 return NULL; 879 } 880 881 882#if defined(X11_t) 883 /* 884 * X has a well known port, that is transport dependent. It is easier 885 * to handle it here, than try and come up with a transport independent 886 * representation that can be passed in and resolved the usual way. 887 * 888 * The port that is passed here is really a string containing the idisplay 889 * from ConnectDisplay(). Since that is what we want for the local transports, 890 * we don't have to do anything special. 891 */ 892#endif /* X11_t */ 893 894 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) 895 { 896 prmsg(1,"LocalOpenClient: calloc(1,%lu) failed\n", 897 sizeof(struct _XtransConnInfo)); 898 return NULL; 899 } 900 901 ciptr->fd = -1; 902 903 TRANS(LocalInitTransports)(protocol); 904 905 index = 0; 906 for(transptr=TRANS(LocalGetNextTransport)(); 907 transptr!=NULL;transptr=TRANS(LocalGetNextTransport)(), index++) 908 { 909 switch( type ) 910 { 911 case XTRANS_OPEN_COTS_CLIENT: 912 ciptr->fd=transptr->devcotsopenclient(ciptr,port); 913 break; 914 case XTRANS_OPEN_COTS_SERVER: 915 prmsg(1, 916 "LocalOpenClient: Should not be opening a server with this function\n"); 917 break; 918 default: 919 prmsg(1, 920 "LocalOpenClient: Unknown Open type %d\n", 921 type); 922 } 923 if( ciptr->fd >= 0 ) 924 break; 925 } 926 927 TRANS(LocalEndTransports)(); 928 929 if( ciptr->fd < 0 ) 930 { 931 free(ciptr); 932 return NULL; 933 } 934 935 ciptr->priv=(char *)transptr; 936 ciptr->index = index; 937 938 return ciptr; 939} 940 941#endif /* TRANS_CLIENT */ 942 943 944#ifdef TRANS_SERVER 945 946static XtransConnInfo 947TRANS(LocalOpenServer)(int type, const char *protocol, 948 const char *host _X_UNUSED, const char *port) 949 950{ 951 int i; 952 XtransConnInfo ciptr; 953 954 prmsg(2,"LocalOpenServer(%d,%s,%s)\n", type, protocol, port); 955 956#if defined(X11_t) 957 /* 958 * For X11, the port will be in the format xserverN where N is the 959 * display number. All of the local connections just need to know 960 * the display number because they don't do any name resolution on 961 * the port. This just truncates port to the display portion. 962 */ 963#endif /* X11_t */ 964 965 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) 966 { 967 prmsg(1,"LocalOpenServer: calloc(1,%lu) failed\n", 968 sizeof(struct _XtransConnInfo)); 969 return NULL; 970 } 971 972 for(i=1;i<NUMTRANSPORTS;i++) 973 { 974 if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 ) 975 continue; 976 switch( type ) 977 { 978 case XTRANS_OPEN_COTS_CLIENT: 979 prmsg(1, 980 "LocalOpenServer: Should not be opening a client with this function\n"); 981 break; 982 case XTRANS_OPEN_COTS_SERVER: 983 ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port); 984 break; 985 default: 986 prmsg(1,"LocalOpenServer: Unknown Open type %d\n", 987 type ); 988 } 989 if( ciptr->fd >= 0 ) { 990 ciptr->priv=(char *)&LOCALtrans2devtab[i]; 991 ciptr->index=i; 992 ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 993 return ciptr; 994 } 995 } 996 997 free(ciptr); 998 return NULL; 999} 1000 1001#endif /* TRANS_SERVER */ 1002 1003 1004#ifdef TRANS_REOPEN 1005 1006static XtransConnInfo 1007TRANS(LocalReopenServer)(int type, int index, int fd, const char *port) 1008 1009{ 1010 XtransConnInfo ciptr; 1011 int stat = 0; 1012 1013 prmsg(2,"LocalReopenServer(%d,%d,%d)\n", type, index, fd); 1014 1015 if( (ciptr = calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) 1016 { 1017 prmsg(1,"LocalReopenServer: calloc(1,%lu) failed\n", 1018 sizeof(struct _XtransConnInfo)); 1019 return NULL; 1020 } 1021 1022 ciptr->fd = fd; 1023 1024 switch( type ) 1025 { 1026 case XTRANS_OPEN_COTS_SERVER: 1027 stat = LOCALtrans2devtab[index].devcotsreopenserver(ciptr,fd,port); 1028 break; 1029 default: 1030 prmsg(1,"LocalReopenServer: Unknown Open type %d\n", 1031 type ); 1032 } 1033 1034 if( stat > 0 ) { 1035 ciptr->priv=(char *)&LOCALtrans2devtab[index]; 1036 ciptr->index=index; 1037 ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS); 1038 return ciptr; 1039 } 1040 1041 free(ciptr); 1042 return NULL; 1043} 1044 1045#endif /* TRANS_REOPEN */ 1046 1047 1048 1049/* 1050 * This is the Local implementation of the X Transport service layer 1051 */ 1052 1053#ifdef TRANS_CLIENT 1054 1055static XtransConnInfo 1056TRANS(LocalOpenCOTSClient)(Xtransport *thistrans _X_UNUSED, const char *protocol, 1057 const char *host, const char *port) 1058 1059{ 1060 prmsg(2,"LocalOpenCOTSClient(%s,%s,%s)\n",protocol,host,port); 1061 1062 return TRANS(LocalOpenClient)(XTRANS_OPEN_COTS_CLIENT, protocol, host, port); 1063} 1064 1065#endif /* TRANS_CLIENT */ 1066 1067 1068#ifdef TRANS_SERVER 1069 1070static XtransConnInfo 1071TRANS(LocalOpenCOTSServer)(Xtransport *thistrans, const char *protocol, 1072 const char *host, const char *port) 1073 1074{ 1075 char *typetocheck = NULL; 1076 int found = 0; 1077 1078 prmsg(2,"LocalOpenCOTSServer(%s,%s,%s)\n",protocol,host,port); 1079 1080 /* Check if this local type is in the XLOCAL list */ 1081 TRANS(LocalInitTransports)("local"); 1082 typetocheck = workingXLOCAL; 1083 while (typetocheck && !found) { 1084#ifndef HAVE_STRCASECMP 1085 int j; 1086 char typebuf[TYPEBUFSIZE]; 1087#endif 1088 1089 workingXLOCAL = strchr(workingXLOCAL, ':'); 1090 if (workingXLOCAL && *workingXLOCAL) 1091 *workingXLOCAL++ = '\0'; 1092#ifndef HAVE_STRCASECMP 1093 strncpy(typebuf, typetocheck, TYPEBUFSIZE); 1094 for (j = 0; j < TYPEBUFSIZE; j++) 1095 if (isupper(typebuf[j])) 1096 typebuf[j] = tolower(typebuf[j]); 1097 if (!strcmp(thistrans->TransName, typebuf)) 1098#else 1099 if (!strcasecmp(thistrans->TransName, typetocheck)) 1100#endif 1101 found = 1; 1102 typetocheck = workingXLOCAL; 1103 } 1104 TRANS(LocalEndTransports)(); 1105 1106 if (!found) { 1107 prmsg(3,"LocalOpenCOTSServer: disabling %s\n",thistrans->TransName); 1108 thistrans->flags |= TRANS_DISABLED; 1109 return NULL; 1110 } 1111 1112 return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port); 1113} 1114 1115#endif /* TRANS_SERVER */ 1116 1117#ifdef TRANS_REOPEN 1118 1119static XtransConnInfo 1120TRANS(LocalReopenCOTSServer)(Xtransport *thistrans, int fd, const char *port) 1121 1122{ 1123 int index; 1124 1125 prmsg(2,"LocalReopenCOTSServer(%d,%s)\n", fd, port); 1126 1127 for(index=1;index<NUMTRANSPORTS;index++) 1128 { 1129 if( strcmp(thistrans->TransName, 1130 LOCALtrans2devtab[index].transname) == 0 ) 1131 break; 1132 } 1133 1134 if (index >= NUMTRANSPORTS) 1135 { 1136 return (NULL); 1137 } 1138 1139 return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER, 1140 index, fd, port); 1141} 1142 1143#endif /* TRANS_REOPEN */ 1144 1145 1146 1147static int 1148TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg) 1149 1150{ 1151 prmsg(2,"LocalSetOption(%d,%d,%d)\n",ciptr->fd,option,arg); 1152 1153 return -1; 1154} 1155 1156 1157#ifdef TRANS_SERVER 1158 1159static int 1160TRANS(LocalCreateListener)(XtransConnInfo ciptr, const char *port, 1161 unsigned int flags _X_UNUSED) 1162 1163{ 1164 prmsg(2,"LocalCreateListener(%p->%d,%s)\n",ciptr,ciptr->fd,port); 1165 1166 return 0; 1167} 1168 1169static int 1170TRANS(LocalResetListener)(XtransConnInfo ciptr) 1171 1172{ 1173 LOCALtrans2dev *transptr; 1174 1175 prmsg(2,"LocalResetListener(%p)\n",ciptr); 1176 1177 transptr=(LOCALtrans2dev *)ciptr->priv; 1178 if (transptr->devreset != NULL) { 1179 return transptr->devreset(ciptr); 1180 } 1181 return TRANS_RESET_NOOP; 1182} 1183 1184 1185static XtransConnInfo 1186TRANS(LocalAccept)(XtransConnInfo ciptr, int *status) 1187 1188{ 1189 XtransConnInfo newciptr; 1190 LOCALtrans2dev *transptr; 1191 1192 prmsg(2,"LocalAccept(%p->%d)\n", ciptr, ciptr->fd); 1193 1194 transptr=(LOCALtrans2dev *)ciptr->priv; 1195 1196 if( (newciptr = calloc(1,sizeof(struct _XtransConnInfo)))==NULL ) 1197 { 1198 prmsg(1,"LocalAccept: calloc(1,%lu) failed\n", 1199 sizeof(struct _XtransConnInfo)); 1200 *status = TRANS_ACCEPT_BAD_MALLOC; 1201 return NULL; 1202 } 1203 1204 newciptr->fd=transptr->devaccept(ciptr,newciptr,status); 1205 1206 if( newciptr->fd < 0 ) 1207 { 1208 free(newciptr); 1209 return NULL; 1210 } 1211 1212 newciptr->priv=(char *)transptr; 1213 newciptr->index = ciptr->index; 1214 1215 *status = 0; 1216 1217 return newciptr; 1218} 1219 1220#endif /* TRANS_SERVER */ 1221 1222 1223#ifdef TRANS_CLIENT 1224 1225static int 1226TRANS(LocalConnect)(XtransConnInfo ciptr, 1227 const char *host _X_UNUSED, const char *port) 1228 1229{ 1230 prmsg(2,"LocalConnect(%p->%d,%s)\n", ciptr, ciptr->fd, port); 1231 1232 return 0; 1233} 1234 1235#endif /* TRANS_CLIENT */ 1236 1237 1238static int 1239TRANS(LocalBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend ) 1240 1241{ 1242 prmsg(2,"LocalBytesReadable(%p->%d,%p)\n", ciptr, ciptr->fd, pend); 1243 1244 return ioctl(ciptr->fd, FIONREAD, (char *)pend); 1245} 1246 1247static int 1248TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size) 1249 1250{ 1251 prmsg(2,"LocalRead(%d,%p,%d)\n", ciptr->fd, buf, size ); 1252 1253 return read(ciptr->fd,buf,size); 1254} 1255 1256static int 1257TRANS(LocalWrite)(XtransConnInfo ciptr, char *buf, int size) 1258 1259{ 1260 prmsg(2,"LocalWrite(%d,%p,%d)\n", ciptr->fd, buf, size ); 1261 1262 return write(ciptr->fd,buf,size); 1263} 1264 1265static int 1266TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size) 1267 1268{ 1269 prmsg(2,"LocalReadv(%d,%p,%d)\n", ciptr->fd, buf, size ); 1270 1271 return READV(ciptr,buf,size); 1272} 1273 1274static int 1275TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size) 1276 1277{ 1278 prmsg(2,"LocalWritev(%d,%p,%d)\n", ciptr->fd, buf, size ); 1279 1280 return WRITEV(ciptr,buf,size); 1281} 1282 1283static int 1284TRANS(LocalDisconnect)(XtransConnInfo ciptr) 1285 1286{ 1287 prmsg(2,"LocalDisconnect(%p->%d)\n", ciptr, ciptr->fd); 1288 1289 return 0; 1290} 1291 1292static int 1293TRANS(LocalClose)(XtransConnInfo ciptr) 1294 1295{ 1296 struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr; 1297 int ret; 1298 1299 prmsg(2,"LocalClose(%p->%d)\n", ciptr, ciptr->fd ); 1300 1301 ret=close(ciptr->fd); 1302 1303 if(ciptr->flags 1304 && sockname 1305 && sockname->sun_family == AF_UNIX 1306 && sockname->sun_path[0] ) 1307 { 1308 if (!(ciptr->flags & TRANS_NOUNLINK)) 1309 unlink(sockname->sun_path); 1310 } 1311 1312 return ret; 1313} 1314 1315static int 1316TRANS(LocalCloseForCloning)(XtransConnInfo ciptr) 1317 1318{ 1319 int ret; 1320 1321 prmsg(2,"LocalCloseForCloning(%p->%d)\n", ciptr, ciptr->fd ); 1322 1323 /* Don't unlink path */ 1324 1325 ret=close(ciptr->fd); 1326 1327 return ret; 1328} 1329 1330 1331/* 1332 * MakeAllCOTSServerListeners() will go through the entire Xtransports[] 1333 * array defined in Xtrans.c and try to OpenCOTSServer() for each entry. 1334 * We will add duplicate entries to that table so that the OpenCOTSServer() 1335 * function will get called once for each type of local transport. 1336 * 1337 * The TransName is in lowercase, so it will never match during a normal 1338 * call to SelectTransport() in Xtrans.c. 1339 */ 1340 1341#ifdef TRANS_SERVER 1342static const char * local_aliases[] = { 1343 "named", 1344 "pipe", /* compatibility with Solaris Xlib */ 1345 NULL }; 1346#endif 1347 1348Xtransport TRANS(LocalFuncs) = { 1349 /* Local Interface */ 1350 "local", 1351 TRANS_ALIAS | TRANS_LOCAL, 1352#ifdef TRANS_CLIENT 1353 TRANS(LocalOpenCOTSClient), 1354#endif /* TRANS_CLIENT */ 1355#ifdef TRANS_SERVER 1356 local_aliases, 1357 TRANS(LocalOpenCOTSServer), 1358#endif /* TRANS_SERVER */ 1359#ifdef TRANS_REOPEN 1360 TRANS(LocalReopenCOTSServer), 1361#endif 1362 TRANS(LocalSetOption), 1363#ifdef TRANS_SERVER 1364 TRANS(LocalCreateListener), 1365 TRANS(LocalResetListener), 1366 TRANS(LocalAccept), 1367#endif /* TRANS_SERVER */ 1368#ifdef TRANS_CLIENT 1369 TRANS(LocalConnect), 1370#endif /* TRANS_CLIENT */ 1371 TRANS(LocalBytesReadable), 1372 TRANS(LocalRead), 1373 TRANS(LocalWrite), 1374 TRANS(LocalReadv), 1375 TRANS(LocalWritev), 1376#if XTRANS_SEND_FDS 1377 TRANS(LocalSendFdInvalid), 1378 TRANS(LocalRecvFdInvalid), 1379#endif 1380 TRANS(LocalDisconnect), 1381 TRANS(LocalClose), 1382 TRANS(LocalCloseForCloning), 1383}; 1384 1385 1386#ifdef LOCAL_TRANS_NAMED 1387 1388Xtransport TRANS(NAMEDFuncs) = { 1389 /* Local Interface */ 1390 "named", 1391 TRANS_LOCAL, 1392#ifdef TRANS_CLIENT 1393 TRANS(LocalOpenCOTSClient), 1394#endif /* TRANS_CLIENT */ 1395#ifdef TRANS_SERVER 1396 NULL, 1397 TRANS(LocalOpenCOTSServer), 1398#endif /* TRANS_SERVER */ 1399#ifdef TRANS_REOPEN 1400 TRANS(LocalReopenCOTSServer), 1401#endif 1402 TRANS(LocalSetOption), 1403#ifdef TRANS_SERVER 1404 TRANS(LocalCreateListener), 1405 TRANS(LocalResetListener), 1406 TRANS(LocalAccept), 1407#endif /* TRANS_SERVER */ 1408#ifdef TRANS_CLIENT 1409 TRANS(LocalConnect), 1410#endif /* TRANS_CLIENT */ 1411 TRANS(LocalBytesReadable), 1412 TRANS(LocalRead), 1413 TRANS(LocalWrite), 1414 TRANS(LocalReadv), 1415 TRANS(LocalWritev), 1416#if XTRANS_SEND_FDS 1417 TRANS(LocalSendFdInvalid), 1418 TRANS(LocalRecvFdInvalid), 1419#endif 1420 TRANS(LocalDisconnect), 1421 TRANS(LocalClose), 1422 TRANS(LocalCloseForCloning), 1423}; 1424 1425Xtransport TRANS(PIPEFuncs) = { 1426 /* Local Interface */ 1427 "pipe", 1428 TRANS_ALIAS | TRANS_LOCAL, 1429#ifdef TRANS_CLIENT 1430 TRANS(LocalOpenCOTSClient), 1431#endif /* TRANS_CLIENT */ 1432#ifdef TRANS_SERVER 1433 NULL, 1434 TRANS(LocalOpenCOTSServer), 1435#endif /* TRANS_SERVER */ 1436#ifdef TRANS_REOPEN 1437 TRANS(LocalReopenCOTSServer), 1438#endif 1439 TRANS(LocalSetOption), 1440#ifdef TRANS_SERVER 1441 TRANS(LocalCreateListener), 1442 TRANS(LocalResetListener), 1443 TRANS(LocalAccept), 1444#endif /* TRANS_SERVER */ 1445#ifdef TRANS_CLIENT 1446 TRANS(LocalConnect), 1447#endif /* TRANS_CLIENT */ 1448 TRANS(LocalBytesReadable), 1449 TRANS(LocalRead), 1450 TRANS(LocalWrite), 1451 TRANS(LocalReadv), 1452 TRANS(LocalWritev), 1453#if XTRANS_SEND_FDS 1454 TRANS(LocalSendFdInvalid), 1455 TRANS(LocalRecvFdInvalid), 1456#endif 1457 TRANS(LocalDisconnect), 1458 TRANS(LocalClose), 1459 TRANS(LocalCloseForCloning), 1460}; 1461#endif /* LOCAL_TRANS_NAMED */ 1462 1463 1464