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