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