Xtrans.c revision 8a0d9095
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>
518a0d9095Smrg#include <stdlib.h>
5275ebec6dSmrg#include <string.h>
538a0d9095Smrg#ifdef HAVE_SYSTEMD_DAEMON
5475ebec6dSmrg#include <systemd/sd-daemon.h>
5575ebec6dSmrg#endif
5673143b9aSmrg
5773143b9aSmrg/*
5873143b9aSmrg * The transport table contains a definition for every transport (protocol)
5973143b9aSmrg * family. All operations that can be made on the transport go through this
6073143b9aSmrg * table.
6173143b9aSmrg *
6273143b9aSmrg * Each transport is assigned a unique transport id.
6373143b9aSmrg *
6473143b9aSmrg * New transports can be added by adding an entry in this table.
6573143b9aSmrg * For compatiblity, the transport ids should never be renumbered.
6673143b9aSmrg * Always add to the end of the list.
6773143b9aSmrg */
6873143b9aSmrg
6973143b9aSmrg#define TRANS_TLI_INET_INDEX		1
7073143b9aSmrg#define TRANS_TLI_TCP_INDEX		2
7173143b9aSmrg#define TRANS_TLI_TLI_INDEX		3
7273143b9aSmrg#define TRANS_SOCKET_UNIX_INDEX		4
7373143b9aSmrg#define TRANS_SOCKET_LOCAL_INDEX	5
7473143b9aSmrg#define TRANS_SOCKET_INET_INDEX		6
7573143b9aSmrg#define TRANS_SOCKET_TCP_INDEX		7
7673143b9aSmrg#define TRANS_DNET_INDEX		8
7773143b9aSmrg#define TRANS_LOCAL_LOCAL_INDEX		9
7873143b9aSmrg#define TRANS_LOCAL_PTS_INDEX		10
7973143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX		11
80af928962Smrg/* 12 used to be ISC, but that's gone. */
8173143b9aSmrg#define TRANS_LOCAL_SCO_INDEX		13
8273143b9aSmrg#define TRANS_SOCKET_INET6_INDEX	14
8373143b9aSmrg#define TRANS_LOCAL_PIPE_INDEX		15
8473143b9aSmrg
8573143b9aSmrg
8673143b9aSmrgstatic
8773143b9aSmrgXtransport_table Xtransports[] = {
8873143b9aSmrg#if defined(TCPCONN)
8973143b9aSmrg    { &TRANS(SocketTCPFuncs),	TRANS_SOCKET_TCP_INDEX },
9073143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
9173143b9aSmrg    { &TRANS(SocketINET6Funcs),	TRANS_SOCKET_INET6_INDEX },
9273143b9aSmrg#endif /* IPv6 */
9373143b9aSmrg    { &TRANS(SocketINETFuncs),	TRANS_SOCKET_INET_INDEX },
9473143b9aSmrg#endif /* TCPCONN */
9573143b9aSmrg#if defined(UNIXCONN)
9673143b9aSmrg#if !defined(LOCALCONN)
9773143b9aSmrg    { &TRANS(SocketLocalFuncs),	TRANS_SOCKET_LOCAL_INDEX },
9873143b9aSmrg#endif /* !LOCALCONN */
9973143b9aSmrg    { &TRANS(SocketUNIXFuncs),	TRANS_SOCKET_UNIX_INDEX },
10073143b9aSmrg#endif /* UNIXCONN */
10173143b9aSmrg#if defined(LOCALCONN)
10273143b9aSmrg    { &TRANS(LocalFuncs),	TRANS_LOCAL_LOCAL_INDEX },
10373143b9aSmrg#ifndef sun
10473143b9aSmrg    { &TRANS(PTSFuncs),		TRANS_LOCAL_PTS_INDEX },
10573143b9aSmrg#endif /* sun */
106e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
10773143b9aSmrg    { &TRANS(NAMEDFuncs),	TRANS_LOCAL_NAMED_INDEX },
10873143b9aSmrg#endif
10973143b9aSmrg#ifdef sun
11073143b9aSmrg    { &TRANS(PIPEFuncs),	TRANS_LOCAL_PIPE_INDEX },
11173143b9aSmrg#endif /* sun */
112af928962Smrg#if defined(__SCO__) || defined(__UNIXWARE__)
113af928962Smrg    { &TRANS(SCOFuncs),		TRANS_LOCAL_SCO_INDEX },
114af928962Smrg#endif /* __SCO__ || __UNIXWARE__ */
11573143b9aSmrg#endif /* LOCALCONN */
11673143b9aSmrg};
11773143b9aSmrg
11873143b9aSmrg#define NUMTRANS	(sizeof(Xtransports)/sizeof(Xtransport_table))
11973143b9aSmrg
12073143b9aSmrg
12173143b9aSmrg#ifdef WIN32
12273143b9aSmrg#define ioctl ioctlsocket
12373143b9aSmrg#endif
12473143b9aSmrg
12573143b9aSmrg
12673143b9aSmrg
12773143b9aSmrg/*
12873143b9aSmrg * These are a few utility function used by the public interface functions.
12973143b9aSmrg */
13073143b9aSmrg
13173143b9aSmrgvoid
13273143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr)
13373143b9aSmrg
13473143b9aSmrg{
135fe567363Smrg    prmsg (3,"FreeConnInfo(%p)\n", ciptr);
13673143b9aSmrg
13773143b9aSmrg    if (ciptr->addr)
138fe567363Smrg	free (ciptr->addr);
13973143b9aSmrg
14073143b9aSmrg    if (ciptr->peeraddr)
141fe567363Smrg	free (ciptr->peeraddr);
14273143b9aSmrg
14373143b9aSmrg    if (ciptr->port)
144fe567363Smrg	free (ciptr->port);
14573143b9aSmrg
146fe567363Smrg    free (ciptr);
14773143b9aSmrg}
14873143b9aSmrg
14973143b9aSmrg
15073143b9aSmrg#define PROTOBUFSIZE	20
15173143b9aSmrg
15273143b9aSmrgstatic Xtransport *
153fe567363SmrgTRANS(SelectTransport) (const char *protocol)
15473143b9aSmrg
15573143b9aSmrg{
15673143b9aSmrg    char 	protobuf[PROTOBUFSIZE];
15773143b9aSmrg    int		i;
15873143b9aSmrg
159fe567363Smrg    prmsg (3,"SelectTransport(%s)\n", protocol);
16073143b9aSmrg
16173143b9aSmrg    /*
16273143b9aSmrg     * Force Protocol to be lowercase as a way of doing
16373143b9aSmrg     * a case insensitive match.
16473143b9aSmrg     */
16573143b9aSmrg
16673143b9aSmrg    strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
16773143b9aSmrg    protobuf[PROTOBUFSIZE-1] = '\0';
16873143b9aSmrg
16973143b9aSmrg    for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
1708a0d9095Smrg	if (isupper ((unsigned char)protobuf[i]))
1718a0d9095Smrg	    protobuf[i] = tolower ((unsigned char)protobuf[i]);
17273143b9aSmrg
17373143b9aSmrg    /* Look at all of the configured protocols */
17473143b9aSmrg
17573143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
17673143b9aSmrg    {
17773143b9aSmrg	if (!strcmp (protobuf, Xtransports[i].transport->TransName))
17873143b9aSmrg	    return Xtransports[i].transport;
17973143b9aSmrg    }
18073143b9aSmrg
18173143b9aSmrg    return NULL;
18273143b9aSmrg}
18373143b9aSmrg
18473143b9aSmrg#ifndef TEST_t
18573143b9aSmrgstatic
18673143b9aSmrg#endif /* TEST_t */
18773143b9aSmrgint
18873143b9aSmrgTRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
18973143b9aSmrg
19073143b9aSmrg{
19173143b9aSmrg    /*
19273143b9aSmrg     * For the font library, the address is a string formatted
19373143b9aSmrg     * as "protocol/host:port[/catalogue]".  Note that the catologue
19473143b9aSmrg     * is optional.  At this time, the catologue info is ignored, but
19573143b9aSmrg     * we have to parse it anyways.
19673143b9aSmrg     *
19773143b9aSmrg     * Other than fontlib, the address is a string formatted
19873143b9aSmrg     * as "protocol/host:port".
19973143b9aSmrg     *
20073143b9aSmrg     * If the protocol part is missing, then assume TCP.
20173143b9aSmrg     * If the protocol part and host part are missing, then assume local.
20273143b9aSmrg     * If a "::" is found then assume DNET.
20373143b9aSmrg     */
20473143b9aSmrg
20573143b9aSmrg    char	*mybuf, *tmpptr;
206fe567363Smrg    const char	*_protocol;
207fe567363Smrg    char	*_host, *_port;
20873143b9aSmrg    char	hostnamebuf[256];
20973143b9aSmrg    int		_host_len;
21073143b9aSmrg
211fe567363Smrg    prmsg (3,"ParseAddress(%s)\n", address);
21273143b9aSmrg
21373143b9aSmrg    /* Copy the string so it can be changed */
21473143b9aSmrg
215fe567363Smrg    tmpptr = mybuf = strdup (address);
21673143b9aSmrg
21773143b9aSmrg    /* Parse the string to get each component */
218fe567363Smrg
21973143b9aSmrg    /* Get the protocol part */
22073143b9aSmrg
22173143b9aSmrg    _protocol = mybuf;
22273143b9aSmrg
22373143b9aSmrg
22473143b9aSmrg   if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
22573143b9aSmrg      ((mybuf = strrchr (tmpptr,':')) == NULL) )
22673143b9aSmrg   {
22773143b9aSmrg	/* address is in a bad format */
22873143b9aSmrg	*protocol = NULL;
22973143b9aSmrg	*host = NULL;
23073143b9aSmrg	*port = NULL;
231fe567363Smrg	free (tmpptr);
23273143b9aSmrg	return 0;
23373143b9aSmrg    }
23473143b9aSmrg
23573143b9aSmrg    if (*mybuf == ':')
23673143b9aSmrg    {
23773143b9aSmrg	/*
23873143b9aSmrg	 * If there is a hostname, then assume tcp, otherwise
23973143b9aSmrg	 * it must be local.
24073143b9aSmrg	 */
24173143b9aSmrg	if (mybuf == tmpptr)
24273143b9aSmrg	{
24373143b9aSmrg	    /* There is neither a protocol or host specified */
24473143b9aSmrg	    _protocol = "local";
24573143b9aSmrg	}
24673143b9aSmrg	else
24773143b9aSmrg	{
24873143b9aSmrg	    /* There is a hostname specified */
24973143b9aSmrg	    _protocol = "tcp";
25073143b9aSmrg	    mybuf = tmpptr;	/* reset to the begining of the host ptr */
25173143b9aSmrg	}
25273143b9aSmrg    }
25373143b9aSmrg    else
25473143b9aSmrg    {
25573143b9aSmrg	/* *mybuf == '/' */
25673143b9aSmrg
25773143b9aSmrg	*mybuf ++= '\0'; /* put a null at the end of the protocol */
25873143b9aSmrg
25973143b9aSmrg	if (strlen(_protocol) == 0)
26073143b9aSmrg	{
26173143b9aSmrg	    /*
26273143b9aSmrg	     * If there is a hostname, then assume tcp, otherwise
26373143b9aSmrg	     * it must be local.
26473143b9aSmrg	     */
26573143b9aSmrg	    if (*mybuf != ':')
26673143b9aSmrg		_protocol = "tcp";
26773143b9aSmrg	    else
26873143b9aSmrg		_protocol = "local";
26973143b9aSmrg	}
27073143b9aSmrg    }
27173143b9aSmrg
27273143b9aSmrg    /* Get the host part */
27373143b9aSmrg
27473143b9aSmrg    _host = mybuf;
27573143b9aSmrg
27673143b9aSmrg    if ((mybuf = strrchr (mybuf,':')) == NULL)
27773143b9aSmrg    {
27873143b9aSmrg	*protocol = NULL;
27973143b9aSmrg	*host = NULL;
28073143b9aSmrg	*port = NULL;
281fe567363Smrg	free (tmpptr);
28273143b9aSmrg	return 0;
28373143b9aSmrg    }
28473143b9aSmrg
28573143b9aSmrg    *mybuf ++= '\0';
28673143b9aSmrg
28773143b9aSmrg    _host_len = strlen(_host);
28873143b9aSmrg    if (_host_len == 0)
28973143b9aSmrg    {
29073143b9aSmrg	TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
29173143b9aSmrg	_host = hostnamebuf;
29273143b9aSmrg    }
29373143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
29473143b9aSmrg    /* hostname in IPv6 [numeric_addr]:0 form? */
295fe567363Smrg    else if ( (_host_len > 3) &&
29673143b9aSmrg      ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
297fe567363Smrg      && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
29873143b9aSmrg	struct sockaddr_in6 sin6;
29973143b9aSmrg
30073143b9aSmrg	*(_host + _host_len - 1) = '\0';
30173143b9aSmrg
30273143b9aSmrg	/* Verify address is valid IPv6 numeric form */
30373143b9aSmrg	if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
30473143b9aSmrg	    /* It is. Use it as such. */
30573143b9aSmrg	    _host++;
30673143b9aSmrg	    _protocol = "inet6";
30773143b9aSmrg	} else {
30873143b9aSmrg	    /* It's not, restore it just in case some other code can use it. */
30973143b9aSmrg	    *(_host + _host_len - 1) = ']';
31073143b9aSmrg	}
31173143b9aSmrg    }
31273143b9aSmrg#endif
31373143b9aSmrg
31473143b9aSmrg
31573143b9aSmrg    /* Get the port */
31673143b9aSmrg
31773143b9aSmrg    _port = mybuf;
31873143b9aSmrg
31973143b9aSmrg#if defined(FONT_t) || defined(FS_t)
32073143b9aSmrg    /*
32173143b9aSmrg     * Is there an optional catalogue list?
32273143b9aSmrg     */
32373143b9aSmrg
32473143b9aSmrg    if ((mybuf = strchr (mybuf,'/')) != NULL)
32573143b9aSmrg	*mybuf ++= '\0';
32673143b9aSmrg
32773143b9aSmrg    /*
32873143b9aSmrg     * The rest, if any, is the (currently unused) catalogue list.
32973143b9aSmrg     *
33073143b9aSmrg     * _catalogue = mybuf;
33173143b9aSmrg     */
33273143b9aSmrg#endif
33373143b9aSmrg
33473143b9aSmrg#ifdef HAVE_LAUNCHD
33573143b9aSmrg    /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
33673143b9aSmrg    if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
33773143b9aSmrg      _protocol="local";
33873143b9aSmrg      _host="";
33973143b9aSmrg      _port=address+6;
34073143b9aSmrg    }
34173143b9aSmrg#endif
34273143b9aSmrg
34373143b9aSmrg    /*
34473143b9aSmrg     * Now that we have all of the components, allocate new
34573143b9aSmrg     * string space for them.
34673143b9aSmrg     */
34773143b9aSmrg
348fe567363Smrg    if ((*protocol = strdup (_protocol)) == NULL)
34973143b9aSmrg    {
35073143b9aSmrg	/* Malloc failed */
35173143b9aSmrg	*port = NULL;
35273143b9aSmrg	*host = NULL;
35373143b9aSmrg	*protocol = NULL;
354fe567363Smrg	free (tmpptr);
35573143b9aSmrg	return 0;
35673143b9aSmrg    }
35773143b9aSmrg
358fe567363Smrg    if ((*host = strdup (_host)) == NULL)
35973143b9aSmrg    {
36073143b9aSmrg	/* Malloc failed */
36173143b9aSmrg	*port = NULL;
36273143b9aSmrg	*host = NULL;
363fe567363Smrg	free (*protocol);
36473143b9aSmrg	*protocol = NULL;
365fe567363Smrg	free (tmpptr);
36673143b9aSmrg	return 0;
367fe567363Smrg    }
36873143b9aSmrg
369fe567363Smrg    if ((*port = strdup (_port)) == NULL)
37073143b9aSmrg    {
37173143b9aSmrg	/* Malloc failed */
37273143b9aSmrg	*port = NULL;
373fe567363Smrg	free (*host);
37473143b9aSmrg	*host = NULL;
375fe567363Smrg	free (*protocol);
37673143b9aSmrg	*protocol = NULL;
377fe567363Smrg	free (tmpptr);
37873143b9aSmrg	return 0;
37973143b9aSmrg    }
38073143b9aSmrg
381fe567363Smrg    free (tmpptr);
38273143b9aSmrg
38373143b9aSmrg    return 1;
38473143b9aSmrg}
38573143b9aSmrg
38673143b9aSmrg
38773143b9aSmrg/*
38873143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only
38973143b9aSmrg * funny part about this is the type parameter which is used to decide which
39073143b9aSmrg * type of open to perform.
39173143b9aSmrg */
39273143b9aSmrg
39373143b9aSmrgstatic XtransConnInfo
39473143b9aSmrgTRANS(Open) (int type, char *address)
39573143b9aSmrg
39673143b9aSmrg{
39773143b9aSmrg    char 		*protocol = NULL, *host = NULL, *port = NULL;
39873143b9aSmrg    XtransConnInfo	ciptr = NULL;
39973143b9aSmrg    Xtransport		*thistrans;
40073143b9aSmrg
401fe567363Smrg    prmsg (2,"Open(%d,%s)\n", type, address);
40273143b9aSmrg
403fe567363Smrg#if defined(WIN32) && defined(TCPCONN)
40473143b9aSmrg    if (TRANS(WSAStartup)())
40573143b9aSmrg    {
406fe567363Smrg	prmsg (1,"Open: WSAStartup failed\n");
40773143b9aSmrg	return NULL;
40873143b9aSmrg    }
40973143b9aSmrg#endif
41073143b9aSmrg
41173143b9aSmrg    /* Parse the Address */
41273143b9aSmrg
41373143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
41473143b9aSmrg    {
415fe567363Smrg	prmsg (1,"Open: Unable to Parse address %s\n", address);
41673143b9aSmrg	return NULL;
41773143b9aSmrg    }
41873143b9aSmrg
41973143b9aSmrg    /* Determine the transport type */
42073143b9aSmrg
42173143b9aSmrg    if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
42273143b9aSmrg    {
423fe567363Smrg	prmsg (1,"Open: Unable to find transport for %s\n",
424fe567363Smrg	       protocol);
42573143b9aSmrg
426fe567363Smrg	free (protocol);
427fe567363Smrg	free (host);
428fe567363Smrg	free (port);
42973143b9aSmrg	return NULL;
43073143b9aSmrg    }
43173143b9aSmrg
43273143b9aSmrg    /* Open the transport */
43373143b9aSmrg
43473143b9aSmrg    switch (type)
43573143b9aSmrg    {
43673143b9aSmrg    case XTRANS_OPEN_COTS_CLIENT:
43773143b9aSmrg#ifdef TRANS_CLIENT
43873143b9aSmrg	ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
43973143b9aSmrg#endif /* TRANS_CLIENT */
44073143b9aSmrg	break;
44173143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
44273143b9aSmrg#ifdef TRANS_SERVER
44373143b9aSmrg	ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
44473143b9aSmrg#endif /* TRANS_SERVER */
44573143b9aSmrg	break;
44673143b9aSmrg    case XTRANS_OPEN_CLTS_CLIENT:
44773143b9aSmrg#ifdef TRANS_CLIENT
44873143b9aSmrg	ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
44973143b9aSmrg#endif /* TRANS_CLIENT */
45073143b9aSmrg	break;
45173143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
45273143b9aSmrg#ifdef TRANS_SERVER
45373143b9aSmrg	ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
45473143b9aSmrg#endif /* TRANS_SERVER */
45573143b9aSmrg	break;
45673143b9aSmrg    default:
457fe567363Smrg	prmsg (1,"Open: Unknown Open type %d\n", type);
45873143b9aSmrg    }
45973143b9aSmrg
46073143b9aSmrg    if (ciptr == NULL)
46173143b9aSmrg    {
462fe567363Smrg	if (!(thistrans->flags & TRANS_DISABLED))
46373143b9aSmrg	{
464fe567363Smrg	    prmsg (1,"Open: transport open failed for %s/%s:%s\n",
46573143b9aSmrg	           protocol, host, port);
46673143b9aSmrg	}
467fe567363Smrg	free (protocol);
468fe567363Smrg	free (host);
469fe567363Smrg	free (port);
47073143b9aSmrg	return NULL;
47173143b9aSmrg    }
47273143b9aSmrg
47373143b9aSmrg    ciptr->transptr = thistrans;
47473143b9aSmrg    ciptr->port = port;			/* We need this for TRANS(Reopen) */
47573143b9aSmrg
476fe567363Smrg    free (protocol);
477fe567363Smrg    free (host);
47873143b9aSmrg
47973143b9aSmrg    return ciptr;
48073143b9aSmrg}
48173143b9aSmrg
48273143b9aSmrg
48373143b9aSmrg#ifdef TRANS_REOPEN
48473143b9aSmrg
48573143b9aSmrg/*
48673143b9aSmrg * We might want to create an XtransConnInfo object based on a previously
48773143b9aSmrg * opened connection.  For example, the font server may clone itself and
48873143b9aSmrg * pass file descriptors to the parent.
48973143b9aSmrg */
49073143b9aSmrg
49173143b9aSmrgstatic XtransConnInfo
49273143b9aSmrgTRANS(Reopen) (int type, int trans_id, int fd, char *port)
49373143b9aSmrg
49473143b9aSmrg{
49573143b9aSmrg    XtransConnInfo	ciptr = NULL;
49673143b9aSmrg    Xtransport		*thistrans = NULL;
49773143b9aSmrg    char		*save_port;
49873143b9aSmrg    int			i;
49973143b9aSmrg
500fe567363Smrg    prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
50173143b9aSmrg
50273143b9aSmrg    /* Determine the transport type */
50373143b9aSmrg
50473143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
50573143b9aSmrg	if (Xtransports[i].transport_id == trans_id)
50673143b9aSmrg	{
50773143b9aSmrg	    thistrans = Xtransports[i].transport;
50873143b9aSmrg	    break;
50973143b9aSmrg	}
51073143b9aSmrg
51173143b9aSmrg    if (thistrans == NULL)
51273143b9aSmrg    {
513fe567363Smrg	prmsg (1,"Reopen: Unable to find transport id %d\n",
514fe567363Smrg	       trans_id);
51573143b9aSmrg
51673143b9aSmrg	return NULL;
51773143b9aSmrg    }
51873143b9aSmrg
519fe567363Smrg    if ((save_port = strdup (port)) == NULL)
52073143b9aSmrg    {
521fe567363Smrg	prmsg (1,"Reopen: Unable to malloc port string\n");
52273143b9aSmrg
52373143b9aSmrg	return NULL;
52473143b9aSmrg    }
52573143b9aSmrg
52673143b9aSmrg    /* Get a new XtransConnInfo object */
52773143b9aSmrg
52873143b9aSmrg    switch (type)
52973143b9aSmrg    {
53073143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
53173143b9aSmrg	ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
53273143b9aSmrg	break;
53373143b9aSmrg    case XTRANS_OPEN_CLTS_SERVER:
53473143b9aSmrg	ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
53573143b9aSmrg	break;
53673143b9aSmrg    default:
537fe567363Smrg	prmsg (1,"Reopen: Bad Open type %d\n", type);
53873143b9aSmrg    }
53973143b9aSmrg
54073143b9aSmrg    if (ciptr == NULL)
54173143b9aSmrg    {
542fe567363Smrg	prmsg (1,"Reopen: transport open failed\n");
543fe567363Smrg	free (save_port);
54473143b9aSmrg	return NULL;
54573143b9aSmrg    }
54673143b9aSmrg
54773143b9aSmrg    ciptr->transptr = thistrans;
54873143b9aSmrg    ciptr->port = save_port;
54973143b9aSmrg
55073143b9aSmrg    return ciptr;
55173143b9aSmrg}
55273143b9aSmrg
55373143b9aSmrg#endif /* TRANS_REOPEN */
55473143b9aSmrg
55573143b9aSmrg
55673143b9aSmrg
55773143b9aSmrg/*
55873143b9aSmrg * These are the public interfaces to this Transport interface.
55973143b9aSmrg * These are the only functions that should have knowledge of the transport
56073143b9aSmrg * table.
56173143b9aSmrg */
56273143b9aSmrg
56373143b9aSmrg#ifdef TRANS_CLIENT
56473143b9aSmrg
56573143b9aSmrgXtransConnInfo
56673143b9aSmrgTRANS(OpenCOTSClient) (char *address)
56773143b9aSmrg
56873143b9aSmrg{
569fe567363Smrg    prmsg (2,"OpenCOTSClient(%s)\n", address);
57073143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
57173143b9aSmrg}
57273143b9aSmrg
57373143b9aSmrg#endif /* TRANS_CLIENT */
57473143b9aSmrg
57573143b9aSmrg
57673143b9aSmrg#ifdef TRANS_SERVER
57773143b9aSmrg
57873143b9aSmrgXtransConnInfo
57973143b9aSmrgTRANS(OpenCOTSServer) (char *address)
58073143b9aSmrg
58173143b9aSmrg{
582fe567363Smrg    prmsg (2,"OpenCOTSServer(%s)\n", address);
58373143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
58473143b9aSmrg}
58573143b9aSmrg
58673143b9aSmrg#endif /* TRANS_SERVER */
58773143b9aSmrg
58873143b9aSmrg
58973143b9aSmrg#ifdef TRANS_CLIENT
59073143b9aSmrg
59173143b9aSmrgXtransConnInfo
59273143b9aSmrgTRANS(OpenCLTSClient) (char *address)
59373143b9aSmrg
59473143b9aSmrg{
595fe567363Smrg    prmsg (2,"OpenCLTSClient(%s)\n", address);
59673143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
59773143b9aSmrg}
59873143b9aSmrg
59973143b9aSmrg#endif /* TRANS_CLIENT */
60073143b9aSmrg
60173143b9aSmrg
60273143b9aSmrg#ifdef TRANS_SERVER
60373143b9aSmrg
60473143b9aSmrgXtransConnInfo
60573143b9aSmrgTRANS(OpenCLTSServer) (char *address)
60673143b9aSmrg
60773143b9aSmrg{
608fe567363Smrg    prmsg (2,"OpenCLTSServer(%s)\n", address);
60973143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
61073143b9aSmrg}
61173143b9aSmrg
61273143b9aSmrg#endif /* TRANS_SERVER */
61373143b9aSmrg
61473143b9aSmrg
61573143b9aSmrg#ifdef TRANS_REOPEN
61673143b9aSmrg
61773143b9aSmrgXtransConnInfo
61873143b9aSmrgTRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
61973143b9aSmrg
62073143b9aSmrg{
621fe567363Smrg    prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
62273143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
62373143b9aSmrg}
62473143b9aSmrg
62573143b9aSmrgXtransConnInfo
62673143b9aSmrgTRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
62773143b9aSmrg
62873143b9aSmrg{
629fe567363Smrg    prmsg (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
63073143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
63173143b9aSmrg}
63273143b9aSmrg
63373143b9aSmrg
63473143b9aSmrgint
635fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr,
63673143b9aSmrg		      int *trans_id, int *fd, char **port)
63773143b9aSmrg
63873143b9aSmrg{
63973143b9aSmrg    int i;
64073143b9aSmrg
64173143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
64273143b9aSmrg	if (Xtransports[i].transport == ciptr->transptr)
64373143b9aSmrg	{
64473143b9aSmrg	    *trans_id = Xtransports[i].transport_id;
64573143b9aSmrg	    *fd = ciptr->fd;
64673143b9aSmrg
647fe567363Smrg	    if ((*port = strdup (ciptr->port)) == NULL)
64873143b9aSmrg		return 0;
64973143b9aSmrg	    else
65073143b9aSmrg		return 1;
65173143b9aSmrg	}
65273143b9aSmrg
65373143b9aSmrg    return 0;
65473143b9aSmrg}
65573143b9aSmrg
65673143b9aSmrg#endif /* TRANS_REOPEN */
65773143b9aSmrg
65873143b9aSmrg
65973143b9aSmrgint
66073143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
66173143b9aSmrg
66273143b9aSmrg{
66373143b9aSmrg    int	fd = ciptr->fd;
66473143b9aSmrg    int	ret = 0;
66573143b9aSmrg
666fe567363Smrg    prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
66773143b9aSmrg
66873143b9aSmrg    /*
66973143b9aSmrg     * For now, all transport type use the same stuff for setting options.
67073143b9aSmrg     * As long as this is true, we can put the common code here. Once a more
67173143b9aSmrg     * complicated transport such as shared memory or an OSI implementation
67273143b9aSmrg     * that uses the session and application libraries is implemented, this
67373143b9aSmrg     * code may have to move to a transport dependent function.
67473143b9aSmrg     *
67573143b9aSmrg     * ret = ciptr->transptr->SetOption (ciptr, option, arg);
67673143b9aSmrg     */
67773143b9aSmrg
67873143b9aSmrg    switch (option)
67973143b9aSmrg    {
68073143b9aSmrg    case TRANS_NONBLOCKING:
68173143b9aSmrg	switch (arg)
68273143b9aSmrg	{
68373143b9aSmrg	case 0:
68473143b9aSmrg	    /* Set to blocking mode */
68573143b9aSmrg	    break;
68673143b9aSmrg	case 1: /* Set to non-blocking mode */
68773143b9aSmrg
688fe567363Smrg#if defined(O_NONBLOCK) && !defined(SCO325)
68973143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
69073143b9aSmrg	    if (ret != -1)
69173143b9aSmrg		ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
69273143b9aSmrg#else
69373143b9aSmrg#ifdef FIOSNBIO
69473143b9aSmrg	{
69573143b9aSmrg	    int arg;
69673143b9aSmrg	    arg = 1;
69773143b9aSmrg	    ret = ioctl (fd, FIOSNBIO, &arg);
69873143b9aSmrg	}
69973143b9aSmrg#else
700fe567363Smrg#if defined(WIN32)
70173143b9aSmrg	{
70273143b9aSmrg#ifdef WIN32
70373143b9aSmrg	    u_long arg;
70473143b9aSmrg#else
70573143b9aSmrg	    int arg;
70673143b9aSmrg#endif
70773143b9aSmrg	    arg = 1;
70873143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
70973143b9aSmrg * eventually with EWOULDBLOCK */
71073143b9aSmrg	    ret = ioctl (fd, FIONBIO, &arg);
71173143b9aSmrg	}
71273143b9aSmrg#else
71373143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
71473143b9aSmrg#ifdef FNDELAY
71573143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | FNDELAY);
71673143b9aSmrg#else
71773143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
71873143b9aSmrg#endif
71973143b9aSmrg#endif /* AIXV3  || uniosu */
72073143b9aSmrg#endif /* FIOSNBIO */
72173143b9aSmrg#endif /* O_NONBLOCK */
72273143b9aSmrg	    break;
72373143b9aSmrg	default:
72473143b9aSmrg	    /* Unknown option */
72573143b9aSmrg	    break;
72673143b9aSmrg	}
72773143b9aSmrg	break;
72873143b9aSmrg    case TRANS_CLOSEONEXEC:
72973143b9aSmrg#ifdef F_SETFD
73073143b9aSmrg#ifdef FD_CLOEXEC
73173143b9aSmrg	ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
73273143b9aSmrg#else
73373143b9aSmrg	ret = fcntl (fd, F_SETFD, 1);
73473143b9aSmrg#endif /* FD_CLOEXEC */
73573143b9aSmrg#endif /* F_SETFD */
73673143b9aSmrg	break;
73773143b9aSmrg    }
738fe567363Smrg
73973143b9aSmrg    return ret;
74073143b9aSmrg}
74173143b9aSmrg
74273143b9aSmrg#ifdef TRANS_SERVER
74373143b9aSmrg
74473143b9aSmrgint
74573143b9aSmrgTRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
74673143b9aSmrg
74773143b9aSmrg{
74873143b9aSmrg    return ciptr->transptr->CreateListener (ciptr, port, flags);
74973143b9aSmrg}
75073143b9aSmrg
75175ebec6dSmrgint
75275ebec6dSmrgTRANS(Received) (const char * protocol)
75375ebec6dSmrg
75475ebec6dSmrg{
75575ebec6dSmrg   Xtransport *trans;
75675ebec6dSmrg   int i = 0, ret = 0;
75775ebec6dSmrg
75875ebec6dSmrg   prmsg (5, "Received(%s)\n", protocol);
75975ebec6dSmrg
76075ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
76175ebec6dSmrg   {
76275ebec6dSmrg	prmsg (1,"Received: unable to find transport: %s\n",
76375ebec6dSmrg	       protocol);
76475ebec6dSmrg
76575ebec6dSmrg	return -1;
76675ebec6dSmrg   }
76775ebec6dSmrg   if (trans->flags & TRANS_ALIAS) {
76875ebec6dSmrg       if (trans->nolisten)
76975ebec6dSmrg	   while (trans->nolisten[i]) {
77075ebec6dSmrg	       ret |= TRANS(Received)(trans->nolisten[i]);
77175ebec6dSmrg	       i++;
77275ebec6dSmrg       }
77375ebec6dSmrg   }
77475ebec6dSmrg
77575ebec6dSmrg   trans->flags |= TRANS_RECEIVED;
77675ebec6dSmrg   return ret;
77775ebec6dSmrg}
77875ebec6dSmrg
77973143b9aSmrgint
780fe567363SmrgTRANS(NoListen) (const char * protocol)
781fe567363Smrg
78273143b9aSmrg{
78373143b9aSmrg   Xtransport *trans;
78473143b9aSmrg   int i = 0, ret = 0;
785fe567363Smrg
786fe567363Smrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
78773143b9aSmrg   {
788fe567363Smrg	prmsg (1,"TransNoListen: unable to find transport: %s\n",
789fe567363Smrg	       protocol);
79073143b9aSmrg
79173143b9aSmrg	return -1;
79273143b9aSmrg   }
79373143b9aSmrg   if (trans->flags & TRANS_ALIAS) {
79473143b9aSmrg       if (trans->nolisten)
79573143b9aSmrg	   while (trans->nolisten[i]) {
79673143b9aSmrg	       ret |= TRANS(NoListen)(trans->nolisten[i]);
79773143b9aSmrg	       i++;
79873143b9aSmrg       }
79973143b9aSmrg   }
80073143b9aSmrg
80173143b9aSmrg   trans->flags |= TRANS_NOLISTEN;
80273143b9aSmrg   return ret;
80373143b9aSmrg}
80473143b9aSmrg
80575ebec6dSmrgint
80675ebec6dSmrgTRANS(IsListening) (const char * protocol)
80775ebec6dSmrg{
80875ebec6dSmrg   Xtransport *trans;
80975ebec6dSmrg
81075ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
81175ebec6dSmrg   {
81275ebec6dSmrg	prmsg (1,"TransIsListening: unable to find transport: %s\n",
81375ebec6dSmrg	       protocol);
81475ebec6dSmrg
81575ebec6dSmrg	return 0;
81675ebec6dSmrg   }
81775ebec6dSmrg
81875ebec6dSmrg   return !(trans->flags & TRANS_NOLISTEN);
81975ebec6dSmrg}
82075ebec6dSmrg
82173143b9aSmrgint
82273143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr)
82373143b9aSmrg
82473143b9aSmrg{
82573143b9aSmrg    if (ciptr->transptr->ResetListener)
82673143b9aSmrg	return ciptr->transptr->ResetListener (ciptr);
82773143b9aSmrg    else
82873143b9aSmrg	return TRANS_RESET_NOOP;
82973143b9aSmrg}
83073143b9aSmrg
83173143b9aSmrg
83273143b9aSmrgXtransConnInfo
83373143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status)
83473143b9aSmrg
83573143b9aSmrg{
83673143b9aSmrg    XtransConnInfo	newciptr;
83773143b9aSmrg
838fe567363Smrg    prmsg (2,"Accept(%d)\n", ciptr->fd);
83973143b9aSmrg
84073143b9aSmrg    newciptr = ciptr->transptr->Accept (ciptr, status);
84173143b9aSmrg
84273143b9aSmrg    if (newciptr)
84373143b9aSmrg	newciptr->transptr = ciptr->transptr;
84473143b9aSmrg
84573143b9aSmrg    return newciptr;
84673143b9aSmrg}
84773143b9aSmrg
84873143b9aSmrg#endif /* TRANS_SERVER */
84973143b9aSmrg
85073143b9aSmrg
85173143b9aSmrg#ifdef TRANS_CLIENT
85273143b9aSmrg
85373143b9aSmrgint
85473143b9aSmrgTRANS(Connect) (XtransConnInfo ciptr, char *address)
85573143b9aSmrg
85673143b9aSmrg{
85773143b9aSmrg    char	*protocol;
85873143b9aSmrg    char	*host;
85973143b9aSmrg    char	*port;
86073143b9aSmrg    int		ret;
86173143b9aSmrg
862fe567363Smrg    prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address);
86373143b9aSmrg
86473143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
86573143b9aSmrg    {
866fe567363Smrg	prmsg (1,"Connect: Unable to Parse address %s\n",
867fe567363Smrg	       address);
86873143b9aSmrg	return -1;
86973143b9aSmrg    }
87073143b9aSmrg
87173143b9aSmrg#ifdef HAVE_LAUNCHD
8728d4c0f7bSmrg    if (!host) host=strdup("");
87373143b9aSmrg#endif
87473143b9aSmrg
87573143b9aSmrg    if (!port || !*port)
87673143b9aSmrg    {
877fe567363Smrg	prmsg (1,"Connect: Missing port specification in %s\n",
878fe567363Smrg	      address);
879fe567363Smrg	if (protocol) free (protocol);
880fe567363Smrg	if (host) free (host);
88173143b9aSmrg	return -1;
88273143b9aSmrg    }
88373143b9aSmrg
88473143b9aSmrg    ret = ciptr->transptr->Connect (ciptr, host, port);
88573143b9aSmrg
886fe567363Smrg    if (protocol) free (protocol);
887fe567363Smrg    if (host) free (host);
888fe567363Smrg    if (port) free (port);
889fe567363Smrg
89073143b9aSmrg    return ret;
89173143b9aSmrg}
89273143b9aSmrg
89373143b9aSmrg#endif /* TRANS_CLIENT */
89473143b9aSmrg
89573143b9aSmrg
89673143b9aSmrgint
89773143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
89873143b9aSmrg
89973143b9aSmrg{
90073143b9aSmrg    return ciptr->transptr->BytesReadable (ciptr, pend);
90173143b9aSmrg}
90273143b9aSmrg
90373143b9aSmrgint
90473143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
90573143b9aSmrg
90673143b9aSmrg{
90773143b9aSmrg    return ciptr->transptr->Read (ciptr, buf, size);
90873143b9aSmrg}
90973143b9aSmrg
91073143b9aSmrgint
91173143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
91273143b9aSmrg
91373143b9aSmrg{
91473143b9aSmrg    return ciptr->transptr->Write (ciptr, buf, size);
91573143b9aSmrg}
91673143b9aSmrg
91773143b9aSmrgint
91873143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
91973143b9aSmrg
92073143b9aSmrg{
92173143b9aSmrg    return ciptr->transptr->Readv (ciptr, buf, size);
92273143b9aSmrg}
92373143b9aSmrg
92473143b9aSmrgint
92573143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
92673143b9aSmrg
92773143b9aSmrg{
92873143b9aSmrg    return ciptr->transptr->Writev (ciptr, buf, size);
92973143b9aSmrg}
93073143b9aSmrg
93175ebec6dSmrg#if XTRANS_SEND_FDS
93275ebec6dSmrgint
93375ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
93475ebec6dSmrg{
93575ebec6dSmrg    return ciptr->transptr->SendFd(ciptr, fd, do_close);
93675ebec6dSmrg}
93775ebec6dSmrg
93875ebec6dSmrgint
93975ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr)
94075ebec6dSmrg{
94175ebec6dSmrg    return ciptr->transptr->RecvFd(ciptr);
94275ebec6dSmrg}
94375ebec6dSmrg#endif
94475ebec6dSmrg
94573143b9aSmrgint
94673143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr)
94773143b9aSmrg
94873143b9aSmrg{
94973143b9aSmrg    return ciptr->transptr->Disconnect (ciptr);
95073143b9aSmrg}
95173143b9aSmrg
95273143b9aSmrgint
95373143b9aSmrgTRANS(Close) (XtransConnInfo ciptr)
95473143b9aSmrg
95573143b9aSmrg{
95673143b9aSmrg    int ret;
95773143b9aSmrg
958fe567363Smrg    prmsg (2,"Close(%d)\n", ciptr->fd);
95973143b9aSmrg
96073143b9aSmrg    ret = ciptr->transptr->Close (ciptr);
96173143b9aSmrg
96273143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
96373143b9aSmrg
96473143b9aSmrg    return ret;
96573143b9aSmrg}
96673143b9aSmrg
96773143b9aSmrgint
96873143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr)
96973143b9aSmrg
97073143b9aSmrg{
97173143b9aSmrg    int ret;
97273143b9aSmrg
973fe567363Smrg    prmsg (2,"CloseForCloning(%d)\n", ciptr->fd);
97473143b9aSmrg
97573143b9aSmrg    ret = ciptr->transptr->CloseForCloning (ciptr);
97673143b9aSmrg
97773143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
97873143b9aSmrg
97973143b9aSmrg    return ret;
98073143b9aSmrg}
98173143b9aSmrg
98273143b9aSmrgint
98373143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr)
98473143b9aSmrg
98573143b9aSmrg{
98673143b9aSmrg    return (ciptr->family == AF_UNIX);
98773143b9aSmrg}
98873143b9aSmrg
98973143b9aSmrg
99073143b9aSmrgint
991fe567363SmrgTRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
99273143b9aSmrg		  Xtransaddr **addrp)
99373143b9aSmrg
99473143b9aSmrg{
995fe567363Smrg    prmsg (2,"GetMyAddr(%d)\n", ciptr->fd);
99673143b9aSmrg
99773143b9aSmrg    *familyp = ciptr->family;
99873143b9aSmrg    *addrlenp = ciptr->addrlen;
99973143b9aSmrg
1000fe567363Smrg    if ((*addrp = malloc (ciptr->addrlen)) == NULL)
100173143b9aSmrg    {
1002fe567363Smrg	prmsg (1,"GetMyAddr: malloc failed\n");
100373143b9aSmrg	return -1;
100473143b9aSmrg    }
100573143b9aSmrg    memcpy(*addrp, ciptr->addr, ciptr->addrlen);
100673143b9aSmrg
100773143b9aSmrg    return 0;
100873143b9aSmrg}
100973143b9aSmrg
101073143b9aSmrgint
1011fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
101273143b9aSmrg		    Xtransaddr **addrp)
101373143b9aSmrg
101473143b9aSmrg{
1015fe567363Smrg    prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd);
101673143b9aSmrg
101773143b9aSmrg    *familyp = ciptr->family;
101873143b9aSmrg    *addrlenp = ciptr->peeraddrlen;
101973143b9aSmrg
1020fe567363Smrg    if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL)
102173143b9aSmrg    {
1022fe567363Smrg	prmsg (1,"GetPeerAddr: malloc failed\n");
102373143b9aSmrg	return -1;
102473143b9aSmrg    }
102573143b9aSmrg    memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
102673143b9aSmrg
102773143b9aSmrg    return 0;
102873143b9aSmrg}
102973143b9aSmrg
103073143b9aSmrg
103173143b9aSmrgint
103273143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr)
103373143b9aSmrg
103473143b9aSmrg{
103573143b9aSmrg    return ciptr->fd;
103673143b9aSmrg}
103773143b9aSmrg
103873143b9aSmrg
103973143b9aSmrg/*
104073143b9aSmrg * These functions are really utility functions, but they require knowledge
104173143b9aSmrg * of the internal data structures, so they have to be part of the Transport
104273143b9aSmrg * Independant API.
104373143b9aSmrg */
104473143b9aSmrg
104573143b9aSmrg#ifdef TRANS_SERVER
104673143b9aSmrg
104773143b9aSmrgstatic int
104873143b9aSmrgcomplete_network_count (void)
104973143b9aSmrg
105073143b9aSmrg{
105173143b9aSmrg    int count = 0;
105273143b9aSmrg    int found_local = 0;
105373143b9aSmrg    int i;
105473143b9aSmrg
105573143b9aSmrg    /*
105673143b9aSmrg     * For a complete network, we only need one LOCALCONN transport to work
105773143b9aSmrg     */
105873143b9aSmrg
105973143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
106073143b9aSmrg    {
106173143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_ALIAS
106273143b9aSmrg   	 || Xtransports[i].transport->flags & TRANS_NOLISTEN)
106373143b9aSmrg	    continue;
106473143b9aSmrg
106573143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_LOCAL)
106673143b9aSmrg	    found_local = 1;
106773143b9aSmrg	else
106873143b9aSmrg	    count++;
106973143b9aSmrg    }
107073143b9aSmrg
107173143b9aSmrg    return (count + found_local);
107273143b9aSmrg}
107373143b9aSmrg
107473143b9aSmrg
107575ebec6dSmrgstatic int
107675ebec6dSmrgreceive_listening_fds(char* port, XtransConnInfo* temp_ciptrs, int* count_ret)
107775ebec6dSmrg
107875ebec6dSmrg{
107975ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON
108075ebec6dSmrg    XtransConnInfo ciptr;
108175ebec6dSmrg    int i, systemd_listen_fds;
108275ebec6dSmrg
108375ebec6dSmrg    systemd_listen_fds = sd_listen_fds(1);
108475ebec6dSmrg    if (systemd_listen_fds < 0)
108575ebec6dSmrg    {
108675ebec6dSmrg        prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n",
108775ebec6dSmrg               strerror(-systemd_listen_fds));
108875ebec6dSmrg        return -1;
108975ebec6dSmrg    }
109075ebec6dSmrg
109175ebec6dSmrg    for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++)
109275ebec6dSmrg    {
109375ebec6dSmrg        struct sockaddr_storage a;
109475ebec6dSmrg        int ti;
109575ebec6dSmrg        const char* tn;
109675ebec6dSmrg        socklen_t al;
109775ebec6dSmrg
109875ebec6dSmrg        al = sizeof(a);
109975ebec6dSmrg        if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) {
110075ebec6dSmrg            prmsg (1, "receive_listening_fds: getsockname error: %s\n",
110175ebec6dSmrg                   strerror(errno));
110275ebec6dSmrg            return -1;
110375ebec6dSmrg        }
110475ebec6dSmrg
110575ebec6dSmrg        switch (a.ss_family)
110675ebec6dSmrg        {
110775ebec6dSmrg        case AF_UNIX:
110875ebec6dSmrg            ti = TRANS_SOCKET_UNIX_INDEX;
110975ebec6dSmrg            if (*((struct sockaddr_un*)&a)->sun_path == '\0' &&
111075ebec6dSmrg                al > sizeof(sa_family_t))
111175ebec6dSmrg                tn = "local";
111275ebec6dSmrg            else
111375ebec6dSmrg                tn = "unix";
111475ebec6dSmrg            break;
111575ebec6dSmrg        case AF_INET:
111675ebec6dSmrg            ti = TRANS_SOCKET_INET_INDEX;
111775ebec6dSmrg            tn = "inet";
111875ebec6dSmrg            break;
111975ebec6dSmrg#if defined(IPv6) && defined(AF_INET6)
112075ebec6dSmrg        case AF_INET6:
112175ebec6dSmrg            ti = TRANS_SOCKET_INET6_INDEX;
112275ebec6dSmrg            tn = "inet6";
112375ebec6dSmrg            break;
112475ebec6dSmrg#endif /* IPv6 */
112575ebec6dSmrg        default:
112675ebec6dSmrg            prmsg (1, "receive_listening_fds:"
112775ebec6dSmrg                   "Got unknown socket address family\n");
112875ebec6dSmrg            return -1;
112975ebec6dSmrg        }
113075ebec6dSmrg
113175ebec6dSmrg        ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port);
113275ebec6dSmrg        if (!ciptr)
113375ebec6dSmrg        {
113475ebec6dSmrg            prmsg (1, "receive_listening_fds:"
113575ebec6dSmrg                   "Got NULL while trying to reopen socket received from systemd.\n");
113675ebec6dSmrg            return -1;
113775ebec6dSmrg        }
113875ebec6dSmrg
113975ebec6dSmrg        prmsg (5, "receive_listening_fds: received listener for %s, %d\n",
114075ebec6dSmrg               tn, ciptr->fd);
114175ebec6dSmrg        temp_ciptrs[(*count_ret)++] = ciptr;
114275ebec6dSmrg        TRANS(Received)(tn);
114375ebec6dSmrg    }
114475ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */
114575ebec6dSmrg    return 0;
114675ebec6dSmrg}
114775ebec6dSmrg
11488d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11498d4c0f7bSmrgextern int xquartz_launchd_fd;
11508d4c0f7bSmrg#endif
115173143b9aSmrg
115273143b9aSmrgint
1153fe567363SmrgTRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
115473143b9aSmrg				   XtransConnInfo **ciptrs_ret)
115573143b9aSmrg
115673143b9aSmrg{
115773143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
115873143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
115973143b9aSmrg    int			status, i, j;
116073143b9aSmrg
116173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
116273143b9aSmrg    int		ipv6_succ = 0;
116373143b9aSmrg#endif
1164fe567363Smrg    prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n",
1165fe567363Smrg	   port ? port : "NULL", ciptrs_ret);
116673143b9aSmrg
116773143b9aSmrg    *count_ret = 0;
116873143b9aSmrg
11698d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11708d4c0f7bSmrg    fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
11718d4c0f7bSmrg    if(xquartz_launchd_fd != -1) {
11728d4c0f7bSmrg        if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
11738d4c0f7bSmrg                                           xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
11748d4c0f7bSmrg            fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
1175fe567363Smrg        else
11768d4c0f7bSmrg            temp_ciptrs[(*count_ret)++] = ciptr;
11778d4c0f7bSmrg    }
117873143b9aSmrg#endif
117973143b9aSmrg
118075ebec6dSmrg    if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0)
118175ebec6dSmrg	return -1;
118275ebec6dSmrg
118373143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
118473143b9aSmrg    {
118573143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
118673143b9aSmrg	unsigned int flags = 0;
118773143b9aSmrg
118875ebec6dSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN ||
118975ebec6dSmrg	    trans->flags&TRANS_RECEIVED)
119073143b9aSmrg	    continue;
119173143b9aSmrg
119273143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
119373143b9aSmrg		 trans->TransName, port ? port : "");
119473143b9aSmrg
1195fe567363Smrg	prmsg (5,"MakeAllCOTSServerListeners: opening %s\n",
1196fe567363Smrg	       buffer);
119773143b9aSmrg
119873143b9aSmrg	if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
119973143b9aSmrg	{
120073143b9aSmrg	    if (trans->flags & TRANS_DISABLED)
120173143b9aSmrg		continue;
120273143b9aSmrg
1203fe567363Smrg	    prmsg (1,
120473143b9aSmrg	  "MakeAllCOTSServerListeners: failed to open listener for %s\n",
1205fe567363Smrg		  trans->TransName);
120673143b9aSmrg	    continue;
120773143b9aSmrg	}
120873143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
120973143b9aSmrg		if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
121073143b9aSmrg		     && ipv6_succ))
121173143b9aSmrg		    flags |= ADDR_IN_USE_ALLOWED;
121273143b9aSmrg#endif
121373143b9aSmrg
121473143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
121573143b9aSmrg	{
121673143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
121773143b9aSmrg	    {
121873143b9aSmrg		/*
121973143b9aSmrg		 * We failed to bind to the specified address because the
122073143b9aSmrg		 * address is in use.  It must be that a server is already
122173143b9aSmrg		 * running at this address, and this function should fail.
122273143b9aSmrg		 */
122373143b9aSmrg
1224fe567363Smrg		prmsg (1,
1225fe567363Smrg		"MakeAllCOTSServerListeners: server already running\n");
122673143b9aSmrg
122773143b9aSmrg		for (j = 0; j < *count_ret; j++)
122873143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
122973143b9aSmrg
123073143b9aSmrg		*count_ret = 0;
123173143b9aSmrg		*ciptrs_ret = NULL;
123273143b9aSmrg		*partial = 0;
123373143b9aSmrg		return -1;
123473143b9aSmrg	    }
123573143b9aSmrg	    else
123673143b9aSmrg	    {
1237fe567363Smrg		prmsg (1,
123873143b9aSmrg	"MakeAllCOTSServerListeners: failed to create listener for %s\n",
1239fe567363Smrg		  trans->TransName);
124073143b9aSmrg
124173143b9aSmrg		continue;
124273143b9aSmrg	    }
124373143b9aSmrg	}
124473143b9aSmrg
124573143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
124673143b9aSmrg	if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
124773143b9aSmrg	    ipv6_succ = 1;
124873143b9aSmrg#endif
1249fe567363Smrg
1250fe567363Smrg	prmsg (5,
125173143b9aSmrg	      "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
1252fe567363Smrg	      trans->TransName, ciptr->fd);
125373143b9aSmrg
125473143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
125573143b9aSmrg	(*count_ret)++;
125673143b9aSmrg    }
125773143b9aSmrg
125873143b9aSmrg    *partial = (*count_ret < complete_network_count());
125973143b9aSmrg
1260fe567363Smrg    prmsg (5,
126173143b9aSmrg     "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
126273143b9aSmrg	*partial, *count_ret, complete_network_count());
126373143b9aSmrg
126473143b9aSmrg    if (*count_ret > 0)
126573143b9aSmrg    {
1266fe567363Smrg	if ((*ciptrs_ret = malloc (
126773143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
126873143b9aSmrg	{
126973143b9aSmrg	    return -1;
127073143b9aSmrg	}
127173143b9aSmrg
127273143b9aSmrg	for (i = 0; i < *count_ret; i++)
127373143b9aSmrg	{
127473143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
127573143b9aSmrg	}
127673143b9aSmrg    }
127773143b9aSmrg    else
127873143b9aSmrg	*ciptrs_ret = NULL;
1279fe567363Smrg
128073143b9aSmrg    return 0;
128173143b9aSmrg}
128273143b9aSmrg
128373143b9aSmrgint
1284fe567363SmrgTRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
128573143b9aSmrg				   XtransConnInfo **ciptrs_ret)
128673143b9aSmrg
128773143b9aSmrg{
128873143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
128973143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
129073143b9aSmrg    int			status, i, j;
129173143b9aSmrg
1292fe567363Smrg    prmsg (2,"MakeAllCLTSServerListeners(%s,%p)\n",
1293fe567363Smrg	port ? port : "NULL", ciptrs_ret);
129473143b9aSmrg
129573143b9aSmrg    *count_ret = 0;
129673143b9aSmrg
129773143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
129873143b9aSmrg    {
129973143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
130073143b9aSmrg
130173143b9aSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
130273143b9aSmrg	    continue;
130373143b9aSmrg
130473143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
130573143b9aSmrg		 trans->TransName, port ? port : "");
130673143b9aSmrg
1307fe567363Smrg	prmsg (5,"MakeAllCLTSServerListeners: opening %s\n",
1308fe567363Smrg	    buffer);
130973143b9aSmrg
131073143b9aSmrg	if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
131173143b9aSmrg	{
1312fe567363Smrg	    prmsg (1,
131373143b9aSmrg	"MakeAllCLTSServerListeners: failed to open listener for %s\n",
1314fe567363Smrg		  trans->TransName);
131573143b9aSmrg	    continue;
131673143b9aSmrg	}
131773143b9aSmrg
131873143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
131973143b9aSmrg	{
132073143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
132173143b9aSmrg	    {
132273143b9aSmrg		/*
132373143b9aSmrg		 * We failed to bind to the specified address because the
132473143b9aSmrg		 * address is in use.  It must be that a server is already
132573143b9aSmrg		 * running at this address, and this function should fail.
132673143b9aSmrg		 */
132773143b9aSmrg
1328fe567363Smrg		prmsg (1,
1329fe567363Smrg		"MakeAllCLTSServerListeners: server already running\n");
133073143b9aSmrg
133173143b9aSmrg		for (j = 0; j < *count_ret; j++)
133273143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
133373143b9aSmrg
133473143b9aSmrg		*count_ret = 0;
133573143b9aSmrg		*ciptrs_ret = NULL;
133673143b9aSmrg		*partial = 0;
133773143b9aSmrg		return -1;
133873143b9aSmrg	    }
133973143b9aSmrg	    else
134073143b9aSmrg	    {
1341fe567363Smrg		prmsg (1,
134273143b9aSmrg	"MakeAllCLTSServerListeners: failed to create listener for %s\n",
1343fe567363Smrg		  trans->TransName);
134473143b9aSmrg
134573143b9aSmrg		continue;
134673143b9aSmrg	    }
134773143b9aSmrg	}
134873143b9aSmrg
1349fe567363Smrg	prmsg (5,
135073143b9aSmrg	"MakeAllCLTSServerListeners: opened listener for %s, %d\n",
1351fe567363Smrg	      trans->TransName, ciptr->fd);
135273143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
135373143b9aSmrg	(*count_ret)++;
135473143b9aSmrg    }
135573143b9aSmrg
135673143b9aSmrg    *partial = (*count_ret < complete_network_count());
135773143b9aSmrg
1358fe567363Smrg    prmsg (5,
135973143b9aSmrg     "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
136073143b9aSmrg	*partial, *count_ret, complete_network_count());
136173143b9aSmrg
136273143b9aSmrg    if (*count_ret > 0)
136373143b9aSmrg    {
1364fe567363Smrg	if ((*ciptrs_ret = malloc (
136573143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
136673143b9aSmrg	{
136773143b9aSmrg	    return -1;
136873143b9aSmrg	}
136973143b9aSmrg
137073143b9aSmrg	for (i = 0; i < *count_ret; i++)
137173143b9aSmrg	{
137273143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
137373143b9aSmrg	}
137473143b9aSmrg    }
137573143b9aSmrg    else
137673143b9aSmrg	*ciptrs_ret = NULL;
1377fe567363Smrg
137873143b9aSmrg    return 0;
137973143b9aSmrg}
138073143b9aSmrg
138173143b9aSmrg#endif /* TRANS_SERVER */
138273143b9aSmrg
138373143b9aSmrg
138473143b9aSmrg
138573143b9aSmrg/*
138673143b9aSmrg * These routines are not part of the X Transport Interface, but they
138773143b9aSmrg * may be used by it.
138873143b9aSmrg */
138973143b9aSmrg
139073143b9aSmrg
1391fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
139273143b9aSmrg
139373143b9aSmrg/*
139473143b9aSmrg * emulate readv
139573143b9aSmrg */
139673143b9aSmrg
139773143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
139873143b9aSmrg
139973143b9aSmrg{
140073143b9aSmrg    int i, len, total;
140173143b9aSmrg    char *base;
140273143b9aSmrg
140373143b9aSmrg    ESET(0);
140473143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
140573143b9aSmrg	len = iov->iov_len;
140673143b9aSmrg	base = iov->iov_base;
140773143b9aSmrg	while (len > 0) {
140873143b9aSmrg	    register int nbytes;
140973143b9aSmrg	    nbytes = TRANS(Read) (ciptr, base, len);
141073143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
141173143b9aSmrg	    if (nbytes <= 0)  return total;
141273143b9aSmrg	    ESET(0);
141373143b9aSmrg	    len   -= nbytes;
141473143b9aSmrg	    total += nbytes;
141573143b9aSmrg	    base  += nbytes;
141673143b9aSmrg	}
141773143b9aSmrg    }
141873143b9aSmrg    return total;
141973143b9aSmrg}
142073143b9aSmrg
142173143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
142273143b9aSmrg
1423fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32)
142473143b9aSmrg
142573143b9aSmrg/*
142673143b9aSmrg * emulate writev
142773143b9aSmrg */
142873143b9aSmrg
142973143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
143073143b9aSmrg
143173143b9aSmrg{
143273143b9aSmrg    int i, len, total;
143373143b9aSmrg    char *base;
143473143b9aSmrg
143573143b9aSmrg    ESET(0);
143673143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
143773143b9aSmrg	len = iov->iov_len;
143873143b9aSmrg	base = iov->iov_base;
143973143b9aSmrg	while (len > 0) {
144073143b9aSmrg	    register int nbytes;
144173143b9aSmrg	    nbytes = TRANS(Write) (ciptr, base, len);
144273143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
144373143b9aSmrg	    if (nbytes <= 0)  return total;
144473143b9aSmrg	    ESET(0);
144573143b9aSmrg	    len   -= nbytes;
144673143b9aSmrg	    total += nbytes;
144773143b9aSmrg	    base  += nbytes;
144873143b9aSmrg	}
144973143b9aSmrg    }
145073143b9aSmrg    return total;
145173143b9aSmrg}
145273143b9aSmrg
145373143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */
145473143b9aSmrg
145573143b9aSmrg
1456e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__)
145773143b9aSmrg#ifndef NEED_UTSNAME
145873143b9aSmrg#define NEED_UTSNAME
145973143b9aSmrg#endif
146073143b9aSmrg#include <sys/utsname.h>
146173143b9aSmrg#endif
146273143b9aSmrg
146373143b9aSmrg/*
146473143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing.
146573143b9aSmrg */
146673143b9aSmrg
146773143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen)
146873143b9aSmrg
146973143b9aSmrg{
147073143b9aSmrg    int len;
147173143b9aSmrg
147273143b9aSmrg#ifdef NEED_UTSNAME
147373143b9aSmrg    struct utsname name;
147473143b9aSmrg
147573143b9aSmrg    uname (&name);
147673143b9aSmrg    len = strlen (name.nodename);
147773143b9aSmrg    if (len >= maxlen) len = maxlen - 1;
147873143b9aSmrg    strncpy (buf, name.nodename, len);
147973143b9aSmrg    buf[len] = '\0';
148073143b9aSmrg#else
148173143b9aSmrg    buf[0] = '\0';
148273143b9aSmrg    (void) gethostname (buf, maxlen);
148373143b9aSmrg    buf [maxlen - 1] = '\0';
148473143b9aSmrg    len = strlen(buf);
148573143b9aSmrg#endif /* NEED_UTSNAME */
148673143b9aSmrg    return len;
148773143b9aSmrg}
1488