Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:26:38

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