Xtrans.c revision 3d2ed3e3
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 },
1033d2ed3e3Smrg#ifndef __sun
10473143b9aSmrg    { &TRANS(PTSFuncs),		TRANS_LOCAL_PTS_INDEX },
1053d2ed3e3Smrg#endif /* __sun */
106e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4)
10773143b9aSmrg    { &TRANS(NAMEDFuncs),	TRANS_LOCAL_NAMED_INDEX },
10873143b9aSmrg#endif
1093d2ed3e3Smrg#ifdef __sun
11073143b9aSmrg    { &TRANS(PIPEFuncs),	TRANS_LOCAL_PIPE_INDEX },
1113d2ed3e3Smrg#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{
1563d2ed3e3Smrg#ifndef HAVE_STRCASECMP
15773143b9aSmrg    char 	protobuf[PROTOBUFSIZE];
1583d2ed3e3Smrg#endif
15973143b9aSmrg    int		i;
16073143b9aSmrg
161fe567363Smrg    prmsg (3,"SelectTransport(%s)\n", protocol);
16273143b9aSmrg
1633d2ed3e3Smrg#ifndef HAVE_STRCASECMP
16473143b9aSmrg    /*
16573143b9aSmrg     * Force Protocol to be lowercase as a way of doing
16673143b9aSmrg     * a case insensitive match.
16773143b9aSmrg     */
16873143b9aSmrg
16973143b9aSmrg    strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
17073143b9aSmrg    protobuf[PROTOBUFSIZE-1] = '\0';
17173143b9aSmrg
17273143b9aSmrg    for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
1738a0d9095Smrg	if (isupper ((unsigned char)protobuf[i]))
1748a0d9095Smrg	    protobuf[i] = tolower ((unsigned char)protobuf[i]);
1753d2ed3e3Smrg#endif
17673143b9aSmrg
17773143b9aSmrg    /* Look at all of the configured protocols */
17873143b9aSmrg
17973143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
18073143b9aSmrg    {
1813d2ed3e3Smrg#ifndef HAVE_STRCASECMP
18273143b9aSmrg	if (!strcmp (protobuf, Xtransports[i].transport->TransName))
1833d2ed3e3Smrg#else
1843d2ed3e3Smrg	if (!strcasecmp (protocol, Xtransports[i].transport->TransName))
1853d2ed3e3Smrg#endif
18673143b9aSmrg	    return Xtransports[i].transport;
18773143b9aSmrg    }
18873143b9aSmrg
18973143b9aSmrg    return NULL;
19073143b9aSmrg}
19173143b9aSmrg
19273143b9aSmrg#ifndef TEST_t
19373143b9aSmrgstatic
19473143b9aSmrg#endif /* TEST_t */
19573143b9aSmrgint
1966a3641a6SsnjTRANS(ParseAddress) (const char *address,
1976a3641a6Ssnj                     char **protocol, char **host, char **port)
19873143b9aSmrg
19973143b9aSmrg{
20073143b9aSmrg    /*
20173143b9aSmrg     * For the font library, the address is a string formatted
20273143b9aSmrg     * as "protocol/host:port[/catalogue]".  Note that the catologue
20373143b9aSmrg     * is optional.  At this time, the catologue info is ignored, but
20473143b9aSmrg     * we have to parse it anyways.
20573143b9aSmrg     *
20673143b9aSmrg     * Other than fontlib, the address is a string formatted
20773143b9aSmrg     * as "protocol/host:port".
20873143b9aSmrg     *
20973143b9aSmrg     * If the protocol part is missing, then assume TCP.
21073143b9aSmrg     * If the protocol part and host part are missing, then assume local.
21173143b9aSmrg     * If a "::" is found then assume DNET.
21273143b9aSmrg     */
21373143b9aSmrg
21473143b9aSmrg    char	*mybuf, *tmpptr;
215fe567363Smrg    const char	*_protocol;
216fe567363Smrg    char	*_host, *_port;
21773143b9aSmrg    char	hostnamebuf[256];
21873143b9aSmrg    int		_host_len;
21973143b9aSmrg
220fe567363Smrg    prmsg (3,"ParseAddress(%s)\n", address);
22173143b9aSmrg
22273143b9aSmrg    /* Copy the string so it can be changed */
22373143b9aSmrg
224fe567363Smrg    tmpptr = mybuf = strdup (address);
22573143b9aSmrg
22673143b9aSmrg    /* Parse the string to get each component */
227fe567363Smrg
22873143b9aSmrg    /* Get the protocol part */
22973143b9aSmrg
23073143b9aSmrg    _protocol = mybuf;
23173143b9aSmrg
23273143b9aSmrg
23373143b9aSmrg   if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
23473143b9aSmrg      ((mybuf = strrchr (tmpptr,':')) == NULL) )
23573143b9aSmrg   {
23673143b9aSmrg	/* address is in a bad format */
23773143b9aSmrg	*protocol = NULL;
23873143b9aSmrg	*host = NULL;
23973143b9aSmrg	*port = NULL;
240fe567363Smrg	free (tmpptr);
24173143b9aSmrg	return 0;
24273143b9aSmrg    }
24373143b9aSmrg
24473143b9aSmrg    if (*mybuf == ':')
24573143b9aSmrg    {
24673143b9aSmrg	/*
24773143b9aSmrg	 * If there is a hostname, then assume tcp, otherwise
24873143b9aSmrg	 * it must be local.
24973143b9aSmrg	 */
25073143b9aSmrg	if (mybuf == tmpptr)
25173143b9aSmrg	{
25273143b9aSmrg	    /* There is neither a protocol or host specified */
25373143b9aSmrg	    _protocol = "local";
25473143b9aSmrg	}
25573143b9aSmrg	else
25673143b9aSmrg	{
25773143b9aSmrg	    /* There is a hostname specified */
25873143b9aSmrg	    _protocol = "tcp";
25973143b9aSmrg	    mybuf = tmpptr;	/* reset to the begining of the host ptr */
26073143b9aSmrg	}
26173143b9aSmrg    }
26273143b9aSmrg    else
26373143b9aSmrg    {
26473143b9aSmrg	/* *mybuf == '/' */
26573143b9aSmrg
26673143b9aSmrg	*mybuf ++= '\0'; /* put a null at the end of the protocol */
26773143b9aSmrg
26873143b9aSmrg	if (strlen(_protocol) == 0)
26973143b9aSmrg	{
27073143b9aSmrg	    /*
27173143b9aSmrg	     * If there is a hostname, then assume tcp, otherwise
27273143b9aSmrg	     * it must be local.
27373143b9aSmrg	     */
27473143b9aSmrg	    if (*mybuf != ':')
27573143b9aSmrg		_protocol = "tcp";
27673143b9aSmrg	    else
27773143b9aSmrg		_protocol = "local";
27873143b9aSmrg	}
27973143b9aSmrg    }
28073143b9aSmrg
28173143b9aSmrg    /* Get the host part */
28273143b9aSmrg
28373143b9aSmrg    _host = mybuf;
28473143b9aSmrg
28573143b9aSmrg    if ((mybuf = strrchr (mybuf,':')) == NULL)
28673143b9aSmrg    {
28773143b9aSmrg	*protocol = NULL;
28873143b9aSmrg	*host = NULL;
28973143b9aSmrg	*port = NULL;
290fe567363Smrg	free (tmpptr);
29173143b9aSmrg	return 0;
29273143b9aSmrg    }
29373143b9aSmrg
29473143b9aSmrg    *mybuf ++= '\0';
29573143b9aSmrg
29673143b9aSmrg    _host_len = strlen(_host);
29773143b9aSmrg    if (_host_len == 0)
29873143b9aSmrg    {
29973143b9aSmrg	TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
30073143b9aSmrg	_host = hostnamebuf;
30173143b9aSmrg    }
30273143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
30373143b9aSmrg    /* hostname in IPv6 [numeric_addr]:0 form? */
304fe567363Smrg    else if ( (_host_len > 3) &&
30573143b9aSmrg      ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
306fe567363Smrg      && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
30773143b9aSmrg	struct sockaddr_in6 sin6;
30873143b9aSmrg
30973143b9aSmrg	*(_host + _host_len - 1) = '\0';
31073143b9aSmrg
31173143b9aSmrg	/* Verify address is valid IPv6 numeric form */
31273143b9aSmrg	if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
31373143b9aSmrg	    /* It is. Use it as such. */
31473143b9aSmrg	    _host++;
31573143b9aSmrg	    _protocol = "inet6";
31673143b9aSmrg	} else {
31773143b9aSmrg	    /* It's not, restore it just in case some other code can use it. */
31873143b9aSmrg	    *(_host + _host_len - 1) = ']';
31973143b9aSmrg	}
32073143b9aSmrg    }
32173143b9aSmrg#endif
32273143b9aSmrg
32373143b9aSmrg
32473143b9aSmrg    /* Get the port */
32573143b9aSmrg
32673143b9aSmrg    _port = mybuf;
32773143b9aSmrg
32873143b9aSmrg#if defined(FONT_t) || defined(FS_t)
32973143b9aSmrg    /*
33073143b9aSmrg     * Is there an optional catalogue list?
33173143b9aSmrg     */
33273143b9aSmrg
33373143b9aSmrg    if ((mybuf = strchr (mybuf,'/')) != NULL)
33473143b9aSmrg	*mybuf ++= '\0';
33573143b9aSmrg
33673143b9aSmrg    /*
33773143b9aSmrg     * The rest, if any, is the (currently unused) catalogue list.
33873143b9aSmrg     *
33973143b9aSmrg     * _catalogue = mybuf;
34073143b9aSmrg     */
34173143b9aSmrg#endif
34273143b9aSmrg
34373143b9aSmrg#ifdef HAVE_LAUNCHD
34473143b9aSmrg    /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */
34573143b9aSmrg    if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) {
34673143b9aSmrg      _protocol="local";
34773143b9aSmrg      _host="";
34873143b9aSmrg      _port=address+6;
34973143b9aSmrg    }
35073143b9aSmrg#endif
35173143b9aSmrg
35273143b9aSmrg    /*
35373143b9aSmrg     * Now that we have all of the components, allocate new
35473143b9aSmrg     * string space for them.
35573143b9aSmrg     */
35673143b9aSmrg
357fe567363Smrg    if ((*protocol = strdup (_protocol)) == NULL)
35873143b9aSmrg    {
35973143b9aSmrg	/* Malloc failed */
36073143b9aSmrg	*port = NULL;
36173143b9aSmrg	*host = NULL;
36273143b9aSmrg	*protocol = NULL;
363fe567363Smrg	free (tmpptr);
36473143b9aSmrg	return 0;
36573143b9aSmrg    }
36673143b9aSmrg
367fe567363Smrg    if ((*host = strdup (_host)) == NULL)
36873143b9aSmrg    {
36973143b9aSmrg	/* Malloc failed */
37073143b9aSmrg	*port = NULL;
37173143b9aSmrg	*host = NULL;
372fe567363Smrg	free (*protocol);
37373143b9aSmrg	*protocol = NULL;
374fe567363Smrg	free (tmpptr);
37573143b9aSmrg	return 0;
376fe567363Smrg    }
37773143b9aSmrg
378fe567363Smrg    if ((*port = strdup (_port)) == NULL)
37973143b9aSmrg    {
38073143b9aSmrg	/* Malloc failed */
38173143b9aSmrg	*port = NULL;
382fe567363Smrg	free (*host);
38373143b9aSmrg	*host = NULL;
384fe567363Smrg	free (*protocol);
38573143b9aSmrg	*protocol = NULL;
386fe567363Smrg	free (tmpptr);
38773143b9aSmrg	return 0;
38873143b9aSmrg    }
38973143b9aSmrg
390fe567363Smrg    free (tmpptr);
39173143b9aSmrg
39273143b9aSmrg    return 1;
39373143b9aSmrg}
39473143b9aSmrg
39573143b9aSmrg
39673143b9aSmrg/*
39773143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only
39873143b9aSmrg * funny part about this is the type parameter which is used to decide which
39973143b9aSmrg * type of open to perform.
40073143b9aSmrg */
40173143b9aSmrg
40273143b9aSmrgstatic XtransConnInfo
4036a3641a6SsnjTRANS(Open) (int type, const char *address)
40473143b9aSmrg
40573143b9aSmrg{
40673143b9aSmrg    char 		*protocol = NULL, *host = NULL, *port = NULL;
40773143b9aSmrg    XtransConnInfo	ciptr = NULL;
40873143b9aSmrg    Xtransport		*thistrans;
40973143b9aSmrg
410fe567363Smrg    prmsg (2,"Open(%d,%s)\n", type, address);
41173143b9aSmrg
412fe567363Smrg#if defined(WIN32) && defined(TCPCONN)
41373143b9aSmrg    if (TRANS(WSAStartup)())
41473143b9aSmrg    {
415fe567363Smrg	prmsg (1,"Open: WSAStartup failed\n");
41673143b9aSmrg	return NULL;
41773143b9aSmrg    }
41873143b9aSmrg#endif
41973143b9aSmrg
42073143b9aSmrg    /* Parse the Address */
42173143b9aSmrg
42273143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
42373143b9aSmrg    {
424fe567363Smrg	prmsg (1,"Open: Unable to Parse address %s\n", address);
42573143b9aSmrg	return NULL;
42673143b9aSmrg    }
42773143b9aSmrg
42873143b9aSmrg    /* Determine the transport type */
42973143b9aSmrg
43073143b9aSmrg    if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
43173143b9aSmrg    {
432fe567363Smrg	prmsg (1,"Open: Unable to find transport for %s\n",
433fe567363Smrg	       protocol);
43473143b9aSmrg
435fe567363Smrg	free (protocol);
436fe567363Smrg	free (host);
437fe567363Smrg	free (port);
43873143b9aSmrg	return NULL;
43973143b9aSmrg    }
44073143b9aSmrg
44173143b9aSmrg    /* Open the transport */
44273143b9aSmrg
44373143b9aSmrg    switch (type)
44473143b9aSmrg    {
44573143b9aSmrg    case XTRANS_OPEN_COTS_CLIENT:
44673143b9aSmrg#ifdef TRANS_CLIENT
44773143b9aSmrg	ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
44873143b9aSmrg#endif /* TRANS_CLIENT */
44973143b9aSmrg	break;
45073143b9aSmrg    case XTRANS_OPEN_COTS_SERVER:
45173143b9aSmrg#ifdef TRANS_SERVER
45273143b9aSmrg	ciptr = thistrans->OpenCOTSServer(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
4916a3641a6SsnjTRANS(Reopen) (int type, int trans_id, int fd, const 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    default:
533fe567363Smrg	prmsg (1,"Reopen: Bad Open type %d\n", type);
53473143b9aSmrg    }
53573143b9aSmrg
53673143b9aSmrg    if (ciptr == NULL)
53773143b9aSmrg    {
538fe567363Smrg	prmsg (1,"Reopen: transport open failed\n");
539fe567363Smrg	free (save_port);
54073143b9aSmrg	return NULL;
54173143b9aSmrg    }
54273143b9aSmrg
54373143b9aSmrg    ciptr->transptr = thistrans;
54473143b9aSmrg    ciptr->port = save_port;
54573143b9aSmrg
54673143b9aSmrg    return ciptr;
54773143b9aSmrg}
54873143b9aSmrg
54973143b9aSmrg#endif /* TRANS_REOPEN */
55073143b9aSmrg
55173143b9aSmrg
55273143b9aSmrg
55373143b9aSmrg/*
55473143b9aSmrg * These are the public interfaces to this Transport interface.
55573143b9aSmrg * These are the only functions that should have knowledge of the transport
55673143b9aSmrg * table.
55773143b9aSmrg */
55873143b9aSmrg
55973143b9aSmrg#ifdef TRANS_CLIENT
56073143b9aSmrg
56173143b9aSmrgXtransConnInfo
5626a3641a6SsnjTRANS(OpenCOTSClient) (const char *address)
56373143b9aSmrg
56473143b9aSmrg{
565fe567363Smrg    prmsg (2,"OpenCOTSClient(%s)\n", address);
56673143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
56773143b9aSmrg}
56873143b9aSmrg
56973143b9aSmrg#endif /* TRANS_CLIENT */
57073143b9aSmrg
57173143b9aSmrg
57273143b9aSmrg#ifdef TRANS_SERVER
57373143b9aSmrg
57473143b9aSmrgXtransConnInfo
5756a3641a6SsnjTRANS(OpenCOTSServer) (const char *address)
57673143b9aSmrg
57773143b9aSmrg{
578fe567363Smrg    prmsg (2,"OpenCOTSServer(%s)\n", address);
57973143b9aSmrg    return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
58073143b9aSmrg}
58173143b9aSmrg
58273143b9aSmrg#endif /* TRANS_SERVER */
58373143b9aSmrg
58473143b9aSmrg
58573143b9aSmrg#ifdef TRANS_REOPEN
58673143b9aSmrg
58773143b9aSmrgXtransConnInfo
5886a3641a6SsnjTRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port)
58973143b9aSmrg
59073143b9aSmrg{
591fe567363Smrg    prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
59273143b9aSmrg    return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
59373143b9aSmrg}
59473143b9aSmrg
59573143b9aSmrgint
596fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr,
59773143b9aSmrg		      int *trans_id, int *fd, char **port)
59873143b9aSmrg
59973143b9aSmrg{
60073143b9aSmrg    int i;
60173143b9aSmrg
60273143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
60373143b9aSmrg	if (Xtransports[i].transport == ciptr->transptr)
60473143b9aSmrg	{
60573143b9aSmrg	    *trans_id = Xtransports[i].transport_id;
60673143b9aSmrg	    *fd = ciptr->fd;
60773143b9aSmrg
608fe567363Smrg	    if ((*port = strdup (ciptr->port)) == NULL)
60973143b9aSmrg		return 0;
61073143b9aSmrg	    else
61173143b9aSmrg		return 1;
61273143b9aSmrg	}
61373143b9aSmrg
61473143b9aSmrg    return 0;
61573143b9aSmrg}
61673143b9aSmrg
61773143b9aSmrg#endif /* TRANS_REOPEN */
61873143b9aSmrg
61973143b9aSmrg
62073143b9aSmrgint
62173143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
62273143b9aSmrg
62373143b9aSmrg{
62473143b9aSmrg    int	fd = ciptr->fd;
62573143b9aSmrg    int	ret = 0;
62673143b9aSmrg
627fe567363Smrg    prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
62873143b9aSmrg
62973143b9aSmrg    /*
63073143b9aSmrg     * For now, all transport type use the same stuff for setting options.
63173143b9aSmrg     * As long as this is true, we can put the common code here. Once a more
63273143b9aSmrg     * complicated transport such as shared memory or an OSI implementation
63373143b9aSmrg     * that uses the session and application libraries is implemented, this
63473143b9aSmrg     * code may have to move to a transport dependent function.
63573143b9aSmrg     *
63673143b9aSmrg     * ret = ciptr->transptr->SetOption (ciptr, option, arg);
63773143b9aSmrg     */
63873143b9aSmrg
63973143b9aSmrg    switch (option)
64073143b9aSmrg    {
64173143b9aSmrg    case TRANS_NONBLOCKING:
64273143b9aSmrg	switch (arg)
64373143b9aSmrg	{
64473143b9aSmrg	case 0:
64573143b9aSmrg	    /* Set to blocking mode */
64673143b9aSmrg	    break;
64773143b9aSmrg	case 1: /* Set to non-blocking mode */
64873143b9aSmrg
649fe567363Smrg#if defined(O_NONBLOCK) && !defined(SCO325)
65073143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
65173143b9aSmrg	    if (ret != -1)
65273143b9aSmrg		ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
65373143b9aSmrg#else
65473143b9aSmrg#ifdef FIOSNBIO
65573143b9aSmrg	{
65673143b9aSmrg	    int arg;
65773143b9aSmrg	    arg = 1;
65873143b9aSmrg	    ret = ioctl (fd, FIOSNBIO, &arg);
65973143b9aSmrg	}
66073143b9aSmrg#else
661fe567363Smrg#if defined(WIN32)
66273143b9aSmrg	{
66373143b9aSmrg#ifdef WIN32
66473143b9aSmrg	    u_long arg;
66573143b9aSmrg#else
66673143b9aSmrg	    int arg;
66773143b9aSmrg#endif
66873143b9aSmrg	    arg = 1;
66973143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
67073143b9aSmrg * eventually with EWOULDBLOCK */
67173143b9aSmrg	    ret = ioctl (fd, FIONBIO, &arg);
67273143b9aSmrg	}
67373143b9aSmrg#else
67473143b9aSmrg	    ret = fcntl (fd, F_GETFL, 0);
67573143b9aSmrg#ifdef FNDELAY
67673143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | FNDELAY);
67773143b9aSmrg#else
67873143b9aSmrg	    ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
67973143b9aSmrg#endif
68073143b9aSmrg#endif /* AIXV3  || uniosu */
68173143b9aSmrg#endif /* FIOSNBIO */
68273143b9aSmrg#endif /* O_NONBLOCK */
68373143b9aSmrg	    break;
68473143b9aSmrg	default:
68573143b9aSmrg	    /* Unknown option */
68673143b9aSmrg	    break;
68773143b9aSmrg	}
68873143b9aSmrg	break;
68973143b9aSmrg    case TRANS_CLOSEONEXEC:
69073143b9aSmrg#ifdef F_SETFD
69173143b9aSmrg#ifdef FD_CLOEXEC
69273143b9aSmrg	ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
69373143b9aSmrg#else
69473143b9aSmrg	ret = fcntl (fd, F_SETFD, 1);
69573143b9aSmrg#endif /* FD_CLOEXEC */
69673143b9aSmrg#endif /* F_SETFD */
69773143b9aSmrg	break;
69873143b9aSmrg    }
699fe567363Smrg
70073143b9aSmrg    return ret;
70173143b9aSmrg}
70273143b9aSmrg
70373143b9aSmrg#ifdef TRANS_SERVER
70473143b9aSmrg
70573143b9aSmrgint
7066a3641a6SsnjTRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags)
70773143b9aSmrg
70873143b9aSmrg{
70973143b9aSmrg    return ciptr->transptr->CreateListener (ciptr, port, flags);
71073143b9aSmrg}
71173143b9aSmrg
71275ebec6dSmrgint
71375ebec6dSmrgTRANS(Received) (const char * protocol)
71475ebec6dSmrg
71575ebec6dSmrg{
71675ebec6dSmrg   Xtransport *trans;
71775ebec6dSmrg   int i = 0, ret = 0;
71875ebec6dSmrg
71975ebec6dSmrg   prmsg (5, "Received(%s)\n", protocol);
72075ebec6dSmrg
72175ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
72275ebec6dSmrg   {
72375ebec6dSmrg	prmsg (1,"Received: unable to find transport: %s\n",
72475ebec6dSmrg	       protocol);
72575ebec6dSmrg
72675ebec6dSmrg	return -1;
72775ebec6dSmrg   }
72875ebec6dSmrg   if (trans->flags & TRANS_ALIAS) {
72975ebec6dSmrg       if (trans->nolisten)
73075ebec6dSmrg	   while (trans->nolisten[i]) {
73175ebec6dSmrg	       ret |= TRANS(Received)(trans->nolisten[i]);
73275ebec6dSmrg	       i++;
73375ebec6dSmrg       }
73475ebec6dSmrg   }
73575ebec6dSmrg
73675ebec6dSmrg   trans->flags |= TRANS_RECEIVED;
73775ebec6dSmrg   return ret;
73875ebec6dSmrg}
73975ebec6dSmrg
74073143b9aSmrgint
741fe567363SmrgTRANS(NoListen) (const char * protocol)
742fe567363Smrg
74373143b9aSmrg{
74473143b9aSmrg   Xtransport *trans;
74573143b9aSmrg   int i = 0, ret = 0;
746fe567363Smrg
747fe567363Smrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
74873143b9aSmrg   {
749fe567363Smrg	prmsg (1,"TransNoListen: unable to find transport: %s\n",
750fe567363Smrg	       protocol);
75173143b9aSmrg
75273143b9aSmrg	return -1;
75373143b9aSmrg   }
75473143b9aSmrg   if (trans->flags & TRANS_ALIAS) {
75573143b9aSmrg       if (trans->nolisten)
75673143b9aSmrg	   while (trans->nolisten[i]) {
75773143b9aSmrg	       ret |= TRANS(NoListen)(trans->nolisten[i]);
75873143b9aSmrg	       i++;
75973143b9aSmrg       }
76073143b9aSmrg   }
76173143b9aSmrg
76273143b9aSmrg   trans->flags |= TRANS_NOLISTEN;
76373143b9aSmrg   return ret;
76473143b9aSmrg}
76573143b9aSmrg
7666a3641a6Ssnjint
7676a3641a6SsnjTRANS(Listen) (const char * protocol)
7686a3641a6Ssnj{
7696a3641a6Ssnj   Xtransport *trans;
7706a3641a6Ssnj   int i = 0, ret = 0;
7716a3641a6Ssnj
7726a3641a6Ssnj   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
7736a3641a6Ssnj   {
7746a3641a6Ssnj	prmsg (1,"TransListen: unable to find transport: %s\n",
7756a3641a6Ssnj	       protocol);
7766a3641a6Ssnj
7776a3641a6Ssnj	return -1;
7786a3641a6Ssnj   }
7796a3641a6Ssnj   if (trans->flags & TRANS_ALIAS) {
7806a3641a6Ssnj       if (trans->nolisten)
7816a3641a6Ssnj	   while (trans->nolisten[i]) {
7826a3641a6Ssnj	       ret |= TRANS(Listen)(trans->nolisten[i]);
7836a3641a6Ssnj	       i++;
7846a3641a6Ssnj       }
7856a3641a6Ssnj   }
7866a3641a6Ssnj
7876a3641a6Ssnj   trans->flags &= ~TRANS_NOLISTEN;
7886a3641a6Ssnj   return ret;
7896a3641a6Ssnj}
7906a3641a6Ssnj
79175ebec6dSmrgint
79275ebec6dSmrgTRANS(IsListening) (const char * protocol)
79375ebec6dSmrg{
79475ebec6dSmrg   Xtransport *trans;
79575ebec6dSmrg
79675ebec6dSmrg   if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
79775ebec6dSmrg   {
79875ebec6dSmrg	prmsg (1,"TransIsListening: unable to find transport: %s\n",
79975ebec6dSmrg	       protocol);
80075ebec6dSmrg
80175ebec6dSmrg	return 0;
80275ebec6dSmrg   }
80375ebec6dSmrg
80475ebec6dSmrg   return !(trans->flags & TRANS_NOLISTEN);
80575ebec6dSmrg}
80675ebec6dSmrg
80773143b9aSmrgint
80873143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr)
80973143b9aSmrg
81073143b9aSmrg{
81173143b9aSmrg    if (ciptr->transptr->ResetListener)
81273143b9aSmrg	return ciptr->transptr->ResetListener (ciptr);
81373143b9aSmrg    else
81473143b9aSmrg	return TRANS_RESET_NOOP;
81573143b9aSmrg}
81673143b9aSmrg
81773143b9aSmrg
81873143b9aSmrgXtransConnInfo
81973143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status)
82073143b9aSmrg
82173143b9aSmrg{
82273143b9aSmrg    XtransConnInfo	newciptr;
82373143b9aSmrg
824fe567363Smrg    prmsg (2,"Accept(%d)\n", ciptr->fd);
82573143b9aSmrg
82673143b9aSmrg    newciptr = ciptr->transptr->Accept (ciptr, status);
82773143b9aSmrg
82873143b9aSmrg    if (newciptr)
82973143b9aSmrg	newciptr->transptr = ciptr->transptr;
83073143b9aSmrg
83173143b9aSmrg    return newciptr;
83273143b9aSmrg}
83373143b9aSmrg
83473143b9aSmrg#endif /* TRANS_SERVER */
83573143b9aSmrg
83673143b9aSmrg
83773143b9aSmrg#ifdef TRANS_CLIENT
83873143b9aSmrg
83973143b9aSmrgint
8406a3641a6SsnjTRANS(Connect) (XtransConnInfo ciptr, const char *address)
84173143b9aSmrg
84273143b9aSmrg{
84373143b9aSmrg    char	*protocol;
84473143b9aSmrg    char	*host;
84573143b9aSmrg    char	*port;
84673143b9aSmrg    int		ret;
84773143b9aSmrg
848fe567363Smrg    prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address);
84973143b9aSmrg
85073143b9aSmrg    if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
85173143b9aSmrg    {
852fe567363Smrg	prmsg (1,"Connect: Unable to Parse address %s\n",
853fe567363Smrg	       address);
85473143b9aSmrg	return -1;
85573143b9aSmrg    }
85673143b9aSmrg
85773143b9aSmrg#ifdef HAVE_LAUNCHD
8588d4c0f7bSmrg    if (!host) host=strdup("");
85973143b9aSmrg#endif
86073143b9aSmrg
86173143b9aSmrg    if (!port || !*port)
86273143b9aSmrg    {
863fe567363Smrg	prmsg (1,"Connect: Missing port specification in %s\n",
864fe567363Smrg	      address);
865fe567363Smrg	if (protocol) free (protocol);
866fe567363Smrg	if (host) free (host);
86773143b9aSmrg	return -1;
86873143b9aSmrg    }
86973143b9aSmrg
87073143b9aSmrg    ret = ciptr->transptr->Connect (ciptr, host, port);
87173143b9aSmrg
872fe567363Smrg    if (protocol) free (protocol);
873fe567363Smrg    if (host) free (host);
874fe567363Smrg    if (port) free (port);
875fe567363Smrg
87673143b9aSmrg    return ret;
87773143b9aSmrg}
87873143b9aSmrg
87973143b9aSmrg#endif /* TRANS_CLIENT */
88073143b9aSmrg
88173143b9aSmrg
88273143b9aSmrgint
88373143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
88473143b9aSmrg
88573143b9aSmrg{
88673143b9aSmrg    return ciptr->transptr->BytesReadable (ciptr, pend);
88773143b9aSmrg}
88873143b9aSmrg
88973143b9aSmrgint
89073143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
89173143b9aSmrg
89273143b9aSmrg{
89373143b9aSmrg    return ciptr->transptr->Read (ciptr, buf, size);
89473143b9aSmrg}
89573143b9aSmrg
89673143b9aSmrgint
89773143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
89873143b9aSmrg
89973143b9aSmrg{
90073143b9aSmrg    return ciptr->transptr->Write (ciptr, buf, size);
90173143b9aSmrg}
90273143b9aSmrg
90373143b9aSmrgint
90473143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
90573143b9aSmrg
90673143b9aSmrg{
90773143b9aSmrg    return ciptr->transptr->Readv (ciptr, buf, size);
90873143b9aSmrg}
90973143b9aSmrg
91073143b9aSmrgint
91173143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
91273143b9aSmrg
91373143b9aSmrg{
91473143b9aSmrg    return ciptr->transptr->Writev (ciptr, buf, size);
91573143b9aSmrg}
91673143b9aSmrg
91775ebec6dSmrg#if XTRANS_SEND_FDS
91875ebec6dSmrgint
91975ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close)
92075ebec6dSmrg{
92175ebec6dSmrg    return ciptr->transptr->SendFd(ciptr, fd, do_close);
92275ebec6dSmrg}
92375ebec6dSmrg
92475ebec6dSmrgint
92575ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr)
92675ebec6dSmrg{
92775ebec6dSmrg    return ciptr->transptr->RecvFd(ciptr);
92875ebec6dSmrg}
92975ebec6dSmrg#endif
93075ebec6dSmrg
93173143b9aSmrgint
93273143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr)
93373143b9aSmrg
93473143b9aSmrg{
93573143b9aSmrg    return ciptr->transptr->Disconnect (ciptr);
93673143b9aSmrg}
93773143b9aSmrg
93873143b9aSmrgint
93973143b9aSmrgTRANS(Close) (XtransConnInfo ciptr)
94073143b9aSmrg
94173143b9aSmrg{
94273143b9aSmrg    int ret;
94373143b9aSmrg
944fe567363Smrg    prmsg (2,"Close(%d)\n", ciptr->fd);
94573143b9aSmrg
94673143b9aSmrg    ret = ciptr->transptr->Close (ciptr);
94773143b9aSmrg
94873143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
94973143b9aSmrg
95073143b9aSmrg    return ret;
95173143b9aSmrg}
95273143b9aSmrg
95373143b9aSmrgint
95473143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr)
95573143b9aSmrg
95673143b9aSmrg{
95773143b9aSmrg    int ret;
95873143b9aSmrg
959fe567363Smrg    prmsg (2,"CloseForCloning(%d)\n", ciptr->fd);
96073143b9aSmrg
96173143b9aSmrg    ret = ciptr->transptr->CloseForCloning (ciptr);
96273143b9aSmrg
96373143b9aSmrg    TRANS(FreeConnInfo) (ciptr);
96473143b9aSmrg
96573143b9aSmrg    return ret;
96673143b9aSmrg}
96773143b9aSmrg
96873143b9aSmrgint
96973143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr)
97073143b9aSmrg
97173143b9aSmrg{
97273143b9aSmrg    return (ciptr->family == AF_UNIX);
97373143b9aSmrg}
97473143b9aSmrg
97573143b9aSmrgint
976fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
97773143b9aSmrg		    Xtransaddr **addrp)
97873143b9aSmrg
97973143b9aSmrg{
980fe567363Smrg    prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd);
98173143b9aSmrg
98273143b9aSmrg    *familyp = ciptr->family;
98373143b9aSmrg    *addrlenp = ciptr->peeraddrlen;
98473143b9aSmrg
985fe567363Smrg    if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL)
98673143b9aSmrg    {
987fe567363Smrg	prmsg (1,"GetPeerAddr: malloc failed\n");
98873143b9aSmrg	return -1;
98973143b9aSmrg    }
99073143b9aSmrg    memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
99173143b9aSmrg
99273143b9aSmrg    return 0;
99373143b9aSmrg}
99473143b9aSmrg
99573143b9aSmrg
99673143b9aSmrgint
99773143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr)
99873143b9aSmrg
99973143b9aSmrg{
100073143b9aSmrg    return ciptr->fd;
100173143b9aSmrg}
100273143b9aSmrg
100373143b9aSmrg
100473143b9aSmrg/*
100573143b9aSmrg * These functions are really utility functions, but they require knowledge
100673143b9aSmrg * of the internal data structures, so they have to be part of the Transport
100773143b9aSmrg * Independant API.
100873143b9aSmrg */
100973143b9aSmrg
101073143b9aSmrg#ifdef TRANS_SERVER
101173143b9aSmrg
101273143b9aSmrgstatic int
101373143b9aSmrgcomplete_network_count (void)
101473143b9aSmrg
101573143b9aSmrg{
101673143b9aSmrg    int count = 0;
101773143b9aSmrg    int found_local = 0;
101873143b9aSmrg    int i;
101973143b9aSmrg
102073143b9aSmrg    /*
102173143b9aSmrg     * For a complete network, we only need one LOCALCONN transport to work
102273143b9aSmrg     */
102373143b9aSmrg
102473143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
102573143b9aSmrg    {
102673143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_ALIAS
102773143b9aSmrg   	 || Xtransports[i].transport->flags & TRANS_NOLISTEN)
102873143b9aSmrg	    continue;
102973143b9aSmrg
103073143b9aSmrg	if (Xtransports[i].transport->flags & TRANS_LOCAL)
103173143b9aSmrg	    found_local = 1;
103273143b9aSmrg	else
103373143b9aSmrg	    count++;
103473143b9aSmrg    }
103573143b9aSmrg
103673143b9aSmrg    return (count + found_local);
103773143b9aSmrg}
103873143b9aSmrg
103973143b9aSmrg
104075ebec6dSmrgstatic int
10416a3641a6Ssnjreceive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs,
10426a3641a6Ssnj                      int* count_ret)
104375ebec6dSmrg
104475ebec6dSmrg{
104575ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON
104675ebec6dSmrg    XtransConnInfo ciptr;
104775ebec6dSmrg    int i, systemd_listen_fds;
104875ebec6dSmrg
104975ebec6dSmrg    systemd_listen_fds = sd_listen_fds(1);
105075ebec6dSmrg    if (systemd_listen_fds < 0)
105175ebec6dSmrg    {
105275ebec6dSmrg        prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n",
105375ebec6dSmrg               strerror(-systemd_listen_fds));
105475ebec6dSmrg        return -1;
105575ebec6dSmrg    }
105675ebec6dSmrg
105775ebec6dSmrg    for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++)
105875ebec6dSmrg    {
105975ebec6dSmrg        struct sockaddr_storage a;
106075ebec6dSmrg        int ti;
106175ebec6dSmrg        const char* tn;
106275ebec6dSmrg        socklen_t al;
106375ebec6dSmrg
106475ebec6dSmrg        al = sizeof(a);
106575ebec6dSmrg        if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) {
106675ebec6dSmrg            prmsg (1, "receive_listening_fds: getsockname error: %s\n",
106775ebec6dSmrg                   strerror(errno));
106875ebec6dSmrg            return -1;
106975ebec6dSmrg        }
107075ebec6dSmrg
107175ebec6dSmrg        switch (a.ss_family)
107275ebec6dSmrg        {
107375ebec6dSmrg        case AF_UNIX:
107475ebec6dSmrg            ti = TRANS_SOCKET_UNIX_INDEX;
107575ebec6dSmrg            if (*((struct sockaddr_un*)&a)->sun_path == '\0' &&
107675ebec6dSmrg                al > sizeof(sa_family_t))
107775ebec6dSmrg                tn = "local";
107875ebec6dSmrg            else
107975ebec6dSmrg                tn = "unix";
108075ebec6dSmrg            break;
108175ebec6dSmrg        case AF_INET:
108275ebec6dSmrg            ti = TRANS_SOCKET_INET_INDEX;
108375ebec6dSmrg            tn = "inet";
108475ebec6dSmrg            break;
108575ebec6dSmrg#if defined(IPv6) && defined(AF_INET6)
108675ebec6dSmrg        case AF_INET6:
108775ebec6dSmrg            ti = TRANS_SOCKET_INET6_INDEX;
108875ebec6dSmrg            tn = "inet6";
108975ebec6dSmrg            break;
109075ebec6dSmrg#endif /* IPv6 */
109175ebec6dSmrg        default:
109275ebec6dSmrg            prmsg (1, "receive_listening_fds:"
109375ebec6dSmrg                   "Got unknown socket address family\n");
109475ebec6dSmrg            return -1;
109575ebec6dSmrg        }
109675ebec6dSmrg
109775ebec6dSmrg        ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port);
109875ebec6dSmrg        if (!ciptr)
109975ebec6dSmrg        {
110075ebec6dSmrg            prmsg (1, "receive_listening_fds:"
110175ebec6dSmrg                   "Got NULL while trying to reopen socket received from systemd.\n");
110275ebec6dSmrg            return -1;
110375ebec6dSmrg        }
110475ebec6dSmrg
110575ebec6dSmrg        prmsg (5, "receive_listening_fds: received listener for %s, %d\n",
110675ebec6dSmrg               tn, ciptr->fd);
110775ebec6dSmrg        temp_ciptrs[(*count_ret)++] = ciptr;
110875ebec6dSmrg        TRANS(Received)(tn);
110975ebec6dSmrg    }
111075ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */
111175ebec6dSmrg    return 0;
111275ebec6dSmrg}
111375ebec6dSmrg
11148d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11158d4c0f7bSmrgextern int xquartz_launchd_fd;
11168d4c0f7bSmrg#endif
111773143b9aSmrg
111873143b9aSmrgint
11196a3641a6SsnjTRANS(MakeAllCOTSServerListeners) (const char *port, int *partial,
11206a3641a6Ssnj                                   int *count_ret, XtransConnInfo **ciptrs_ret)
112173143b9aSmrg
112273143b9aSmrg{
112373143b9aSmrg    char		buffer[256]; /* ??? What size ?? */
112473143b9aSmrg    XtransConnInfo	ciptr, temp_ciptrs[NUMTRANS];
112573143b9aSmrg    int			status, i, j;
112673143b9aSmrg
112773143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
112873143b9aSmrg    int		ipv6_succ = 0;
112973143b9aSmrg#endif
1130fe567363Smrg    prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n",
1131fe567363Smrg	   port ? port : "NULL", ciptrs_ret);
113273143b9aSmrg
113373143b9aSmrg    *count_ret = 0;
113473143b9aSmrg
11358d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD
11368d4c0f7bSmrg    fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd);
11378d4c0f7bSmrg    if(xquartz_launchd_fd != -1) {
11388d4c0f7bSmrg        if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX,
11398d4c0f7bSmrg                                           xquartz_launchd_fd, getenv("DISPLAY"))))==NULL)
11408d4c0f7bSmrg            fprintf(stderr,"Got NULL while trying to Reopen launchd port\n");
1141fe567363Smrg        else
11428d4c0f7bSmrg            temp_ciptrs[(*count_ret)++] = ciptr;
11438d4c0f7bSmrg    }
114473143b9aSmrg#endif
114573143b9aSmrg
114675ebec6dSmrg    if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0)
114775ebec6dSmrg	return -1;
114875ebec6dSmrg
114973143b9aSmrg    for (i = 0; i < NUMTRANS; i++)
115073143b9aSmrg    {
115173143b9aSmrg	Xtransport *trans = Xtransports[i].transport;
115273143b9aSmrg	unsigned int flags = 0;
115373143b9aSmrg
115475ebec6dSmrg	if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN ||
115575ebec6dSmrg	    trans->flags&TRANS_RECEIVED)
115673143b9aSmrg	    continue;
115773143b9aSmrg
115873143b9aSmrg	snprintf(buffer, sizeof(buffer), "%s/:%s",
115973143b9aSmrg		 trans->TransName, port ? port : "");
116073143b9aSmrg
1161fe567363Smrg	prmsg (5,"MakeAllCOTSServerListeners: opening %s\n",
1162fe567363Smrg	       buffer);
116373143b9aSmrg
116473143b9aSmrg	if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
116573143b9aSmrg	{
116673143b9aSmrg	    if (trans->flags & TRANS_DISABLED)
116773143b9aSmrg		continue;
116873143b9aSmrg
1169fe567363Smrg	    prmsg (1,
117073143b9aSmrg	  "MakeAllCOTSServerListeners: failed to open listener for %s\n",
1171fe567363Smrg		  trans->TransName);
117273143b9aSmrg	    continue;
117373143b9aSmrg	}
117473143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
117573143b9aSmrg		if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
117673143b9aSmrg		     && ipv6_succ))
117773143b9aSmrg		    flags |= ADDR_IN_USE_ALLOWED;
117873143b9aSmrg#endif
117973143b9aSmrg
118073143b9aSmrg	if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
118173143b9aSmrg	{
118273143b9aSmrg	    if (status == TRANS_ADDR_IN_USE)
118373143b9aSmrg	    {
118473143b9aSmrg		/*
118573143b9aSmrg		 * We failed to bind to the specified address because the
118673143b9aSmrg		 * address is in use.  It must be that a server is already
118773143b9aSmrg		 * running at this address, and this function should fail.
118873143b9aSmrg		 */
118973143b9aSmrg
1190fe567363Smrg		prmsg (1,
1191fe567363Smrg		"MakeAllCOTSServerListeners: server already running\n");
119273143b9aSmrg
119373143b9aSmrg		for (j = 0; j < *count_ret; j++)
119473143b9aSmrg		    TRANS(Close) (temp_ciptrs[j]);
119573143b9aSmrg
119673143b9aSmrg		*count_ret = 0;
119773143b9aSmrg		*ciptrs_ret = NULL;
119873143b9aSmrg		*partial = 0;
119973143b9aSmrg		return -1;
120073143b9aSmrg	    }
120173143b9aSmrg	    else
120273143b9aSmrg	    {
1203fe567363Smrg		prmsg (1,
120473143b9aSmrg	"MakeAllCOTSServerListeners: failed to create listener for %s\n",
1205fe567363Smrg		  trans->TransName);
120673143b9aSmrg
120773143b9aSmrg		continue;
120873143b9aSmrg	    }
120973143b9aSmrg	}
121073143b9aSmrg
121173143b9aSmrg#if defined(IPv6) && defined(AF_INET6)
121273143b9aSmrg	if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
121373143b9aSmrg	    ipv6_succ = 1;
121473143b9aSmrg#endif
1215fe567363Smrg
1216fe567363Smrg	prmsg (5,
121773143b9aSmrg	      "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
1218fe567363Smrg	      trans->TransName, ciptr->fd);
121973143b9aSmrg
122073143b9aSmrg	temp_ciptrs[*count_ret] = ciptr;
122173143b9aSmrg	(*count_ret)++;
122273143b9aSmrg    }
122373143b9aSmrg
122473143b9aSmrg    *partial = (*count_ret < complete_network_count());
122573143b9aSmrg
1226fe567363Smrg    prmsg (5,
122773143b9aSmrg     "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
122873143b9aSmrg	*partial, *count_ret, complete_network_count());
122973143b9aSmrg
123073143b9aSmrg    if (*count_ret > 0)
123173143b9aSmrg    {
1232fe567363Smrg	if ((*ciptrs_ret = malloc (
123373143b9aSmrg	    *count_ret * sizeof (XtransConnInfo))) == NULL)
123473143b9aSmrg	{
123573143b9aSmrg	    return -1;
123673143b9aSmrg	}
123773143b9aSmrg
123873143b9aSmrg	for (i = 0; i < *count_ret; i++)
123973143b9aSmrg	{
124073143b9aSmrg	    (*ciptrs_ret)[i] = temp_ciptrs[i];
124173143b9aSmrg	}
124273143b9aSmrg    }
124373143b9aSmrg    else
124473143b9aSmrg	*ciptrs_ret = NULL;
1245fe567363Smrg
124673143b9aSmrg    return 0;
124773143b9aSmrg}
124873143b9aSmrg
124973143b9aSmrg#endif /* TRANS_SERVER */
125073143b9aSmrg
125173143b9aSmrg
125273143b9aSmrg
125373143b9aSmrg/*
125473143b9aSmrg * These routines are not part of the X Transport Interface, but they
125573143b9aSmrg * may be used by it.
125673143b9aSmrg */
125773143b9aSmrg
125873143b9aSmrg
12593d2ed3e3Smrg#ifdef WIN32
126073143b9aSmrg
126173143b9aSmrg/*
126273143b9aSmrg * emulate readv
126373143b9aSmrg */
126473143b9aSmrg
126573143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
126673143b9aSmrg
126773143b9aSmrg{
126873143b9aSmrg    int i, len, total;
126973143b9aSmrg    char *base;
127073143b9aSmrg
127173143b9aSmrg    ESET(0);
127273143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
127373143b9aSmrg	len = iov->iov_len;
127473143b9aSmrg	base = iov->iov_base;
127573143b9aSmrg	while (len > 0) {
127673143b9aSmrg	    register int nbytes;
127773143b9aSmrg	    nbytes = TRANS(Read) (ciptr, base, len);
127873143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
127973143b9aSmrg	    if (nbytes <= 0)  return total;
128073143b9aSmrg	    ESET(0);
128173143b9aSmrg	    len   -= nbytes;
128273143b9aSmrg	    total += nbytes;
128373143b9aSmrg	    base  += nbytes;
128473143b9aSmrg	}
128573143b9aSmrg    }
128673143b9aSmrg    return total;
128773143b9aSmrg}
128873143b9aSmrg
128973143b9aSmrg
129073143b9aSmrg/*
129173143b9aSmrg * emulate writev
129273143b9aSmrg */
129373143b9aSmrg
129473143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
129573143b9aSmrg
129673143b9aSmrg{
129773143b9aSmrg    int i, len, total;
129873143b9aSmrg    char *base;
129973143b9aSmrg
130073143b9aSmrg    ESET(0);
130173143b9aSmrg    for (i = 0, total = 0;  i < iovcnt;  i++, iov++) {
130273143b9aSmrg	len = iov->iov_len;
130373143b9aSmrg	base = iov->iov_base;
130473143b9aSmrg	while (len > 0) {
130573143b9aSmrg	    register int nbytes;
130673143b9aSmrg	    nbytes = TRANS(Write) (ciptr, base, len);
130773143b9aSmrg	    if (nbytes < 0 && total == 0)  return -1;
130873143b9aSmrg	    if (nbytes <= 0)  return total;
130973143b9aSmrg	    ESET(0);
131073143b9aSmrg	    len   -= nbytes;
131173143b9aSmrg	    total += nbytes;
131273143b9aSmrg	    base  += nbytes;
131373143b9aSmrg	}
131473143b9aSmrg    }
131573143b9aSmrg    return total;
131673143b9aSmrg}
131773143b9aSmrg
13183d2ed3e3Smrg#endif /* WIN32 */
131973143b9aSmrg
132073143b9aSmrg
1321e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__)
132273143b9aSmrg#ifndef NEED_UTSNAME
132373143b9aSmrg#define NEED_UTSNAME
132473143b9aSmrg#endif
132573143b9aSmrg#include <sys/utsname.h>
132673143b9aSmrg#endif
132773143b9aSmrg
132873143b9aSmrg/*
132973143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing.
133073143b9aSmrg */
133173143b9aSmrg
133273143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen)
133373143b9aSmrg
133473143b9aSmrg{
133573143b9aSmrg    int len;
133673143b9aSmrg
133773143b9aSmrg#ifdef NEED_UTSNAME
133873143b9aSmrg    struct utsname name;
133973143b9aSmrg
134073143b9aSmrg    uname (&name);
134173143b9aSmrg    len = strlen (name.nodename);
134273143b9aSmrg    if (len >= maxlen) len = maxlen - 1;
134373143b9aSmrg    strncpy (buf, name.nodename, len);
134473143b9aSmrg    buf[len] = '\0';
134573143b9aSmrg#else
134673143b9aSmrg    buf[0] = '\0';
134773143b9aSmrg    (void) gethostname (buf, maxlen);
134873143b9aSmrg    buf [maxlen - 1] = '\0';
134973143b9aSmrg    len = strlen(buf);
135073143b9aSmrg#endif /* NEED_UTSNAME */
135173143b9aSmrg    return len;
135273143b9aSmrg}
1353