Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:18:46

0001 /*
0002 
0003 Copyright 1993, 1994, 1998  The Open Group
0004 
0005 Permission to use, copy, modify, distribute, and sell this software and its
0006 documentation for any purpose is hereby granted without fee, provided that
0007 the above copyright notice appear in all copies and that both that
0008 copyright notice and this permission notice appear in supporting
0009 documentation.
0010 
0011 The above copyright notice and this permission notice shall be included
0012 in all copies or substantial portions of the Software.
0013 
0014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0015 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0016 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0017 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020 OTHER DEALINGS IN THE SOFTWARE.
0021 
0022 Except as contained in this notice, the name of The Open Group shall
0023 not be used in advertising or otherwise to promote the sale, use or
0024 other dealings in this Software without prior written authorization
0025 from The Open Group.
0026 
0027  * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
0028  *
0029  * All Rights Reserved
0030  *
0031  * Permission to use, copy, modify, and distribute this software and its
0032  * documentation for any purpose and without fee is hereby granted, provided
0033  * that the above copyright notice appear in all copies and that both that
0034  * copyright notice and this permission notice appear in supporting
0035  * documentation, and that the name NCR not be used in advertising
0036  * or publicity pertaining to distribution of the software without specific,
0037  * written prior permission.  NCR makes no representations about the
0038  * suitability of this software for any purpose.  It is provided "as is"
0039  * without express or implied warranty.
0040  *
0041  * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
0042  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
0043  * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
0044  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
0045  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0046  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0047  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0048  */
0049 
0050 #include <ctype.h>
0051 #include <stdlib.h>
0052 #include <string.h>
0053 #ifdef HAVE_SYSTEMD_DAEMON
0054 #include <systemd/sd-daemon.h>
0055 #endif
0056 
0057 /*
0058  * The transport table contains a definition for every transport (protocol)
0059  * family. All operations that can be made on the transport go through this
0060  * table.
0061  *
0062  * Each transport is assigned a unique transport id.
0063  *
0064  * New transports can be added by adding an entry in this table.
0065  * For compatibility, the transport ids should never be renumbered.
0066  * Always add to the end of the list.
0067  */
0068 
0069 #define TRANS_TLI_INET_INDEX        1
0070 #define TRANS_TLI_TCP_INDEX     2
0071 #define TRANS_TLI_TLI_INDEX     3
0072 #define TRANS_SOCKET_UNIX_INDEX     4
0073 #define TRANS_SOCKET_LOCAL_INDEX    5
0074 #define TRANS_SOCKET_INET_INDEX     6
0075 #define TRANS_SOCKET_TCP_INDEX      7
0076 #define TRANS_DNET_INDEX        8
0077 #define TRANS_LOCAL_LOCAL_INDEX     9
0078 /* 10 used to be PTS, but that's gone. */
0079 #define TRANS_LOCAL_NAMED_INDEX     11
0080 /* 12 used to be ISC, but that's gone. */
0081 /* 13 used to be SCO, but that's gone. */
0082 #define TRANS_SOCKET_INET6_INDEX    14
0083 #define TRANS_LOCAL_PIPE_INDEX      15
0084 
0085 #if defined(IPv6) && !defined(AF_INET6)
0086 #error "Cannot build IPv6 support without AF_INET6"
0087 #endif
0088 
0089 static
0090 Xtransport_table Xtransports[] = {
0091 #if defined(TCPCONN)
0092     { &TRANS(SocketTCPFuncs),   TRANS_SOCKET_TCP_INDEX },
0093 #if defined(IPv6)
0094     { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX },
0095 #endif /* IPv6 */
0096     { &TRANS(SocketINETFuncs),  TRANS_SOCKET_INET_INDEX },
0097 #endif /* TCPCONN */
0098 #if defined(UNIXCONN)
0099 #if !defined(LOCALCONN)
0100     { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
0101 #endif /* !LOCALCONN */
0102     { &TRANS(SocketUNIXFuncs),  TRANS_SOCKET_UNIX_INDEX },
0103 #endif /* UNIXCONN */
0104 #if defined(LOCALCONN)
0105     { &TRANS(LocalFuncs),   TRANS_LOCAL_LOCAL_INDEX },
0106 #if defined(SVR4) || defined(__SVR4)
0107     { &TRANS(NAMEDFuncs),   TRANS_LOCAL_NAMED_INDEX },
0108 #endif
0109 #ifdef __sun
0110     { &TRANS(PIPEFuncs),    TRANS_LOCAL_PIPE_INDEX },
0111 #endif /* __sun */
0112 #endif /* LOCALCONN */
0113 };
0114 
0115 #define NUMTRANS    (sizeof(Xtransports)/sizeof(Xtransport_table))
0116 
0117 
0118 #ifdef WIN32
0119 #define ioctl ioctlsocket
0120 #endif
0121 
0122 
0123 
0124 /*
0125  * These are a few utility function used by the public interface functions.
0126  */
0127 
0128 void
0129 TRANS(FreeConnInfo) (XtransConnInfo ciptr)
0130 
0131 {
0132     prmsg (3,"FreeConnInfo(%p)\n", (void *) ciptr);
0133 
0134     if (ciptr->addr)
0135     free (ciptr->addr);
0136 
0137     if (ciptr->peeraddr)
0138     free (ciptr->peeraddr);
0139 
0140     if (ciptr->port)
0141     free (ciptr->port);
0142 
0143     free (ciptr);
0144 }
0145 
0146 
0147 #define PROTOBUFSIZE    20
0148 
0149 static Xtransport *
0150 TRANS(SelectTransport) (const char *protocol)
0151 
0152 {
0153 #ifndef HAVE_STRCASECMP
0154     char    protobuf[PROTOBUFSIZE];
0155 #endif
0156 
0157     prmsg (3,"SelectTransport(%s)\n", protocol);
0158 
0159 #ifndef HAVE_STRCASECMP
0160     /*
0161      * Force Protocol to be lowercase as a way of doing
0162      * a case insensitive match.
0163      */
0164 
0165     strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
0166     protobuf[PROTOBUFSIZE-1] = '\0';
0167 
0168     for (unsigned int i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
0169     if (isupper ((unsigned char)protobuf[i]))
0170         protobuf[i] = tolower ((unsigned char)protobuf[i]);
0171 #endif
0172 
0173     /* Look at all of the configured protocols */
0174 
0175     for (unsigned int i = 0; i < NUMTRANS; i++)
0176     {
0177 #ifndef HAVE_STRCASECMP
0178     if (!strcmp (protobuf, Xtransports[i].transport->TransName))
0179 #else
0180     if (!strcasecmp (protocol, Xtransports[i].transport->TransName))
0181 #endif
0182         return Xtransports[i].transport;
0183     }
0184 
0185     return NULL;
0186 }
0187 
0188 static int
0189 TRANS(ParseAddress) (const char *address,
0190                      char **protocol, char **host, char **port)
0191 
0192 {
0193     /*
0194      * For the font library, the address is a string formatted
0195      * as "protocol/host:port[/catalogue]".  Note that the catologue
0196      * is optional.  At this time, the catologue info is ignored, but
0197      * we have to parse it anyways.
0198      *
0199      * Other than fontlib, the address is a string formatted
0200      * as "protocol/host:port".
0201      *
0202      * If the protocol part is missing, then assume TCP.
0203      * If the protocol part and host part are missing, then assume local.
0204      * If a "::" is found then assume DNET.
0205      */
0206 
0207     char    *mybuf, *tmpptr = NULL;
0208     const char  *_protocol = NULL;
0209     const char  *_host, *_port;
0210     char    hostnamebuf[256];
0211     char    *_host_buf;
0212     int     _host_len;
0213 
0214     prmsg (3,"ParseAddress(%s)\n", address);
0215 
0216     /* First, check for AF_UNIX socket paths */
0217     if (address[0] == '/') {
0218         _protocol = "local";
0219         _host = "";
0220         _port = address;
0221     } else
0222 #ifdef HAVE_LAUNCHD
0223     /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
0224     if(!strncmp(address,"local//",7)) {
0225         _protocol="local";
0226         _host="";
0227         _port=address+6;
0228     } else
0229 #endif
0230     if (!strncmp(address, "unix:", 5)) {
0231         _protocol = "local";
0232         _host = "";
0233         _port = address + 5;
0234     }
0235     if (_protocol)
0236         goto done_parsing;
0237 
0238     /* Copy the string so it can be changed */
0239 
0240     tmpptr = mybuf = strdup (address);
0241 
0242     /* Parse the string to get each component */
0243 
0244     /* Get the protocol part */
0245 
0246     _protocol = mybuf;
0247 
0248 
0249     if ((mybuf == NULL) ||
0250         ( ((mybuf = strchr (mybuf, '/')) == NULL) &&
0251           ((mybuf = strrchr (tmpptr, ':')) == NULL) ) )
0252     {
0253     /* address is in a bad format */
0254     *protocol = NULL;
0255     *host = NULL;
0256     *port = NULL;
0257     free (tmpptr);
0258     return 0;
0259     }
0260 
0261     if (*mybuf == ':')
0262     {
0263     /*
0264      * If there is a hostname, then assume tcp, otherwise
0265      * it must be local.
0266      */
0267     if (mybuf == tmpptr)
0268     {
0269         /* There is neither a protocol or host specified */
0270         _protocol = "local";
0271     }
0272     else
0273     {
0274         /* There is a hostname specified */
0275         _protocol = "tcp";
0276         mybuf = tmpptr; /* reset to the beginning of the host ptr */
0277     }
0278     }
0279     else
0280     {
0281     /* *mybuf == '/' */
0282 
0283     *mybuf ++= '\0'; /* put a null at the end of the protocol */
0284 
0285     if (strlen(_protocol) == 0)
0286     {
0287         /*
0288          * If there is a hostname, then assume tcp, otherwise
0289          * it must be local.
0290          */
0291         if (*mybuf != ':')
0292         _protocol = "tcp";
0293         else
0294         _protocol = "local";
0295     }
0296     }
0297 
0298     /* Get the host part */
0299 
0300     _host = _host_buf = mybuf;
0301 
0302     if ((mybuf = strrchr (mybuf,':')) == NULL)
0303     {
0304     *protocol = NULL;
0305     *host = NULL;
0306     *port = NULL;
0307     free (tmpptr);
0308     return 0;
0309     }
0310 
0311     *mybuf ++= '\0';
0312 
0313     _host_len = strlen(_host);
0314     if (_host_len == 0)
0315     {
0316     TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
0317     _host = hostnamebuf;
0318     }
0319 #ifdef IPv6
0320     /* hostname in IPv6 [numeric_addr]:0 form? */
0321     else if ( (_host_len > 3) &&
0322       ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
0323       && (_host_buf[0] == '[') && (_host_buf[_host_len - 1] == ']') ) {
0324     struct sockaddr_in6 sin6;
0325 
0326     _host_buf[_host_len - 1] = '\0';
0327 
0328     /* Verify address is valid IPv6 numeric form */
0329     if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
0330         /* It is. Use it as such. */
0331         _host++;
0332         _protocol = "inet6";
0333     } else {
0334         /* It's not, restore it just in case some other code can use it. */
0335         _host_buf[_host_len - 1] = ']';
0336     }
0337     }
0338 #endif
0339 
0340 
0341     /* Get the port */
0342 
0343     _port = mybuf;
0344 
0345 #if defined(FONT_t) || defined(FS_t)
0346     /*
0347      * Is there an optional catalogue list?
0348      */
0349 
0350     if ((mybuf = strchr (mybuf,'/')) != NULL)
0351     *mybuf ++= '\0';
0352 
0353     /*
0354      * The rest, if any, is the (currently unused) catalogue list.
0355      *
0356      * _catalogue = mybuf;
0357      */
0358 #endif
0359 
0360 done_parsing:
0361     /*
0362      * Now that we have all of the components, allocate new
0363      * string space for them.
0364      */
0365 
0366     if ((*protocol = strdup (_protocol)) == NULL)
0367     {
0368     /* Malloc failed */
0369     *port = NULL;
0370     *host = NULL;
0371     *protocol = NULL;
0372     free (tmpptr);
0373     return 0;
0374     }
0375 
0376     if ((*host = strdup (_host)) == NULL)
0377     {
0378     /* Malloc failed */
0379     *port = NULL;
0380     *host = NULL;
0381     free (*protocol);
0382     *protocol = NULL;
0383     free (tmpptr);
0384     return 0;
0385     }
0386 
0387     if ((*port = strdup (_port)) == NULL)
0388     {
0389     /* Malloc failed */
0390     *port = NULL;
0391     free (*host);
0392     *host = NULL;
0393     free (*protocol);
0394     *protocol = NULL;
0395     free (tmpptr);
0396     return 0;
0397     }
0398 
0399     free (tmpptr);
0400 
0401     return 1;
0402 }
0403 
0404 
0405 /*
0406  * TRANS(Open) does all of the real work opening a connection. The only
0407  * funny part about this is the type parameter which is used to decide which
0408  * type of open to perform.
0409  */
0410 
0411 static XtransConnInfo
0412 TRANS(Open) (int type, const char *address)
0413 
0414 {
0415     char        *protocol = NULL, *host = NULL, *port = NULL;
0416     XtransConnInfo  ciptr = NULL;
0417     Xtransport      *thistrans;
0418 
0419     prmsg (2,"Open(%d,%s)\n", type, address);
0420 
0421 #if defined(WIN32) && defined(TCPCONN)
0422     if (TRANS(WSAStartup)())
0423     {
0424     prmsg (1,"Open: WSAStartup failed\n");
0425     return NULL;
0426     }
0427 #endif
0428 
0429     /* Parse the Address */
0430 
0431     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
0432     {
0433     prmsg (1,"Open: Unable to Parse address %s\n", address);
0434     return NULL;
0435     }
0436 
0437     /* Determine the transport type */
0438 
0439     if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
0440     {
0441     prmsg (1,"Open: Unable to find transport for %s\n",
0442            protocol);
0443 
0444     free (protocol);
0445     free (host);
0446     free (port);
0447     return NULL;
0448     }
0449 
0450     /* Open the transport */
0451 
0452     switch (type)
0453     {
0454     case XTRANS_OPEN_COTS_CLIENT:
0455 #ifdef TRANS_CLIENT
0456     ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
0457 #endif /* TRANS_CLIENT */
0458     break;
0459     case XTRANS_OPEN_COTS_SERVER:
0460 #ifdef TRANS_SERVER
0461     ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
0462 #endif /* TRANS_SERVER */
0463     break;
0464     default:
0465     prmsg (1,"Open: Unknown Open type %d\n", type);
0466     }
0467 
0468     if (ciptr == NULL)
0469     {
0470     if (!(thistrans->flags & TRANS_DISABLED))
0471     {
0472         prmsg (1,"Open: transport open failed for %s/%s:%s\n",
0473                protocol, host, port);
0474     }
0475     free (protocol);
0476     free (host);
0477     free (port);
0478     return NULL;
0479     }
0480 
0481     ciptr->transptr = thistrans;
0482     ciptr->port = port;         /* We need this for TRANS(Reopen) */
0483 
0484     free (protocol);
0485     free (host);
0486 
0487     return ciptr;
0488 }
0489 
0490 
0491 #ifdef TRANS_REOPEN
0492 
0493 /*
0494  * We might want to create an XtransConnInfo object based on a previously
0495  * opened connection.  For example, the font server may clone itself and
0496  * pass file descriptors to the parent.
0497  */
0498 
0499 static XtransConnInfo
0500 TRANS(Reopen) (int type, int trans_id, int fd, const char *port)
0501 
0502 {
0503     XtransConnInfo  ciptr = NULL;
0504     Xtransport      *thistrans = NULL;
0505     char        *save_port;
0506 
0507     prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
0508 
0509     /* Determine the transport type */
0510 
0511     for (unsigned int i = 0; i < NUMTRANS; i++)
0512     {
0513     if (Xtransports[i].transport_id == trans_id)
0514     {
0515         thistrans = Xtransports[i].transport;
0516         break;
0517     }
0518     }
0519 
0520     if (thistrans == NULL)
0521     {
0522     prmsg (1,"Reopen: Unable to find transport id %d\n",
0523            trans_id);
0524 
0525     return NULL;
0526     }
0527 
0528     if ((save_port = strdup (port)) == NULL)
0529     {
0530     prmsg (1,"Reopen: Unable to malloc port string\n");
0531 
0532     return NULL;
0533     }
0534 
0535     /* Get a new XtransConnInfo object */
0536 
0537     switch (type)
0538     {
0539     case XTRANS_OPEN_COTS_SERVER:
0540     ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
0541     break;
0542     default:
0543     prmsg (1,"Reopen: Bad Open type %d\n", type);
0544     }
0545 
0546     if (ciptr == NULL)
0547     {
0548     prmsg (1,"Reopen: transport open failed\n");
0549     free (save_port);
0550     return NULL;
0551     }
0552 
0553     ciptr->transptr = thistrans;
0554     ciptr->port = save_port;
0555 
0556     return ciptr;
0557 }
0558 
0559 #endif /* TRANS_REOPEN */
0560 
0561 
0562 
0563 /*
0564  * These are the public interfaces to this Transport interface.
0565  * These are the only functions that should have knowledge of the transport
0566  * table.
0567  */
0568 
0569 #ifdef TRANS_CLIENT
0570 
0571 XtransConnInfo
0572 TRANS(OpenCOTSClient) (const char *address)
0573 
0574 {
0575     prmsg (2,"OpenCOTSClient(%s)\n", address);
0576     return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
0577 }
0578 
0579 #endif /* TRANS_CLIENT */
0580 
0581 
0582 #ifdef TRANS_SERVER
0583 
0584 XtransConnInfo
0585 TRANS(OpenCOTSServer) (const char *address)
0586 
0587 {
0588     prmsg (2,"OpenCOTSServer(%s)\n", address);
0589     return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
0590 }
0591 
0592 #endif /* TRANS_SERVER */
0593 
0594 
0595 #ifdef TRANS_REOPEN
0596 
0597 XtransConnInfo
0598 TRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port)
0599 
0600 {
0601     prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
0602     return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
0603 }
0604 
0605 int
0606 TRANS(GetReopenInfo) (XtransConnInfo ciptr,
0607               int *trans_id, int *fd, char **port)
0608 
0609 {
0610     for (unsigned int i = 0; i < NUMTRANS; i++)
0611     {
0612     if (Xtransports[i].transport == ciptr->transptr)
0613     {
0614         *trans_id = Xtransports[i].transport_id;
0615         *fd = ciptr->fd;
0616 
0617         if ((*port = strdup (ciptr->port)) == NULL)
0618         return 0;
0619         else
0620         return 1;
0621     }
0622     }
0623 
0624     return 0;
0625 }
0626 
0627 #endif /* TRANS_REOPEN */
0628 
0629 
0630 int
0631 TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
0632 
0633 {
0634     int fd = ciptr->fd;
0635     int ret = 0;
0636 
0637     prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
0638 
0639     /*
0640      * For now, all transport type use the same stuff for setting options.
0641      * As long as this is true, we can put the common code here. Once a more
0642      * complicated transport such as shared memory or an OSI implementation
0643      * that uses the session and application libraries is implemented, this
0644      * code may have to move to a transport dependent function.
0645      *
0646      * ret = ciptr->transptr->SetOption (ciptr, option, arg);
0647      */
0648 
0649     switch (option)
0650     {
0651     case TRANS_NONBLOCKING:
0652     switch (arg)
0653     {
0654     case 0:
0655         /* Set to blocking mode */
0656         break;
0657     case 1: /* Set to non-blocking mode */
0658 
0659 #if defined(O_NONBLOCK)
0660         ret = fcntl (fd, F_GETFL, 0);
0661         if (ret != -1)
0662         ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
0663 #else
0664 #ifdef FIOSNBIO
0665     {
0666         int arg;
0667         arg = 1;
0668         ret = ioctl (fd, FIOSNBIO, &arg);
0669     }
0670 #else
0671 #if defined(WIN32)
0672     {
0673 #ifdef WIN32
0674         u_long arg;
0675 #else
0676         int arg;
0677 #endif
0678         arg = 1;
0679 /* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
0680  * eventually with EWOULDBLOCK */
0681         ret = ioctl (fd, FIONBIO, &arg);
0682     }
0683 #else
0684         ret = fcntl (fd, F_GETFL, 0);
0685 #ifdef FNDELAY
0686         ret = fcntl (fd, F_SETFL, ret | FNDELAY);
0687 #else
0688         ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
0689 #endif
0690 #endif /* AIXV3  || uniosu */
0691 #endif /* FIOSNBIO */
0692 #endif /* O_NONBLOCK */
0693         break;
0694     default:
0695         /* Unknown option */
0696         break;
0697     }
0698     break;
0699     case TRANS_CLOSEONEXEC:
0700 #ifdef F_SETFD
0701 #ifdef FD_CLOEXEC
0702     ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
0703 #else
0704     ret = fcntl (fd, F_SETFD, 1);
0705 #endif /* FD_CLOEXEC */
0706 #endif /* F_SETFD */
0707     break;
0708     }
0709 
0710     return ret;
0711 }
0712 
0713 #ifdef TRANS_SERVER
0714 
0715 int
0716 TRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags)
0717 
0718 {
0719     return ciptr->transptr->CreateListener (ciptr, port, flags);
0720 }
0721 
0722 int
0723 TRANS(Received) (const char * protocol)
0724 
0725 {
0726    Xtransport *trans;
0727    int i = 0, ret = 0;
0728 
0729    prmsg (5, "Received(%s)\n", protocol);
0730 
0731    if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
0732    {
0733     prmsg (1,"Received: unable to find transport: %s\n",
0734            protocol);
0735 
0736     return -1;
0737    }
0738    if (trans->flags & TRANS_ALIAS) {
0739        if (trans->nolisten)
0740        while (trans->nolisten[i]) {
0741            ret |= TRANS(Received)(trans->nolisten[i]);
0742            i++;
0743        }
0744    }
0745 
0746    trans->flags |= TRANS_RECEIVED;
0747    return ret;
0748 }
0749 
0750 int
0751 TRANS(NoListen) (const char * protocol)
0752 
0753 {
0754    Xtransport *trans;
0755    int i = 0, ret = 0;
0756 
0757    if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
0758    {
0759     prmsg (1,"TransNoListen: unable to find transport: %s\n",
0760            protocol);
0761 
0762     return -1;
0763    }
0764    if (trans->flags & TRANS_ALIAS) {
0765        if (trans->nolisten)
0766        while (trans->nolisten[i]) {
0767            ret |= TRANS(NoListen)(trans->nolisten[i]);
0768            i++;
0769        }
0770    }
0771 
0772    trans->flags |= TRANS_NOLISTEN;
0773    return ret;
0774 }
0775 
0776 int
0777 TRANS(Listen) (const char * protocol)
0778 {
0779    Xtransport *trans;
0780    int i = 0, ret = 0;
0781 
0782    if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
0783    {
0784     prmsg (1,"TransListen: unable to find transport: %s\n",
0785            protocol);
0786 
0787     return -1;
0788    }
0789    if (trans->flags & TRANS_ALIAS) {
0790        if (trans->nolisten)
0791        while (trans->nolisten[i]) {
0792            ret |= TRANS(Listen)(trans->nolisten[i]);
0793            i++;
0794        }
0795    }
0796 
0797    trans->flags &= ~TRANS_NOLISTEN;
0798    return ret;
0799 }
0800 
0801 int
0802 TRANS(IsListening) (const char * protocol)
0803 {
0804    Xtransport *trans;
0805 
0806    if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
0807    {
0808     prmsg (1,"TransIsListening: unable to find transport: %s\n",
0809            protocol);
0810 
0811     return 0;
0812    }
0813 
0814    return !(trans->flags & TRANS_NOLISTEN);
0815 }
0816 
0817 int
0818 TRANS(ResetListener) (XtransConnInfo ciptr)
0819 
0820 {
0821     if (ciptr->transptr->ResetListener)
0822     return ciptr->transptr->ResetListener (ciptr);
0823     else
0824     return TRANS_RESET_NOOP;
0825 }
0826 
0827 
0828 XtransConnInfo
0829 TRANS(Accept) (XtransConnInfo ciptr, int *status)
0830 
0831 {
0832     XtransConnInfo  newciptr;
0833 
0834     prmsg (2,"Accept(%d)\n", ciptr->fd);
0835 
0836     newciptr = ciptr->transptr->Accept (ciptr, status);
0837 
0838     if (newciptr)
0839     newciptr->transptr = ciptr->transptr;
0840 
0841     return newciptr;
0842 }
0843 
0844 #endif /* TRANS_SERVER */
0845 
0846 
0847 #ifdef TRANS_CLIENT
0848 
0849 int
0850 TRANS(Connect) (XtransConnInfo ciptr, const char *address)
0851 
0852 {
0853     char    *protocol;
0854     char    *host;
0855     char    *port;
0856     int     ret;
0857 
0858     prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address);
0859 
0860     if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
0861     {
0862     prmsg (1,"Connect: Unable to Parse address %s\n",
0863            address);
0864     return -1;
0865     }
0866 
0867 #ifdef HAVE_LAUNCHD
0868     if (!host) host=strdup("");
0869 #endif
0870 
0871     if (!port || !*port)
0872     {
0873     prmsg (1,"Connect: Missing port specification in %s\n",
0874           address);
0875     if (protocol) free (protocol);
0876     if (host) free (host);
0877     return -1;
0878     }
0879 
0880     ret = ciptr->transptr->Connect (ciptr, host, port);
0881 
0882     if (protocol) free (protocol);
0883     if (host) free (host);
0884     if (port) free (port);
0885 
0886     return ret;
0887 }
0888 
0889 #endif /* TRANS_CLIENT */
0890 
0891 
0892 int
0893 TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
0894 
0895 {
0896     return ciptr->transptr->BytesReadable (ciptr, pend);
0897 }
0898 
0899 int
0900 TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
0901 
0902 {
0903     return ciptr->transptr->Read (ciptr, buf, size);
0904 }
0905 
0906 int
0907 TRANS(Write) (XtransConnInfo ciptr, const char *buf, int size)
0908 
0909 {
0910     return ciptr->transptr->Write (ciptr, buf, size);
0911 }
0912 
0913 int
0914 TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
0915 
0916 {
0917     return ciptr->transptr->Readv (ciptr, buf, size);
0918 }
0919 
0920 int
0921 TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
0922 
0923 {
0924     return ciptr->transptr->Writev (ciptr, buf, size);
0925 }
0926 
0927 #if XTRANS_SEND_FDS
0928 int
0929 TRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
0930 {
0931     return ciptr->transptr->SendFd(ciptr, fd, do_close);
0932 }
0933 
0934 int
0935 TRANS(RecvFd) (XtransConnInfo ciptr)
0936 {
0937     return ciptr->transptr->RecvFd(ciptr);
0938 }
0939 #endif
0940 
0941 int
0942 TRANS(Disconnect) (XtransConnInfo ciptr)
0943 
0944 {
0945     return ciptr->transptr->Disconnect (ciptr);
0946 }
0947 
0948 int
0949 TRANS(Close) (XtransConnInfo ciptr)
0950 
0951 {
0952     int ret;
0953 
0954     prmsg (2,"Close(%d)\n", ciptr->fd);
0955 
0956     ret = ciptr->transptr->Close (ciptr);
0957 
0958     TRANS(FreeConnInfo) (ciptr);
0959 
0960     return ret;
0961 }
0962 
0963 int
0964 TRANS(CloseForCloning) (XtransConnInfo ciptr)
0965 
0966 {
0967     int ret;
0968 
0969     prmsg (2,"CloseForCloning(%d)\n", ciptr->fd);
0970 
0971     ret = ciptr->transptr->CloseForCloning (ciptr);
0972 
0973     TRANS(FreeConnInfo) (ciptr);
0974 
0975     return ret;
0976 }
0977 
0978 int
0979 TRANS(IsLocal) (XtransConnInfo ciptr)
0980 
0981 {
0982     return (ciptr->family == AF_UNIX);
0983 }
0984 
0985 int
0986 TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
0987             Xtransaddr **addrp)
0988 
0989 {
0990     prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd);
0991 
0992     *familyp = ciptr->family;
0993     *addrlenp = ciptr->peeraddrlen;
0994 
0995     if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL)
0996     {
0997     prmsg (1,"GetPeerAddr: malloc failed\n");
0998     return -1;
0999     }
1000     memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
1001 
1002     return 0;
1003 }
1004 
1005 
1006 int
1007 TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
1008 
1009 {
1010     return ciptr->fd;
1011 }
1012 
1013 
1014 /*
1015  * These functions are really utility functions, but they require knowledge
1016  * of the internal data structures, so they have to be part of the Transport
1017  * Independent API.
1018  */
1019 
1020 #ifdef TRANS_SERVER
1021 
1022 static int
1023 complete_network_count (void)
1024 
1025 {
1026     int count = 0;
1027     int found_local = 0;
1028 
1029     /*
1030      * For a complete network, we only need one LOCALCONN transport to work
1031      */
1032 
1033     for (unsigned int i = 0; i < NUMTRANS; i++)
1034     {
1035     if (Xtransports[i].transport->flags & TRANS_ALIAS
1036      || Xtransports[i].transport->flags & TRANS_NOLISTEN)
1037         continue;
1038 
1039     if (Xtransports[i].transport->flags & TRANS_LOCAL)
1040         found_local = 1;
1041     else
1042         count++;
1043     }
1044 
1045     return (count + found_local);
1046 }
1047 
1048 
1049 static int
1050 receive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs,
1051                       int* count_ret)
1052 
1053 {
1054 #ifdef HAVE_SYSTEMD_DAEMON
1055     XtransConnInfo ciptr;
1056     int i, systemd_listen_fds;
1057 
1058     systemd_listen_fds = sd_listen_fds(1);
1059     if (systemd_listen_fds < 0)
1060     {
1061         prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n",
1062                strerror(-systemd_listen_fds));
1063         return -1;
1064     }
1065 
1066     for (i = 0; i < systemd_listen_fds && *count_ret < (int)NUMTRANS; i++)
1067     {
1068         struct sockaddr_storage a;
1069         int ti;
1070         const char* tn;
1071         socklen_t al;
1072 
1073         al = sizeof(a);
1074         if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) {
1075             prmsg (1, "receive_listening_fds: getsockname error: %s\n",
1076                    strerror(errno));
1077             return -1;
1078         }
1079 
1080         switch (a.ss_family)
1081         {
1082         case AF_UNIX:
1083             ti = TRANS_SOCKET_UNIX_INDEX;
1084             if (*((struct sockaddr_un*)&a)->sun_path == '\0' &&
1085                 al > sizeof(sa_family_t))
1086                 tn = "local";
1087             else
1088                 tn = "unix";
1089             break;
1090         case AF_INET:
1091             ti = TRANS_SOCKET_INET_INDEX;
1092             tn = "inet";
1093             break;
1094 #ifdef IPv6
1095         case AF_INET6:
1096             ti = TRANS_SOCKET_INET6_INDEX;
1097             tn = "inet6";
1098             break;
1099 #endif /* IPv6 */
1100         default:
1101             prmsg (1, "receive_listening_fds:"
1102                    "Got unknown socket address family\n");
1103             return -1;
1104         }
1105 
1106         ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port);
1107         if (!ciptr)
1108         {
1109             prmsg (1, "receive_listening_fds:"
1110                    "Got NULL while trying to reopen socket received from systemd.\n");
1111             return -1;
1112         }
1113 
1114         prmsg (5, "receive_listening_fds: received listener for %s, %d\n",
1115                tn, ciptr->fd);
1116         temp_ciptrs[(*count_ret)++] = ciptr;
1117         TRANS(Received)(tn);
1118     }
1119 #endif /* HAVE_SYSTEMD_DAEMON */
1120     return 0;
1121 }
1122 
1123 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
1124 extern int xquartz_launchd_fd;
1125 #endif
1126 
1127 int
1128 TRANS(MakeAllCOTSServerListeners) (const char *port, int *partial,
1129                                    int *count_ret, XtransConnInfo **ciptrs_ret)
1130 
1131 {
1132     char        buffer[256]; /* ??? What size ?? */
1133     XtransConnInfo  ciptr, temp_ciptrs[NUMTRANS] = { NULL };
1134     int         status, j;
1135 
1136 #ifdef IPv6
1137     int     ipv6_succ = 0;
1138 #endif
1139     prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n",
1140        port ? port : "NULL", (void *) ciptrs_ret);
1141 
1142     *count_ret = 0;
1143 
1144 #ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
1145     fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
1146     if(xquartz_launchd_fd != -1) {
1147         if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
1148                                            xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
1149             fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
1150         else
1151             temp_ciptrs[(*count_ret)++] = ciptr;
1152     }
1153 #endif
1154 
1155     if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0)
1156     return -1;
1157 
1158     for (unsigned int i = 0; i < NUMTRANS; i++)
1159     {
1160     Xtransport *trans = Xtransports[i].transport;
1161     unsigned int flags = 0;
1162 
1163     if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN ||
1164         trans->flags&TRANS_RECEIVED)
1165         continue;
1166 
1167     snprintf(buffer, sizeof(buffer), "%s/:%s",
1168          trans->TransName, port ? port : "");
1169 
1170     prmsg (5,"MakeAllCOTSServerListeners: opening %s\n",
1171            buffer);
1172 
1173     if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
1174     {
1175         if (trans->flags & TRANS_DISABLED)
1176         continue;
1177 
1178         prmsg (1,
1179       "MakeAllCOTSServerListeners: failed to open listener for %s\n",
1180           trans->TransName);
1181         continue;
1182     }
1183 #ifdef IPv6
1184         if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
1185              && ipv6_succ))
1186             flags |= ADDR_IN_USE_ALLOWED;
1187 #endif
1188 
1189     if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
1190     {
1191             if (*partial != 0)
1192         continue;
1193 
1194         if (status == TRANS_ADDR_IN_USE)
1195         {
1196         /*
1197          * We failed to bind to the specified address because the
1198          * address is in use.  It must be that a server is already
1199          * running at this address, and this function should fail.
1200          */
1201 
1202         prmsg (1,
1203         "MakeAllCOTSServerListeners: server already running\n");
1204 
1205         for (j = 0; j < *count_ret; j++)
1206             if (temp_ciptrs[j] != NULL)
1207             TRANS(Close) (temp_ciptrs[j]);
1208 
1209         *count_ret = 0;
1210         *ciptrs_ret = NULL;
1211         *partial = 0;
1212         return -1;
1213         }
1214         else
1215         {
1216         prmsg (1,
1217     "MakeAllCOTSServerListeners: failed to create listener for %s\n",
1218           trans->TransName);
1219 
1220         continue;
1221         }
1222     }
1223 
1224 #ifdef IPv6
1225     if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
1226         ipv6_succ = 1;
1227 #endif
1228 
1229     prmsg (5,
1230           "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
1231           trans->TransName, ciptr->fd);
1232 
1233     temp_ciptrs[*count_ret] = ciptr;
1234     (*count_ret)++;
1235     }
1236 
1237     *partial = (*count_ret < complete_network_count());
1238 
1239     prmsg (5,
1240      "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
1241     *partial, *count_ret, complete_network_count());
1242 
1243     if (*count_ret > 0)
1244     {
1245     if ((*ciptrs_ret = malloc (
1246         *count_ret * sizeof (XtransConnInfo))) == NULL)
1247     {
1248         return -1;
1249     }
1250 
1251     for (int i = 0; i < *count_ret; i++)
1252     {
1253         (*ciptrs_ret)[i] = temp_ciptrs[i];
1254     }
1255     }
1256     else
1257     *ciptrs_ret = NULL;
1258 
1259     return 0;
1260 }
1261 
1262 #endif /* TRANS_SERVER */
1263 
1264 
1265 
1266 /*
1267  * These routines are not part of the X Transport Interface, but they
1268  * may be used by it.
1269  */
1270 
1271 
1272 #ifdef WIN32
1273 
1274 /*
1275  * emulate readv
1276  */
1277 
1278 static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
1279 
1280 {
1281     int i, len, total;
1282     char *base;
1283 
1284     ESET(0);
1285     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
1286     len = iov->iov_len;
1287     base = iov->iov_base;
1288     while (len > 0) {
1289         register int nbytes;
1290         nbytes = TRANS(Read) (ciptr, base, len);
1291         if (nbytes < 0 && total == 0)  return -1;
1292         if (nbytes <= 0)  return total;
1293         ESET(0);
1294         len   -= nbytes;
1295         total += nbytes;
1296         base  += nbytes;
1297     }
1298     }
1299     return total;
1300 }
1301 
1302 
1303 /*
1304  * emulate writev
1305  */
1306 
1307 static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
1308 
1309 {
1310     int i, len, total;
1311     char *base;
1312 
1313     ESET(0);
1314     for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
1315     len = iov->iov_len;
1316     base = iov->iov_base;
1317     while (len > 0) {
1318         register int nbytes;
1319         nbytes = TRANS(Write) (ciptr, base, len);
1320         if (nbytes < 0 && total == 0)  return -1;
1321         if (nbytes <= 0)  return total;
1322         ESET(0);
1323         len   -= nbytes;
1324         total += nbytes;
1325         base  += nbytes;
1326     }
1327     }
1328     return total;
1329 }
1330 
1331 #endif /* WIN32 */
1332 
1333 
1334 #if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__SVR4)
1335 #ifndef NEED_UTSNAME
1336 #define NEED_UTSNAME
1337 #endif
1338 #include <sys/utsname.h>
1339 #endif
1340 
1341 /*
1342  * TRANS(GetHostname) - similar to gethostname but allows special processing.
1343  */
1344 
1345 int TRANS(GetHostname) (char *buf, int maxlen)
1346 
1347 {
1348     int len;
1349 
1350 #ifdef NEED_UTSNAME
1351     struct utsname name;
1352 
1353     uname (&name);
1354     len = strlen (name.nodename);
1355     if (len >= maxlen) len = maxlen - 1;
1356     memcpy (buf, name.nodename, len);
1357     buf[len] = '\0';
1358 #else
1359     buf[0] = '\0';
1360     (void) gethostname (buf, maxlen);
1361     buf [maxlen - 1] = '\0';
1362     len = strlen(buf);
1363 #endif /* NEED_UTSNAME */
1364     return len;
1365 }