Xtrans.c revision 75ebec6d
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>
5175ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON
5275ebec6dSmrg#include <string.h>
5375ebec6dSmrg#include <systemd/sd-daemon.h>
5475ebec6dSmrg#endif
5573143b9aSmrg
5673143b9aSmrg/*
5773143b9aSmrg * The transport table contains a definition for every transport (protocol)
5873143b9aSmrg * family. All operations that can be made on the transport go through this
5973143b9aSmrg * table.
6073143b9aSmrg *
6173143b9aSmrg * Each transport is assigned a unique transport id.
6273143b9aSmrg *
6373143b9aSmrg * New transports can be added by adding an entry in this table.
6473143b9aSmrg * For compatiblity, the transport ids should never be renumbered.
6573143b9aSmrg * Always add to the end of the list.
6673143b9aSmrg */
6773143b9aSmrg
6873143b9aSmrg#define TRANS_TLI_INET_INDEX		1
6973143b9aSmrg#define TRANS_TLI_TCP_INDEX		2
7073143b9aSmrg#define TRANS_TLI_TLI_INDEX		3
7173143b9aSmrg#define TRANS_SOCKET_UNIX_INDEX		4
7273143b9aSmrg#define TRANS_SOCKET_LOCAL_INDEX	5
7373143b9aSmrg#define TRANS_SOCKET_INET_INDEX		6
7473143b9aSmrg#define TRANS_SOCKET_TCP_INDEX		7
7573143b9aSmrg#define TRANS_DNET_INDEX		8
7673143b9aSmrg#define TRANS_LOCAL_LOCAL_INDEX		9
7773143b9aSmrg#define TRANS_LOCAL_PTS_INDEX		10
7873143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX		11
79af928962Smrg/* 12 used to be ISC, but that's gone. */
8073143b9aSmrg#define TRANS_LOCAL_SCO_INDEX		13
8173143b9aSmrg#define TRANS_SOCKET_INET6_INDEX	14
8273143b9aSmrg#define TRANS_LOCAL_PIPE_INDEX		15
8373143b9aSmrg
8473143b9aSmrg
8573143b9aSmrgstatic
8673143b9aSmrgXtransport_table Xtransports[] = {
8773143b9aSmrg#if defined(TCPCONN)
8873143b9aSmrg    { &TRANS(SocketTCPFuncs),	TRANS_SOCKET_TCP_INDEX },
8973143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
9073143b9aSmrg    { &TRANS(SocketINET6Funcs),	TRANS_SOCKET_INET6_INDEX },
9173143b9aSmrg#endif /* IPv6 */
9273143b9aSmrg    { &TRANS(SocketINETFuncs),	TRANS_SOCKET_INET_INDEX },
9373143b9aSmrg#endif /* TCPCONN */
9473143b9aSmrg#if defined(UNIXCONN)
9573143b9aSmrg#if !defined(LOCALCONN)
9673143b9aSmrg    { &TRANS(SocketLocalFuncs),	TRANS_SOCKET_LOCAL_INDEX },
9773143b9aSmrg#endif /* !LOCALCONN */
9873143b9aSmrg    { &TRANS(SocketUNIXFuncs),	TRANS_SOCKET_UNIX_INDEX },
9973143b9aSmrg#endif /* UNIXCONN */
10073143b9aSmrg#if defined(LOCALCONN)
10173143b9aSmrg    { &TRANS(LocalFuncs),	TRANS_LOCAL_LOCAL_INDEX },
10273143b9aSmrg#ifndef sun
10373143b9aSmrg    { &TRANS(PTSFuncs),		TRANS_LOCAL_PTS_INDEX },
10473143b9aSmrg#endif /* sun */
105e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
10673143b9aSmrg    { &TRANS(NAMEDFuncs),	TRANS_LOCAL_NAMED_INDEX },
10773143b9aSmrg#endif
10873143b9aSmrg#ifdef sun
10973143b9aSmrg    { &TRANS(PIPEFuncs),	TRANS_LOCAL_PIPE_INDEX },
11073143b9aSmrg#endif /* sun */
111af928962Smrg#if defined(__SCO__) || defined(__UNIXWARE__)
112af928962Smrg    { &TRANS(SCOFuncs),		TRANS_LOCAL_SCO_INDEX },
113af928962Smrg#endif /* __SCO__ || __UNIXWARE__ */
11473143b9aSmrg#endif /* LOCALCONN */
11573143b9aSmrg};
11673143b9aSmrg
11773143b9aSmrg#define NUMTRANS	(sizeof(Xtransports)/sizeof(Xtransport_table))
11873143b9aSmrg
11973143b9aSmrg
12073143b9aSmrg#ifdef WIN32
12173143b9aSmrg#define ioctl ioctlsocket
12273143b9aSmrg#endif
12373143b9aSmrg
12473143b9aSmrg
12573143b9aSmrg
12673143b9aSmrg/*
12773143b9aSmrg * These are a few utility function used by the public interface functions.
12873143b9aSmrg */
12973143b9aSmrg
13073143b9aSmrgvoid
13173143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr)
13273143b9aSmrg
13373143b9aSmrg{
134fe567363Smrg    prmsg (3,"FreeConnInfo(%p)\n", ciptr);
13573143b9aSmrg
13673143b9aSmrg    if (ciptr->addr)
137fe567363Smrg	free (ciptr->addr);
13873143b9aSmrg
13973143b9aSmrg    if (ciptr->peeraddr)
140fe567363Smrg	free (ciptr->peeraddr);
14173143b9aSmrg
14273143b9aSmrg    if (ciptr->port)
143fe567363Smrg	free (ciptr->port);
14473143b9aSmrg
145fe567363Smrg    free (ciptr);
14673143b9aSmrg}
14773143b9aSmrg
14873143b9aSmrg
14973143b9aSmrg#define PROTOBUFSIZE	20
15073143b9aSmrg
15173143b9aSmrgstatic Xtransport *
152fe567363SmrgTRANS(SelectTransport) (const char *protocol)
15373143b9aSmrg
15473143b9aSmrg{
15573143b9aSmrg    char 	protobuf[PROTOBUFSIZE];
15673143b9aSmrg    int		i;
15773143b9aSmrg
158fe567363Smrg    prmsg (3,"SelectTransport(%s)\n", protocol);
15973143b9aSmrg
16073143b9aSmrg    /*
16173143b9aSmrg     * Force Protocol to be lowercase as a way of doing
16273143b9aSmrg     * a case insensitive match.
16373143b9aSmrg     */
16473143b9aSmrg
16573143b9aSmrg    strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
16673143b9aSmrg    protobuf[PROTOBUFSIZE-1] = '\0';
16773143b9aSmrg
16873143b9aSmrg    for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
16973143b9aSmrg	if (isupper (protobuf[i]))
17073143b9aSmrg	    protobuf[i] = tolower (protobuf[i]);
17173143b9aSmrg
17273143b9aSmrg    /* Look at all of the configured protocols */
17373143b9aSmrg
17473143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
17573143b9aSmrg    {
17673143b9aSmrg	if (!strcmp (protobuf, Xtransports[i].transport->TransName))
17773143b9aSmrg	    return Xtransports[i].transport;
17873143b9aSmrg    }
17973143b9aSmrg
18073143b9aSmrg    return NULL;
18173143b9aSmrg}
18273143b9aSmrg
18373143b9aSmrg#ifndef TEST_t
18473143b9aSmrgstatic
18573143b9aSmrg#endif /* TEST_t */
18673143b9aSmrgint
18773143b9aSmrgTRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
18873143b9aSmrg
18973143b9aSmrg{
19073143b9aSmrg    /*
19173143b9aSmrg     * For the font library, the address is a string formatted
19273143b9aSmrg     * as "protocol/host:port[/catalogue]".  Note that the catologue
19373143b9aSmrg     * is optional.  At this time, the catologue info is ignored, but
19473143b9aSmrg     * we have to parse it anyways.
19573143b9aSmrg     *
19673143b9aSmrg     * Other than fontlib, the address is a string formatted
19773143b9aSmrg     * as "protocol/host:port".
19873143b9aSmrg     *
19973143b9aSmrg     * If the protocol part is missing, then assume TCP.
20073143b9aSmrg     * If the protocol part and host part are missing, then assume local.
20173143b9aSmrg     * If a "::" is found then assume DNET.
20273143b9aSmrg     */
20373143b9aSmrg
20473143b9aSmrg    char	*mybuf, *tmpptr;
205fe567363Smrg    const char	*_protocol;
206fe567363Smrg    char	*_host, *_port;
20773143b9aSmrg    char	hostnamebuf[256];
20873143b9aSmrg    int		_host_len;
20973143b9aSmrg
210fe567363Smrg    prmsg (3,"ParseAddress(%s)\n", address);
21173143b9aSmrg
21273143b9aSmrg    /* Copy the string so it can be changed */
21373143b9aSmrg
214fe567363Smrg    tmpptr = mybuf = strdup (address);
21573143b9aSmrg
21673143b9aSmrg    /* Parse the string to get each component */
217fe567363Smrg
21873143b9aSmrg    /* Get the protocol part */
21973143b9aSmrg
22073143b9aSmrg    _protocol = mybuf;
22173143b9aSmrg
22273143b9aSmrg
22373143b9aSmrg   if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
22473143b9aSmrg      ((mybuf = strrchr (tmpptr,':')) == NULL) )
22573143b9aSmrg   {
22673143b9aSmrg	/* address is in a bad format */
22773143b9aSmrg	*protocol = NULL;
22873143b9aSmrg	*host = NULL;
22973143b9aSmrg	*port = NULL;
230fe567363Smrg	free (tmpptr);
23173143b9aSmrg	return 0;
23273143b9aSmrg    }
23373143b9aSmrg
23473143b9aSmrg    if (*mybuf == ':')
23573143b9aSmrg    {
23673143b9aSmrg	/*
23773143b9aSmrg	 * If there is a hostname, then assume tcp, otherwise
23873143b9aSmrg	 * it must be local.
23973143b9aSmrg	 */
24073143b9aSmrg	if (mybuf == tmpptr)
24173143b9aSmrg	{
24273143b9aSmrg	    /* There is neither a protocol or host specified */
24373143b9aSmrg	    _protocol = "local";
24473143b9aSmrg	}
24573143b9aSmrg	else
24673143b9aSmrg	{
24773143b9aSmrg	    /* There is a hostname specified */
24873143b9aSmrg	    _protocol = "tcp";
24973143b9aSmrg	    mybuf = tmpptr;	/* reset to the begining of the host ptr */
25073143b9aSmrg	}
25173143b9aSmrg    }
25273143b9aSmrg    else
25373143b9aSmrg    {
25473143b9aSmrg	/* *mybuf == '/' */
25573143b9aSmrg
25673143b9aSmrg	*mybuf ++= '\0'; /* put a null at the end of the protocol */
25773143b9aSmrg
25873143b9aSmrg	if (strlen(_protocol) == 0)
25973143b9aSmrg	{
26073143b9aSmrg	    /*
26173143b9aSmrg	     * If there is a hostname, then assume tcp, otherwise
26273143b9aSmrg	     * it must be local.
26373143b9aSmrg	     */
26473143b9aSmrg	    if (*mybuf != ':')
26573143b9aSmrg		_protocol = "tcp";
26673143b9aSmrg	    else
26773143b9aSmrg		_protocol = "local";
26873143b9aSmrg	}
26973143b9aSmrg    }
27073143b9aSmrg
27173143b9aSmrg    /* Get the host part */
27273143b9aSmrg
27373143b9aSmrg    _host = mybuf;
27473143b9aSmrg
27573143b9aSmrg    if ((mybuf = strrchr (mybuf,':')) == NULL)
27673143b9aSmrg    {
27773143b9aSmrg	*protocol = NULL;
27873143b9aSmrg	*host = NULL;
27973143b9aSmrg	*port = NULL;
280fe567363Smrg	free (tmpptr);
28173143b9aSmrg	return 0;
28273143b9aSmrg    }
28373143b9aSmrg
28473143b9aSmrg    *mybuf ++= '\0';
28573143b9aSmrg
28673143b9aSmrg    _host_len = strlen(_host);
28773143b9aSmrg    if (_host_len == 0)
28873143b9aSmrg    {
28973143b9aSmrg	TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
29073143b9aSmrg	_host = hostnamebuf;
29173143b9aSmrg    }
29273143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
29373143b9aSmrg    /* hostname in IPv6 [numeric_addr]:0 form? */
294fe567363Smrg    else if ( (_host_len > 3) &&
29573143b9aSmrg      ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
296fe567363Smrg      && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
29773143b9aSmrg	struct sockaddr_in6 sin6;
29873143b9aSmrg
29973143b9aSmrg	*(_host + _host_len - 1) = '\0';
30073143b9aSmrg
30173143b9aSmrg	/* Verify address is valid IPv6 numeric form */
30273143b9aSmrg	if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
30373143b9aSmrg	    /* It is. Use it as such. */
30473143b9aSmrg	    _host++;
30573143b9aSmrg	    _protocol = "inet6";
30673143b9aSmrg	} else {
30773143b9aSmrg	    /* It's not, restore it just in case some other code can use it. */
30873143b9aSmrg	    *(_host + _host_len - 1) = ']';
30973143b9aSmrg	}
31073143b9aSmrg    }
31173143b9aSmrg#endif
31273143b9aSmrg
31373143b9aSmrg
31473143b9aSmrg    /* Get the port */
31573143b9aSmrg
31673143b9aSmrg    _port = mybuf;
31773143b9aSmrg
31873143b9aSmrg#if defined(FONT_t) || defined(FS_t)
31973143b9aSmrg    /*
32073143b9aSmrg     * Is there an optional catalogue list?
32173143b9aSmrg     */
32273143b9aSmrg
32373143b9aSmrg    if ((mybuf = strchr (mybuf,'/')) != NULL)
32473143b9aSmrg	*mybuf ++= '\0';
32573143b9aSmrg
32673143b9aSmrg    /*
32773143b9aSmrg     * The rest, if any, is the (currently unused) catalogue list.
32873143b9aSmrg     *
32973143b9aSmrg     * _catalogue = mybuf;
33073143b9aSmrg     */
33173143b9aSmrg#endif
33273143b9aSmrg
33373143b9aSmrg#ifdef HAVE_LAUNCHD
33473143b9aSmrg    /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
33573143b9aSmrg    if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
33673143b9aSmrg      _protocol="local";
33773143b9aSmrg      _host="";
33873143b9aSmrg      _port=address+6;
33973143b9aSmrg    }
34073143b9aSmrg#endif
34173143b9aSmrg
34273143b9aSmrg    /*
34373143b9aSmrg     * Now that we have all of the components, allocate new
34473143b9aSmrg     * string space for them.
34573143b9aSmrg     */
34673143b9aSmrg
347fe567363Smrg    if ((*protocol = strdup (_protocol)) == NULL)
34873143b9aSmrg    {
34973143b9aSmrg	/* Malloc failed */
35073143b9aSmrg	*port = NULL;
35173143b9aSmrg	*host = NULL;
35273143b9aSmrg	*protocol = NULL;
353fe567363Smrg	free (tmpptr);
35473143b9aSmrg	return 0;
35573143b9aSmrg    }
35673143b9aSmrg
357fe567363Smrg    if ((*host = strdup (_host)) == NULL)
35873143b9aSmrg    {
35973143b9aSmrg	/* Malloc failed */
36073143b9aSmrg	*port = NULL;
36173143b9aSmrg	*host = NULL;
362fe567363Smrg	free (*protocol);
36373143b9aSmrg	*protocol = NULL;
364fe567363Smrg	free (tmpptr);
36573143b9aSmrg	return 0;
366fe567363Smrg    }
36773143b9aSmrg
368fe567363Smrg    if ((*port = strdup (_port)) == NULL)
36973143b9aSmrg    {
37073143b9aSmrg	/* Malloc failed */
37173143b9aSmrg	*port = NULL;
372fe567363Smrg	free (*host);
37373143b9aSmrg	*host = NULL;
374fe567363Smrg	free (*protocol);
37573143b9aSmrg	*protocol = NULL;
376fe567363Smrg	free (tmpptr);
37773143b9aSmrg	return 0;
37873143b9aSmrg    }
37973143b9aSmrg
380fe567363Smrg    free (tmpptr);
38173143b9aSmrg
38273143b9aSmrg    return 1;
38373143b9aSmrg}
38473143b9aSmrg
38573143b9aSmrg
38673143b9aSmrg/*
38773143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only
38873143b9aSmrg * funny part about this is the type parameter which is used to decide which
38973143b9aSmrg * type of open to perform.
39073143b9aSmrg */
39173143b9aSmrg
39273143b9aSmrgstatic XtransConnInfo
39373143b9aSmrgTRANS(Open) (int type, char *address)
39473143b9aSmrg
39573143b9aSmrg{
39673143b9aSmrg    char 		*protocol = NULL, *host = NULL, *port = NULL;
39773143b9aSmrg    XtransConnInfo	ciptr = NULL;
39873143b9aSmrg    Xtransport		*thistrans;
39973143b9aSmrg
400fe567363Smrg    prmsg (2,"Open(%d,%s)\n", type, address);
40173143b9aSmrg
402fe567363Smrg#if defined(WIN32) && defined(TCPCONN)
40373143b9aSmrg    if (TRANS(WSAStartup)())
40473143b9aSmrg    {
405fe567363Smrg	prmsg (1,"Open: WSAStartup failed\n");
40673143b9aSmrg	return NULL;
40773143b9aSmrg    }
40873143b9aSmrg#endif
40973143b9aSmrg
41073143b9aSmrg    /* Parse the Address */
41173143b9aSmrg
41273143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
41373143b9aSmrg    {
414fe567363Smrg	prmsg (1,"Open: Unable to Parse address %s\n", address);
41573143b9aSmrg	return NULL;
41673143b9aSmrg    }
41773143b9aSmrg
41873143b9aSmrg    /* Determine the transport type */
41973143b9aSmrg
42073143b9aSmrg    if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
42173143b9aSmrg    {
422fe567363Smrg	prmsg (1,"Open: Unable to find transport for %s\n",
423fe567363Smrg	       protocol);
42473143b9aSmrg
425fe567363Smrg	free (protocol);
426fe567363Smrg	free (host);
427fe567363Smrg	free (port);
42873143b9aSmrg	return NULL;
42973143b9aSmrg    }
43073143b9aSmrg
43173143b9aSmrg    /* Open the transport */
43273143b9aSmrg
43373143b9aSmrg    switch (type)
43473143b9aSmrg    {
43573143b9aSmrg    case XTRANS_OPEN_COTS_CLIENT:
43673143b9aSmrg#ifdef TRANS_CLIENT
43773143b9aSmrg	ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
43873143b9aSmrg#endif /* TRANS_CLIENT */
43973143b9aSmrg	break;
44073143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
44173143b9aSmrg#ifdef TRANS_SERVER
44273143b9aSmrg	ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
44373143b9aSmrg#endif /* TRANS_SERVER */
44473143b9aSmrg	break;
44573143b9aSmrg    case XTRANS_OPEN_CLTS_CLIENT:
44673143b9aSmrg#ifdef TRANS_CLIENT
44773143b9aSmrg	ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
44873143b9aSmrg#endif /* TRANS_CLIENT */
44973143b9aSmrg	break;
45073143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
45173143b9aSmrg#ifdef TRANS_SERVER
45273143b9aSmrg	ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
45373143b9aSmrg#endif /* TRANS_SERVER */
45473143b9aSmrg	break;
45573143b9aSmrg    default:
456fe567363Smrg	prmsg (1,"Open: Unknown Open type %d\n", type);
45773143b9aSmrg    }
45873143b9aSmrg
45973143b9aSmrg    if (ciptr == NULL)
46073143b9aSmrg    {
461fe567363Smrg	if (!(thistrans->flags & TRANS_DISABLED))
46273143b9aSmrg	{
463fe567363Smrg	    prmsg (1,"Open: transport open failed for %s/%s:%s\n",
46473143b9aSmrg	           protocol, host, port);
46573143b9aSmrg	}
466fe567363Smrg	free (protocol);
467fe567363Smrg	free (host);
468fe567363Smrg	free (port);
46973143b9aSmrg	return NULL;
47073143b9aSmrg    }
47173143b9aSmrg
47273143b9aSmrg    ciptr->transptr = thistrans;
47373143b9aSmrg    ciptr->port = port;			/* We need this for TRANS(Reopen) */
47473143b9aSmrg
475fe567363Smrg    free (protocol);
476fe567363Smrg    free (host);
47773143b9aSmrg
47873143b9aSmrg    return ciptr;
47973143b9aSmrg}
48073143b9aSmrg
48173143b9aSmrg
48273143b9aSmrg#ifdef TRANS_REOPEN
48373143b9aSmrg
48473143b9aSmrg/*
48573143b9aSmrg * We might want to create an XtransConnInfo object based on a previously
48673143b9aSmrg * opened connection.  For example, the font server may clone itself and
48773143b9aSmrg * pass file descriptors to the parent.
48873143b9aSmrg */
48973143b9aSmrg
49073143b9aSmrgstatic XtransConnInfo
49173143b9aSmrgTRANS(Reopen) (int type, int trans_id, int fd, char *port)
49273143b9aSmrg
49373143b9aSmrg{
49473143b9aSmrg    XtransConnInfo	ciptr = NULL;
49573143b9aSmrg    Xtransport		*thistrans = NULL;
49673143b9aSmrg    char		*save_port;
49773143b9aSmrg    int			i;
49873143b9aSmrg
499fe567363Smrg    prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
50073143b9aSmrg
50173143b9aSmrg    /* Determine the transport type */
50273143b9aSmrg
50373143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
50473143b9aSmrg	if (Xtransports[i].transport_id == trans_id)
50573143b9aSmrg	{
50673143b9aSmrg	    thistrans = Xtransports[i].transport;
50773143b9aSmrg	    break;
50873143b9aSmrg	}
50973143b9aSmrg
51073143b9aSmrg    if (thistrans == NULL)
51173143b9aSmrg    {
512fe567363Smrg	prmsg (1,"Reopen: Unable to find transport id %d\n",
513fe567363Smrg	       trans_id);
51473143b9aSmrg
51573143b9aSmrg	return NULL;
51673143b9aSmrg    }
51773143b9aSmrg
518fe567363Smrg    if ((save_port = strdup (port)) == NULL)
51973143b9aSmrg    {
520fe567363Smrg	prmsg (1,"Reopen: Unable to malloc port string\n");
52173143b9aSmrg
52273143b9aSmrg	return NULL;
52373143b9aSmrg    }
52473143b9aSmrg
52573143b9aSmrg    /* Get a new XtransConnInfo object */
52673143b9aSmrg
52773143b9aSmrg    switch (type)
52873143b9aSmrg    {
52973143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
53073143b9aSmrg	ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
53173143b9aSmrg	break;
53273143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
53373143b9aSmrg	ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
53473143b9aSmrg	break;
53573143b9aSmrg    default:
536fe567363Smrg	prmsg (1,"Reopen: Bad Open type %d\n", type);
53773143b9aSmrg    }
53873143b9aSmrg
53973143b9aSmrg    if (ciptr == NULL)
54073143b9aSmrg    {
541fe567363Smrg	prmsg (1,"Reopen: transport open failed\n");
542fe567363Smrg	free (save_port);
54373143b9aSmrg	return NULL;
54473143b9aSmrg    }
54573143b9aSmrg
54673143b9aSmrg    ciptr->transptr = thistrans;
54773143b9aSmrg    ciptr->port = save_port;
54873143b9aSmrg
54973143b9aSmrg    return ciptr;
55073143b9aSmrg}
55173143b9aSmrg
55273143b9aSmrg#endif /* TRANS_REOPEN */
55373143b9aSmrg
55473143b9aSmrg
55573143b9aSmrg
55673143b9aSmrg/*
55773143b9aSmrg * These are the public interfaces to this Transport interface.
55873143b9aSmrg * These are the only functions that should have knowledge of the transport
55973143b9aSmrg * table.
56073143b9aSmrg */
56173143b9aSmrg
56273143b9aSmrg#ifdef TRANS_CLIENT
56373143b9aSmrg
56473143b9aSmrgXtransConnInfo
56573143b9aSmrgTRANS(OpenCOTSClient) (char *address)
56673143b9aSmrg
56773143b9aSmrg{
568fe567363Smrg    prmsg (2,"OpenCOTSClient(%s)\n", address);
56973143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
57073143b9aSmrg}
57173143b9aSmrg
57273143b9aSmrg#endif /* TRANS_CLIENT */
57373143b9aSmrg
57473143b9aSmrg
57573143b9aSmrg#ifdef TRANS_SERVER
57673143b9aSmrg
57773143b9aSmrgXtransConnInfo
57873143b9aSmrgTRANS(OpenCOTSServer) (char *address)
57973143b9aSmrg
58073143b9aSmrg{
581fe567363Smrg    prmsg (2,"OpenCOTSServer(%s)\n", address);
58273143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
58373143b9aSmrg}
58473143b9aSmrg
58573143b9aSmrg#endif /* TRANS_SERVER */
58673143b9aSmrg
58773143b9aSmrg
58873143b9aSmrg#ifdef TRANS_CLIENT
58973143b9aSmrg
59073143b9aSmrgXtransConnInfo
59173143b9aSmrgTRANS(OpenCLTSClient) (char *address)
59273143b9aSmrg
59373143b9aSmrg{
594fe567363Smrg    prmsg (2,"OpenCLTSClient(%s)\n", address);
59573143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
59673143b9aSmrg}
59773143b9aSmrg
59873143b9aSmrg#endif /* TRANS_CLIENT */
59973143b9aSmrg
60073143b9aSmrg
60173143b9aSmrg#ifdef TRANS_SERVER
60273143b9aSmrg
60373143b9aSmrgXtransConnInfo
60473143b9aSmrgTRANS(OpenCLTSServer) (char *address)
60573143b9aSmrg
60673143b9aSmrg{
607fe567363Smrg    prmsg (2,"OpenCLTSServer(%s)\n", address);
60873143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
60973143b9aSmrg}
61073143b9aSmrg
61173143b9aSmrg#endif /* TRANS_SERVER */
61273143b9aSmrg
61373143b9aSmrg
61473143b9aSmrg#ifdef TRANS_REOPEN
61573143b9aSmrg
61673143b9aSmrgXtransConnInfo
61773143b9aSmrgTRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
61873143b9aSmrg
61973143b9aSmrg{
620fe567363Smrg    prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
62173143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
62273143b9aSmrg}
62373143b9aSmrg
62473143b9aSmrgXtransConnInfo
62573143b9aSmrgTRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
62673143b9aSmrg
62773143b9aSmrg{
628fe567363Smrg    prmsg (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
62973143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
63073143b9aSmrg}
63173143b9aSmrg
63273143b9aSmrg
63373143b9aSmrgint
634fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr,
63573143b9aSmrg		      int *trans_id, int *fd, char **port)
63673143b9aSmrg
63773143b9aSmrg{
63873143b9aSmrg    int i;
63973143b9aSmrg
64073143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
64173143b9aSmrg	if (Xtransports[i].transport == ciptr->transptr)
64273143b9aSmrg	{
64373143b9aSmrg	    *trans_id = Xtransports[i].transport_id;
64473143b9aSmrg	    *fd = ciptr->fd;
64573143b9aSmrg
646fe567363Smrg	    if ((*port = strdup (ciptr->port)) == NULL)
64773143b9aSmrg		return 0;
64873143b9aSmrg	    else
64973143b9aSmrg		return 1;
65073143b9aSmrg	}
65173143b9aSmrg
65273143b9aSmrg    return 0;
65373143b9aSmrg}
65473143b9aSmrg
65573143b9aSmrg#endif /* TRANS_REOPEN */
65673143b9aSmrg
65773143b9aSmrg
65873143b9aSmrgint
65973143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
66073143b9aSmrg
66173143b9aSmrg{
66273143b9aSmrg    int	fd = ciptr->fd;
66373143b9aSmrg    int	ret = 0;
66473143b9aSmrg
665fe567363Smrg    prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
66673143b9aSmrg
66773143b9aSmrg    /*
66873143b9aSmrg     * For now, all transport type use the same stuff for setting options.
66973143b9aSmrg     * As long as this is true, we can put the common code here. Once a more
67073143b9aSmrg     * complicated transport such as shared memory or an OSI implementation
67173143b9aSmrg     * that uses the session and application libraries is implemented, this
67273143b9aSmrg     * code may have to move to a transport dependent function.
67373143b9aSmrg     *
67473143b9aSmrg     * ret = ciptr->transptr->SetOption (ciptr, option, arg);
67573143b9aSmrg     */
67673143b9aSmrg
67773143b9aSmrg    switch (option)
67873143b9aSmrg    {
67973143b9aSmrg    case TRANS_NONBLOCKING:
68073143b9aSmrg	switch (arg)
68173143b9aSmrg	{
68273143b9aSmrg	case 0:
68373143b9aSmrg	    /* Set to blocking mode */
68473143b9aSmrg	    break;
68573143b9aSmrg	case 1: /* Set to non-blocking mode */
68673143b9aSmrg
687fe567363Smrg#if defined(O_NONBLOCK) && !defined(SCO325)
68873143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
68973143b9aSmrg	    if (ret != -1)
69073143b9aSmrg		ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
69173143b9aSmrg#else
69273143b9aSmrg#ifdef FIOSNBIO
69373143b9aSmrg	{
69473143b9aSmrg	    int arg;
69573143b9aSmrg	    arg = 1;
69673143b9aSmrg	    ret = ioctl (fd, FIOSNBIO, &arg);
69773143b9aSmrg	}
69873143b9aSmrg#else
699fe567363Smrg#if defined(WIN32)
70073143b9aSmrg	{
70173143b9aSmrg#ifdef WIN32
70273143b9aSmrg	    u_long arg;
70373143b9aSmrg#else
70473143b9aSmrg	    int arg;
70573143b9aSmrg#endif
70673143b9aSmrg	    arg = 1;
70773143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
70873143b9aSmrg * eventually with EWOULDBLOCK */
70973143b9aSmrg	    ret = ioctl (fd, FIONBIO, &arg);
71073143b9aSmrg	}
71173143b9aSmrg#else
71273143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
71373143b9aSmrg#ifdef FNDELAY
71473143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | FNDELAY);
71573143b9aSmrg#else
71673143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
71773143b9aSmrg#endif
71873143b9aSmrg#endif /* AIXV3  || uniosu */
71973143b9aSmrg#endif /* FIOSNBIO */
72073143b9aSmrg#endif /* O_NONBLOCK */
72173143b9aSmrg	    break;
72273143b9aSmrg	default:
72373143b9aSmrg	    /* Unknown option */
72473143b9aSmrg	    break;
72573143b9aSmrg	}
72673143b9aSmrg	break;
72773143b9aSmrg    case TRANS_CLOSEONEXEC:
72873143b9aSmrg#ifdef F_SETFD
72973143b9aSmrg#ifdef FD_CLOEXEC
73073143b9aSmrg	ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
73173143b9aSmrg#else
73273143b9aSmrg	ret = fcntl (fd, F_SETFD, 1);
73373143b9aSmrg#endif /* FD_CLOEXEC */
73473143b9aSmrg#endif /* F_SETFD */
73573143b9aSmrg	break;
73673143b9aSmrg    }
737fe567363Smrg
73873143b9aSmrg    return ret;
73973143b9aSmrg}
74073143b9aSmrg
74173143b9aSmrg#ifdef TRANS_SERVER
74273143b9aSmrg
74373143b9aSmrgint
74473143b9aSmrgTRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
74573143b9aSmrg
74673143b9aSmrg{
74773143b9aSmrg    return ciptr->transptr->CreateListener (ciptr, port, flags);
74873143b9aSmrg}
74973143b9aSmrg
75075ebec6dSmrgint
75175ebec6dSmrgTRANS(Received) (const char * protocol)
75275ebec6dSmrg
75375ebec6dSmrg{
75475ebec6dSmrg   Xtransport *trans;
75575ebec6dSmrg   int i = 0, ret = 0;
75675ebec6dSmrg
75775ebec6dSmrg   prmsg (5, "Received(%s)\n", protocol);
75875ebec6dSmrg
75975ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
76075ebec6dSmrg   {
76175ebec6dSmrg	prmsg (1,"Received: unable to find transport: %s\n",
76275ebec6dSmrg	       protocol);
76375ebec6dSmrg
76475ebec6dSmrg	return -1;
76575ebec6dSmrg   }
76675ebec6dSmrg   if (trans->flags & TRANS_ALIAS) {
76775ebec6dSmrg       if (trans->nolisten)
76875ebec6dSmrg	   while (trans->nolisten[i]) {
76975ebec6dSmrg	       ret |= TRANS(Received)(trans->nolisten[i]);
77075ebec6dSmrg	       i++;
77175ebec6dSmrg       }
77275ebec6dSmrg   }
77375ebec6dSmrg
77475ebec6dSmrg   trans->flags |= TRANS_RECEIVED;
77575ebec6dSmrg   return ret;
77675ebec6dSmrg}
77775ebec6dSmrg
77873143b9aSmrgint
779fe567363SmrgTRANS(NoListen) (const char * protocol)
780fe567363Smrg
78173143b9aSmrg{
78273143b9aSmrg   Xtransport *trans;
78373143b9aSmrg   int i = 0, ret = 0;
784fe567363Smrg
785fe567363Smrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
78673143b9aSmrg   {
787fe567363Smrg	prmsg (1,"TransNoListen: unable to find transport: %s\n",
788fe567363Smrg	       protocol);
78973143b9aSmrg
79073143b9aSmrg	return -1;
79173143b9aSmrg   }
79273143b9aSmrg   if (trans->flags & TRANS_ALIAS) {
79373143b9aSmrg       if (trans->nolisten)
79473143b9aSmrg	   while (trans->nolisten[i]) {
79573143b9aSmrg	       ret |= TRANS(NoListen)(trans->nolisten[i]);
79673143b9aSmrg	       i++;
79773143b9aSmrg       }
79873143b9aSmrg   }
79973143b9aSmrg
80073143b9aSmrg   trans->flags |= TRANS_NOLISTEN;
80173143b9aSmrg   return ret;
80273143b9aSmrg}
80373143b9aSmrg
80475ebec6dSmrgint
80575ebec6dSmrgTRANS(IsListening) (const char * protocol)
80675ebec6dSmrg{
80775ebec6dSmrg   Xtransport *trans;
80875ebec6dSmrg
80975ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
81075ebec6dSmrg   {
81175ebec6dSmrg	prmsg (1,"TransIsListening: unable to find transport: %s\n",
81275ebec6dSmrg	       protocol);
81375ebec6dSmrg
81475ebec6dSmrg	return 0;
81575ebec6dSmrg   }
81675ebec6dSmrg
81775ebec6dSmrg   return !(trans->flags & TRANS_NOLISTEN);
81875ebec6dSmrg}
81975ebec6dSmrg
82073143b9aSmrgint
82173143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr)
82273143b9aSmrg
82373143b9aSmrg{
82473143b9aSmrg    if (ciptr->transptr->ResetListener)
82573143b9aSmrg	return ciptr->transptr->ResetListener (ciptr);
82673143b9aSmrg    else
82773143b9aSmrg	return TRANS_RESET_NOOP;
82873143b9aSmrg}
82973143b9aSmrg
83073143b9aSmrg
83173143b9aSmrgXtransConnInfo
83273143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status)
83373143b9aSmrg
83473143b9aSmrg{
83573143b9aSmrg    XtransConnInfo	newciptr;
83673143b9aSmrg
837fe567363Smrg    prmsg (2,"Accept(%d)\n", ciptr->fd);
83873143b9aSmrg
83973143b9aSmrg    newciptr = ciptr->transptr->Accept (ciptr, status);
84073143b9aSmrg
84173143b9aSmrg    if (newciptr)
84273143b9aSmrg	newciptr->transptr = ciptr->transptr;
84373143b9aSmrg
84473143b9aSmrg    return newciptr;
84573143b9aSmrg}
84673143b9aSmrg
84773143b9aSmrg#endif /* TRANS_SERVER */
84873143b9aSmrg
84973143b9aSmrg
85073143b9aSmrg#ifdef TRANS_CLIENT
85173143b9aSmrg
85273143b9aSmrgint
85373143b9aSmrgTRANS(Connect) (XtransConnInfo ciptr, char *address)
85473143b9aSmrg
85573143b9aSmrg{
85673143b9aSmrg    char	*protocol;
85773143b9aSmrg    char	*host;
85873143b9aSmrg    char	*port;
85973143b9aSmrg    int		ret;
86073143b9aSmrg
861fe567363Smrg    prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address);
86273143b9aSmrg
86373143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
86473143b9aSmrg    {
865fe567363Smrg	prmsg (1,"Connect: Unable to Parse address %s\n",
866fe567363Smrg	       address);
86773143b9aSmrg	return -1;
86873143b9aSmrg    }
86973143b9aSmrg
87073143b9aSmrg#ifdef HAVE_LAUNCHD
8718d4c0f7bSmrg    if (!host) host=strdup("");
87273143b9aSmrg#endif
87373143b9aSmrg
87473143b9aSmrg    if (!port || !*port)
87573143b9aSmrg    {
876fe567363Smrg	prmsg (1,"Connect: Missing port specification in %s\n",
877fe567363Smrg	      address);
878fe567363Smrg	if (protocol) free (protocol);
879fe567363Smrg	if (host) free (host);
88073143b9aSmrg	return -1;
88173143b9aSmrg    }
88273143b9aSmrg
88373143b9aSmrg    ret = ciptr->transptr->Connect (ciptr, host, port);
88473143b9aSmrg
885fe567363Smrg    if (protocol) free (protocol);
886fe567363Smrg    if (host) free (host);
887fe567363Smrg    if (port) free (port);
888fe567363Smrg
88973143b9aSmrg    return ret;
89073143b9aSmrg}
89173143b9aSmrg
89273143b9aSmrg#endif /* TRANS_CLIENT */
89373143b9aSmrg
89473143b9aSmrg
89573143b9aSmrgint
89673143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
89773143b9aSmrg
89873143b9aSmrg{
89973143b9aSmrg    return ciptr->transptr->BytesReadable (ciptr, pend);
90073143b9aSmrg}
90173143b9aSmrg
90273143b9aSmrgint
90373143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
90473143b9aSmrg
90573143b9aSmrg{
90673143b9aSmrg    return ciptr->transptr->Read (ciptr, buf, size);
90773143b9aSmrg}
90873143b9aSmrg
90973143b9aSmrgint
91073143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
91173143b9aSmrg
91273143b9aSmrg{
91373143b9aSmrg    return ciptr->transptr->Write (ciptr, buf, size);
91473143b9aSmrg}
91573143b9aSmrg
91673143b9aSmrgint
91773143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
91873143b9aSmrg
91973143b9aSmrg{
92073143b9aSmrg    return ciptr->transptr->Readv (ciptr, buf, size);
92173143b9aSmrg}
92273143b9aSmrg
92373143b9aSmrgint
92473143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
92573143b9aSmrg
92673143b9aSmrg{
92773143b9aSmrg    return ciptr->transptr->Writev (ciptr, buf, size);
92873143b9aSmrg}
92973143b9aSmrg
93075ebec6dSmrg#if XTRANS_SEND_FDS
93175ebec6dSmrgint
93275ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
93375ebec6dSmrg{
93475ebec6dSmrg    return ciptr->transptr->SendFd(ciptr, fd, do_close);
93575ebec6dSmrg}
93675ebec6dSmrg
93775ebec6dSmrgint
93875ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr)
93975ebec6dSmrg{
94075ebec6dSmrg    return ciptr->transptr->RecvFd(ciptr);
94175ebec6dSmrg}
94275ebec6dSmrg#endif
94375ebec6dSmrg
94473143b9aSmrgint
94573143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr)
94673143b9aSmrg
94773143b9aSmrg{
94873143b9aSmrg    return ciptr->transptr->Disconnect (ciptr);
94973143b9aSmrg}
95073143b9aSmrg
95173143b9aSmrgint
95273143b9aSmrgTRANS(Close) (XtransConnInfo ciptr)
95373143b9aSmrg
95473143b9aSmrg{
95573143b9aSmrg    int ret;
95673143b9aSmrg
957fe567363Smrg    prmsg (2,"Close(%d)\n", ciptr->fd);
95873143b9aSmrg
95973143b9aSmrg    ret = ciptr->transptr->Close (ciptr);
96073143b9aSmrg
96173143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
96273143b9aSmrg
96373143b9aSmrg    return ret;
96473143b9aSmrg}
96573143b9aSmrg
96673143b9aSmrgint
96773143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr)
96873143b9aSmrg
96973143b9aSmrg{
97073143b9aSmrg    int ret;
97173143b9aSmrg
972fe567363Smrg    prmsg (2,"CloseForCloning(%d)\n", ciptr->fd);
97373143b9aSmrg
97473143b9aSmrg    ret = ciptr->transptr->CloseForCloning (ciptr);
97573143b9aSmrg
97673143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
97773143b9aSmrg
97873143b9aSmrg    return ret;
97973143b9aSmrg}
98073143b9aSmrg
98173143b9aSmrgint
98273143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr)
98373143b9aSmrg
98473143b9aSmrg{
98573143b9aSmrg    return (ciptr->family == AF_UNIX);
98673143b9aSmrg}
98773143b9aSmrg
98873143b9aSmrg
98973143b9aSmrgint
990fe567363SmrgTRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
99173143b9aSmrg		  Xtransaddr **addrp)
99273143b9aSmrg
99373143b9aSmrg{
994fe567363Smrg    prmsg (2,"GetMyAddr(%d)\n", ciptr->fd);
99573143b9aSmrg
99673143b9aSmrg    *familyp = ciptr->family;
99773143b9aSmrg    *addrlenp = ciptr->addrlen;
99873143b9aSmrg
999fe567363Smrg    if ((*addrp = malloc (ciptr->addrlen)) == NULL)
100073143b9aSmrg    {
1001fe567363Smrg	prmsg (1,"GetMyAddr: malloc failed\n");
100273143b9aSmrg	return -1;
100373143b9aSmrg    }
100473143b9aSmrg    memcpy(*addrp, ciptr->addr, ciptr->addrlen);
100573143b9aSmrg
100673143b9aSmrg    return 0;
100773143b9aSmrg}
100873143b9aSmrg
100973143b9aSmrgint
1010fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
101173143b9aSmrg		    Xtransaddr **addrp)
101273143b9aSmrg
101373143b9aSmrg{
1014fe567363Smrg    prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd);
101573143b9aSmrg
101673143b9aSmrg    *familyp = ciptr->family;
101773143b9aSmrg    *addrlenp = ciptr->peeraddrlen;
101873143b9aSmrg
1019fe567363Smrg    if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL)
102073143b9aSmrg    {
1021fe567363Smrg	prmsg (1,"GetPeerAddr: malloc failed\n");
102273143b9aSmrg	return -1;
102373143b9aSmrg    }
102473143b9aSmrg    memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
102573143b9aSmrg
102673143b9aSmrg    return 0;
102773143b9aSmrg}
102873143b9aSmrg
102973143b9aSmrg
103073143b9aSmrgint
103173143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr)
103273143b9aSmrg
103373143b9aSmrg{
103473143b9aSmrg    return ciptr->fd;
103573143b9aSmrg}
103673143b9aSmrg
103773143b9aSmrg
103873143b9aSmrg/*
103973143b9aSmrg * These functions are really utility functions, but they require knowledge
104073143b9aSmrg * of the internal data structures, so they have to be part of the Transport
104173143b9aSmrg * Independant API.
104273143b9aSmrg */
104373143b9aSmrg
104473143b9aSmrg#ifdef TRANS_SERVER
104573143b9aSmrg
104673143b9aSmrgstatic int
104773143b9aSmrgcomplete_network_count (void)
104873143b9aSmrg
104973143b9aSmrg{
105073143b9aSmrg    int count = 0;
105173143b9aSmrg    int found_local = 0;
105273143b9aSmrg    int i;
105373143b9aSmrg
105473143b9aSmrg    /*
105573143b9aSmrg     * For a complete network, we only need one LOCALCONN transport to work
105673143b9aSmrg     */
105773143b9aSmrg
105873143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
105973143b9aSmrg    {
106073143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_ALIAS
106173143b9aSmrg   	 || Xtransports[i].transport->flags & TRANS_NOLISTEN)
106273143b9aSmrg	    continue;
106373143b9aSmrg
106473143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_LOCAL)
106573143b9aSmrg	    found_local = 1;
106673143b9aSmrg	else
106773143b9aSmrg	    count++;
106873143b9aSmrg    }
106973143b9aSmrg
107073143b9aSmrg    return (count + found_local);
107173143b9aSmrg}
107273143b9aSmrg
107373143b9aSmrg
107475ebec6dSmrgstatic int
107575ebec6dSmrgreceive_listening_fds(char* port, XtransConnInfo* temp_ciptrs, int* count_ret)
107675ebec6dSmrg
107775ebec6dSmrg{
107875ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON
107975ebec6dSmrg    XtransConnInfo ciptr;
108075ebec6dSmrg    int i, systemd_listen_fds;
108175ebec6dSmrg
108275ebec6dSmrg    systemd_listen_fds = sd_listen_fds(1);
108375ebec6dSmrg    if (systemd_listen_fds < 0)
108475ebec6dSmrg    {
108575ebec6dSmrg        prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n",
108675ebec6dSmrg               strerror(-systemd_listen_fds));
108775ebec6dSmrg        return -1;
108875ebec6dSmrg    }
108975ebec6dSmrg
109075ebec6dSmrg    for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++)
109175ebec6dSmrg    {
109275ebec6dSmrg        struct sockaddr_storage a;
109375ebec6dSmrg        int ti;
109475ebec6dSmrg        const char* tn;
109575ebec6dSmrg        socklen_t al;
109675ebec6dSmrg
109775ebec6dSmrg        al = sizeof(a);
109875ebec6dSmrg        if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) {
109975ebec6dSmrg            prmsg (1, "receive_listening_fds: getsockname error: %s\n",
110075ebec6dSmrg                   strerror(errno));
110175ebec6dSmrg            return -1;
110275ebec6dSmrg        }
110375ebec6dSmrg
110475ebec6dSmrg        switch (a.ss_family)
110575ebec6dSmrg        {
110675ebec6dSmrg        case AF_UNIX:
110775ebec6dSmrg            ti = TRANS_SOCKET_UNIX_INDEX;
110875ebec6dSmrg            if (*((struct sockaddr_un*)&a)->sun_path == '\0' &&
110975ebec6dSmrg                al > sizeof(sa_family_t))
111075ebec6dSmrg                tn = "local";
111175ebec6dSmrg            else
111275ebec6dSmrg                tn = "unix";
111375ebec6dSmrg            break;
111475ebec6dSmrg        case AF_INET:
111575ebec6dSmrg            ti = TRANS_SOCKET_INET_INDEX;
111675ebec6dSmrg            tn = "inet";
111775ebec6dSmrg            break;
111875ebec6dSmrg#if defined(IPv6) && defined(AF_INET6)
111975ebec6dSmrg        case AF_INET6:
112075ebec6dSmrg            ti = TRANS_SOCKET_INET6_INDEX;
112175ebec6dSmrg            tn = "inet6";
112275ebec6dSmrg            break;
112375ebec6dSmrg#endif /* IPv6 */
112475ebec6dSmrg        default:
112575ebec6dSmrg            prmsg (1, "receive_listening_fds:"
112675ebec6dSmrg                   "Got unknown socket address family\n");
112775ebec6dSmrg            return -1;
112875ebec6dSmrg        }
112975ebec6dSmrg
113075ebec6dSmrg        ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port);
113175ebec6dSmrg        if (!ciptr)
113275ebec6dSmrg        {
113375ebec6dSmrg            prmsg (1, "receive_listening_fds:"
113475ebec6dSmrg                   "Got NULL while trying to reopen socket received from systemd.\n");
113575ebec6dSmrg            return -1;
113675ebec6dSmrg        }
113775ebec6dSmrg
113875ebec6dSmrg        prmsg (5, "receive_listening_fds: received listener for %s, %d\n",
113975ebec6dSmrg               tn, ciptr->fd);
114075ebec6dSmrg        temp_ciptrs[(*count_ret)++] = ciptr;
114175ebec6dSmrg        TRANS(Received)(tn);
114275ebec6dSmrg    }
114375ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */
114475ebec6dSmrg    return 0;
114575ebec6dSmrg}
114675ebec6dSmrg
11478d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11488d4c0f7bSmrgextern int xquartz_launchd_fd;
11498d4c0f7bSmrg#endif
115073143b9aSmrg
115173143b9aSmrgint
1152fe567363SmrgTRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
115373143b9aSmrg				   XtransConnInfo **ciptrs_ret)
115473143b9aSmrg
115573143b9aSmrg{
115673143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
115773143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
115873143b9aSmrg    int			status, i, j;
115973143b9aSmrg
116073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
116173143b9aSmrg    int		ipv6_succ = 0;
116273143b9aSmrg#endif
1163fe567363Smrg    prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n",
1164fe567363Smrg	   port ? port : "NULL", ciptrs_ret);
116573143b9aSmrg
116673143b9aSmrg    *count_ret = 0;
116773143b9aSmrg
11688d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11698d4c0f7bSmrg    fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
11708d4c0f7bSmrg    if(xquartz_launchd_fd != -1) {
11718d4c0f7bSmrg        if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
11728d4c0f7bSmrg                                           xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
11738d4c0f7bSmrg            fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
1174fe567363Smrg        else
11758d4c0f7bSmrg            temp_ciptrs[(*count_ret)++] = ciptr;
11768d4c0f7bSmrg    }
117773143b9aSmrg#endif
117873143b9aSmrg
117975ebec6dSmrg    if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0)
118075ebec6dSmrg	return -1;
118175ebec6dSmrg
118273143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
118373143b9aSmrg    {
118473143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
118573143b9aSmrg	unsigned int flags = 0;
118673143b9aSmrg
118775ebec6dSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN ||
118875ebec6dSmrg	    trans->flags&TRANS_RECEIVED)
118973143b9aSmrg	    continue;
119073143b9aSmrg
119173143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
119273143b9aSmrg		 trans->TransName, port ? port : "");
119373143b9aSmrg
1194fe567363Smrg	prmsg (5,"MakeAllCOTSServerListeners: opening %s\n",
1195fe567363Smrg	       buffer);
119673143b9aSmrg
119773143b9aSmrg	if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
119873143b9aSmrg	{
119973143b9aSmrg	    if (trans->flags & TRANS_DISABLED)
120073143b9aSmrg		continue;
120173143b9aSmrg
1202fe567363Smrg	    prmsg (1,
120373143b9aSmrg	  "MakeAllCOTSServerListeners: failed to open listener for %s\n",
1204fe567363Smrg		  trans->TransName);
120573143b9aSmrg	    continue;
120673143b9aSmrg	}
120773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
120873143b9aSmrg		if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
120973143b9aSmrg		     && ipv6_succ))
121073143b9aSmrg		    flags |= ADDR_IN_USE_ALLOWED;
121173143b9aSmrg#endif
121273143b9aSmrg
121373143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
121473143b9aSmrg	{
121573143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
121673143b9aSmrg	    {
121773143b9aSmrg		/*
121873143b9aSmrg		 * We failed to bind to the specified address because the
121973143b9aSmrg		 * address is in use.  It must be that a server is already
122073143b9aSmrg		 * running at this address, and this function should fail.
122173143b9aSmrg		 */
122273143b9aSmrg
1223fe567363Smrg		prmsg (1,
1224fe567363Smrg		"MakeAllCOTSServerListeners: server already running\n");
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	    {
1236fe567363Smrg		prmsg (1,
123773143b9aSmrg	"MakeAllCOTSServerListeners: failed to create listener for %s\n",
1238fe567363Smrg		  trans->TransName);
123973143b9aSmrg
124073143b9aSmrg		continue;
124173143b9aSmrg	    }
124273143b9aSmrg	}
124373143b9aSmrg
124473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
124573143b9aSmrg	if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
124673143b9aSmrg	    ipv6_succ = 1;
124773143b9aSmrg#endif
1248fe567363Smrg
1249fe567363Smrg	prmsg (5,
125073143b9aSmrg	      "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
1251fe567363Smrg	      trans->TransName, ciptr->fd);
125273143b9aSmrg
125373143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
125473143b9aSmrg	(*count_ret)++;
125573143b9aSmrg    }
125673143b9aSmrg
125773143b9aSmrg    *partial = (*count_ret < complete_network_count());
125873143b9aSmrg
1259fe567363Smrg    prmsg (5,
126073143b9aSmrg     "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
126173143b9aSmrg	*partial, *count_ret, complete_network_count());
126273143b9aSmrg
126373143b9aSmrg    if (*count_ret > 0)
126473143b9aSmrg    {
1265fe567363Smrg	if ((*ciptrs_ret = malloc (
126673143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
126773143b9aSmrg	{
126873143b9aSmrg	    return -1;
126973143b9aSmrg	}
127073143b9aSmrg
127173143b9aSmrg	for (i = 0; i < *count_ret; i++)
127273143b9aSmrg	{
127373143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
127473143b9aSmrg	}
127573143b9aSmrg    }
127673143b9aSmrg    else
127773143b9aSmrg	*ciptrs_ret = NULL;
1278fe567363Smrg
127973143b9aSmrg    return 0;
128073143b9aSmrg}
128173143b9aSmrg
128273143b9aSmrgint
1283fe567363SmrgTRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
128473143b9aSmrg				   XtransConnInfo **ciptrs_ret)
128573143b9aSmrg
128673143b9aSmrg{
128773143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
128873143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
128973143b9aSmrg    int			status, i, j;
129073143b9aSmrg
1291fe567363Smrg    prmsg (2,"MakeAllCLTSServerListeners(%s,%p)\n",
1292fe567363Smrg	port ? port : "NULL", ciptrs_ret);
129373143b9aSmrg
129473143b9aSmrg    *count_ret = 0;
129573143b9aSmrg
129673143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
129773143b9aSmrg    {
129873143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
129973143b9aSmrg
130073143b9aSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
130173143b9aSmrg	    continue;
130273143b9aSmrg
130373143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
130473143b9aSmrg		 trans->TransName, port ? port : "");
130573143b9aSmrg
1306fe567363Smrg	prmsg (5,"MakeAllCLTSServerListeners: opening %s\n",
1307fe567363Smrg	    buffer);
130873143b9aSmrg
130973143b9aSmrg	if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
131073143b9aSmrg	{
1311fe567363Smrg	    prmsg (1,
131273143b9aSmrg	"MakeAllCLTSServerListeners: failed to open listener for %s\n",
1313fe567363Smrg		  trans->TransName);
131473143b9aSmrg	    continue;
131573143b9aSmrg	}
131673143b9aSmrg
131773143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
131873143b9aSmrg	{
131973143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
132073143b9aSmrg	    {
132173143b9aSmrg		/*
132273143b9aSmrg		 * We failed to bind to the specified address because the
132373143b9aSmrg		 * address is in use.  It must be that a server is already
132473143b9aSmrg		 * running at this address, and this function should fail.
132573143b9aSmrg		 */
132673143b9aSmrg
1327fe567363Smrg		prmsg (1,
1328fe567363Smrg		"MakeAllCLTSServerListeners: server already running\n");
132973143b9aSmrg
133073143b9aSmrg		for (j = 0; j < *count_ret; j++)
133173143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
133273143b9aSmrg
133373143b9aSmrg		*count_ret = 0;
133473143b9aSmrg		*ciptrs_ret = NULL;
133573143b9aSmrg		*partial = 0;
133673143b9aSmrg		return -1;
133773143b9aSmrg	    }
133873143b9aSmrg	    else
133973143b9aSmrg	    {
1340fe567363Smrg		prmsg (1,
134173143b9aSmrg	"MakeAllCLTSServerListeners: failed to create listener for %s\n",
1342fe567363Smrg		  trans->TransName);
134373143b9aSmrg
134473143b9aSmrg		continue;
134573143b9aSmrg	    }
134673143b9aSmrg	}
134773143b9aSmrg
1348fe567363Smrg	prmsg (5,
134973143b9aSmrg	"MakeAllCLTSServerListeners: opened listener for %s, %d\n",
1350fe567363Smrg	      trans->TransName, ciptr->fd);
135173143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
135273143b9aSmrg	(*count_ret)++;
135373143b9aSmrg    }
135473143b9aSmrg
135573143b9aSmrg    *partial = (*count_ret < complete_network_count());
135673143b9aSmrg
1357fe567363Smrg    prmsg (5,
135873143b9aSmrg     "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
135973143b9aSmrg	*partial, *count_ret, complete_network_count());
136073143b9aSmrg
136173143b9aSmrg    if (*count_ret > 0)
136273143b9aSmrg    {
1363fe567363Smrg	if ((*ciptrs_ret = malloc (
136473143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
136573143b9aSmrg	{
136673143b9aSmrg	    return -1;
136773143b9aSmrg	}
136873143b9aSmrg
136973143b9aSmrg	for (i = 0; i < *count_ret; i++)
137073143b9aSmrg	{
137173143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
137273143b9aSmrg	}
137373143b9aSmrg    }
137473143b9aSmrg    else
137573143b9aSmrg	*ciptrs_ret = NULL;
1376fe567363Smrg
137773143b9aSmrg    return 0;
137873143b9aSmrg}
137973143b9aSmrg
138073143b9aSmrg#endif /* TRANS_SERVER */
138173143b9aSmrg
138273143b9aSmrg
138373143b9aSmrg
138473143b9aSmrg/*
138573143b9aSmrg * These routines are not part of the X Transport Interface, but they
138673143b9aSmrg * may be used by it.
138773143b9aSmrg */
138873143b9aSmrg
138973143b9aSmrg
1390fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
139173143b9aSmrg
139273143b9aSmrg/*
139373143b9aSmrg * emulate readv
139473143b9aSmrg */
139573143b9aSmrg
139673143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
139773143b9aSmrg
139873143b9aSmrg{
139973143b9aSmrg    int i, len, total;
140073143b9aSmrg    char *base;
140173143b9aSmrg
140273143b9aSmrg    ESET(0);
140373143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
140473143b9aSmrg	len = iov->iov_len;
140573143b9aSmrg	base = iov->iov_base;
140673143b9aSmrg	while (len > 0) {
140773143b9aSmrg	    register int nbytes;
140873143b9aSmrg	    nbytes = TRANS(Read) (ciptr, base, len);
140973143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
141073143b9aSmrg	    if (nbytes <= 0)  return total;
141173143b9aSmrg	    ESET(0);
141273143b9aSmrg	    len   -= nbytes;
141373143b9aSmrg	    total += nbytes;
141473143b9aSmrg	    base  += nbytes;
141573143b9aSmrg	}
141673143b9aSmrg    }
141773143b9aSmrg    return total;
141873143b9aSmrg}
141973143b9aSmrg
142073143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
142173143b9aSmrg
1422fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
142373143b9aSmrg
142473143b9aSmrg/*
142573143b9aSmrg * emulate writev
142673143b9aSmrg */
142773143b9aSmrg
142873143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
142973143b9aSmrg
143073143b9aSmrg{
143173143b9aSmrg    int i, len, total;
143273143b9aSmrg    char *base;
143373143b9aSmrg
143473143b9aSmrg    ESET(0);
143573143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
143673143b9aSmrg	len = iov->iov_len;
143773143b9aSmrg	base = iov->iov_base;
143873143b9aSmrg	while (len > 0) {
143973143b9aSmrg	    register int nbytes;
144073143b9aSmrg	    nbytes = TRANS(Write) (ciptr, base, len);
144173143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
144273143b9aSmrg	    if (nbytes <= 0)  return total;
144373143b9aSmrg	    ESET(0);
144473143b9aSmrg	    len   -= nbytes;
144573143b9aSmrg	    total += nbytes;
144673143b9aSmrg	    base  += nbytes;
144773143b9aSmrg	}
144873143b9aSmrg    }
144973143b9aSmrg    return total;
145073143b9aSmrg}
145173143b9aSmrg
145273143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
145373143b9aSmrg
145473143b9aSmrg
1455e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__)
145673143b9aSmrg#ifndef NEED_UTSNAME
145773143b9aSmrg#define NEED_UTSNAME
145873143b9aSmrg#endif
145973143b9aSmrg#include <sys/utsname.h>
146073143b9aSmrg#endif
146173143b9aSmrg
146273143b9aSmrg/*
146373143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing.
146473143b9aSmrg */
146573143b9aSmrg
146673143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen)
146773143b9aSmrg
146873143b9aSmrg{
146973143b9aSmrg    int len;
147073143b9aSmrg
147173143b9aSmrg#ifdef NEED_UTSNAME
147273143b9aSmrg    struct utsname name;
147373143b9aSmrg
147473143b9aSmrg    uname (&name);
147573143b9aSmrg    len = strlen (name.nodename);
147673143b9aSmrg    if (len >= maxlen) len = maxlen - 1;
147773143b9aSmrg    strncpy (buf, name.nodename, len);
147873143b9aSmrg    buf[len] = '\0';
147973143b9aSmrg#else
148073143b9aSmrg    buf[0] = '\0';
148173143b9aSmrg    (void) gethostname (buf, maxlen);
148273143b9aSmrg    buf [maxlen - 1] = '\0';
148373143b9aSmrg    len = strlen(buf);
148473143b9aSmrg#endif /* NEED_UTSNAME */
148573143b9aSmrg    return len;
148673143b9aSmrg}
1487