Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/X11/Xtrans/Xtrans.c
$ cat -n /usr/include/X11/Xtrans/Xtrans.c 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 #include
51 #include
52 #include
53 #ifdef HAVE_SYSTEMD_DAEMON 54 #include
55 #endif 56 57 /* 58 * The transport table contains a definition for every transport (protocol) 59 * family. All operations that can be made on the transport go through this 60 * table. 61 * 62 * Each transport is assigned a unique transport id. 63 * 64 * New transports can be added by adding an entry in this table. 65 * For compatiblity, the transport ids should never be renumbered. 66 * Always add to the end of the list. 67 */ 68 69 #define TRANS_TLI_INET_INDEX 1 70 #define TRANS_TLI_TCP_INDEX 2 71 #define TRANS_TLI_TLI_INDEX 3 72 #define TRANS_SOCKET_UNIX_INDEX 4 73 #define TRANS_SOCKET_LOCAL_INDEX 5 74 #define TRANS_SOCKET_INET_INDEX 6 75 #define TRANS_SOCKET_TCP_INDEX 7 76 #define TRANS_DNET_INDEX 8 77 #define TRANS_LOCAL_LOCAL_INDEX 9 78 #define TRANS_LOCAL_PTS_INDEX 10 79 #define TRANS_LOCAL_NAMED_INDEX 11 80 /* 12 used to be ISC, but that's gone. */ 81 #define TRANS_LOCAL_SCO_INDEX 13 82 #define TRANS_SOCKET_INET6_INDEX 14 83 #define TRANS_LOCAL_PIPE_INDEX 15 84 85 86 static 87 Xtransport_table Xtransports[] = { 88 #if defined(TCPCONN) 89 { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, 90 #if defined(IPv6) && defined(AF_INET6) 91 { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, 92 #endif /* IPv6 */ 93 { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, 94 #endif /* TCPCONN */ 95 #if defined(UNIXCONN) 96 #if !defined(LOCALCONN) 97 { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX }, 98 #endif /* !LOCALCONN */ 99 { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, 100 #endif /* UNIXCONN */ 101 #if defined(LOCALCONN) 102 { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, 103 #ifndef __sun 104 { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX }, 105 #endif /* __sun */ 106 #if defined(SVR4) || defined(__SVR4) 107 { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX }, 108 #endif 109 #ifdef __sun 110 { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX }, 111 #endif /* __sun */ 112 #if defined(__SCO__) || defined(__UNIXWARE__) 113 { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX }, 114 #endif /* __SCO__ || __UNIXWARE__ */ 115 #endif /* LOCALCONN */ 116 }; 117 118 #define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) 119 120 121 #ifdef WIN32 122 #define ioctl ioctlsocket 123 #endif 124 125 126 127 /* 128 * These are a few utility function used by the public interface functions. 129 */ 130 131 void 132 TRANS(FreeConnInfo) (XtransConnInfo ciptr) 133 134 { 135 prmsg (3,"FreeConnInfo(%p)\n", ciptr); 136 137 if (ciptr->addr) 138 free (ciptr->addr); 139 140 if (ciptr->peeraddr) 141 free (ciptr->peeraddr); 142 143 if (ciptr->port) 144 free (ciptr->port); 145 146 free (ciptr); 147 } 148 149 150 #define PROTOBUFSIZE 20 151 152 static Xtransport * 153 TRANS(SelectTransport) (const char *protocol) 154 155 { 156 #ifndef HAVE_STRCASECMP 157 char protobuf[PROTOBUFSIZE]; 158 #endif 159 int i; 160 161 prmsg (3,"SelectTransport(%s)\n", protocol); 162 163 #ifndef HAVE_STRCASECMP 164 /* 165 * Force Protocol to be lowercase as a way of doing 166 * a case insensitive match. 167 */ 168 169 strncpy (protobuf, protocol, PROTOBUFSIZE - 1); 170 protobuf[PROTOBUFSIZE-1] = '\0'; 171 172 for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) 173 if (isupper ((unsigned char)protobuf[i])) 174 protobuf[i] = tolower ((unsigned char)protobuf[i]); 175 #endif 176 177 /* Look at all of the configured protocols */ 178 179 for (i = 0; i < NUMTRANS; i++) 180 { 181 #ifndef HAVE_STRCASECMP 182 if (!strcmp (protobuf, Xtransports[i].transport->TransName)) 183 #else 184 if (!strcasecmp (protocol, Xtransports[i].transport->TransName)) 185 #endif 186 return Xtransports[i].transport; 187 } 188 189 return NULL; 190 } 191 192 #ifndef TEST_t 193 static 194 #endif /* TEST_t */ 195 int 196 TRANS(ParseAddress) (const char *address, 197 char **protocol, char **host, char **port) 198 199 { 200 /* 201 * For the font library, the address is a string formatted 202 * as "protocol/host:port[/catalogue]". Note that the catologue 203 * is optional. At this time, the catologue info is ignored, but 204 * we have to parse it anyways. 205 * 206 * Other than fontlib, the address is a string formatted 207 * as "protocol/host:port". 208 * 209 * If the protocol part is missing, then assume TCP. 210 * If the protocol part and host part are missing, then assume local. 211 * If a "::" is found then assume DNET. 212 */ 213 214 char *mybuf, *tmpptr; 215 const char *_protocol; 216 char *_host, *_port; 217 char hostnamebuf[256]; 218 int _host_len; 219 220 prmsg (3,"ParseAddress(%s)\n", address); 221 222 /* Copy the string so it can be changed */ 223 224 tmpptr = mybuf = strdup (address); 225 226 /* Parse the string to get each component */ 227 228 /* Get the protocol part */ 229 230 _protocol = mybuf; 231 232 233 if ( ((mybuf = strchr (mybuf,'/')) == NULL) && 234 ((mybuf = strrchr (tmpptr,':')) == NULL) ) 235 { 236 /* address is in a bad format */ 237 *protocol = NULL; 238 *host = NULL; 239 *port = NULL; 240 free (tmpptr); 241 return 0; 242 } 243 244 if (*mybuf == ':') 245 { 246 /* 247 * If there is a hostname, then assume tcp, otherwise 248 * it must be local. 249 */ 250 if (mybuf == tmpptr) 251 { 252 /* There is neither a protocol or host specified */ 253 _protocol = "local"; 254 } 255 else 256 { 257 /* There is a hostname specified */ 258 _protocol = "tcp"; 259 mybuf = tmpptr; /* reset to the begining of the host ptr */ 260 } 261 } 262 else 263 { 264 /* *mybuf == '/' */ 265 266 *mybuf ++= '\0'; /* put a null at the end of the protocol */ 267 268 if (strlen(_protocol) == 0) 269 { 270 /* 271 * If there is a hostname, then assume tcp, otherwise 272 * it must be local. 273 */ 274 if (*mybuf != ':') 275 _protocol = "tcp"; 276 else 277 _protocol = "local"; 278 } 279 } 280 281 /* Get the host part */ 282 283 _host = mybuf; 284 285 if ((mybuf = strrchr (mybuf,':')) == NULL) 286 { 287 *protocol = NULL; 288 *host = NULL; 289 *port = NULL; 290 free (tmpptr); 291 return 0; 292 } 293 294 *mybuf ++= '\0'; 295 296 _host_len = strlen(_host); 297 if (_host_len == 0) 298 { 299 TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 300 _host = hostnamebuf; 301 } 302 #if defined(IPv6) && defined(AF_INET6) 303 /* hostname in IPv6 [numeric_addr]:0 form? */ 304 else if ( (_host_len > 3) && 305 ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) 306 && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { 307 struct sockaddr_in6 sin6; 308 309 *(_host + _host_len - 1) = '\0'; 310 311 /* Verify address is valid IPv6 numeric form */ 312 if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { 313 /* It is. Use it as such. */ 314 _host++; 315 _protocol = "inet6"; 316 } else { 317 /* It's not, restore it just in case some other code can use it. */ 318 *(_host + _host_len - 1) = ']'; 319 } 320 } 321 #endif 322 323 324 /* Get the port */ 325 326 _port = mybuf; 327 328 #if defined(FONT_t) || defined(FS_t) 329 /* 330 * Is there an optional catalogue list? 331 */ 332 333 if ((mybuf = strchr (mybuf,'/')) != NULL) 334 *mybuf ++= '\0'; 335 336 /* 337 * The rest, if any, is the (currently unused) catalogue list. 338 * 339 * _catalogue = mybuf; 340 */ 341 #endif 342 343 #ifdef HAVE_LAUNCHD 344 /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ 345 if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) { 346 _protocol="local"; 347 _host=""; 348 _port=address+6; 349 } 350 #endif 351 352 /* 353 * Now that we have all of the components, allocate new 354 * string space for them. 355 */ 356 357 if ((*protocol = strdup (_protocol)) == NULL) 358 { 359 /* Malloc failed */ 360 *port = NULL; 361 *host = NULL; 362 *protocol = NULL; 363 free (tmpptr); 364 return 0; 365 } 366 367 if ((*host = strdup (_host)) == NULL) 368 { 369 /* Malloc failed */ 370 *port = NULL; 371 *host = NULL; 372 free (*protocol); 373 *protocol = NULL; 374 free (tmpptr); 375 return 0; 376 } 377 378 if ((*port = strdup (_port)) == NULL) 379 { 380 /* Malloc failed */ 381 *port = NULL; 382 free (*host); 383 *host = NULL; 384 free (*protocol); 385 *protocol = NULL; 386 free (tmpptr); 387 return 0; 388 } 389 390 free (tmpptr); 391 392 return 1; 393 } 394 395 396 /* 397 * TRANS(Open) does all of the real work opening a connection. The only 398 * funny part about this is the type parameter which is used to decide which 399 * type of open to perform. 400 */ 401 402 static XtransConnInfo 403 TRANS(Open) (int type, const char *address) 404 405 { 406 char *protocol = NULL, *host = NULL, *port = NULL; 407 XtransConnInfo ciptr = NULL; 408 Xtransport *thistrans; 409 410 prmsg (2,"Open(%d,%s)\n", type, address); 411 412 #if defined(WIN32) && defined(TCPCONN) 413 if (TRANS(WSAStartup)()) 414 { 415 prmsg (1,"Open: WSAStartup failed\n"); 416 return NULL; 417 } 418 #endif 419 420 /* Parse the Address */ 421 422 if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 423 { 424 prmsg (1,"Open: Unable to Parse address %s\n", address); 425 return NULL; 426 } 427 428 /* Determine the transport type */ 429 430 if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) 431 { 432 prmsg (1,"Open: Unable to find transport for %s\n", 433 protocol); 434 435 free (protocol); 436 free (host); 437 free (port); 438 return NULL; 439 } 440 441 /* Open the transport */ 442 443 switch (type) 444 { 445 case XTRANS_OPEN_COTS_CLIENT: 446 #ifdef TRANS_CLIENT 447 ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); 448 #endif /* TRANS_CLIENT */ 449 break; 450 case XTRANS_OPEN_COTS_SERVER: 451 #ifdef TRANS_SERVER 452 ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); 453 #endif /* TRANS_SERVER */ 454 break; 455 default: 456 prmsg (1,"Open: Unknown Open type %d\n", type); 457 } 458 459 if (ciptr == NULL) 460 { 461 if (!(thistrans->flags & TRANS_DISABLED)) 462 { 463 prmsg (1,"Open: transport open failed for %s/%s:%s\n", 464 protocol, host, port); 465 } 466 free (protocol); 467 free (host); 468 free (port); 469 return NULL; 470 } 471 472 ciptr->transptr = thistrans; 473 ciptr->port = port; /* We need this for TRANS(Reopen) */ 474 475 free (protocol); 476 free (host); 477 478 return ciptr; 479 } 480 481 482 #ifdef TRANS_REOPEN 483 484 /* 485 * We might want to create an XtransConnInfo object based on a previously 486 * opened connection. For example, the font server may clone itself and 487 * pass file descriptors to the parent. 488 */ 489 490 static XtransConnInfo 491 TRANS(Reopen) (int type, int trans_id, int fd, const char *port) 492 493 { 494 XtransConnInfo ciptr = NULL; 495 Xtransport *thistrans = NULL; 496 char *save_port; 497 int i; 498 499 prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); 500 501 /* Determine the transport type */ 502 503 for (i = 0; i < NUMTRANS; i++) 504 if (Xtransports[i].transport_id == trans_id) 505 { 506 thistrans = Xtransports[i].transport; 507 break; 508 } 509 510 if (thistrans == NULL) 511 { 512 prmsg (1,"Reopen: Unable to find transport id %d\n", 513 trans_id); 514 515 return NULL; 516 } 517 518 if ((save_port = strdup (port)) == NULL) 519 { 520 prmsg (1,"Reopen: Unable to malloc port string\n"); 521 522 return NULL; 523 } 524 525 /* Get a new XtransConnInfo object */ 526 527 switch (type) 528 { 529 case XTRANS_OPEN_COTS_SERVER: 530 ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); 531 break; 532 default: 533 prmsg (1,"Reopen: Bad Open type %d\n", type); 534 } 535 536 if (ciptr == NULL) 537 { 538 prmsg (1,"Reopen: transport open failed\n"); 539 free (save_port); 540 return NULL; 541 } 542 543 ciptr->transptr = thistrans; 544 ciptr->port = save_port; 545 546 return ciptr; 547 } 548 549 #endif /* TRANS_REOPEN */ 550 551 552 553 /* 554 * These are the public interfaces to this Transport interface. 555 * These are the only functions that should have knowledge of the transport 556 * table. 557 */ 558 559 #ifdef TRANS_CLIENT 560 561 XtransConnInfo 562 TRANS(OpenCOTSClient) (const char *address) 563 564 { 565 prmsg (2,"OpenCOTSClient(%s)\n", address); 566 return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); 567 } 568 569 #endif /* TRANS_CLIENT */ 570 571 572 #ifdef TRANS_SERVER 573 574 XtransConnInfo 575 TRANS(OpenCOTSServer) (const char *address) 576 577 { 578 prmsg (2,"OpenCOTSServer(%s)\n", address); 579 return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); 580 } 581 582 #endif /* TRANS_SERVER */ 583 584 585 #ifdef TRANS_REOPEN 586 587 XtransConnInfo 588 TRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port) 589 590 { 591 prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); 592 return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); 593 } 594 595 int 596 TRANS(GetReopenInfo) (XtransConnInfo ciptr, 597 int *trans_id, int *fd, char **port) 598 599 { 600 int i; 601 602 for (i = 0; i < NUMTRANS; i++) 603 if (Xtransports[i].transport == ciptr->transptr) 604 { 605 *trans_id = Xtransports[i].transport_id; 606 *fd = ciptr->fd; 607 608 if ((*port = strdup (ciptr->port)) == NULL) 609 return 0; 610 else 611 return 1; 612 } 613 614 return 0; 615 } 616 617 #endif /* TRANS_REOPEN */ 618 619 620 int 621 TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) 622 623 { 624 int fd = ciptr->fd; 625 int ret = 0; 626 627 prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg); 628 629 /* 630 * For now, all transport type use the same stuff for setting options. 631 * As long as this is true, we can put the common code here. Once a more 632 * complicated transport such as shared memory or an OSI implementation 633 * that uses the session and application libraries is implemented, this 634 * code may have to move to a transport dependent function. 635 * 636 * ret = ciptr->transptr->SetOption (ciptr, option, arg); 637 */ 638 639 switch (option) 640 { 641 case TRANS_NONBLOCKING: 642 switch (arg) 643 { 644 case 0: 645 /* Set to blocking mode */ 646 break; 647 case 1: /* Set to non-blocking mode */ 648 649 #if defined(O_NONBLOCK) && !defined(SCO325) 650 ret = fcntl (fd, F_GETFL, 0); 651 if (ret != -1) 652 ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); 653 #else 654 #ifdef FIOSNBIO 655 { 656 int arg; 657 arg = 1; 658 ret = ioctl (fd, FIOSNBIO, &arg); 659 } 660 #else 661 #if defined(WIN32) 662 { 663 #ifdef WIN32 664 u_long arg; 665 #else 666 int arg; 667 #endif 668 arg = 1; 669 /* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail 670 * eventually with EWOULDBLOCK */ 671 ret = ioctl (fd, FIONBIO, &arg); 672 } 673 #else 674 ret = fcntl (fd, F_GETFL, 0); 675 #ifdef FNDELAY 676 ret = fcntl (fd, F_SETFL, ret | FNDELAY); 677 #else 678 ret = fcntl (fd, F_SETFL, ret | O_NDELAY); 679 #endif 680 #endif /* AIXV3 || uniosu */ 681 #endif /* FIOSNBIO */ 682 #endif /* O_NONBLOCK */ 683 break; 684 default: 685 /* Unknown option */ 686 break; 687 } 688 break; 689 case TRANS_CLOSEONEXEC: 690 #ifdef F_SETFD 691 #ifdef FD_CLOEXEC 692 ret = fcntl (fd, F_SETFD, FD_CLOEXEC); 693 #else 694 ret = fcntl (fd, F_SETFD, 1); 695 #endif /* FD_CLOEXEC */ 696 #endif /* F_SETFD */ 697 break; 698 } 699 700 return ret; 701 } 702 703 #ifdef TRANS_SERVER 704 705 int 706 TRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags) 707 708 { 709 return ciptr->transptr->CreateListener (ciptr, port, flags); 710 } 711 712 int 713 TRANS(Received) (const char * protocol) 714 715 { 716 Xtransport *trans; 717 int i = 0, ret = 0; 718 719 prmsg (5, "Received(%s)\n", protocol); 720 721 if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 722 { 723 prmsg (1,"Received: unable to find transport: %s\n", 724 protocol); 725 726 return -1; 727 } 728 if (trans->flags & TRANS_ALIAS) { 729 if (trans->nolisten) 730 while (trans->nolisten[i]) { 731 ret |= TRANS(Received)(trans->nolisten[i]); 732 i++; 733 } 734 } 735 736 trans->flags |= TRANS_RECEIVED; 737 return ret; 738 } 739 740 int 741 TRANS(NoListen) (const char * protocol) 742 743 { 744 Xtransport *trans; 745 int i = 0, ret = 0; 746 747 if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 748 { 749 prmsg (1,"TransNoListen: unable to find transport: %s\n", 750 protocol); 751 752 return -1; 753 } 754 if (trans->flags & TRANS_ALIAS) { 755 if (trans->nolisten) 756 while (trans->nolisten[i]) { 757 ret |= TRANS(NoListen)(trans->nolisten[i]); 758 i++; 759 } 760 } 761 762 trans->flags |= TRANS_NOLISTEN; 763 return ret; 764 } 765 766 int 767 TRANS(Listen) (const char * protocol) 768 { 769 Xtransport *trans; 770 int i = 0, ret = 0; 771 772 if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 773 { 774 prmsg (1,"TransListen: unable to find transport: %s\n", 775 protocol); 776 777 return -1; 778 } 779 if (trans->flags & TRANS_ALIAS) { 780 if (trans->nolisten) 781 while (trans->nolisten[i]) { 782 ret |= TRANS(Listen)(trans->nolisten[i]); 783 i++; 784 } 785 } 786 787 trans->flags &= ~TRANS_NOLISTEN; 788 return ret; 789 } 790 791 int 792 TRANS(IsListening) (const char * protocol) 793 { 794 Xtransport *trans; 795 796 if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 797 { 798 prmsg (1,"TransIsListening: unable to find transport: %s\n", 799 protocol); 800 801 return 0; 802 } 803 804 return !(trans->flags & TRANS_NOLISTEN); 805 } 806 807 int 808 TRANS(ResetListener) (XtransConnInfo ciptr) 809 810 { 811 if (ciptr->transptr->ResetListener) 812 return ciptr->transptr->ResetListener (ciptr); 813 else 814 return TRANS_RESET_NOOP; 815 } 816 817 818 XtransConnInfo 819 TRANS(Accept) (XtransConnInfo ciptr, int *status) 820 821 { 822 XtransConnInfo newciptr; 823 824 prmsg (2,"Accept(%d)\n", ciptr->fd); 825 826 newciptr = ciptr->transptr->Accept (ciptr, status); 827 828 if (newciptr) 829 newciptr->transptr = ciptr->transptr; 830 831 return newciptr; 832 } 833 834 #endif /* TRANS_SERVER */ 835 836 837 #ifdef TRANS_CLIENT 838 839 int 840 TRANS(Connect) (XtransConnInfo ciptr, const char *address) 841 842 { 843 char *protocol; 844 char *host; 845 char *port; 846 int ret; 847 848 prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address); 849 850 if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 851 { 852 prmsg (1,"Connect: Unable to Parse address %s\n", 853 address); 854 return -1; 855 } 856 857 #ifdef HAVE_LAUNCHD 858 if (!host) host=strdup(""); 859 #endif 860 861 if (!port || !*port) 862 { 863 prmsg (1,"Connect: Missing port specification in %s\n", 864 address); 865 if (protocol) free (protocol); 866 if (host) free (host); 867 return -1; 868 } 869 870 ret = ciptr->transptr->Connect (ciptr, host, port); 871 872 if (protocol) free (protocol); 873 if (host) free (host); 874 if (port) free (port); 875 876 return ret; 877 } 878 879 #endif /* TRANS_CLIENT */ 880 881 882 int 883 TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 884 885 { 886 return ciptr->transptr->BytesReadable (ciptr, pend); 887 } 888 889 int 890 TRANS(Read) (XtransConnInfo ciptr, char *buf, int size) 891 892 { 893 return ciptr->transptr->Read (ciptr, buf, size); 894 } 895 896 int 897 TRANS(Write) (XtransConnInfo ciptr, char *buf, int size) 898 899 { 900 return ciptr->transptr->Write (ciptr, buf, size); 901 } 902 903 int 904 TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) 905 906 { 907 return ciptr->transptr->Readv (ciptr, buf, size); 908 } 909 910 int 911 TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) 912 913 { 914 return ciptr->transptr->Writev (ciptr, buf, size); 915 } 916 917 #if XTRANS_SEND_FDS 918 int 919 TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) 920 { 921 return ciptr->transptr->SendFd(ciptr, fd, do_close); 922 } 923 924 int 925 TRANS(RecvFd) (XtransConnInfo ciptr) 926 { 927 return ciptr->transptr->RecvFd(ciptr); 928 } 929 #endif 930 931 int 932 TRANS(Disconnect) (XtransConnInfo ciptr) 933 934 { 935 return ciptr->transptr->Disconnect (ciptr); 936 } 937 938 int 939 TRANS(Close) (XtransConnInfo ciptr) 940 941 { 942 int ret; 943 944 prmsg (2,"Close(%d)\n", ciptr->fd); 945 946 ret = ciptr->transptr->Close (ciptr); 947 948 TRANS(FreeConnInfo) (ciptr); 949 950 return ret; 951 } 952 953 int 954 TRANS(CloseForCloning) (XtransConnInfo ciptr) 955 956 { 957 int ret; 958 959 prmsg (2,"CloseForCloning(%d)\n", ciptr->fd); 960 961 ret = ciptr->transptr->CloseForCloning (ciptr); 962 963 TRANS(FreeConnInfo) (ciptr); 964 965 return ret; 966 } 967 968 int 969 TRANS(IsLocal) (XtransConnInfo ciptr) 970 971 { 972 return (ciptr->family == AF_UNIX); 973 } 974 975 int 976 TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 977 Xtransaddr **addrp) 978 979 { 980 prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd); 981 982 *familyp = ciptr->family; 983 *addrlenp = ciptr->peeraddrlen; 984 985 if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL) 986 { 987 prmsg (1,"GetPeerAddr: malloc failed\n"); 988 return -1; 989 } 990 memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); 991 992 return 0; 993 } 994 995 996 int 997 TRANS(GetConnectionNumber) (XtransConnInfo ciptr) 998 999 { 1000 return ciptr->fd; 1001 } 1002 1003 1004 /* 1005 * These functions are really utility functions, but they require knowledge 1006 * of the internal data structures, so they have to be part of the Transport 1007 * Independant API. 1008 */ 1009 1010 #ifdef TRANS_SERVER 1011 1012 static int 1013 complete_network_count (void) 1014 1015 { 1016 int count = 0; 1017 int found_local = 0; 1018 int i; 1019 1020 /* 1021 * For a complete network, we only need one LOCALCONN transport to work 1022 */ 1023 1024 for (i = 0; i < NUMTRANS; i++) 1025 { 1026 if (Xtransports[i].transport->flags & TRANS_ALIAS 1027 || Xtransports[i].transport->flags & TRANS_NOLISTEN) 1028 continue; 1029 1030 if (Xtransports[i].transport->flags & TRANS_LOCAL) 1031 found_local = 1; 1032 else 1033 count++; 1034 } 1035 1036 return (count + found_local); 1037 } 1038 1039 1040 static int 1041 receive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs, 1042 int* count_ret) 1043 1044 { 1045 #ifdef HAVE_SYSTEMD_DAEMON 1046 XtransConnInfo ciptr; 1047 int i, systemd_listen_fds; 1048 1049 systemd_listen_fds = sd_listen_fds(1); 1050 if (systemd_listen_fds < 0) 1051 { 1052 prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n", 1053 strerror(-systemd_listen_fds)); 1054 return -1; 1055 } 1056 1057 for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++) 1058 { 1059 struct sockaddr_storage a; 1060 int ti; 1061 const char* tn; 1062 socklen_t al; 1063 1064 al = sizeof(a); 1065 if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) { 1066 prmsg (1, "receive_listening_fds: getsockname error: %s\n", 1067 strerror(errno)); 1068 return -1; 1069 } 1070 1071 switch (a.ss_family) 1072 { 1073 case AF_UNIX: 1074 ti = TRANS_SOCKET_UNIX_INDEX; 1075 if (*((struct sockaddr_un*)&a)->sun_path == '\0' && 1076 al > sizeof(sa_family_t)) 1077 tn = "local"; 1078 else 1079 tn = "unix"; 1080 break; 1081 case AF_INET: 1082 ti = TRANS_SOCKET_INET_INDEX; 1083 tn = "inet"; 1084 break; 1085 #if defined(IPv6) && defined(AF_INET6) 1086 case AF_INET6: 1087 ti = TRANS_SOCKET_INET6_INDEX; 1088 tn = "inet6"; 1089 break; 1090 #endif /* IPv6 */ 1091 default: 1092 prmsg (1, "receive_listening_fds:" 1093 "Got unknown socket address family\n"); 1094 return -1; 1095 } 1096 1097 ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port); 1098 if (!ciptr) 1099 { 1100 prmsg (1, "receive_listening_fds:" 1101 "Got NULL while trying to reopen socket received from systemd.\n"); 1102 return -1; 1103 } 1104 1105 prmsg (5, "receive_listening_fds: received listener for %s, %d\n", 1106 tn, ciptr->fd); 1107 temp_ciptrs[(*count_ret)++] = ciptr; 1108 TRANS(Received)(tn); 1109 } 1110 #endif /* HAVE_SYSTEMD_DAEMON */ 1111 return 0; 1112 } 1113 1114 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 1115 extern int xquartz_launchd_fd; 1116 #endif 1117 1118 int 1119 TRANS(MakeAllCOTSServerListeners) (const char *port, int *partial, 1120 int *count_ret, XtransConnInfo **ciptrs_ret) 1121 1122 { 1123 char buffer[256]; /* ??? What size ?? */ 1124 XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; 1125 int status, i, j; 1126 1127 #if defined(IPv6) && defined(AF_INET6) 1128 int ipv6_succ = 0; 1129 #endif 1130 prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n", 1131 port ? port : "NULL", ciptrs_ret); 1132 1133 *count_ret = 0; 1134 1135 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 1136 fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd); 1137 if(xquartz_launchd_fd != -1) { 1138 if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, 1139 xquartz_launchd_fd, getenv("DISPLAY"))))==NULL) 1140 fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); 1141 else 1142 temp_ciptrs[(*count_ret)++] = ciptr; 1143 } 1144 #endif 1145 1146 if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0) 1147 return -1; 1148 1149 for (i = 0; i < NUMTRANS; i++) 1150 { 1151 Xtransport *trans = Xtransports[i].transport; 1152 unsigned int flags = 0; 1153 1154 if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN || 1155 trans->flags&TRANS_RECEIVED) 1156 continue; 1157 1158 snprintf(buffer, sizeof(buffer), "%s/:%s", 1159 trans->TransName, port ? port : ""); 1160 1161 prmsg (5,"MakeAllCOTSServerListeners: opening %s\n", 1162 buffer); 1163 1164 if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) 1165 { 1166 if (trans->flags & TRANS_DISABLED) 1167 continue; 1168 1169 prmsg (1, 1170 "MakeAllCOTSServerListeners: failed to open listener for %s\n", 1171 trans->TransName); 1172 continue; 1173 } 1174 #if defined(IPv6) && defined(AF_INET6) 1175 if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX 1176 && ipv6_succ)) 1177 flags |= ADDR_IN_USE_ALLOWED; 1178 #endif 1179 1180 if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) 1181 { 1182 if (status == TRANS_ADDR_IN_USE) 1183 { 1184 /* 1185 * We failed to bind to the specified address because the 1186 * address is in use. It must be that a server is already 1187 * running at this address, and this function should fail. 1188 */ 1189 1190 prmsg (1, 1191 "MakeAllCOTSServerListeners: server already running\n"); 1192 1193 for (j = 0; j < *count_ret; j++) 1194 TRANS(Close) (temp_ciptrs[j]); 1195 1196 *count_ret = 0; 1197 *ciptrs_ret = NULL; 1198 *partial = 0; 1199 return -1; 1200 } 1201 else 1202 { 1203 prmsg (1, 1204 "MakeAllCOTSServerListeners: failed to create listener for %s\n", 1205 trans->TransName); 1206 1207 continue; 1208 } 1209 } 1210 1211 #if defined(IPv6) && defined(AF_INET6) 1212 if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) 1213 ipv6_succ = 1; 1214 #endif 1215 1216 prmsg (5, 1217 "MakeAllCOTSServerListeners: opened listener for %s, %d\n", 1218 trans->TransName, ciptr->fd); 1219 1220 temp_ciptrs[*count_ret] = ciptr; 1221 (*count_ret)++; 1222 } 1223 1224 *partial = (*count_ret < complete_network_count()); 1225 1226 prmsg (5, 1227 "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", 1228 *partial, *count_ret, complete_network_count()); 1229 1230 if (*count_ret > 0) 1231 { 1232 if ((*ciptrs_ret = malloc ( 1233 *count_ret * sizeof (XtransConnInfo))) == NULL) 1234 { 1235 return -1; 1236 } 1237 1238 for (i = 0; i < *count_ret; i++) 1239 { 1240 (*ciptrs_ret)[i] = temp_ciptrs[i]; 1241 } 1242 } 1243 else 1244 *ciptrs_ret = NULL; 1245 1246 return 0; 1247 } 1248 1249 #endif /* TRANS_SERVER */ 1250 1251 1252 1253 /* 1254 * These routines are not part of the X Transport Interface, but they 1255 * may be used by it. 1256 */ 1257 1258 1259 #ifdef WIN32 1260 1261 /* 1262 * emulate readv 1263 */ 1264 1265 static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 1266 1267 { 1268 int i, len, total; 1269 char *base; 1270 1271 ESET(0); 1272 for (i = 0, total = 0; i < iovcnt; i++, iov++) { 1273 len = iov->iov_len; 1274 base = iov->iov_base; 1275 while (len > 0) { 1276 register int nbytes; 1277 nbytes = TRANS(Read) (ciptr, base, len); 1278 if (nbytes < 0 && total == 0) return -1; 1279 if (nbytes <= 0) return total; 1280 ESET(0); 1281 len -= nbytes; 1282 total += nbytes; 1283 base += nbytes; 1284 } 1285 } 1286 return total; 1287 } 1288 1289 1290 /* 1291 * emulate writev 1292 */ 1293 1294 static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 1295 1296 { 1297 int i, len, total; 1298 char *base; 1299 1300 ESET(0); 1301 for (i = 0, total = 0; i < iovcnt; i++, iov++) { 1302 len = iov->iov_len; 1303 base = iov->iov_base; 1304 while (len > 0) { 1305 register int nbytes; 1306 nbytes = TRANS(Write) (ciptr, base, len); 1307 if (nbytes < 0 && total == 0) return -1; 1308 if (nbytes <= 0) return total; 1309 ESET(0); 1310 len -= nbytes; 1311 total += nbytes; 1312 base += nbytes; 1313 } 1314 } 1315 return total; 1316 } 1317 1318 #endif /* WIN32 */ 1319 1320 1321 #if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__) 1322 #ifndef NEED_UTSNAME 1323 #define NEED_UTSNAME 1324 #endif 1325 #include
1326 #endif 1327 1328 /* 1329 * TRANS(GetHostname) - similar to gethostname but allows special processing. 1330 */ 1331 1332 int TRANS(GetHostname) (char *buf, int maxlen) 1333 1334 { 1335 int len; 1336 1337 #ifdef NEED_UTSNAME 1338 struct utsname name; 1339 1340 uname (&name); 1341 len = strlen (name.nodename); 1342 if (len >= maxlen) len = maxlen - 1; 1343 strncpy (buf, name.nodename, len); 1344 buf[len] = '\0'; 1345 #else 1346 buf[0] = '\0'; 1347 (void) gethostname (buf, maxlen); 1348 buf [maxlen - 1] = '\0'; 1349 len = strlen(buf); 1350 #endif /* NEED_UTSNAME */ 1351 return len; 1352 }
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™