Xtrans.c
上传用户:lctgjx
上传日期:2022-06-04
资源大小:8887k
文件大小:30k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2. Copyright 1993, 1994, 1998  The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included
  9. in all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  11. OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  12. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  13. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
  14. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  15. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  16. OTHER DEALINGS IN THE SOFTWARE.
  17. Except as contained in this notice, the name of The Open Group shall
  18. not be used in advertising or otherwise to promote the sale, use or
  19. other dealings in this Software without prior written authorization
  20. from The Open Group.
  21.  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
  22.  *
  23.  * All Rights Reserved
  24.  *
  25.  * Permission to use, copy, modify, and distribute this software and its
  26.  * documentation for any purpose and without fee is hereby granted, provided
  27.  * that the above copyright notice appear in all copies and that both that
  28.  * copyright notice and this permission notice appear in supporting
  29.  * documentation, and that the name NCR not be used in advertising
  30.  * or publicity pertaining to distribution of the software without specific,
  31.  * written prior permission.  NCR makes no representations about the
  32.  * suitability of this software for any purpose.  It is provided "as is"
  33.  * without express or implied warranty.
  34.  *
  35.  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  36.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  37.  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  38.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  39.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  40.  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  41.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  42.  */
  43. #include <ctype.h>
  44. /*
  45.  * The transport table contains a definition for every transport (protocol)
  46.  * family. All operations that can be made on the transport go through this
  47.  * table.
  48.  *
  49.  * Each transport is assigned a unique transport id.
  50.  *
  51.  * New transports can be added by adding an entry in this table.
  52.  * For compatiblity, the transport ids should never be renumbered.
  53.  * Always add to the end of the list.
  54.  */
  55. #define TRANS_TLI_INET_INDEX 1
  56. #define TRANS_TLI_TCP_INDEX 2
  57. #define TRANS_TLI_TLI_INDEX 3
  58. #define TRANS_SOCKET_UNIX_INDEX 4
  59. #define TRANS_SOCKET_LOCAL_INDEX 5
  60. #define TRANS_SOCKET_INET_INDEX 6
  61. #define TRANS_SOCKET_TCP_INDEX 7
  62. #define TRANS_DNET_INDEX 8
  63. #define TRANS_LOCAL_LOCAL_INDEX 9
  64. #define TRANS_LOCAL_PTS_INDEX 10
  65. #define TRANS_LOCAL_NAMED_INDEX 11
  66. #define TRANS_LOCAL_ISC_INDEX 12
  67. #define TRANS_LOCAL_SCO_INDEX 13
  68. #define TRANS_SOCKET_INET6_INDEX 14
  69. #define TRANS_LOCAL_PIPE_INDEX 15
  70. static
  71. Xtransport_table Xtransports[] = {
  72. #if defined(STREAMSCONN)
  73.     { &TRANS(TLITCPFuncs), TRANS_TLI_TCP_INDEX },
  74.     { &TRANS(TLIINETFuncs), TRANS_TLI_INET_INDEX },
  75.     { &TRANS(TLITLIFuncs), TRANS_TLI_TLI_INDEX },
  76. #endif /* STREAMSCONN */
  77. #if defined(TCPCONN)
  78.     { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX },
  79. #if defined(IPv6) && defined(AF_INET6)
  80.     { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX },
  81. #endif /* IPv6 */
  82.     { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX },
  83. #endif /* TCPCONN */
  84. #if defined(UNIXCONN)
  85. #if !defined(LOCALCONN)
  86.     { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
  87. #endif /* !LOCALCONN */
  88.     { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX },
  89. #endif /* UNIXCONN */
  90. #if defined(LOCALCONN)
  91.     { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX },
  92. #ifndef sun
  93.     { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX },
  94. #endif /* sun */
  95. #ifdef SVR4
  96.     { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX },
  97. #endif
  98. #ifdef sun
  99.     { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX },
  100. #else /* !sun */
  101. #if !defined(__SCO__) && !defined(__UNIXWARE__)
  102.     { &TRANS(ISCFuncs), TRANS_LOCAL_ISC_INDEX },
  103. #endif
  104.     { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX },
  105. #endif /* sun */
  106. #endif /* LOCALCONN */
  107. };
  108. #define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table))
  109. #ifdef WIN32
  110. #define ioctl ioctlsocket
  111. #endif
  112. /*
  113.  * These are a few utility function used by the public interface functions.
  114.  */
  115. void
  116. TRANS(FreeConnInfo) (XtransConnInfo ciptr)
  117. {
  118.     PRMSG (3,"FreeConnInfo(%p)n", ciptr, 0, 0);
  119.     if (ciptr->addr)
  120. xfree (ciptr->addr);
  121.     if (ciptr->peeraddr)
  122. xfree (ciptr->peeraddr);
  123.     if (ciptr->port)
  124. xfree (ciptr->port);
  125.     xfree ((char *) ciptr);
  126. }
  127. #define PROTOBUFSIZE 20
  128. static Xtransport *
  129. TRANS(SelectTransport) (char *protocol)
  130. {
  131.     char  protobuf[PROTOBUFSIZE];
  132.     int i;
  133.     PRMSG (3,"SelectTransport(%s)n", protocol, 0, 0);
  134.     /*
  135.      * Force Protocol to be lowercase as a way of doing
  136.      * a case insensitive match.
  137.      */
  138.     strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
  139.     protobuf[PROTOBUFSIZE-1] = '';
  140.     for (i = 0; i < PROTOBUFSIZE && protobuf[i] != ''; i++)
  141. if (isupper (protobuf[i]))
  142.     protobuf[i] = tolower (protobuf[i]);
  143.     /* Look at all of the configured protocols */
  144.     for (i = 0; i < NUMTRANS; i++)
  145.     {
  146. if (!strcmp (protobuf, Xtransports[i].transport->TransName))
  147.     return Xtransports[i].transport;
  148.     }
  149.     return NULL;
  150. }
  151. #ifndef TEST_t
  152. static
  153. #endif /* TEST_t */
  154. int
  155. TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
  156. {
  157.     /*
  158.      * For the font library, the address is a string formatted
  159.      * as "protocol/host:port[/catalogue]".  Note that the catologue
  160.      * is optional.  At this time, the catologue info is ignored, but
  161.      * we have to parse it anyways.
  162.      *
  163.      * Other than fontlib, the address is a string formatted
  164.      * as "protocol/host:port".
  165.      *
  166.      * If the protocol part is missing, then assume TCP.
  167.      * If the protocol part and host part are missing, then assume local.
  168.      * If a "::" is found then assume DNET.
  169.      */
  170.     char *mybuf, *tmpptr;
  171.     char *_protocol, *_host, *_port;
  172.     char hostnamebuf[256];
  173.     int _host_len;
  174.     PRMSG (3,"ParseAddress(%s)n", address, 0, 0);
  175.     /* Copy the string so it can be changed */
  176.     tmpptr = mybuf = (char *) xalloc (strlen (address) + 1);
  177.     strcpy (mybuf, address);
  178.     /* Parse the string to get each component */
  179.     
  180.     /* Get the protocol part */
  181.     _protocol = mybuf;
  182.    if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
  183.       ((mybuf = strrchr (tmpptr,':')) == NULL) )
  184.    {
  185. /* address is in a bad format */
  186. *protocol = NULL;
  187. *host = NULL;
  188. *port = NULL;
  189. xfree (tmpptr);
  190. return 0;
  191.     }
  192.     if (*mybuf == ':')
  193.     {
  194. /*
  195.  * If there is a hostname, then assume tcp, otherwise
  196.  * it must be local.
  197.  */
  198. if (mybuf == tmpptr)
  199. {
  200.     /* There is neither a protocol or host specified */
  201.     _protocol = "local";
  202. }
  203. else
  204. {
  205.     /* There is a hostname specified */
  206.     _protocol = "tcp";
  207.     mybuf = tmpptr; /* reset to the begining of the host ptr */
  208. }
  209.     }
  210.     else
  211.     {
  212. /* *mybuf == '/' */
  213. *mybuf ++= ''; /* put a null at the end of the protocol */
  214. if (strlen(_protocol) == 0)
  215. {
  216.     /*
  217.      * If there is a hostname, then assume tcp, otherwise
  218.      * it must be local.
  219.      */
  220.     if (*mybuf != ':')
  221. _protocol = "tcp";
  222.     else
  223. _protocol = "local";
  224. }
  225.     }
  226.     /* Get the host part */
  227.     _host = mybuf;
  228.     if ((mybuf = strrchr (mybuf,':')) == NULL)
  229.     {
  230. *protocol = NULL;
  231. *host = NULL;
  232. *port = NULL;
  233. xfree (tmpptr);
  234. return 0;
  235.     }
  236.     /* Check for DECnet */
  237.     if ((mybuf != _host) && (*(mybuf - 1) == ':')
  238. #if defined(IPv6) && defined(AF_INET6)
  239.       /* An IPv6 address can end in :: so three : in a row is assumed to be
  240.  an IPv6 host and not a DECnet node with a : in it's name, unless
  241.          DECnet is specifically requested */
  242.       && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') ||
  243. ((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) )
  244. #endif
  245. )
  246.     {
  247. _protocol = "dnet";
  248. *(mybuf - 1) = '';
  249.     }
  250.     *mybuf ++= '';
  251.     _host_len = strlen(_host);
  252.     if (_host_len == 0)
  253.     {
  254. TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
  255. _host = hostnamebuf;
  256.     }
  257. #if defined(IPv6) && defined(AF_INET6)
  258.     /* hostname in IPv6 [numeric_addr]:0 form? */
  259.     else if ( (_host_len > 3) && 
  260.       ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
  261.       && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { 
  262. struct sockaddr_in6 sin6;
  263. *(_host + _host_len - 1) = '';
  264. /* Verify address is valid IPv6 numeric form */
  265. if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
  266.     /* It is. Use it as such. */
  267.     _host++;
  268.     _protocol = "inet6";
  269. } else {
  270.     /* It's not, restore it just in case some other code can use it. */
  271.     *(_host + _host_len - 1) = ']';
  272. }
  273.     }
  274. #endif
  275.     /* Get the port */
  276.     _port = mybuf;
  277. #if defined(FONT_t) || defined(FS_t)
  278.     /*
  279.      * Is there an optional catalogue list?
  280.      */
  281.     if ((mybuf = strchr (mybuf,'/')) != NULL)
  282. *mybuf ++= '';
  283.     /*
  284.      * The rest, if any, is the (currently unused) catalogue list.
  285.      *
  286.      * _catalogue = mybuf;
  287.      */
  288. #endif
  289. #ifdef HAVE_LAUNCHD
  290.     /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
  291.     if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
  292.       _protocol="local";
  293.       _host="";
  294.       _port=address+6;
  295.     }
  296. #endif
  297.     /*
  298.      * Now that we have all of the components, allocate new
  299.      * string space for them.
  300.      */
  301.     if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL)
  302.     {
  303. /* Malloc failed */
  304. *port = NULL;
  305. *host = NULL;
  306. *protocol = NULL;
  307. xfree (tmpptr);
  308. return 0;
  309.     }
  310.     else
  311.         strcpy (*protocol, _protocol);
  312.     if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL)
  313.     {
  314. /* Malloc failed */
  315. *port = NULL;
  316. *host = NULL;
  317. xfree (*protocol);
  318. *protocol = NULL;
  319. xfree (tmpptr);
  320. return 0;
  321. }
  322.     else
  323.         strcpy (*host, _host);
  324.     if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL)
  325.     {
  326. /* Malloc failed */
  327. *port = NULL;
  328. xfree (*host);
  329. *host = NULL;
  330. xfree (*protocol);
  331. *protocol = NULL;
  332. xfree (tmpptr);
  333. return 0;
  334.     }
  335.     else
  336.         strcpy (*port, _port);
  337.     xfree (tmpptr);
  338.     return 1;
  339. }
  340. /*
  341.  * TRANS(Open) does all of the real work opening a connection. The only
  342.  * funny part about this is the type parameter which is used to decide which
  343.  * type of open to perform.
  344.  */
  345. static XtransConnInfo
  346. TRANS(Open) (int type, char *address)
  347. {
  348.     char  *protocol = NULL, *host = NULL, *port = NULL;
  349.     XtransConnInfo ciptr = NULL;
  350.     Xtransport *thistrans;
  351.     PRMSG (2,"Open(%d,%s)n", type, address, 0);
  352. #if defined(WIN32) && defined(TCPCONN) 
  353.     if (TRANS(WSAStartup)())
  354.     {
  355. PRMSG (1,"Open: WSAStartup failedn", 0, 0, 0);
  356. return NULL;
  357.     }
  358. #endif
  359.     /* Parse the Address */
  360.     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
  361.     {
  362. PRMSG (1,"Open: Unable to Parse address %sn", address, 0, 0);
  363. return NULL;
  364.     }
  365.     /* Determine the transport type */
  366.     if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
  367.     {
  368. PRMSG (1,"Open: Unable to find transport for %sn",
  369.        protocol, 0, 0);
  370. xfree (protocol);
  371. xfree (host);
  372. xfree (port);
  373. return NULL;
  374.     }
  375.     /* Open the transport */
  376.     switch (type)
  377.     {
  378.     case XTRANS_OPEN_COTS_CLIENT:
  379. #ifdef TRANS_CLIENT
  380. ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
  381. #endif /* TRANS_CLIENT */
  382. break;
  383.     case XTRANS_OPEN_COTS_SERVER:
  384. #ifdef TRANS_SERVER
  385. ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
  386. #endif /* TRANS_SERVER */
  387. break;
  388.     case XTRANS_OPEN_CLTS_CLIENT:
  389. #ifdef TRANS_CLIENT
  390. ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
  391. #endif /* TRANS_CLIENT */
  392. break;
  393.     case XTRANS_OPEN_CLTS_SERVER:
  394. #ifdef TRANS_SERVER
  395. ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
  396. #endif /* TRANS_SERVER */
  397. break;
  398.     default:
  399. PRMSG (1,"Open: Unknown Open type %dn", type, 0, 0);
  400.     }
  401.     if (ciptr == NULL)
  402.     {
  403. if (!(thistrans->flags & TRANS_DISABLED)) 
  404. {
  405.     PRMSG (1,"Open: transport open failed for %s/%s:%sn",
  406.            protocol, host, port);
  407. }
  408. xfree (protocol);
  409. xfree (host);
  410. xfree (port);
  411. return NULL;
  412.     }
  413.     ciptr->transptr = thistrans;
  414.     ciptr->port = port; /* We need this for TRANS(Reopen) */
  415.     xfree (protocol);
  416.     xfree (host);
  417.     return ciptr;
  418. }
  419. #ifdef TRANS_REOPEN
  420. /*
  421.  * We might want to create an XtransConnInfo object based on a previously
  422.  * opened connection.  For example, the font server may clone itself and
  423.  * pass file descriptors to the parent.
  424.  */
  425. static XtransConnInfo
  426. TRANS(Reopen) (int type, int trans_id, int fd, char *port)
  427. {
  428.     XtransConnInfo ciptr = NULL;
  429.     Xtransport *thistrans = NULL;
  430.     char *save_port;
  431.     int i;
  432.     PRMSG (2,"Reopen(%d,%d,%s)n", trans_id, fd, port);
  433.     /* Determine the transport type */
  434.     for (i = 0; i < NUMTRANS; i++)
  435. if (Xtransports[i].transport_id == trans_id)
  436. {
  437.     thistrans = Xtransports[i].transport;
  438.     break;
  439. }
  440.     if (thistrans == NULL)
  441.     {
  442. PRMSG (1,"Reopen: Unable to find transport id %dn",
  443.        trans_id, 0, 0);
  444. return NULL;
  445.     }
  446.     if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL)
  447.     {
  448. PRMSG (1,"Reopen: Unable to malloc port stringn", 0, 0, 0);
  449. return NULL;
  450.     }
  451.     strcpy (save_port, port);
  452.     /* Get a new XtransConnInfo object */
  453.     switch (type)
  454.     {
  455.     case XTRANS_OPEN_COTS_SERVER:
  456. ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
  457. break;
  458.     case XTRANS_OPEN_CLTS_SERVER:
  459. ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
  460. break;
  461.     default:
  462. PRMSG (1,"Reopen: Bad Open type %dn", type, 0, 0);
  463.     }
  464.     if (ciptr == NULL)
  465.     {
  466. PRMSG (1,"Reopen: transport open failedn", 0, 0, 0);
  467. return NULL;
  468.     }
  469.     ciptr->transptr = thistrans;
  470.     ciptr->port = save_port;
  471.     return ciptr;
  472. }
  473. #endif /* TRANS_REOPEN */
  474. /*
  475.  * These are the public interfaces to this Transport interface.
  476.  * These are the only functions that should have knowledge of the transport
  477.  * table.
  478.  */
  479. #ifdef TRANS_CLIENT
  480. XtransConnInfo
  481. TRANS(OpenCOTSClient) (char *address)
  482. {
  483.     PRMSG (2,"OpenCOTSClient(%s)n", address, 0, 0);
  484.     return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
  485. }
  486. #endif /* TRANS_CLIENT */
  487. #ifdef TRANS_SERVER
  488. XtransConnInfo
  489. TRANS(OpenCOTSServer) (char *address)
  490. {
  491.     PRMSG (2,"OpenCOTSServer(%s)n", address, 0, 0);
  492.     return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
  493. }
  494. #endif /* TRANS_SERVER */
  495. #ifdef TRANS_CLIENT
  496. XtransConnInfo
  497. TRANS(OpenCLTSClient) (char *address)
  498. {
  499.     PRMSG (2,"OpenCLTSClient(%s)n", address, 0, 0);
  500.     return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
  501. }
  502. #endif /* TRANS_CLIENT */
  503. #ifdef TRANS_SERVER
  504. XtransConnInfo
  505. TRANS(OpenCLTSServer) (char *address)
  506. {
  507.     PRMSG (2,"OpenCLTSServer(%s)n", address, 0, 0);
  508.     return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
  509. }
  510. #endif /* TRANS_SERVER */
  511. #ifdef TRANS_REOPEN
  512. XtransConnInfo
  513. TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
  514. {
  515.     PRMSG (2,"ReopenCOTSServer(%d, %d, %s)n", trans_id, fd, port);
  516.     return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
  517. }
  518. XtransConnInfo
  519. TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
  520. {
  521.     PRMSG (2,"ReopenCLTSServer(%d, %d, %s)n", trans_id, fd, port);
  522.     return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
  523. }
  524. int
  525. TRANS(GetReopenInfo) (XtransConnInfo ciptr, 
  526.       int *trans_id, int *fd, char **port)
  527. {
  528.     int i;
  529.     for (i = 0; i < NUMTRANS; i++)
  530. if (Xtransports[i].transport == ciptr->transptr)
  531. {
  532.     *trans_id = Xtransports[i].transport_id;
  533.     *fd = ciptr->fd;
  534.     if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL)
  535. return 0;
  536.     else
  537.     {
  538. strcpy (*port, ciptr->port);
  539. return 1;
  540.     }
  541. }
  542.     return 0;
  543. }
  544. #endif /* TRANS_REOPEN */
  545. int
  546. TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
  547. {
  548.     int fd = ciptr->fd;
  549.     int ret = 0;
  550.     PRMSG (2,"SetOption(%d,%d,%d)n", fd, option, arg);
  551.     /*
  552.      * For now, all transport type use the same stuff for setting options.
  553.      * As long as this is true, we can put the common code here. Once a more
  554.      * complicated transport such as shared memory or an OSI implementation
  555.      * that uses the session and application libraries is implemented, this
  556.      * code may have to move to a transport dependent function.
  557.      *
  558.      * ret = ciptr->transptr->SetOption (ciptr, option, arg);
  559.      */
  560.     switch (option)
  561.     {
  562.     case TRANS_NONBLOCKING:
  563. switch (arg)
  564. {
  565. case 0:
  566.     /* Set to blocking mode */
  567.     break;
  568. case 1: /* Set to non-blocking mode */
  569. #if defined(O_NONBLOCK) && !defined(SCO325) 
  570.     ret = fcntl (fd, F_GETFL, 0);
  571.     if (ret != -1)
  572. ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
  573. #else
  574. #ifdef FIOSNBIO
  575. {
  576.     int arg;
  577.     arg = 1;
  578.     ret = ioctl (fd, FIOSNBIO, &arg);
  579. }
  580. #else
  581. #if defined(WIN32) 
  582. {
  583. #ifdef WIN32
  584.     u_long arg;
  585. #else
  586.     int arg;
  587. #endif
  588.     arg = 1;
  589. /* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
  590.  * eventually with EWOULDBLOCK */
  591.     ret = ioctl (fd, FIONBIO, &arg);
  592. }
  593. #else
  594.     ret = fcntl (fd, F_GETFL, 0);
  595. #ifdef FNDELAY
  596.     ret = fcntl (fd, F_SETFL, ret | FNDELAY);
  597. #else
  598.     ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
  599. #endif
  600. #endif /* AIXV3  || uniosu */
  601. #endif /* FIOSNBIO */
  602. #endif /* O_NONBLOCK */
  603.     break;
  604. default:
  605.     /* Unknown option */
  606.     break;
  607. }
  608. break;
  609.     case TRANS_CLOSEONEXEC:
  610. #ifdef F_SETFD
  611. #ifdef FD_CLOEXEC
  612. ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
  613. #else
  614. ret = fcntl (fd, F_SETFD, 1);
  615. #endif /* FD_CLOEXEC */
  616. #endif /* F_SETFD */
  617. break;
  618.     }
  619.     
  620.     return ret;
  621. }
  622. #ifdef TRANS_SERVER
  623. int
  624. TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
  625. {
  626.     return ciptr->transptr->CreateListener (ciptr, port, flags);
  627. }
  628. int
  629. TRANS(NoListen) (char * protocol)
  630. {
  631.    Xtransport *trans;
  632.    int i = 0, ret = 0;
  633.    
  634.    if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 
  635.    {
  636. PRMSG (1,"TransNoListen: unable to find transport: %sn", 
  637.        protocol, 0, 0);
  638. return -1;
  639.    }
  640.    if (trans->flags & TRANS_ALIAS) {
  641.        if (trans->nolisten)
  642.    while (trans->nolisten[i]) {
  643.        ret |= TRANS(NoListen)(trans->nolisten[i]);
  644.        i++;
  645.        }
  646.    }
  647.    trans->flags |= TRANS_NOLISTEN;
  648.    return ret;
  649. }
  650. int
  651. TRANS(ResetListener) (XtransConnInfo ciptr)
  652. {
  653.     if (ciptr->transptr->ResetListener)
  654. return ciptr->transptr->ResetListener (ciptr);
  655.     else
  656. return TRANS_RESET_NOOP;
  657. }
  658. XtransConnInfo
  659. TRANS(Accept) (XtransConnInfo ciptr, int *status)
  660. {
  661.     XtransConnInfo newciptr;
  662.     PRMSG (2,"Accept(%d)n", ciptr->fd, 0, 0);
  663.     newciptr = ciptr->transptr->Accept (ciptr, status);
  664.     if (newciptr)
  665. newciptr->transptr = ciptr->transptr;
  666.     return newciptr;
  667. }
  668. #endif /* TRANS_SERVER */
  669. #ifdef TRANS_CLIENT
  670. int
  671. TRANS(Connect) (XtransConnInfo ciptr, char *address)
  672. {
  673.     char *protocol;
  674.     char *host;
  675.     char *port;
  676.     int ret;
  677.     PRMSG (2,"Connect(%d,%s)n", ciptr->fd, address, 0);
  678.     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
  679.     {
  680. PRMSG (1,"Connect: Unable to Parse address %sn",
  681.        address, 0, 0);
  682. return -1;
  683.     }
  684. #ifdef HAVE_LAUNCHD
  685.     if (!host) host=strdup("");
  686. #endif
  687.     if (!port || !*port)
  688.     {
  689. PRMSG (1,"Connect: Missing port specification in %sn",
  690.       address, 0, 0);
  691. if (protocol) xfree (protocol);
  692. if (host) xfree (host);
  693. return -1;
  694.     }
  695.     ret = ciptr->transptr->Connect (ciptr, host, port);
  696.     if (protocol) xfree (protocol);
  697.     if (host) xfree (host);
  698.     if (port) xfree (port);
  699.     
  700.     return ret;
  701. }
  702. #endif /* TRANS_CLIENT */
  703. int
  704. TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
  705. {
  706.     return ciptr->transptr->BytesReadable (ciptr, pend);
  707. }
  708. int
  709. TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
  710. {
  711.     return ciptr->transptr->Read (ciptr, buf, size);
  712. }
  713. int
  714. TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
  715. {
  716.     return ciptr->transptr->Write (ciptr, buf, size);
  717. }
  718. int
  719. TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
  720. {
  721.     return ciptr->transptr->Readv (ciptr, buf, size);
  722. }
  723. int
  724. TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
  725. {
  726.     return ciptr->transptr->Writev (ciptr, buf, size);
  727. }
  728. int
  729. TRANS(Disconnect) (XtransConnInfo ciptr)
  730. {
  731.     return ciptr->transptr->Disconnect (ciptr);
  732. }
  733. int
  734. TRANS(Close) (XtransConnInfo ciptr)
  735. {
  736.     int ret;
  737.     PRMSG (2,"Close(%d)n", ciptr->fd, 0, 0);
  738.     ret = ciptr->transptr->Close (ciptr);
  739.     TRANS(FreeConnInfo) (ciptr);
  740.     return ret;
  741. }
  742. int
  743. TRANS(CloseForCloning) (XtransConnInfo ciptr)
  744. {
  745.     int ret;
  746.     PRMSG (2,"CloseForCloning(%d)n", ciptr->fd, 0, 0);
  747.     ret = ciptr->transptr->CloseForCloning (ciptr);
  748.     TRANS(FreeConnInfo) (ciptr);
  749.     return ret;
  750. }
  751. int
  752. TRANS(IsLocal) (XtransConnInfo ciptr)
  753. {
  754.     return (ciptr->family == AF_UNIX);
  755. }
  756. int
  757. TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 
  758.   Xtransaddr **addrp)
  759. {
  760.     PRMSG (2,"GetMyAddr(%d)n", ciptr->fd, 0, 0);
  761.     *familyp = ciptr->family;
  762.     *addrlenp = ciptr->addrlen;
  763.     if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL)
  764.     {
  765. PRMSG (1,"GetMyAddr: malloc failedn", 0, 0, 0);
  766. return -1;
  767.     }
  768.     memcpy(*addrp, ciptr->addr, ciptr->addrlen);
  769.     return 0;
  770. }
  771. int
  772. TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 
  773.     Xtransaddr **addrp)
  774. {
  775.     PRMSG (2,"GetPeerAddr(%d)n", ciptr->fd, 0, 0);
  776.     *familyp = ciptr->family;
  777.     *addrlenp = ciptr->peeraddrlen;
  778.     if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL)
  779.     {
  780. PRMSG (1,"GetPeerAddr: malloc failedn", 0, 0, 0);
  781. return -1;
  782.     }
  783.     memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
  784.     return 0;
  785. }
  786. int
  787. TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
  788. {
  789.     return ciptr->fd;
  790. }
  791. /*
  792.  * These functions are really utility functions, but they require knowledge
  793.  * of the internal data structures, so they have to be part of the Transport
  794.  * Independant API.
  795.  */
  796. #ifdef TRANS_SERVER
  797. static int
  798. complete_network_count (void)
  799. {
  800.     int count = 0;
  801.     int found_local = 0;
  802.     int i;
  803.     /*
  804.      * For a complete network, we only need one LOCALCONN transport to work
  805.      */
  806.     for (i = 0; i < NUMTRANS; i++)
  807.     {
  808. if (Xtransports[i].transport->flags & TRANS_ALIAS
  809.      || Xtransports[i].transport->flags & TRANS_NOLISTEN)
  810.     continue;
  811. if (Xtransports[i].transport->flags & TRANS_LOCAL)
  812.     found_local = 1;
  813. else
  814.     count++;
  815.     }
  816.     return (count + found_local);
  817. }
  818. #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
  819. extern int xquartz_launchd_fd;
  820. #endif
  821. int
  822. TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, 
  823.    XtransConnInfo **ciptrs_ret)
  824. {
  825.     char buffer[256]; /* ??? What size ?? */
  826.     XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
  827.     int status, i, j;
  828. #if defined(IPv6) && defined(AF_INET6)
  829.     int ipv6_succ = 0;
  830. #endif
  831.     PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)n",
  832.    port ? port : "NULL", ciptrs_ret, 0);
  833.     *count_ret = 0;
  834. #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
  835.     fprintf(stderr, "Launchd socket fd: %dn", xquartz_launchd_fd);
  836.     if(xquartz_launchd_fd != -1) {
  837.         if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
  838.                                            xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
  839.             fprintf(stderr,"Got NULL while trying to Reopen launchd portn");
  840.         else 
  841.             temp_ciptrs[(*count_ret)++] = ciptr;
  842.     }
  843. #endif
  844.     for (i = 0; i < NUMTRANS; i++)
  845.     {
  846. Xtransport *trans = Xtransports[i].transport;
  847. unsigned int flags = 0;
  848. if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
  849.     continue;
  850. snprintf(buffer, sizeof(buffer), "%s/:%s",
  851.  trans->TransName, port ? port : "");
  852. PRMSG (5,"MakeAllCOTSServerListeners: opening %sn",
  853.        buffer, 0, 0);
  854. if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
  855. {
  856.     if (trans->flags & TRANS_DISABLED)
  857. continue;
  858.     PRMSG (1,
  859.   "MakeAllCOTSServerListeners: failed to open listener for %sn",
  860.   trans->TransName, 0, 0);
  861.     continue;
  862. }
  863. #if defined(IPv6) && defined(AF_INET6)
  864. if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
  865.      && ipv6_succ))
  866.     flags |= ADDR_IN_USE_ALLOWED;
  867. #endif
  868. if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
  869. {
  870.     if (status == TRANS_ADDR_IN_USE)
  871.     {
  872. /*
  873.  * We failed to bind to the specified address because the
  874.  * address is in use.  It must be that a server is already
  875.  * running at this address, and this function should fail.
  876.  */
  877. PRMSG (1,
  878. "MakeAllCOTSServerListeners: server already runningn",
  879.   0, 0, 0);
  880. for (j = 0; j < *count_ret; j++)
  881.     TRANS(Close) (temp_ciptrs[j]);
  882. *count_ret = 0;
  883. *ciptrs_ret = NULL;
  884. *partial = 0;
  885. return -1;
  886.     }
  887.     else
  888.     {
  889. PRMSG (1,
  890. "MakeAllCOTSServerListeners: failed to create listener for %sn",
  891.   trans->TransName, 0, 0);
  892. continue;
  893.     }
  894. }
  895. #if defined(IPv6) && defined(AF_INET6)
  896. if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
  897.     ipv6_succ = 1;
  898. #endif
  899. PRMSG (5,
  900.       "MakeAllCOTSServerListeners: opened listener for %s, %dn",
  901.       trans->TransName, ciptr->fd, 0);
  902. temp_ciptrs[*count_ret] = ciptr;
  903. (*count_ret)++;
  904.     }
  905.     *partial = (*count_ret < complete_network_count());
  906.     PRMSG (5,
  907.      "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d n",
  908. *partial, *count_ret, complete_network_count());
  909.     if (*count_ret > 0)
  910.     {
  911. if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
  912.     *count_ret * sizeof (XtransConnInfo))) == NULL)
  913. {
  914.     return -1;
  915. }
  916. for (i = 0; i < *count_ret; i++)
  917. {
  918.     (*ciptrs_ret)[i] = temp_ciptrs[i];
  919. }
  920.     }
  921.     else
  922. *ciptrs_ret = NULL;
  923.  
  924.     return 0;
  925. }
  926. int
  927. TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, 
  928.    XtransConnInfo **ciptrs_ret)
  929. {
  930.     char buffer[256]; /* ??? What size ?? */
  931.     XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
  932.     int status, i, j;
  933.     PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)n",
  934. port ? port : "NULL", ciptrs_ret, 0);
  935.     *count_ret = 0;
  936.     for (i = 0; i < NUMTRANS; i++)
  937.     {
  938. Xtransport *trans = Xtransports[i].transport;
  939. if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
  940.     continue;
  941. snprintf(buffer, sizeof(buffer), "%s/:%s",
  942.  trans->TransName, port ? port : "");
  943. PRMSG (5,"MakeAllCLTSServerListeners: opening %sn",
  944.     buffer, 0, 0);
  945. if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
  946. {
  947.     PRMSG (1,
  948. "MakeAllCLTSServerListeners: failed to open listener for %sn",
  949.   trans->TransName, 0, 0);
  950.     continue;
  951. }
  952. if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
  953. {
  954.     if (status == TRANS_ADDR_IN_USE)
  955.     {
  956. /*
  957.  * We failed to bind to the specified address because the
  958.  * address is in use.  It must be that a server is already
  959.  * running at this address, and this function should fail.
  960.  */
  961. PRMSG (1,
  962. "MakeAllCLTSServerListeners: server already runningn",
  963.   0, 0, 0);
  964. for (j = 0; j < *count_ret; j++)
  965.     TRANS(Close) (temp_ciptrs[j]);
  966. *count_ret = 0;
  967. *ciptrs_ret = NULL;
  968. *partial = 0;
  969. return -1;
  970.     }
  971.     else
  972.     {
  973. PRMSG (1,
  974. "MakeAllCLTSServerListeners: failed to create listener for %sn",
  975.   trans->TransName, 0, 0);
  976. continue;
  977.     }
  978. }
  979. PRMSG (5,
  980. "MakeAllCLTSServerListeners: opened listener for %s, %dn",
  981.       trans->TransName, ciptr->fd, 0);
  982. temp_ciptrs[*count_ret] = ciptr;
  983. (*count_ret)++;
  984.     }
  985.     *partial = (*count_ret < complete_network_count());
  986.     PRMSG (5,
  987.      "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d n",
  988. *partial, *count_ret, complete_network_count());
  989.     if (*count_ret > 0)
  990.     {
  991. if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
  992.     *count_ret * sizeof (XtransConnInfo))) == NULL)
  993. {
  994.     return -1;
  995. }
  996. for (i = 0; i < *count_ret; i++)
  997. {
  998.     (*ciptrs_ret)[i] = temp_ciptrs[i];
  999. }
  1000.     }
  1001.     else
  1002. *ciptrs_ret = NULL;
  1003.     
  1004.     return 0;
  1005. }
  1006. #endif /* TRANS_SERVER */
  1007. /*
  1008.  * These routines are not part of the X Transport Interface, but they
  1009.  * may be used by it.
  1010.  */
  1011. #if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32) 
  1012. /*
  1013.  * emulate readv
  1014.  */
  1015. static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
  1016. {
  1017.     int i, len, total;
  1018.     char *base;
  1019.     ESET(0);
  1020.     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
  1021. len = iov->iov_len;
  1022. base = iov->iov_base;
  1023. while (len > 0) {
  1024.     register int nbytes;
  1025.     nbytes = TRANS(Read) (ciptr, base, len);
  1026.     if (nbytes < 0 && total == 0)  return -1;
  1027.     if (nbytes <= 0)  return total;
  1028.     ESET(0);
  1029.     len   -= nbytes;
  1030.     total += nbytes;
  1031.     base  += nbytes;
  1032. }
  1033.     }
  1034.     return total;
  1035. }
  1036. #endif /* SYSV && __i386__ || WIN32 || __sxg__ */
  1037. #if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32) 
  1038. /*
  1039.  * emulate writev
  1040.  */
  1041. static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
  1042. {
  1043.     int i, len, total;
  1044.     char *base;
  1045.     ESET(0);
  1046.     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
  1047. len = iov->iov_len;
  1048. base = iov->iov_base;
  1049. while (len > 0) {
  1050.     register int nbytes;
  1051.     nbytes = TRANS(Write) (ciptr, base, len);
  1052.     if (nbytes < 0 && total == 0)  return -1;
  1053.     if (nbytes <= 0)  return total;
  1054.     ESET(0);
  1055.     len   -= nbytes;
  1056.     total += nbytes;
  1057.     base  += nbytes;
  1058. }
  1059.     }
  1060.     return total;
  1061. }
  1062. #endif /* SYSV && __i386__ || WIN32 || __sxg__ */
  1063. #if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SCO__)
  1064. #ifndef NEED_UTSNAME
  1065. #define NEED_UTSNAME
  1066. #endif
  1067. #include <sys/utsname.h>
  1068. #endif
  1069. /*
  1070.  * TRANS(GetHostname) - similar to gethostname but allows special processing.
  1071.  */
  1072. int TRANS(GetHostname) (char *buf, int maxlen)
  1073. {
  1074.     int len;
  1075. #ifdef NEED_UTSNAME
  1076.     struct utsname name;
  1077.     uname (&name);
  1078.     len = strlen (name.nodename);
  1079.     if (len >= maxlen) len = maxlen - 1;
  1080.     strncpy (buf, name.nodename, len);
  1081.     buf[len] = '';
  1082. #else
  1083.     buf[0] = '';
  1084.     (void) gethostname (buf, maxlen);
  1085.     buf [maxlen - 1] = '';
  1086.     len = strlen(buf);
  1087. #endif /* NEED_UTSNAME */
  1088.     return len;
  1089. }