Xtrans.c revision e8a71cdf
173143b9aSmrg/*
273143b9aSmrg
373143b9aSmrgCopyright 1993, 1994, 1998  The Open Group
473143b9aSmrg
573143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its
673143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that
773143b9aSmrgthe above copyright notice appear in all copies and that both that
873143b9aSmrgcopyright notice and this permission notice appear in supporting
973143b9aSmrgdocumentation.
1073143b9aSmrg
1173143b9aSmrgThe above copyright notice and this permission notice shall be included
1273143b9aSmrgin all copies or substantial portions of the Software.
1373143b9aSmrg
1473143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1573143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1673143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1773143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
1873143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
1973143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2073143b9aSmrgOTHER DEALINGS IN THE SOFTWARE.
2173143b9aSmrg
2273143b9aSmrgExcept as contained in this notice, the name of The Open Group shall
2373143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or
2473143b9aSmrgother dealings in this Software without prior written authorization
2573143b9aSmrgfrom The Open Group.
2673143b9aSmrg
2773143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
2873143b9aSmrg *
2973143b9aSmrg * All Rights Reserved
3073143b9aSmrg *
3173143b9aSmrg * Permission to use, copy, modify, and distribute this software and its
3273143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided
3373143b9aSmrg * that the above copyright notice appear in all copies and that both that
3473143b9aSmrg * copyright notice and this permission notice appear in supporting
3573143b9aSmrg * documentation, and that the name NCR not be used in advertising
3673143b9aSmrg * or publicity pertaining to distribution of the software without specific,
3773143b9aSmrg * written prior permission.  NCR makes no representations about the
3873143b9aSmrg * suitability of this software for any purpose.  It is provided "as is"
3973143b9aSmrg * without express or implied warranty.
4073143b9aSmrg *
4173143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
4273143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
4373143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
4473143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
4573143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4673143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
4773143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4873143b9aSmrg */
4973143b9aSmrg
5073143b9aSmrg#include <ctype.h>
5173143b9aSmrg
5273143b9aSmrg/*
5373143b9aSmrg * The transport table contains a definition for every transport (protocol)
5473143b9aSmrg * family. All operations that can be made on the transport go through this
5573143b9aSmrg * table.
5673143b9aSmrg *
5773143b9aSmrg * Each transport is assigned a unique transport id.
5873143b9aSmrg *
5973143b9aSmrg * New transports can be added by adding an entry in this table.
6073143b9aSmrg * For compatiblity, the transport ids should never be renumbered.
6173143b9aSmrg * Always add to the end of the list.
6273143b9aSmrg */
6373143b9aSmrg
6473143b9aSmrg#define TRANS_TLI_INET_INDEX		1
6573143b9aSmrg#define TRANS_TLI_TCP_INDEX		2
6673143b9aSmrg#define TRANS_TLI_TLI_INDEX		3
6773143b9aSmrg#define TRANS_SOCKET_UNIX_INDEX		4
6873143b9aSmrg#define TRANS_SOCKET_LOCAL_INDEX	5
6973143b9aSmrg#define TRANS_SOCKET_INET_INDEX		6
7073143b9aSmrg#define TRANS_SOCKET_TCP_INDEX		7
7173143b9aSmrg#define TRANS_DNET_INDEX		8
7273143b9aSmrg#define TRANS_LOCAL_LOCAL_INDEX		9
7373143b9aSmrg#define TRANS_LOCAL_PTS_INDEX		10
7473143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX		11
7573143b9aSmrg#define TRANS_LOCAL_ISC_INDEX		12
7673143b9aSmrg#define TRANS_LOCAL_SCO_INDEX		13
7773143b9aSmrg#define TRANS_SOCKET_INET6_INDEX	14
7873143b9aSmrg#define TRANS_LOCAL_PIPE_INDEX		15
7973143b9aSmrg
8073143b9aSmrg
8173143b9aSmrgstatic
8273143b9aSmrgXtransport_table Xtransports[] = {
8373143b9aSmrg#if defined(STREAMSCONN)
8473143b9aSmrg    { &TRANS(TLITCPFuncs),	TRANS_TLI_TCP_INDEX },
8573143b9aSmrg    { &TRANS(TLIINETFuncs),	TRANS_TLI_INET_INDEX },
8673143b9aSmrg    { &TRANS(TLITLIFuncs),	TRANS_TLI_TLI_INDEX },
8773143b9aSmrg#endif /* STREAMSCONN */
8873143b9aSmrg#if defined(TCPCONN)
8973143b9aSmrg    { &TRANS(SocketTCPFuncs),	TRANS_SOCKET_TCP_INDEX },
9073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
9173143b9aSmrg    { &TRANS(SocketINET6Funcs),	TRANS_SOCKET_INET6_INDEX },
9273143b9aSmrg#endif /* IPv6 */
9373143b9aSmrg    { &TRANS(SocketINETFuncs),	TRANS_SOCKET_INET_INDEX },
9473143b9aSmrg#endif /* TCPCONN */
9573143b9aSmrg#if defined(UNIXCONN)
9673143b9aSmrg#if !defined(LOCALCONN)
9773143b9aSmrg    { &TRANS(SocketLocalFuncs),	TRANS_SOCKET_LOCAL_INDEX },
9873143b9aSmrg#endif /* !LOCALCONN */
9973143b9aSmrg    { &TRANS(SocketUNIXFuncs),	TRANS_SOCKET_UNIX_INDEX },
10073143b9aSmrg#endif /* UNIXCONN */
10173143b9aSmrg#if defined(LOCALCONN)
10273143b9aSmrg    { &TRANS(LocalFuncs),	TRANS_LOCAL_LOCAL_INDEX },
10373143b9aSmrg#ifndef sun
10473143b9aSmrg    { &TRANS(PTSFuncs),		TRANS_LOCAL_PTS_INDEX },
10573143b9aSmrg#endif /* sun */
106e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
10773143b9aSmrg    { &TRANS(NAMEDFuncs),	TRANS_LOCAL_NAMED_INDEX },
10873143b9aSmrg#endif
10973143b9aSmrg#ifdef sun
11073143b9aSmrg    { &TRANS(PIPEFuncs),	TRANS_LOCAL_PIPE_INDEX },
11173143b9aSmrg#else /* !sun */
11273143b9aSmrg#if !defined(__SCO__) && !defined(__UNIXWARE__)
11373143b9aSmrg    { &TRANS(ISCFuncs),		TRANS_LOCAL_ISC_INDEX },
11473143b9aSmrg#endif
11573143b9aSmrg    { &TRANS(SCOFuncs),		TRANS_LOCAL_SCO_INDEX },
11673143b9aSmrg#endif /* sun */
11773143b9aSmrg#endif /* LOCALCONN */
11873143b9aSmrg};
11973143b9aSmrg
12073143b9aSmrg#define NUMTRANS	(sizeof(Xtransports)/sizeof(Xtransport_table))
12173143b9aSmrg
12273143b9aSmrg
12373143b9aSmrg#ifdef WIN32
12473143b9aSmrg#define ioctl ioctlsocket
12573143b9aSmrg#endif
12673143b9aSmrg
12773143b9aSmrg
12873143b9aSmrg
12973143b9aSmrg/*
13073143b9aSmrg * These are a few utility function used by the public interface functions.
13173143b9aSmrg */
13273143b9aSmrg
13373143b9aSmrgvoid
13473143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr)
13573143b9aSmrg
13673143b9aSmrg{
13773143b9aSmrg    PRMSG (3,"FreeConnInfo(%p)\n", ciptr, 0, 0);
13873143b9aSmrg
13973143b9aSmrg    if (ciptr->addr)
14073143b9aSmrg	xfree (ciptr->addr);
14173143b9aSmrg
14273143b9aSmrg    if (ciptr->peeraddr)
14373143b9aSmrg	xfree (ciptr->peeraddr);
14473143b9aSmrg
14573143b9aSmrg    if (ciptr->port)
14673143b9aSmrg	xfree (ciptr->port);
14773143b9aSmrg
14873143b9aSmrg    xfree ((char *) ciptr);
14973143b9aSmrg}
15073143b9aSmrg
15173143b9aSmrg
15273143b9aSmrg#define PROTOBUFSIZE	20
15373143b9aSmrg
15473143b9aSmrgstatic Xtransport *
15573143b9aSmrgTRANS(SelectTransport) (char *protocol)
15673143b9aSmrg
15773143b9aSmrg{
15873143b9aSmrg    char 	protobuf[PROTOBUFSIZE];
15973143b9aSmrg    int		i;
16073143b9aSmrg
16173143b9aSmrg    PRMSG (3,"SelectTransport(%s)\n", protocol, 0, 0);
16273143b9aSmrg
16373143b9aSmrg    /*
16473143b9aSmrg     * Force Protocol to be lowercase as a way of doing
16573143b9aSmrg     * a case insensitive match.
16673143b9aSmrg     */
16773143b9aSmrg
16873143b9aSmrg    strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
16973143b9aSmrg    protobuf[PROTOBUFSIZE-1] = '\0';
17073143b9aSmrg
17173143b9aSmrg    for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
17273143b9aSmrg	if (isupper (protobuf[i]))
17373143b9aSmrg	    protobuf[i] = tolower (protobuf[i]);
17473143b9aSmrg
17573143b9aSmrg    /* Look at all of the configured protocols */
17673143b9aSmrg
17773143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
17873143b9aSmrg    {
17973143b9aSmrg	if (!strcmp (protobuf, Xtransports[i].transport->TransName))
18073143b9aSmrg	    return Xtransports[i].transport;
18173143b9aSmrg    }
18273143b9aSmrg
18373143b9aSmrg    return NULL;
18473143b9aSmrg}
18573143b9aSmrg
18673143b9aSmrg#ifndef TEST_t
18773143b9aSmrgstatic
18873143b9aSmrg#endif /* TEST_t */
18973143b9aSmrgint
19073143b9aSmrgTRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
19173143b9aSmrg
19273143b9aSmrg{
19373143b9aSmrg    /*
19473143b9aSmrg     * For the font library, the address is a string formatted
19573143b9aSmrg     * as "protocol/host:port[/catalogue]".  Note that the catologue
19673143b9aSmrg     * is optional.  At this time, the catologue info is ignored, but
19773143b9aSmrg     * we have to parse it anyways.
19873143b9aSmrg     *
19973143b9aSmrg     * Other than fontlib, the address is a string formatted
20073143b9aSmrg     * as "protocol/host:port".
20173143b9aSmrg     *
20273143b9aSmrg     * If the protocol part is missing, then assume TCP.
20373143b9aSmrg     * If the protocol part and host part are missing, then assume local.
20473143b9aSmrg     * If a "::" is found then assume DNET.
20573143b9aSmrg     */
20673143b9aSmrg
20773143b9aSmrg    char	*mybuf, *tmpptr;
20873143b9aSmrg    char	*_protocol, *_host, *_port;
20973143b9aSmrg    char	hostnamebuf[256];
21073143b9aSmrg    int		_host_len;
21173143b9aSmrg
21273143b9aSmrg    PRMSG (3,"ParseAddress(%s)\n", address, 0, 0);
21373143b9aSmrg
21473143b9aSmrg    /* Copy the string so it can be changed */
21573143b9aSmrg
21673143b9aSmrg    tmpptr = mybuf = (char *) xalloc (strlen (address) + 1);
21773143b9aSmrg    strcpy (mybuf, address);
21873143b9aSmrg
21973143b9aSmrg    /* Parse the string to get each component */
22073143b9aSmrg
22173143b9aSmrg    /* Get the protocol part */
22273143b9aSmrg
22373143b9aSmrg    _protocol = mybuf;
22473143b9aSmrg
22573143b9aSmrg
22673143b9aSmrg   if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
22773143b9aSmrg      ((mybuf = strrchr (tmpptr,':')) == NULL) )
22873143b9aSmrg   {
22973143b9aSmrg	/* address is in a bad format */
23073143b9aSmrg	*protocol = NULL;
23173143b9aSmrg	*host = NULL;
23273143b9aSmrg	*port = NULL;
23373143b9aSmrg	xfree (tmpptr);
23473143b9aSmrg	return 0;
23573143b9aSmrg    }
23673143b9aSmrg
23773143b9aSmrg    if (*mybuf == ':')
23873143b9aSmrg    {
23973143b9aSmrg	/*
24073143b9aSmrg	 * If there is a hostname, then assume tcp, otherwise
24173143b9aSmrg	 * it must be local.
24273143b9aSmrg	 */
24373143b9aSmrg	if (mybuf == tmpptr)
24473143b9aSmrg	{
24573143b9aSmrg	    /* There is neither a protocol or host specified */
24673143b9aSmrg	    _protocol = "local";
24773143b9aSmrg	}
24873143b9aSmrg	else
24973143b9aSmrg	{
25073143b9aSmrg	    /* There is a hostname specified */
25173143b9aSmrg	    _protocol = "tcp";
25273143b9aSmrg	    mybuf = tmpptr;	/* reset to the begining of the host ptr */
25373143b9aSmrg	}
25473143b9aSmrg    }
25573143b9aSmrg    else
25673143b9aSmrg    {
25773143b9aSmrg	/* *mybuf == '/' */
25873143b9aSmrg
25973143b9aSmrg	*mybuf ++= '\0'; /* put a null at the end of the protocol */
26073143b9aSmrg
26173143b9aSmrg	if (strlen(_protocol) == 0)
26273143b9aSmrg	{
26373143b9aSmrg	    /*
26473143b9aSmrg	     * If there is a hostname, then assume tcp, otherwise
26573143b9aSmrg	     * it must be local.
26673143b9aSmrg	     */
26773143b9aSmrg	    if (*mybuf != ':')
26873143b9aSmrg		_protocol = "tcp";
26973143b9aSmrg	    else
27073143b9aSmrg		_protocol = "local";
27173143b9aSmrg	}
27273143b9aSmrg    }
27373143b9aSmrg
27473143b9aSmrg    /* Get the host part */
27573143b9aSmrg
27673143b9aSmrg    _host = mybuf;
27773143b9aSmrg
27873143b9aSmrg    if ((mybuf = strrchr (mybuf,':')) == NULL)
27973143b9aSmrg    {
28073143b9aSmrg	*protocol = NULL;
28173143b9aSmrg	*host = NULL;
28273143b9aSmrg	*port = NULL;
28373143b9aSmrg	xfree (tmpptr);
28473143b9aSmrg	return 0;
28573143b9aSmrg    }
28673143b9aSmrg
28773143b9aSmrg    /* Check for DECnet */
28873143b9aSmrg
28973143b9aSmrg    if ((mybuf != _host) && (*(mybuf - 1) == ':')
29073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
29173143b9aSmrg      /* An IPv6 address can end in :: so three : in a row is assumed to be
29273143b9aSmrg	 an IPv6 host and not a DECnet node with a : in it's name, unless
29373143b9aSmrg         DECnet is specifically requested */
29473143b9aSmrg      && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') ||
29573143b9aSmrg	((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) )
29673143b9aSmrg#endif
29773143b9aSmrg	)
29873143b9aSmrg    {
29973143b9aSmrg	_protocol = "dnet";
30073143b9aSmrg	*(mybuf - 1) = '\0';
30173143b9aSmrg    }
30273143b9aSmrg
30373143b9aSmrg    *mybuf ++= '\0';
30473143b9aSmrg
30573143b9aSmrg    _host_len = strlen(_host);
30673143b9aSmrg    if (_host_len == 0)
30773143b9aSmrg    {
30873143b9aSmrg	TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
30973143b9aSmrg	_host = hostnamebuf;
31073143b9aSmrg    }
31173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
31273143b9aSmrg    /* hostname in IPv6 [numeric_addr]:0 form? */
31373143b9aSmrg    else if ( (_host_len > 3) &&
31473143b9aSmrg      ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
31573143b9aSmrg      && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
31673143b9aSmrg	struct sockaddr_in6 sin6;
31773143b9aSmrg
31873143b9aSmrg	*(_host + _host_len - 1) = '\0';
31973143b9aSmrg
32073143b9aSmrg	/* Verify address is valid IPv6 numeric form */
32173143b9aSmrg	if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
32273143b9aSmrg	    /* It is. Use it as such. */
32373143b9aSmrg	    _host++;
32473143b9aSmrg	    _protocol = "inet6";
32573143b9aSmrg	} else {
32673143b9aSmrg	    /* It's not, restore it just in case some other code can use it. */
32773143b9aSmrg	    *(_host + _host_len - 1) = ']';
32873143b9aSmrg	}
32973143b9aSmrg    }
33073143b9aSmrg#endif
33173143b9aSmrg
33273143b9aSmrg
33373143b9aSmrg    /* Get the port */
33473143b9aSmrg
33573143b9aSmrg    _port = mybuf;
33673143b9aSmrg
33773143b9aSmrg#if defined(FONT_t) || defined(FS_t)
33873143b9aSmrg    /*
33973143b9aSmrg     * Is there an optional catalogue list?
34073143b9aSmrg     */
34173143b9aSmrg
34273143b9aSmrg    if ((mybuf = strchr (mybuf,'/')) != NULL)
34373143b9aSmrg	*mybuf ++= '\0';
34473143b9aSmrg
34573143b9aSmrg    /*
34673143b9aSmrg     * The rest, if any, is the (currently unused) catalogue list.
34773143b9aSmrg     *
34873143b9aSmrg     * _catalogue = mybuf;
34973143b9aSmrg     */
35073143b9aSmrg#endif
35173143b9aSmrg
35273143b9aSmrg#ifdef HAVE_LAUNCHD
35373143b9aSmrg    /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
35473143b9aSmrg    if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
35573143b9aSmrg      _protocol="local";
35673143b9aSmrg      _host="";
35773143b9aSmrg      _port=address+6;
35873143b9aSmrg    }
35973143b9aSmrg#endif
36073143b9aSmrg
36173143b9aSmrg    /*
36273143b9aSmrg     * Now that we have all of the components, allocate new
36373143b9aSmrg     * string space for them.
36473143b9aSmrg     */
36573143b9aSmrg
36673143b9aSmrg    if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL)
36773143b9aSmrg    {
36873143b9aSmrg	/* Malloc failed */
36973143b9aSmrg	*port = NULL;
37073143b9aSmrg	*host = NULL;
37173143b9aSmrg	*protocol = NULL;
37273143b9aSmrg	xfree (tmpptr);
37373143b9aSmrg	return 0;
37473143b9aSmrg    }
37573143b9aSmrg    else
37673143b9aSmrg        strcpy (*protocol, _protocol);
37773143b9aSmrg
37873143b9aSmrg    if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL)
37973143b9aSmrg    {
38073143b9aSmrg	/* Malloc failed */
38173143b9aSmrg	*port = NULL;
38273143b9aSmrg	*host = NULL;
38373143b9aSmrg	xfree (*protocol);
38473143b9aSmrg	*protocol = NULL;
38573143b9aSmrg	xfree (tmpptr);
38673143b9aSmrg	return 0;
38773143b9aSmrg	}
38873143b9aSmrg    else
38973143b9aSmrg        strcpy (*host, _host);
39073143b9aSmrg
39173143b9aSmrg    if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL)
39273143b9aSmrg    {
39373143b9aSmrg	/* Malloc failed */
39473143b9aSmrg	*port = NULL;
39573143b9aSmrg	xfree (*host);
39673143b9aSmrg	*host = NULL;
39773143b9aSmrg	xfree (*protocol);
39873143b9aSmrg	*protocol = NULL;
39973143b9aSmrg	xfree (tmpptr);
40073143b9aSmrg	return 0;
40173143b9aSmrg    }
40273143b9aSmrg    else
40373143b9aSmrg        strcpy (*port, _port);
40473143b9aSmrg
40573143b9aSmrg    xfree (tmpptr);
40673143b9aSmrg
40773143b9aSmrg    return 1;
40873143b9aSmrg}
40973143b9aSmrg
41073143b9aSmrg
41173143b9aSmrg/*
41273143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only
41373143b9aSmrg * funny part about this is the type parameter which is used to decide which
41473143b9aSmrg * type of open to perform.
41573143b9aSmrg */
41673143b9aSmrg
41773143b9aSmrgstatic XtransConnInfo
41873143b9aSmrgTRANS(Open) (int type, char *address)
41973143b9aSmrg
42073143b9aSmrg{
42173143b9aSmrg    char 		*protocol = NULL, *host = NULL, *port = NULL;
42273143b9aSmrg    XtransConnInfo	ciptr = NULL;
42373143b9aSmrg    Xtransport		*thistrans;
42473143b9aSmrg
42573143b9aSmrg    PRMSG (2,"Open(%d,%s)\n", type, address, 0);
42673143b9aSmrg
4278d4c0f7bSmrg#if defined(WIN32) && defined(TCPCONN)
42873143b9aSmrg    if (TRANS(WSAStartup)())
42973143b9aSmrg    {
43073143b9aSmrg	PRMSG (1,"Open: WSAStartup failed\n", 0, 0, 0);
43173143b9aSmrg	return NULL;
43273143b9aSmrg    }
43373143b9aSmrg#endif
43473143b9aSmrg
43573143b9aSmrg    /* Parse the Address */
43673143b9aSmrg
43773143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
43873143b9aSmrg    {
43973143b9aSmrg	PRMSG (1,"Open: Unable to Parse address %s\n", address, 0, 0);
44073143b9aSmrg	return NULL;
44173143b9aSmrg    }
44273143b9aSmrg
44373143b9aSmrg    /* Determine the transport type */
44473143b9aSmrg
44573143b9aSmrg    if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
44673143b9aSmrg    {
44773143b9aSmrg	PRMSG (1,"Open: Unable to find transport for %s\n",
44873143b9aSmrg	       protocol, 0, 0);
44973143b9aSmrg
45073143b9aSmrg	xfree (protocol);
45173143b9aSmrg	xfree (host);
45273143b9aSmrg	xfree (port);
45373143b9aSmrg	return NULL;
45473143b9aSmrg    }
45573143b9aSmrg
45673143b9aSmrg    /* Open the transport */
45773143b9aSmrg
45873143b9aSmrg    switch (type)
45973143b9aSmrg    {
46073143b9aSmrg    case XTRANS_OPEN_COTS_CLIENT:
46173143b9aSmrg#ifdef TRANS_CLIENT
46273143b9aSmrg	ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
46373143b9aSmrg#endif /* TRANS_CLIENT */
46473143b9aSmrg	break;
46573143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
46673143b9aSmrg#ifdef TRANS_SERVER
46773143b9aSmrg	ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
46873143b9aSmrg#endif /* TRANS_SERVER */
46973143b9aSmrg	break;
47073143b9aSmrg    case XTRANS_OPEN_CLTS_CLIENT:
47173143b9aSmrg#ifdef TRANS_CLIENT
47273143b9aSmrg	ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
47373143b9aSmrg#endif /* TRANS_CLIENT */
47473143b9aSmrg	break;
47573143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
47673143b9aSmrg#ifdef TRANS_SERVER
47773143b9aSmrg	ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
47873143b9aSmrg#endif /* TRANS_SERVER */
47973143b9aSmrg	break;
48073143b9aSmrg    default:
48173143b9aSmrg	PRMSG (1,"Open: Unknown Open type %d\n", type, 0, 0);
48273143b9aSmrg    }
48373143b9aSmrg
48473143b9aSmrg    if (ciptr == NULL)
48573143b9aSmrg    {
48673143b9aSmrg	if (!(thistrans->flags & TRANS_DISABLED))
48773143b9aSmrg	{
48873143b9aSmrg	    PRMSG (1,"Open: transport open failed for %s/%s:%s\n",
48973143b9aSmrg	           protocol, host, port);
49073143b9aSmrg	}
49173143b9aSmrg	xfree (protocol);
49273143b9aSmrg	xfree (host);
49373143b9aSmrg	xfree (port);
49473143b9aSmrg	return NULL;
49573143b9aSmrg    }
49673143b9aSmrg
49773143b9aSmrg    ciptr->transptr = thistrans;
49873143b9aSmrg    ciptr->port = port;			/* We need this for TRANS(Reopen) */
49973143b9aSmrg
50073143b9aSmrg    xfree (protocol);
50173143b9aSmrg    xfree (host);
50273143b9aSmrg
50373143b9aSmrg    return ciptr;
50473143b9aSmrg}
50573143b9aSmrg
50673143b9aSmrg
50773143b9aSmrg#ifdef TRANS_REOPEN
50873143b9aSmrg
50973143b9aSmrg/*
51073143b9aSmrg * We might want to create an XtransConnInfo object based on a previously
51173143b9aSmrg * opened connection.  For example, the font server may clone itself and
51273143b9aSmrg * pass file descriptors to the parent.
51373143b9aSmrg */
51473143b9aSmrg
51573143b9aSmrgstatic XtransConnInfo
51673143b9aSmrgTRANS(Reopen) (int type, int trans_id, int fd, char *port)
51773143b9aSmrg
51873143b9aSmrg{
51973143b9aSmrg    XtransConnInfo	ciptr = NULL;
52073143b9aSmrg    Xtransport		*thistrans = NULL;
52173143b9aSmrg    char		*save_port;
52273143b9aSmrg    int			i;
52373143b9aSmrg
52473143b9aSmrg    PRMSG (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
52573143b9aSmrg
52673143b9aSmrg    /* Determine the transport type */
52773143b9aSmrg
52873143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
52973143b9aSmrg	if (Xtransports[i].transport_id == trans_id)
53073143b9aSmrg	{
53173143b9aSmrg	    thistrans = Xtransports[i].transport;
53273143b9aSmrg	    break;
53373143b9aSmrg	}
53473143b9aSmrg
53573143b9aSmrg    if (thistrans == NULL)
53673143b9aSmrg    {
53773143b9aSmrg	PRMSG (1,"Reopen: Unable to find transport id %d\n",
53873143b9aSmrg	       trans_id, 0, 0);
53973143b9aSmrg
54073143b9aSmrg	return NULL;
54173143b9aSmrg    }
54273143b9aSmrg
54373143b9aSmrg    if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL)
54473143b9aSmrg    {
54573143b9aSmrg	PRMSG (1,"Reopen: Unable to malloc port string\n", 0, 0, 0);
54673143b9aSmrg
54773143b9aSmrg	return NULL;
54873143b9aSmrg    }
54973143b9aSmrg
55073143b9aSmrg    strcpy (save_port, port);
55173143b9aSmrg
55273143b9aSmrg    /* Get a new XtransConnInfo object */
55373143b9aSmrg
55473143b9aSmrg    switch (type)
55573143b9aSmrg    {
55673143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
55773143b9aSmrg	ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
55873143b9aSmrg	break;
55973143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
56073143b9aSmrg	ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
56173143b9aSmrg	break;
56273143b9aSmrg    default:
56373143b9aSmrg	PRMSG (1,"Reopen: Bad Open type %d\n", type, 0, 0);
56473143b9aSmrg    }
56573143b9aSmrg
56673143b9aSmrg    if (ciptr == NULL)
56773143b9aSmrg    {
56873143b9aSmrg	PRMSG (1,"Reopen: transport open failed\n", 0, 0, 0);
56973143b9aSmrg	return NULL;
57073143b9aSmrg    }
57173143b9aSmrg
57273143b9aSmrg    ciptr->transptr = thistrans;
57373143b9aSmrg    ciptr->port = save_port;
57473143b9aSmrg
57573143b9aSmrg    return ciptr;
57673143b9aSmrg}
57773143b9aSmrg
57873143b9aSmrg#endif /* TRANS_REOPEN */
57973143b9aSmrg
58073143b9aSmrg
58173143b9aSmrg
58273143b9aSmrg/*
58373143b9aSmrg * These are the public interfaces to this Transport interface.
58473143b9aSmrg * These are the only functions that should have knowledge of the transport
58573143b9aSmrg * table.
58673143b9aSmrg */
58773143b9aSmrg
58873143b9aSmrg#ifdef TRANS_CLIENT
58973143b9aSmrg
59073143b9aSmrgXtransConnInfo
59173143b9aSmrgTRANS(OpenCOTSClient) (char *address)
59273143b9aSmrg
59373143b9aSmrg{
59473143b9aSmrg    PRMSG (2,"OpenCOTSClient(%s)\n", address, 0, 0);
59573143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
59673143b9aSmrg}
59773143b9aSmrg
59873143b9aSmrg#endif /* TRANS_CLIENT */
59973143b9aSmrg
60073143b9aSmrg
60173143b9aSmrg#ifdef TRANS_SERVER
60273143b9aSmrg
60373143b9aSmrgXtransConnInfo
60473143b9aSmrgTRANS(OpenCOTSServer) (char *address)
60573143b9aSmrg
60673143b9aSmrg{
60773143b9aSmrg    PRMSG (2,"OpenCOTSServer(%s)\n", address, 0, 0);
60873143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
60973143b9aSmrg}
61073143b9aSmrg
61173143b9aSmrg#endif /* TRANS_SERVER */
61273143b9aSmrg
61373143b9aSmrg
61473143b9aSmrg#ifdef TRANS_CLIENT
61573143b9aSmrg
61673143b9aSmrgXtransConnInfo
61773143b9aSmrgTRANS(OpenCLTSClient) (char *address)
61873143b9aSmrg
61973143b9aSmrg{
62073143b9aSmrg    PRMSG (2,"OpenCLTSClient(%s)\n", address, 0, 0);
62173143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
62273143b9aSmrg}
62373143b9aSmrg
62473143b9aSmrg#endif /* TRANS_CLIENT */
62573143b9aSmrg
62673143b9aSmrg
62773143b9aSmrg#ifdef TRANS_SERVER
62873143b9aSmrg
62973143b9aSmrgXtransConnInfo
63073143b9aSmrgTRANS(OpenCLTSServer) (char *address)
63173143b9aSmrg
63273143b9aSmrg{
63373143b9aSmrg    PRMSG (2,"OpenCLTSServer(%s)\n", address, 0, 0);
63473143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
63573143b9aSmrg}
63673143b9aSmrg
63773143b9aSmrg#endif /* TRANS_SERVER */
63873143b9aSmrg
63973143b9aSmrg
64073143b9aSmrg#ifdef TRANS_REOPEN
64173143b9aSmrg
64273143b9aSmrgXtransConnInfo
64373143b9aSmrgTRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
64473143b9aSmrg
64573143b9aSmrg{
64673143b9aSmrg    PRMSG (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
64773143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
64873143b9aSmrg}
64973143b9aSmrg
65073143b9aSmrgXtransConnInfo
65173143b9aSmrgTRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
65273143b9aSmrg
65373143b9aSmrg{
65473143b9aSmrg    PRMSG (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
65573143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
65673143b9aSmrg}
65773143b9aSmrg
65873143b9aSmrg
65973143b9aSmrgint
66073143b9aSmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr,
66173143b9aSmrg		      int *trans_id, int *fd, char **port)
66273143b9aSmrg
66373143b9aSmrg{
66473143b9aSmrg    int i;
66573143b9aSmrg
66673143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
66773143b9aSmrg	if (Xtransports[i].transport == ciptr->transptr)
66873143b9aSmrg	{
66973143b9aSmrg	    *trans_id = Xtransports[i].transport_id;
67073143b9aSmrg	    *fd = ciptr->fd;
67173143b9aSmrg
67273143b9aSmrg	    if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL)
67373143b9aSmrg		return 0;
67473143b9aSmrg	    else
67573143b9aSmrg	    {
67673143b9aSmrg		strcpy (*port, ciptr->port);
67773143b9aSmrg		return 1;
67873143b9aSmrg	    }
67973143b9aSmrg	}
68073143b9aSmrg
68173143b9aSmrg    return 0;
68273143b9aSmrg}
68373143b9aSmrg
68473143b9aSmrg#endif /* TRANS_REOPEN */
68573143b9aSmrg
68673143b9aSmrg
68773143b9aSmrgint
68873143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
68973143b9aSmrg
69073143b9aSmrg{
69173143b9aSmrg    int	fd = ciptr->fd;
69273143b9aSmrg    int	ret = 0;
69373143b9aSmrg
69473143b9aSmrg    PRMSG (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
69573143b9aSmrg
69673143b9aSmrg    /*
69773143b9aSmrg     * For now, all transport type use the same stuff for setting options.
69873143b9aSmrg     * As long as this is true, we can put the common code here. Once a more
69973143b9aSmrg     * complicated transport such as shared memory or an OSI implementation
70073143b9aSmrg     * that uses the session and application libraries is implemented, this
70173143b9aSmrg     * code may have to move to a transport dependent function.
70273143b9aSmrg     *
70373143b9aSmrg     * ret = ciptr->transptr->SetOption (ciptr, option, arg);
70473143b9aSmrg     */
70573143b9aSmrg
70673143b9aSmrg    switch (option)
70773143b9aSmrg    {
70873143b9aSmrg    case TRANS_NONBLOCKING:
70973143b9aSmrg	switch (arg)
71073143b9aSmrg	{
71173143b9aSmrg	case 0:
71273143b9aSmrg	    /* Set to blocking mode */
71373143b9aSmrg	    break;
71473143b9aSmrg	case 1: /* Set to non-blocking mode */
71573143b9aSmrg
7168d4c0f7bSmrg#if defined(O_NONBLOCK) && !defined(SCO325)
71773143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
71873143b9aSmrg	    if (ret != -1)
71973143b9aSmrg		ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
72073143b9aSmrg#else
72173143b9aSmrg#ifdef FIOSNBIO
72273143b9aSmrg	{
72373143b9aSmrg	    int arg;
72473143b9aSmrg	    arg = 1;
72573143b9aSmrg	    ret = ioctl (fd, FIOSNBIO, &arg);
72673143b9aSmrg	}
72773143b9aSmrg#else
7288d4c0f7bSmrg#if defined(WIN32)
72973143b9aSmrg	{
73073143b9aSmrg#ifdef WIN32
73173143b9aSmrg	    u_long arg;
73273143b9aSmrg#else
73373143b9aSmrg	    int arg;
73473143b9aSmrg#endif
73573143b9aSmrg	    arg = 1;
73673143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
73773143b9aSmrg * eventually with EWOULDBLOCK */
73873143b9aSmrg	    ret = ioctl (fd, FIONBIO, &arg);
73973143b9aSmrg	}
74073143b9aSmrg#else
74173143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
74273143b9aSmrg#ifdef FNDELAY
74373143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | FNDELAY);
74473143b9aSmrg#else
74573143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
74673143b9aSmrg#endif
74773143b9aSmrg#endif /* AIXV3  || uniosu */
74873143b9aSmrg#endif /* FIOSNBIO */
74973143b9aSmrg#endif /* O_NONBLOCK */
75073143b9aSmrg	    break;
75173143b9aSmrg	default:
75273143b9aSmrg	    /* Unknown option */
75373143b9aSmrg	    break;
75473143b9aSmrg	}
75573143b9aSmrg	break;
75673143b9aSmrg    case TRANS_CLOSEONEXEC:
75773143b9aSmrg#ifdef F_SETFD
75873143b9aSmrg#ifdef FD_CLOEXEC
75973143b9aSmrg	ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
76073143b9aSmrg#else
76173143b9aSmrg	ret = fcntl (fd, F_SETFD, 1);
76273143b9aSmrg#endif /* FD_CLOEXEC */
76373143b9aSmrg#endif /* F_SETFD */
76473143b9aSmrg	break;
76573143b9aSmrg    }
76673143b9aSmrg
76773143b9aSmrg    return ret;
76873143b9aSmrg}
76973143b9aSmrg
77073143b9aSmrg#ifdef TRANS_SERVER
77173143b9aSmrg
77273143b9aSmrgint
77373143b9aSmrgTRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
77473143b9aSmrg
77573143b9aSmrg{
77673143b9aSmrg    return ciptr->transptr->CreateListener (ciptr, port, flags);
77773143b9aSmrg}
77873143b9aSmrg
77973143b9aSmrgint
78073143b9aSmrgTRANS(NoListen) (char * protocol)
78173143b9aSmrg
78273143b9aSmrg{
78373143b9aSmrg   Xtransport *trans;
78473143b9aSmrg   int i = 0, ret = 0;
78573143b9aSmrg
78673143b9aSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
78773143b9aSmrg   {
78873143b9aSmrg	PRMSG (1,"TransNoListen: unable to find transport: %s\n",
78973143b9aSmrg	       protocol, 0, 0);
79073143b9aSmrg
79173143b9aSmrg	return -1;
79273143b9aSmrg   }
79373143b9aSmrg   if (trans->flags & TRANS_ALIAS) {
79473143b9aSmrg       if (trans->nolisten)
79573143b9aSmrg	   while (trans->nolisten[i]) {
79673143b9aSmrg	       ret |= TRANS(NoListen)(trans->nolisten[i]);
79773143b9aSmrg	       i++;
79873143b9aSmrg       }
79973143b9aSmrg   }
80073143b9aSmrg
80173143b9aSmrg   trans->flags |= TRANS_NOLISTEN;
80273143b9aSmrg   return ret;
80373143b9aSmrg}
80473143b9aSmrg
80573143b9aSmrgint
80673143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr)
80773143b9aSmrg
80873143b9aSmrg{
80973143b9aSmrg    if (ciptr->transptr->ResetListener)
81073143b9aSmrg	return ciptr->transptr->ResetListener (ciptr);
81173143b9aSmrg    else
81273143b9aSmrg	return TRANS_RESET_NOOP;
81373143b9aSmrg}
81473143b9aSmrg
81573143b9aSmrg
81673143b9aSmrgXtransConnInfo
81773143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status)
81873143b9aSmrg
81973143b9aSmrg{
82073143b9aSmrg    XtransConnInfo	newciptr;
82173143b9aSmrg
82273143b9aSmrg    PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0);
82373143b9aSmrg
82473143b9aSmrg    newciptr = ciptr->transptr->Accept (ciptr, status);
82573143b9aSmrg
82673143b9aSmrg    if (newciptr)
82773143b9aSmrg	newciptr->transptr = ciptr->transptr;
82873143b9aSmrg
82973143b9aSmrg    return newciptr;
83073143b9aSmrg}
83173143b9aSmrg
83273143b9aSmrg#endif /* TRANS_SERVER */
83373143b9aSmrg
83473143b9aSmrg
83573143b9aSmrg#ifdef TRANS_CLIENT
83673143b9aSmrg
83773143b9aSmrgint
83873143b9aSmrgTRANS(Connect) (XtransConnInfo ciptr, char *address)
83973143b9aSmrg
84073143b9aSmrg{
84173143b9aSmrg    char	*protocol;
84273143b9aSmrg    char	*host;
84373143b9aSmrg    char	*port;
84473143b9aSmrg    int		ret;
84573143b9aSmrg
84673143b9aSmrg    PRMSG (2,"Connect(%d,%s)\n", ciptr->fd, address, 0);
84773143b9aSmrg
84873143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
84973143b9aSmrg    {
85073143b9aSmrg	PRMSG (1,"Connect: Unable to Parse address %s\n",
85173143b9aSmrg	       address, 0, 0);
85273143b9aSmrg	return -1;
85373143b9aSmrg    }
85473143b9aSmrg
85573143b9aSmrg#ifdef HAVE_LAUNCHD
8568d4c0f7bSmrg    if (!host) host=strdup("");
85773143b9aSmrg#endif
85873143b9aSmrg
85973143b9aSmrg    if (!port || !*port)
86073143b9aSmrg    {
86173143b9aSmrg	PRMSG (1,"Connect: Missing port specification in %s\n",
86273143b9aSmrg	      address, 0, 0);
86373143b9aSmrg	if (protocol) xfree (protocol);
86473143b9aSmrg	if (host) xfree (host);
86573143b9aSmrg	return -1;
86673143b9aSmrg    }
86773143b9aSmrg
86873143b9aSmrg    ret = ciptr->transptr->Connect (ciptr, host, port);
86973143b9aSmrg
87073143b9aSmrg    if (protocol) xfree (protocol);
87173143b9aSmrg    if (host) xfree (host);
87273143b9aSmrg    if (port) xfree (port);
87373143b9aSmrg
87473143b9aSmrg    return ret;
87573143b9aSmrg}
87673143b9aSmrg
87773143b9aSmrg#endif /* TRANS_CLIENT */
87873143b9aSmrg
87973143b9aSmrg
88073143b9aSmrgint
88173143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
88273143b9aSmrg
88373143b9aSmrg{
88473143b9aSmrg    return ciptr->transptr->BytesReadable (ciptr, pend);
88573143b9aSmrg}
88673143b9aSmrg
88773143b9aSmrgint
88873143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
88973143b9aSmrg
89073143b9aSmrg{
89173143b9aSmrg    return ciptr->transptr->Read (ciptr, buf, size);
89273143b9aSmrg}
89373143b9aSmrg
89473143b9aSmrgint
89573143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
89673143b9aSmrg
89773143b9aSmrg{
89873143b9aSmrg    return ciptr->transptr->Write (ciptr, buf, size);
89973143b9aSmrg}
90073143b9aSmrg
90173143b9aSmrgint
90273143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
90373143b9aSmrg
90473143b9aSmrg{
90573143b9aSmrg    return ciptr->transptr->Readv (ciptr, buf, size);
90673143b9aSmrg}
90773143b9aSmrg
90873143b9aSmrgint
90973143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
91073143b9aSmrg
91173143b9aSmrg{
91273143b9aSmrg    return ciptr->transptr->Writev (ciptr, buf, size);
91373143b9aSmrg}
91473143b9aSmrg
91573143b9aSmrgint
91673143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr)
91773143b9aSmrg
91873143b9aSmrg{
91973143b9aSmrg    return ciptr->transptr->Disconnect (ciptr);
92073143b9aSmrg}
92173143b9aSmrg
92273143b9aSmrgint
92373143b9aSmrgTRANS(Close) (XtransConnInfo ciptr)
92473143b9aSmrg
92573143b9aSmrg{
92673143b9aSmrg    int ret;
92773143b9aSmrg
92873143b9aSmrg    PRMSG (2,"Close(%d)\n", ciptr->fd, 0, 0);
92973143b9aSmrg
93073143b9aSmrg    ret = ciptr->transptr->Close (ciptr);
93173143b9aSmrg
93273143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
93373143b9aSmrg
93473143b9aSmrg    return ret;
93573143b9aSmrg}
93673143b9aSmrg
93773143b9aSmrgint
93873143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr)
93973143b9aSmrg
94073143b9aSmrg{
94173143b9aSmrg    int ret;
94273143b9aSmrg
94373143b9aSmrg    PRMSG (2,"CloseForCloning(%d)\n", ciptr->fd, 0, 0);
94473143b9aSmrg
94573143b9aSmrg    ret = ciptr->transptr->CloseForCloning (ciptr);
94673143b9aSmrg
94773143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
94873143b9aSmrg
94973143b9aSmrg    return ret;
95073143b9aSmrg}
95173143b9aSmrg
95273143b9aSmrgint
95373143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr)
95473143b9aSmrg
95573143b9aSmrg{
95673143b9aSmrg    return (ciptr->family == AF_UNIX);
95773143b9aSmrg}
95873143b9aSmrg
95973143b9aSmrg
96073143b9aSmrgint
96173143b9aSmrgTRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
96273143b9aSmrg		  Xtransaddr **addrp)
96373143b9aSmrg
96473143b9aSmrg{
96573143b9aSmrg    PRMSG (2,"GetMyAddr(%d)\n", ciptr->fd, 0, 0);
96673143b9aSmrg
96773143b9aSmrg    *familyp = ciptr->family;
96873143b9aSmrg    *addrlenp = ciptr->addrlen;
96973143b9aSmrg
97073143b9aSmrg    if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL)
97173143b9aSmrg    {
97273143b9aSmrg	PRMSG (1,"GetMyAddr: malloc failed\n", 0, 0, 0);
97373143b9aSmrg	return -1;
97473143b9aSmrg    }
97573143b9aSmrg    memcpy(*addrp, ciptr->addr, ciptr->addrlen);
97673143b9aSmrg
97773143b9aSmrg    return 0;
97873143b9aSmrg}
97973143b9aSmrg
98073143b9aSmrgint
98173143b9aSmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
98273143b9aSmrg		    Xtransaddr **addrp)
98373143b9aSmrg
98473143b9aSmrg{
98573143b9aSmrg    PRMSG (2,"GetPeerAddr(%d)\n", ciptr->fd, 0, 0);
98673143b9aSmrg
98773143b9aSmrg    *familyp = ciptr->family;
98873143b9aSmrg    *addrlenp = ciptr->peeraddrlen;
98973143b9aSmrg
99073143b9aSmrg    if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL)
99173143b9aSmrg    {
99273143b9aSmrg	PRMSG (1,"GetPeerAddr: malloc failed\n", 0, 0, 0);
99373143b9aSmrg	return -1;
99473143b9aSmrg    }
99573143b9aSmrg    memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
99673143b9aSmrg
99773143b9aSmrg    return 0;
99873143b9aSmrg}
99973143b9aSmrg
100073143b9aSmrg
100173143b9aSmrgint
100273143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr)
100373143b9aSmrg
100473143b9aSmrg{
100573143b9aSmrg    return ciptr->fd;
100673143b9aSmrg}
100773143b9aSmrg
100873143b9aSmrg
100973143b9aSmrg/*
101073143b9aSmrg * These functions are really utility functions, but they require knowledge
101173143b9aSmrg * of the internal data structures, so they have to be part of the Transport
101273143b9aSmrg * Independant API.
101373143b9aSmrg */
101473143b9aSmrg
101573143b9aSmrg#ifdef TRANS_SERVER
101673143b9aSmrg
101773143b9aSmrgstatic int
101873143b9aSmrgcomplete_network_count (void)
101973143b9aSmrg
102073143b9aSmrg{
102173143b9aSmrg    int count = 0;
102273143b9aSmrg    int found_local = 0;
102373143b9aSmrg    int i;
102473143b9aSmrg
102573143b9aSmrg    /*
102673143b9aSmrg     * For a complete network, we only need one LOCALCONN transport to work
102773143b9aSmrg     */
102873143b9aSmrg
102973143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
103073143b9aSmrg    {
103173143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_ALIAS
103273143b9aSmrg   	 || Xtransports[i].transport->flags & TRANS_NOLISTEN)
103373143b9aSmrg	    continue;
103473143b9aSmrg
103573143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_LOCAL)
103673143b9aSmrg	    found_local = 1;
103773143b9aSmrg	else
103873143b9aSmrg	    count++;
103973143b9aSmrg    }
104073143b9aSmrg
104173143b9aSmrg    return (count + found_local);
104273143b9aSmrg}
104373143b9aSmrg
104473143b9aSmrg
10458d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
10468d4c0f7bSmrgextern int xquartz_launchd_fd;
10478d4c0f7bSmrg#endif
104873143b9aSmrg
104973143b9aSmrgint
105073143b9aSmrgTRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
105173143b9aSmrg				   XtransConnInfo **ciptrs_ret)
105273143b9aSmrg
105373143b9aSmrg{
105473143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
105573143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
105673143b9aSmrg    int			status, i, j;
105773143b9aSmrg
105873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
105973143b9aSmrg    int		ipv6_succ = 0;
106073143b9aSmrg#endif
106173143b9aSmrg    PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n",
106273143b9aSmrg	   port ? port : "NULL", ciptrs_ret, 0);
106373143b9aSmrg
106473143b9aSmrg    *count_ret = 0;
106573143b9aSmrg
10668d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
10678d4c0f7bSmrg    fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
10688d4c0f7bSmrg    if(xquartz_launchd_fd != -1) {
10698d4c0f7bSmrg        if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
10708d4c0f7bSmrg                                           xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
10718d4c0f7bSmrg            fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
10728d4c0f7bSmrg        else
10738d4c0f7bSmrg            temp_ciptrs[(*count_ret)++] = ciptr;
10748d4c0f7bSmrg    }
107573143b9aSmrg#endif
107673143b9aSmrg
107773143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
107873143b9aSmrg    {
107973143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
108073143b9aSmrg	unsigned int flags = 0;
108173143b9aSmrg
108273143b9aSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
108373143b9aSmrg	    continue;
108473143b9aSmrg
108573143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
108673143b9aSmrg		 trans->TransName, port ? port : "");
108773143b9aSmrg
108873143b9aSmrg	PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n",
108973143b9aSmrg	       buffer, 0, 0);
109073143b9aSmrg
109173143b9aSmrg	if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
109273143b9aSmrg	{
109373143b9aSmrg	    if (trans->flags & TRANS_DISABLED)
109473143b9aSmrg		continue;
109573143b9aSmrg
109673143b9aSmrg	    PRMSG (1,
109773143b9aSmrg	  "MakeAllCOTSServerListeners: failed to open listener for %s\n",
109873143b9aSmrg		  trans->TransName, 0, 0);
109973143b9aSmrg	    continue;
110073143b9aSmrg	}
110173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
110273143b9aSmrg		if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
110373143b9aSmrg		     && ipv6_succ))
110473143b9aSmrg		    flags |= ADDR_IN_USE_ALLOWED;
110573143b9aSmrg#endif
110673143b9aSmrg
110773143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
110873143b9aSmrg	{
110973143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
111073143b9aSmrg	    {
111173143b9aSmrg		/*
111273143b9aSmrg		 * We failed to bind to the specified address because the
111373143b9aSmrg		 * address is in use.  It must be that a server is already
111473143b9aSmrg		 * running at this address, and this function should fail.
111573143b9aSmrg		 */
111673143b9aSmrg
111773143b9aSmrg		PRMSG (1,
111873143b9aSmrg		"MakeAllCOTSServerListeners: server already running\n",
111973143b9aSmrg		  0, 0, 0);
112073143b9aSmrg
112173143b9aSmrg		for (j = 0; j < *count_ret; j++)
112273143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
112373143b9aSmrg
112473143b9aSmrg		*count_ret = 0;
112573143b9aSmrg		*ciptrs_ret = NULL;
112673143b9aSmrg		*partial = 0;
112773143b9aSmrg		return -1;
112873143b9aSmrg	    }
112973143b9aSmrg	    else
113073143b9aSmrg	    {
113173143b9aSmrg		PRMSG (1,
113273143b9aSmrg	"MakeAllCOTSServerListeners: failed to create listener for %s\n",
113373143b9aSmrg		  trans->TransName, 0, 0);
113473143b9aSmrg
113573143b9aSmrg		continue;
113673143b9aSmrg	    }
113773143b9aSmrg	}
113873143b9aSmrg
113973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
114073143b9aSmrg	if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
114173143b9aSmrg	    ipv6_succ = 1;
114273143b9aSmrg#endif
114373143b9aSmrg
114473143b9aSmrg	PRMSG (5,
114573143b9aSmrg	      "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
114673143b9aSmrg	      trans->TransName, ciptr->fd, 0);
114773143b9aSmrg
114873143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
114973143b9aSmrg	(*count_ret)++;
115073143b9aSmrg    }
115173143b9aSmrg
115273143b9aSmrg    *partial = (*count_ret < complete_network_count());
115373143b9aSmrg
115473143b9aSmrg    PRMSG (5,
115573143b9aSmrg     "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
115673143b9aSmrg	*partial, *count_ret, complete_network_count());
115773143b9aSmrg
115873143b9aSmrg    if (*count_ret > 0)
115973143b9aSmrg    {
116073143b9aSmrg	if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
116173143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
116273143b9aSmrg	{
116373143b9aSmrg	    return -1;
116473143b9aSmrg	}
116573143b9aSmrg
116673143b9aSmrg	for (i = 0; i < *count_ret; i++)
116773143b9aSmrg	{
116873143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
116973143b9aSmrg	}
117073143b9aSmrg    }
117173143b9aSmrg    else
117273143b9aSmrg	*ciptrs_ret = NULL;
117373143b9aSmrg
117473143b9aSmrg    return 0;
117573143b9aSmrg}
117673143b9aSmrg
117773143b9aSmrgint
117873143b9aSmrgTRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
117973143b9aSmrg				   XtransConnInfo **ciptrs_ret)
118073143b9aSmrg
118173143b9aSmrg{
118273143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
118373143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
118473143b9aSmrg    int			status, i, j;
118573143b9aSmrg
118673143b9aSmrg    PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)\n",
118773143b9aSmrg	port ? port : "NULL", ciptrs_ret, 0);
118873143b9aSmrg
118973143b9aSmrg    *count_ret = 0;
119073143b9aSmrg
119173143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
119273143b9aSmrg    {
119373143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
119473143b9aSmrg
119573143b9aSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
119673143b9aSmrg	    continue;
119773143b9aSmrg
119873143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
119973143b9aSmrg		 trans->TransName, port ? port : "");
120073143b9aSmrg
120173143b9aSmrg	PRMSG (5,"MakeAllCLTSServerListeners: opening %s\n",
120273143b9aSmrg	    buffer, 0, 0);
120373143b9aSmrg
120473143b9aSmrg	if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
120573143b9aSmrg	{
120673143b9aSmrg	    PRMSG (1,
120773143b9aSmrg	"MakeAllCLTSServerListeners: failed to open listener for %s\n",
120873143b9aSmrg		  trans->TransName, 0, 0);
120973143b9aSmrg	    continue;
121073143b9aSmrg	}
121173143b9aSmrg
121273143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
121373143b9aSmrg	{
121473143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
121573143b9aSmrg	    {
121673143b9aSmrg		/*
121773143b9aSmrg		 * We failed to bind to the specified address because the
121873143b9aSmrg		 * address is in use.  It must be that a server is already
121973143b9aSmrg		 * running at this address, and this function should fail.
122073143b9aSmrg		 */
122173143b9aSmrg
122273143b9aSmrg		PRMSG (1,
122373143b9aSmrg		"MakeAllCLTSServerListeners: server already running\n",
122473143b9aSmrg		  0, 0, 0);
122573143b9aSmrg
122673143b9aSmrg		for (j = 0; j < *count_ret; j++)
122773143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
122873143b9aSmrg
122973143b9aSmrg		*count_ret = 0;
123073143b9aSmrg		*ciptrs_ret = NULL;
123173143b9aSmrg		*partial = 0;
123273143b9aSmrg		return -1;
123373143b9aSmrg	    }
123473143b9aSmrg	    else
123573143b9aSmrg	    {
123673143b9aSmrg		PRMSG (1,
123773143b9aSmrg	"MakeAllCLTSServerListeners: failed to create listener for %s\n",
123873143b9aSmrg		  trans->TransName, 0, 0);
123973143b9aSmrg
124073143b9aSmrg		continue;
124173143b9aSmrg	    }
124273143b9aSmrg	}
124373143b9aSmrg
124473143b9aSmrg	PRMSG (5,
124573143b9aSmrg	"MakeAllCLTSServerListeners: opened listener for %s, %d\n",
124673143b9aSmrg	      trans->TransName, ciptr->fd, 0);
124773143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
124873143b9aSmrg	(*count_ret)++;
124973143b9aSmrg    }
125073143b9aSmrg
125173143b9aSmrg    *partial = (*count_ret < complete_network_count());
125273143b9aSmrg
125373143b9aSmrg    PRMSG (5,
125473143b9aSmrg     "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
125573143b9aSmrg	*partial, *count_ret, complete_network_count());
125673143b9aSmrg
125773143b9aSmrg    if (*count_ret > 0)
125873143b9aSmrg    {
125973143b9aSmrg	if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
126073143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
126173143b9aSmrg	{
126273143b9aSmrg	    return -1;
126373143b9aSmrg	}
126473143b9aSmrg
126573143b9aSmrg	for (i = 0; i < *count_ret; i++)
126673143b9aSmrg	{
126773143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
126873143b9aSmrg	}
126973143b9aSmrg    }
127073143b9aSmrg    else
127173143b9aSmrg	*ciptrs_ret = NULL;
127273143b9aSmrg
127373143b9aSmrg    return 0;
127473143b9aSmrg}
127573143b9aSmrg
127673143b9aSmrg#endif /* TRANS_SERVER */
127773143b9aSmrg
127873143b9aSmrg
127973143b9aSmrg
128073143b9aSmrg/*
128173143b9aSmrg * These routines are not part of the X Transport Interface, but they
128273143b9aSmrg * may be used by it.
128373143b9aSmrg */
128473143b9aSmrg
128573143b9aSmrg
12868d4c0f7bSmrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
128773143b9aSmrg
128873143b9aSmrg/*
128973143b9aSmrg * emulate readv
129073143b9aSmrg */
129173143b9aSmrg
129273143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
129373143b9aSmrg
129473143b9aSmrg{
129573143b9aSmrg    int i, len, total;
129673143b9aSmrg    char *base;
129773143b9aSmrg
129873143b9aSmrg    ESET(0);
129973143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
130073143b9aSmrg	len = iov->iov_len;
130173143b9aSmrg	base = iov->iov_base;
130273143b9aSmrg	while (len > 0) {
130373143b9aSmrg	    register int nbytes;
130473143b9aSmrg	    nbytes = TRANS(Read) (ciptr, base, len);
130573143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
130673143b9aSmrg	    if (nbytes <= 0)  return total;
130773143b9aSmrg	    ESET(0);
130873143b9aSmrg	    len   -= nbytes;
130973143b9aSmrg	    total += nbytes;
131073143b9aSmrg	    base  += nbytes;
131173143b9aSmrg	}
131273143b9aSmrg    }
131373143b9aSmrg    return total;
131473143b9aSmrg}
131573143b9aSmrg
131673143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
131773143b9aSmrg
13188d4c0f7bSmrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
131973143b9aSmrg
132073143b9aSmrg/*
132173143b9aSmrg * emulate writev
132273143b9aSmrg */
132373143b9aSmrg
132473143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
132573143b9aSmrg
132673143b9aSmrg{
132773143b9aSmrg    int i, len, total;
132873143b9aSmrg    char *base;
132973143b9aSmrg
133073143b9aSmrg    ESET(0);
133173143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
133273143b9aSmrg	len = iov->iov_len;
133373143b9aSmrg	base = iov->iov_base;
133473143b9aSmrg	while (len > 0) {
133573143b9aSmrg	    register int nbytes;
133673143b9aSmrg	    nbytes = TRANS(Write) (ciptr, base, len);
133773143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
133873143b9aSmrg	    if (nbytes <= 0)  return total;
133973143b9aSmrg	    ESET(0);
134073143b9aSmrg	    len   -= nbytes;
134173143b9aSmrg	    total += nbytes;
134273143b9aSmrg	    base  += nbytes;
134373143b9aSmrg	}
134473143b9aSmrg    }
134573143b9aSmrg    return total;
134673143b9aSmrg}
134773143b9aSmrg
134873143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
134973143b9aSmrg
135073143b9aSmrg
1351e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__)
135273143b9aSmrg#ifndef NEED_UTSNAME
135373143b9aSmrg#define NEED_UTSNAME
135473143b9aSmrg#endif
135573143b9aSmrg#include <sys/utsname.h>
135673143b9aSmrg#endif
135773143b9aSmrg
135873143b9aSmrg/*
135973143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing.
136073143b9aSmrg */
136173143b9aSmrg
136273143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen)
136373143b9aSmrg
136473143b9aSmrg{
136573143b9aSmrg    int len;
136673143b9aSmrg
136773143b9aSmrg#ifdef NEED_UTSNAME
136873143b9aSmrg    struct utsname name;
136973143b9aSmrg
137073143b9aSmrg    uname (&name);
137173143b9aSmrg    len = strlen (name.nodename);
137273143b9aSmrg    if (len >= maxlen) len = maxlen - 1;
137373143b9aSmrg    strncpy (buf, name.nodename, len);
137473143b9aSmrg    buf[len] = '\0';
137573143b9aSmrg#else
137673143b9aSmrg    buf[0] = '\0';
137773143b9aSmrg    (void) gethostname (buf, maxlen);
137873143b9aSmrg    buf [maxlen - 1] = '\0';
137973143b9aSmrg    len = strlen(buf);
138073143b9aSmrg#endif /* NEED_UTSNAME */
138173143b9aSmrg    return len;
138273143b9aSmrg}
1383