aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/xtrans
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
committerReinhard Tartler <siretart@tauware.de>2011-10-10 17:43:39 +0200
commitf4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch)
tree2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/xtrans
parenta840692edc9c6d19cd7c057f68e39c7d95eb767d (diff)
downloadnx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2
nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository
Diffstat (limited to 'nx-X11/lib/xtrans')
-rw-r--r--nx-X11/lib/xtrans/Imakefile24
-rw-r--r--nx-X11/lib/xtrans/Xtrans.c1402
-rw-r--r--nx-X11/lib/xtrans/Xtrans.h490
-rw-r--r--nx-X11/lib/xtrans/Xtransdnet.c668
-rw-r--r--nx-X11/lib/xtrans/Xtransint.h485
-rw-r--r--nx-X11/lib/xtrans/Xtranslcl.c2755
-rw-r--r--nx-X11/lib/xtrans/Xtransos2.c887
-rw-r--r--nx-X11/lib/xtrans/Xtranssock.c3417
-rw-r--r--nx-X11/lib/xtrans/Xtranssock.c.NX.original3417
-rw-r--r--nx-X11/lib/xtrans/Xtranssock.c.X.original2504
-rw-r--r--nx-X11/lib/xtrans/Xtranstli.c1422
-rw-r--r--nx-X11/lib/xtrans/Xtransutil.c691
-rw-r--r--nx-X11/lib/xtrans/transport.c86
13 files changed, 18248 insertions, 0 deletions
diff --git a/nx-X11/lib/xtrans/Imakefile b/nx-X11/lib/xtrans/Imakefile
new file mode 100644
index 000000000..e29a38591
--- /dev/null
+++ b/nx-X11/lib/xtrans/Imakefile
@@ -0,0 +1,24 @@
+XCOMM $Xorg: Imakefile,v 1.3 2000/08/17 19:46:44 cpqbld Exp $
+
+#define IncSubdir X11
+
+all::
+
+DEFINES = $(FAILDEFINES)
+
+# Since xtrans source is #include'd into software that uses it, we install
+# the .c files as if they were headers.
+HEADERS = \
+ Xtrans.h \
+ Xtrans.c \
+ Xtransdnet.c \
+ Xtransint.h \
+ Xtranslcl.c \
+ Xtransos2.c \
+ Xtranssock.c \
+ Xtranstli.c \
+ Xtransutil.c \
+ transport.c
+
+DependTarget()
+BuildIncludes($(HEADERS),IncSubdir/Xtrans,../..)
diff --git a/nx-X11/lib/xtrans/Xtrans.c b/nx-X11/lib/xtrans/Xtrans.c
new file mode 100644
index 000000000..a6bfbedc6
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtrans.c
@@ -0,0 +1,1402 @@
+/* $XdotOrg: xc/lib/xtrans/Xtrans.c,v 1.6 2005/11/08 06:33:26 jkj Exp $ */
+/* $Xorg: Xtrans.c,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtrans.c,v 3.33 2003/08/11 17:41:29 eich Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ctype.h>
+
+/*
+ * The transport table contains a definition for every transport (protocol)
+ * family. All operations that can be made on the transport go through this
+ * table.
+ *
+ * Each transport is assigned a unique transport id.
+ *
+ * New transports can be added by adding an entry in this table.
+ * For compatiblity, the transport ids should never be renumbered.
+ * Always add to the end of the list.
+ */
+
+#define TRANS_TLI_INET_INDEX 1
+#define TRANS_TLI_TCP_INDEX 2
+#define TRANS_TLI_TLI_INDEX 3
+#define TRANS_SOCKET_UNIX_INDEX 4
+#define TRANS_SOCKET_LOCAL_INDEX 5
+#define TRANS_SOCKET_INET_INDEX 6
+#define TRANS_SOCKET_TCP_INDEX 7
+#define TRANS_DNET_INDEX 8
+#define TRANS_LOCAL_LOCAL_INDEX 9
+#define TRANS_LOCAL_PTS_INDEX 10
+#define TRANS_LOCAL_NAMED_INDEX 11
+#define TRANS_LOCAL_ISC_INDEX 12
+#define TRANS_LOCAL_SCO_INDEX 13
+#define TRANS_SOCKET_INET6_INDEX 14
+
+
+static
+Xtransport_table Xtransports[] = {
+#if defined(STREAMSCONN)
+ { &TRANS(TLITCPFuncs), TRANS_TLI_TCP_INDEX },
+ { &TRANS(TLIINETFuncs), TRANS_TLI_INET_INDEX },
+ { &TRANS(TLITLIFuncs), TRANS_TLI_TLI_INDEX },
+#endif /* STREAMSCONN */
+#if defined(TCPCONN)
+ { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX },
+#if defined(IPv6) && defined(AF_INET6)
+ { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX },
+#endif /* IPv6 */
+ { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX },
+#endif /* TCPCONN */
+#if defined(DNETCONN)
+ { &TRANS(DNETFuncs), TRANS_DNET_INDEX },
+#endif /* DNETCONN */
+#if defined(UNIXCONN)
+#if !defined(LOCALCONN)
+ { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX },
+#endif /* !LOCALCONN */
+ { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX },
+#endif /* UNIXCONN */
+#if defined(OS2PIPECONN)
+ { &TRANS(OS2LocalFuncs), TRANS_LOCAL_LOCAL_INDEX },
+#endif /* OS2PIPECONN */
+#if defined(LOCALCONN)
+ { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX },
+#ifndef sun
+ { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX },
+#endif /* sun */
+#ifdef SVR4
+ { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX },
+#endif
+#ifndef sun
+#if !defined(__SCO__) && !defined(__UNIXWARE__)
+ { &TRANS(ISCFuncs), TRANS_LOCAL_ISC_INDEX },
+#endif
+ { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX },
+#endif /* sun */
+#endif /* LOCALCONN */
+};
+
+#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table))
+
+
+#ifdef WIN32
+#define ioctl ioctlsocket
+#endif
+
+
+
+/*
+ * These are a few utility function used by the public interface functions.
+ */
+
+void
+TRANS(FreeConnInfo) (XtransConnInfo ciptr)
+
+{
+ PRMSG (3,"FreeConnInfo(%p)\n", ciptr, 0, 0);
+
+ if (ciptr->addr)
+ xfree (ciptr->addr);
+
+ if (ciptr->peeraddr)
+ xfree (ciptr->peeraddr);
+
+ if (ciptr->port)
+ xfree (ciptr->port);
+
+ xfree ((char *) ciptr);
+}
+
+
+#define PROTOBUFSIZE 20
+
+static Xtransport *
+TRANS(SelectTransport) (char *protocol)
+
+{
+ char protobuf[PROTOBUFSIZE];
+ int i;
+
+ PRMSG (3,"SelectTransport(%s)\n", protocol, 0, 0);
+
+ /*
+ * Force Protocol to be lowercase as a way of doing
+ * a case insensitive match.
+ */
+
+ strncpy (protobuf, protocol, PROTOBUFSIZE - 1);
+ protobuf[PROTOBUFSIZE-1] = '\0';
+
+ for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++)
+ if (isupper (protobuf[i]))
+ protobuf[i] = tolower (protobuf[i]);
+
+ /* Look at all of the configured protocols */
+
+ for (i = 0; i < NUMTRANS; i++)
+ {
+ if (!strcmp (protobuf, Xtransports[i].transport->TransName))
+ return Xtransports[i].transport;
+ }
+
+ return NULL;
+}
+
+#ifndef TEST_t
+static
+#endif /* TEST_t */
+int
+TRANS(ParseAddress) (char *address, char **protocol, char **host, char **port)
+
+{
+ /*
+ * For the font library, the address is a string formatted
+ * as "protocol/host:port[/catalogue]". Note that the catologue
+ * is optional. At this time, the catologue info is ignored, but
+ * we have to parse it anyways.
+ *
+ * Other than fontlib, the address is a string formatted
+ * as "protocol/host:port".
+ *
+ * If the protocol part is missing, then assume TCP.
+ * If the protocol part and host part are missing, then assume local.
+ * If a "::" is found then assume DNET.
+ */
+
+ char *mybuf, *tmpptr;
+ char *_protocol, *_host, *_port;
+ char hostnamebuf[256];
+ int _host_len;
+
+ PRMSG (3,"ParseAddress(%s)\n", address, 0, 0);
+
+ /* Copy the string so it can be changed */
+
+ tmpptr = mybuf = (char *) xalloc (strlen (address) + 1);
+ strcpy (mybuf, address);
+
+ /* Parse the string to get each component */
+
+ /* Get the protocol part */
+
+ _protocol = mybuf;
+
+
+ if ( ((mybuf = strchr (mybuf,'/')) == NULL) &&
+ ((mybuf = strrchr (tmpptr,':')) == NULL) )
+ {
+ /* address is in a bad format */
+ *protocol = NULL;
+ *host = NULL;
+ *port = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+
+ if (*mybuf == ':')
+ {
+ /*
+ * If there is a hostname, then assume tcp, otherwise
+ * it must be local.
+ */
+ if (mybuf == tmpptr)
+ {
+ /* There is neither a protocol or host specified */
+ _protocol = "local";
+ }
+ else
+ {
+ /* There is a hostname specified */
+ _protocol = "tcp";
+ mybuf = tmpptr; /* reset to the begining of the host ptr */
+ }
+ }
+ else
+ {
+ /* *mybuf == '/' */
+
+ *mybuf ++= '\0'; /* put a null at the end of the protocol */
+
+ if (strlen(_protocol) == 0)
+ {
+ /*
+ * If there is a hostname, then assume tcp, otherwise
+ * it must be local.
+ */
+ if (*mybuf != ':')
+ _protocol = "tcp";
+ else
+ _protocol = "local";
+ }
+ }
+
+ /* Get the host part */
+
+ _host = mybuf;
+
+ if ((mybuf = strrchr (mybuf,':')) == NULL)
+ {
+ *protocol = NULL;
+ *host = NULL;
+ *port = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+
+ /* Check for DECnet */
+
+ if ((mybuf != _host) && (*(mybuf - 1) == ':')
+#if defined(IPv6) && defined(AF_INET6)
+ /* An IPv6 address can end in :: so three : in a row is assumed to be
+ an IPv6 host and not a DECnet node with a : in it's name, unless
+ DECnet is specifically requested */
+ && ( ((mybuf - 1) == _host) || (*(mybuf - 2) != ':') ||
+ ((_protocol != NULL) && (strcmp(_protocol, "dnet") == 0)) )
+#endif
+ )
+ {
+ _protocol = "dnet";
+ *(mybuf - 1) = '\0';
+ }
+
+ *mybuf ++= '\0';
+
+ _host_len = strlen(_host);
+ if (_host_len == 0)
+ {
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+ _host = hostnamebuf;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ /* hostname in IPv6 [numeric_addr]:0 form? */
+ else if ( (_host_len > 3) &&
+ ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0))
+ && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) {
+ struct sockaddr_in6 sin6;
+
+ *(_host + _host_len - 1) = '\0';
+
+ /* Verify address is valid IPv6 numeric form */
+ if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) {
+ /* It is. Use it as such. */
+ _host++;
+ _protocol = "inet6";
+ } else {
+ /* It's not, restore it just in case some other code can use it. */
+ *(_host + _host_len - 1) = ']';
+ }
+ }
+#endif
+
+
+ /* Get the port */
+
+ _port = mybuf;
+
+#if defined(FONT_t) || defined(FS_t)
+ /*
+ * Is there an optional catalogue list?
+ */
+
+ if ((mybuf = strchr (mybuf,'/')) != NULL)
+ *mybuf ++= '\0';
+
+ /*
+ * The rest, if any, is the (currently unused) catalogue list.
+ *
+ * _catalogue = mybuf;
+ */
+#endif
+
+ /*
+ * Now that we have all of the components, allocate new
+ * string space for them.
+ */
+
+ if ((*protocol = (char *) xalloc(strlen (_protocol) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ *host = NULL;
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*protocol, _protocol);
+
+ if ((*host = (char *) xalloc (strlen (_host) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ *host = NULL;
+ xfree (*protocol);
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*host, _host);
+
+ if ((*port = (char *) xalloc (strlen (_port) + 1)) == NULL)
+ {
+ /* Malloc failed */
+ *port = NULL;
+ xfree (*host);
+ *host = NULL;
+ xfree (*protocol);
+ *protocol = NULL;
+ xfree (tmpptr);
+ return 0;
+ }
+ else
+ strcpy (*port, _port);
+
+ xfree (tmpptr);
+
+ return 1;
+}
+
+
+/*
+ * TRANS(Open) does all of the real work opening a connection. The only
+ * funny part about this is the type parameter which is used to decide which
+ * type of open to perform.
+ */
+
+static XtransConnInfo
+TRANS(Open) (int type, char *address)
+
+{
+ char *protocol = NULL, *host = NULL, *port = NULL;
+ XtransConnInfo ciptr = NULL;
+ Xtransport *thistrans;
+
+ PRMSG (2,"Open(%d,%s)\n", type, address, 0);
+
+#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+ if (TRANS(WSAStartup)())
+ {
+ PRMSG (1,"Open: WSAStartup failed\n", 0, 0, 0);
+ return NULL;
+ }
+#endif
+
+ /* Parse the Address */
+
+ if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
+ {
+ PRMSG (1,"Open: Unable to Parse address %s\n", address, 0, 0);
+ return NULL;
+ }
+
+ /* Determine the transport type */
+
+ if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL)
+ {
+ PRMSG (1,"Open: Unable to find transport for %s\n",
+ protocol, 0, 0);
+
+ xfree (protocol);
+ xfree (host);
+ xfree (port);
+ return NULL;
+ }
+
+ /* Open the transport */
+
+ switch (type)
+ {
+ case XTRANS_OPEN_COTS_CLIENT:
+#ifdef TRANS_CLIENT
+ ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port);
+#endif /* TRANS_CLIENT */
+ break;
+ case XTRANS_OPEN_COTS_SERVER:
+#ifdef TRANS_SERVER
+ ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port);
+#endif /* TRANS_SERVER */
+ break;
+ case XTRANS_OPEN_CLTS_CLIENT:
+#ifdef TRANS_CLIENT
+ ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port);
+#endif /* TRANS_CLIENT */
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+#ifdef TRANS_SERVER
+ ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port);
+#endif /* TRANS_SERVER */
+ break;
+ default:
+ PRMSG (1,"Open: Unknown Open type %d\n", type, 0, 0);
+ }
+
+ if (ciptr == NULL)
+ {
+ if (!(thistrans->flags & TRANS_DISABLED))
+ {
+ PRMSG (1,"Open: transport open failed for %s/%s:%s\n",
+ protocol, host, port);
+ }
+ xfree (protocol);
+ xfree (host);
+ xfree (port);
+ return NULL;
+ }
+
+ ciptr->transptr = thistrans;
+ ciptr->port = port; /* We need this for TRANS(Reopen) */
+
+ xfree (protocol);
+ xfree (host);
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+/*
+ * We might want to create an XtransConnInfo object based on a previously
+ * opened connection. For example, the font server may clone itself and
+ * pass file descriptors to the parent.
+ */
+
+static XtransConnInfo
+TRANS(Reopen) (int type, int trans_id, int fd, char *port)
+
+{
+ XtransConnInfo ciptr = NULL;
+ Xtransport *thistrans = NULL;
+ char *save_port;
+ int i;
+
+ PRMSG (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port);
+
+ /* Determine the transport type */
+
+ for (i = 0; i < NUMTRANS; i++)
+ if (Xtransports[i].transport_id == trans_id)
+ {
+ thistrans = Xtransports[i].transport;
+ break;
+ }
+
+ if (thistrans == NULL)
+ {
+ PRMSG (1,"Reopen: Unable to find transport id %d\n",
+ trans_id, 0, 0);
+
+ return NULL;
+ }
+
+ if ((save_port = (char *) xalloc (strlen (port) + 1)) == NULL)
+ {
+ PRMSG (1,"Reopen: Unable to malloc port string\n", 0, 0, 0);
+
+ return NULL;
+ }
+
+ strcpy (save_port, port);
+
+ /* Get a new XtransConnInfo object */
+
+ switch (type)
+ {
+ case XTRANS_OPEN_COTS_SERVER:
+ ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port);
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+ ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port);
+ break;
+ default:
+ PRMSG (1,"Reopen: Bad Open type %d\n", type, 0, 0);
+ }
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1,"Reopen: transport open failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->transptr = thistrans;
+ ciptr->port = save_port;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+/*
+ * These are the public interfaces to this Transport interface.
+ * These are the only functions that should have knowledge of the transport
+ * table.
+ */
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo
+TRANS(OpenCOTSClient) (char *address)
+
+{
+ PRMSG (2,"OpenCOTSClient(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo
+TRANS(OpenCOTSServer) (char *address)
+
+{
+ PRMSG (2,"OpenCOTSServer(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo
+TRANS(OpenCLTSClient) (char *address)
+
+{
+ PRMSG (2,"OpenCLTSClient(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo
+TRANS(OpenCLTSServer) (char *address)
+
+{
+ PRMSG (2,"OpenCLTSServer(%s)\n", address, 0, 0);
+ return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+XtransConnInfo
+TRANS(ReopenCOTSServer) (int trans_id, int fd, char *port)
+
+{
+ PRMSG (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port);
+ return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port);
+}
+
+XtransConnInfo
+TRANS(ReopenCLTSServer) (int trans_id, int fd, char *port)
+
+{
+ PRMSG (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port);
+ return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port);
+}
+
+
+int
+TRANS(GetReopenInfo) (XtransConnInfo ciptr,
+ int *trans_id, int *fd, char **port)
+
+{
+ int i;
+
+ for (i = 0; i < NUMTRANS; i++)
+ if (Xtransports[i].transport == ciptr->transptr)
+ {
+ *trans_id = Xtransports[i].transport_id;
+ *fd = ciptr->fd;
+
+ if ((*port = (char *) xalloc (strlen (ciptr->port) + 1)) == NULL)
+ return 0;
+ else
+ {
+ strcpy (*port, ciptr->port);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+int
+TRANS(SetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ int fd = ciptr->fd;
+ int ret = 0;
+
+ PRMSG (2,"SetOption(%d,%d,%d)\n", fd, option, arg);
+
+ /*
+ * For now, all transport type use the same stuff for setting options.
+ * As long as this is true, we can put the common code here. Once a more
+ * complicated transport such as shared memory or an OSI implementation
+ * that uses the session and application libraries is implemented, this
+ * code may have to move to a transport dependent function.
+ *
+ * ret = ciptr->transptr->SetOption (ciptr, option, arg);
+ */
+
+ switch (option)
+ {
+ case TRANS_NONBLOCKING:
+ switch (arg)
+ {
+ case 0:
+ /* Set to blocking mode */
+ break;
+ case 1: /* Set to non-blocking mode */
+
+#if defined(O_NONBLOCK) && (!defined(ultrix) && !defined(hpux) && !defined(AIXV3) && !defined(uniosu) && !defined(__UNIXOS2__) && !defined(SCO325)) && !defined(__QNX__)
+ ret = fcntl (fd, F_GETFL, 0);
+ if (ret != -1)
+ ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK);
+#else
+#ifdef FIOSNBIO
+ {
+ int arg;
+ arg = 1;
+ ret = ioctl (fd, FIOSNBIO, &arg);
+ }
+#else
+#if (defined(AIXV3) || defined(uniosu) || defined(WIN32) || defined(__UNIXOS2__) || defined(__QNX__)) && defined(FIONBIO)
+ {
+#ifdef WIN32
+ u_long arg;
+#else
+ int arg;
+#endif
+ arg = 1;
+/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail
+ * eventually with EWOULDBLOCK */
+#ifndef __UNIXOS2__
+ ret = ioctl (fd, FIONBIO, &arg);
+#else
+/* ret = ioctl(fd, FIONBIO, &arg, sizeof(int));*/
+#endif
+ }
+#else
+ ret = fcntl (fd, F_GETFL, 0);
+#ifdef FNDELAY
+ ret = fcntl (fd, F_SETFL, ret | FNDELAY);
+#else
+ ret = fcntl (fd, F_SETFL, ret | O_NDELAY);
+#endif
+#endif /* AIXV3 || uniosu */
+#endif /* FIOSNBIO */
+#endif /* O_NONBLOCK */
+ break;
+ default:
+ /* Unknown option */
+ break;
+ }
+ break;
+ case TRANS_CLOSEONEXEC:
+#ifdef F_SETFD
+#ifdef FD_CLOEXEC
+ ret = fcntl (fd, F_SETFD, FD_CLOEXEC);
+#else
+ ret = fcntl (fd, F_SETFD, 1);
+#endif /* FD_CLOEXEC */
+#endif /* F_SETFD */
+ break;
+ }
+
+ return ret;
+}
+
+#ifdef TRANS_SERVER
+
+int
+TRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+ return ciptr->transptr->CreateListener (ciptr, port, flags);
+}
+
+int
+TRANS(NoListen) (char * protocol)
+
+{
+ Xtransport *trans;
+ int i = 0, ret = 0;
+
+ if ((trans = TRANS(SelectTransport)(protocol)) == NULL)
+ {
+ PRMSG (1,"TransNoListen: unable to find transport: %s\n",
+ protocol, 0, 0);
+
+ return -1;
+ }
+ if (trans->flags & TRANS_ALIAS) {
+ if (trans->nolisten)
+ while (trans->nolisten[i]) {
+ ret |= TRANS(NoListen)(trans->nolisten[i]);
+ i++;
+ }
+ }
+
+ trans->flags |= TRANS_NOLISTEN;
+ return ret;
+}
+
+int
+TRANS(ResetListener) (XtransConnInfo ciptr)
+
+{
+ if (ciptr->transptr->ResetListener)
+ return ciptr->transptr->ResetListener (ciptr);
+ else
+ return TRANS_RESET_NOOP;
+}
+
+
+XtransConnInfo
+TRANS(Accept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+
+ PRMSG (2,"Accept(%d)\n", ciptr->fd, 0, 0);
+
+ newciptr = ciptr->transptr->Accept (ciptr, status);
+
+ if (newciptr)
+ newciptr->transptr = ciptr->transptr;
+
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+int
+TRANS(Connect) (XtransConnInfo ciptr, char *address)
+
+{
+ char *protocol;
+ char *host;
+ char *port;
+ int ret;
+
+ PRMSG (2,"Connect(%d,%s)\n", ciptr->fd, address, 0);
+
+ if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0)
+ {
+ PRMSG (1,"Connect: Unable to Parse address %s\n",
+ address, 0, 0);
+ return -1;
+ }
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"Connect: Missing port specification in %s\n",
+ address, 0, 0);
+ if (protocol) xfree (protocol);
+ if (host) xfree (host);
+ return -1;
+ }
+
+ ret = ciptr->transptr->Connect (ciptr, host, port);
+
+ if (protocol) xfree (protocol);
+ if (host) xfree (host);
+ if (port) xfree (port);
+
+ return ret;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+int
+TRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ return ciptr->transptr->BytesReadable (ciptr, pend);
+}
+
+int
+TRANS(Read) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ return ciptr->transptr->Read (ciptr, buf, size);
+}
+
+int
+TRANS(Write) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ return ciptr->transptr->Write (ciptr, buf, size);
+}
+
+int
+TRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ return ciptr->transptr->Readv (ciptr, buf, size);
+}
+
+int
+TRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ return ciptr->transptr->Writev (ciptr, buf, size);
+}
+
+int
+TRANS(Disconnect) (XtransConnInfo ciptr)
+
+{
+ return ciptr->transptr->Disconnect (ciptr);
+}
+
+int
+TRANS(Close) (XtransConnInfo ciptr)
+
+{
+ int ret;
+
+ PRMSG (2,"Close(%d)\n", ciptr->fd, 0, 0);
+
+ ret = ciptr->transptr->Close (ciptr);
+
+ TRANS(FreeConnInfo) (ciptr);
+
+ return ret;
+}
+
+int
+TRANS(CloseForCloning) (XtransConnInfo ciptr)
+
+{
+ int ret;
+
+ PRMSG (2,"CloseForCloning(%d)\n", ciptr->fd, 0, 0);
+
+ ret = ciptr->transptr->CloseForCloning (ciptr);
+
+ TRANS(FreeConnInfo) (ciptr);
+
+ return ret;
+}
+
+int
+TRANS(IsLocal) (XtransConnInfo ciptr)
+
+{
+ return (ciptr->family == AF_UNIX);
+}
+
+
+int
+TRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
+ Xtransaddr **addrp)
+
+{
+ PRMSG (2,"GetMyAddr(%d)\n", ciptr->fd, 0, 0);
+
+ *familyp = ciptr->family;
+ *addrlenp = ciptr->addrlen;
+
+ if ((*addrp = (Xtransaddr *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,"GetMyAddr: malloc failed\n", 0, 0, 0);
+ return -1;
+ }
+ memcpy(*addrp, ciptr->addr, ciptr->addrlen);
+
+ return 0;
+}
+
+int
+TRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp,
+ Xtransaddr **addrp)
+
+{
+ PRMSG (2,"GetPeerAddr(%d)\n", ciptr->fd, 0, 0);
+
+ *familyp = ciptr->family;
+ *addrlenp = ciptr->peeraddrlen;
+
+ if ((*addrp = (Xtransaddr *) xalloc (ciptr->peeraddrlen)) == NULL)
+ {
+ PRMSG (1,"GetPeerAddr: malloc failed\n", 0, 0, 0);
+ return -1;
+ }
+ memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+int
+TRANS(GetConnectionNumber) (XtransConnInfo ciptr)
+
+{
+ return ciptr->fd;
+}
+
+
+/*
+ * These functions are really utility functions, but they require knowledge
+ * of the internal data structures, so they have to be part of the Transport
+ * Independant API.
+ */
+
+#ifdef TRANS_SERVER
+
+static int
+complete_network_count (void)
+
+{
+ int count = 0;
+ int found_local = 0;
+ int i;
+
+ /*
+ * For a complete network, we only need one LOCALCONN transport to work
+ */
+
+ for (i = 0; i < NUMTRANS; i++)
+ {
+ if (Xtransports[i].transport->flags & TRANS_ALIAS
+ || Xtransports[i].transport->flags & TRANS_NOLISTEN)
+ continue;
+
+ if (Xtransports[i].transport->flags & TRANS_LOCAL)
+ found_local = 1;
+ else
+ count++;
+ }
+
+ return (count + found_local);
+}
+
+
+
+int
+TRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret,
+ XtransConnInfo **ciptrs_ret)
+
+{
+ char buffer[256]; /* ??? What size ?? */
+ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
+ int status, i, j;
+#if defined(IPv6) && defined(AF_INET6)
+ int ipv6_succ = 0;
+#endif
+
+ PRMSG (2,"MakeAllCOTSServerListeners(%s,%p)\n",
+ port ? port : "NULL", ciptrs_ret, 0);
+
+ *count_ret = 0;
+
+ for (i = 0; i < NUMTRANS; i++)
+ {
+ Xtransport *trans = Xtransports[i].transport;
+ unsigned int flags = 0;
+
+ if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
+ continue;
+
+ sprintf(buffer,"%s/:%s", trans->TransName, port ? port : "");
+
+ PRMSG (5,"MakeAllCOTSServerListeners: opening %s\n",
+ buffer, 0, 0);
+
+ if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL)
+ {
+ if (trans->flags & TRANS_DISABLED)
+ continue;
+
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: failed to open listener for %s\n",
+ trans->TransName, 0, 0);
+ continue;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX
+ && ipv6_succ))
+ flags |= ADDR_IN_USE_ALLOWED;
+#endif
+
+ if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0)
+ {
+ if (status == TRANS_ADDR_IN_USE)
+ {
+ /*
+ * We failed to bind to the specified address because the
+ * address is in use. It must be that a server is already
+ * running at this address, and this function should fail.
+ */
+
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: server already running\n",
+ 0, 0, 0);
+
+ for (j = 0; j < *count_ret; j++)
+ TRANS(Close) (temp_ciptrs[j]);
+
+ *count_ret = 0;
+ *ciptrs_ret = NULL;
+ *partial = 0;
+ return -1;
+ }
+ else
+ {
+ PRMSG (1,
+ "MakeAllCOTSServerListeners: failed to create listener for %s\n",
+ trans->TransName, 0, 0);
+
+ continue;
+ }
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX)
+ ipv6_succ = 1;
+#endif
+
+ PRMSG (5,
+ "MakeAllCOTSServerListeners: opened listener for %s, %d\n",
+ trans->TransName, ciptr->fd, 0);
+
+ temp_ciptrs[*count_ret] = ciptr;
+ (*count_ret)++;
+ }
+
+ *partial = (*count_ret < complete_network_count());
+
+ PRMSG (5,
+ "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n",
+ *partial, *count_ret, complete_network_count());
+
+ if (*count_ret > 0)
+ {
+ if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
+ *count_ret * sizeof (XtransConnInfo))) == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < *count_ret; i++)
+ {
+ (*ciptrs_ret)[i] = temp_ciptrs[i];
+ }
+ }
+ else
+ *ciptrs_ret = NULL;
+
+ return 0;
+}
+
+int
+TRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret,
+ XtransConnInfo **ciptrs_ret)
+
+{
+ char buffer[256]; /* ??? What size ?? */
+ XtransConnInfo ciptr, temp_ciptrs[NUMTRANS];
+ int status, i, j;
+
+ PRMSG (2,"MakeAllCLTSServerListeners(%s,%p)\n",
+ port ? port : "NULL", ciptrs_ret, 0);
+
+ *count_ret = 0;
+
+ for (i = 0; i < NUMTRANS; i++)
+ {
+ Xtransport *trans = Xtransports[i].transport;
+
+ if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN)
+ continue;
+
+ sprintf(buffer,"%s/:%s", trans->TransName, port ? port : "");
+
+ PRMSG (5,"MakeAllCLTSServerListeners: opening %s\n",
+ buffer, 0, 0);
+
+ if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL)
+ {
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: failed to open listener for %s\n",
+ trans->TransName, 0, 0);
+ continue;
+ }
+
+ if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0)
+ {
+ if (status == TRANS_ADDR_IN_USE)
+ {
+ /*
+ * We failed to bind to the specified address because the
+ * address is in use. It must be that a server is already
+ * running at this address, and this function should fail.
+ */
+
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: server already running\n",
+ 0, 0, 0);
+
+ for (j = 0; j < *count_ret; j++)
+ TRANS(Close) (temp_ciptrs[j]);
+
+ *count_ret = 0;
+ *ciptrs_ret = NULL;
+ *partial = 0;
+ return -1;
+ }
+ else
+ {
+ PRMSG (1,
+ "MakeAllCLTSServerListeners: failed to create listener for %s\n",
+ trans->TransName, 0, 0);
+
+ continue;
+ }
+ }
+
+ PRMSG (5,
+ "MakeAllCLTSServerListeners: opened listener for %s, %d\n",
+ trans->TransName, ciptr->fd, 0);
+ temp_ciptrs[*count_ret] = ciptr;
+ (*count_ret)++;
+ }
+
+ *partial = (*count_ret < complete_network_count());
+
+ PRMSG (5,
+ "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n",
+ *partial, *count_ret, complete_network_count());
+
+ if (*count_ret > 0)
+ {
+ if ((*ciptrs_ret = (XtransConnInfo *) xalloc (
+ *count_ret * sizeof (XtransConnInfo))) == NULL)
+ {
+ return -1;
+ }
+
+ for (i = 0; i < *count_ret; i++)
+ {
+ (*ciptrs_ret)[i] = temp_ciptrs[i];
+ }
+ }
+ else
+ *ciptrs_ret = NULL;
+
+ return 0;
+}
+
+#endif /* TRANS_SERVER */
+
+
+
+/*
+ * These routines are not part of the X Transport Interface, but they
+ * may be used by it.
+ */
+
+#ifdef CRAY
+
+/*
+ * Cray UniCOS does not have readv and writev so we emulate
+ */
+
+static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ struct msghdr hdr;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = iovcnt;
+ hdr.msg_accrights = 0;
+ hdr.msg_accrightslen = 0;
+ hdr.msg_name = 0;
+ hdr.msg_namelen = 0;
+
+ return (recvmsg (ciptr->fd, &hdr, 0));
+}
+
+static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ struct msghdr hdr;
+
+ hdr.msg_iov = iov;
+ hdr.msg_iovlen = iovcnt;
+ hdr.msg_accrights = 0;
+ hdr.msg_accrightslen = 0;
+ hdr.msg_name = 0;
+ hdr.msg_namelen = 0;
+
+ return (sendmsg (ciptr->fd, &hdr, 0));
+}
+
+#endif /* CRAY */
+
+#if (defined(SYSV) && defined(i386) && !defined(__SCO__)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
+
+/*
+ * emulate readv
+ */
+
+static int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ int i, len, total;
+ char *base;
+
+ ESET(0);
+ for (i = 0, total = 0; i < iovcnt; i++, iov++) {
+ len = iov->iov_len;
+ base = iov->iov_base;
+ while (len > 0) {
+ register int nbytes;
+ nbytes = TRANS(Read) (ciptr, base, len);
+ if (nbytes < 0 && total == 0) return -1;
+ if (nbytes <= 0) return total;
+ ESET(0);
+ len -= nbytes;
+ total += nbytes;
+ base += nbytes;
+ }
+ }
+ return total;
+}
+
+#endif /* SYSV && i386 || WIN32 || __sxg__ */
+
+#if (defined(SYSV) && defined(i386) && !defined(__SCO__)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
+
+/*
+ * emulate writev
+ */
+
+static int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt)
+
+{
+ int i, len, total;
+ char *base;
+
+ ESET(0);
+ for (i = 0, total = 0; i < iovcnt; i++, iov++) {
+ len = iov->iov_len;
+ base = iov->iov_base;
+ while (len > 0) {
+ register int nbytes;
+ nbytes = TRANS(Write) (ciptr, base, len);
+ if (nbytes < 0 && total == 0) return -1;
+ if (nbytes <= 0) return total;
+ ESET(0);
+ len -= nbytes;
+ total += nbytes;
+ base += nbytes;
+ }
+ }
+ return total;
+}
+
+#endif /* SYSV && i386 || WIN32 || __sxg__ */
+
+
+#if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(__SCO__)
+#ifndef NEED_UTSNAME
+#define NEED_UTSNAME
+#endif
+#include <sys/utsname.h>
+#endif
+
+/*
+ * TRANS(GetHostname) - similar to gethostname but allows special processing.
+ */
+
+int TRANS(GetHostname) (char *buf, int maxlen)
+
+{
+ int len;
+
+#ifdef NEED_UTSNAME
+ struct utsname name;
+
+ uname (&name);
+ len = strlen (name.nodename);
+ if (len >= maxlen) len = maxlen - 1;
+ strncpy (buf, name.nodename, len);
+ buf[len] = '\0';
+#else
+ buf[0] = '\0';
+ (void) gethostname (buf, maxlen);
+ buf [maxlen - 1] = '\0';
+ len = strlen(buf);
+#endif /* NEED_UTSNAME */
+ return len;
+}
diff --git a/nx-X11/lib/xtrans/Xtrans.h b/nx-X11/lib/xtrans/Xtrans.h
new file mode 100644
index 000000000..e8d4bdfcd
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtrans.h
@@ -0,0 +1,490 @@
+/* $Xorg: Xtrans.h,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtrans.h,v 3.21 2003/07/20 16:12:15 tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XTRANS_H_
+#define _XTRANS_H_
+
+#include <X11/Xfuncproto.h>
+#include <X11/Xos.h>
+
+#ifndef WIN32
+#ifndef Lynx
+#include <sys/socket.h>
+#else
+#include <socket.h>
+#endif
+#endif
+
+
+/*
+ * Set the functions names according to where this code is being compiled.
+ */
+
+#ifdef X11_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _X11Trans##func
+#else
+#define TRANS(func) _X11Trans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_X11Trans";
+#endif
+#endif /* X11_t */
+
+#ifdef XSERV_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _XSERVTrans##func
+#else
+#define TRANS(func) _XSERVTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XSERVTrans";
+#endif
+#define X11_t
+#endif /* XSERV_t */
+
+#ifdef XIM_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _XimXTrans##func
+#else
+#define TRANS(func) _XimXTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XimTrans";
+#endif
+#endif /* XIM_t */
+
+#ifdef FS_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _FSTrans##func
+#else
+#define TRANS(func) _FSTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_FSTrans";
+#endif
+#endif /* FS_t */
+
+#ifdef FONT_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _FontTrans##func
+#else
+#define TRANS(func) _FontTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_FontTrans";
+#endif
+#endif /* FONT_t */
+
+#ifdef ICE_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _IceTrans##func
+#else
+#define TRANS(func) _IceTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_IceTrans";
+#endif
+#endif /* ICE_t */
+
+#ifdef TEST_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _TESTTrans##func
+#else
+#define TRANS(func) _TESTTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_TESTTrans";
+#endif
+#endif /* TEST_t */
+
+#ifdef LBXPROXY_t
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _LBXPROXYTrans##func
+#else
+#define TRANS(func) _LBXPROXYTrans/**/func
+#endif
+#define X11_t /* The server defines this - so should the LBX proxy */
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_LBXPROXYTrans";
+#endif
+#endif /* LBXPROXY_t */
+
+#if !defined(TRANS)
+#if !defined(UNIXCPP) || defined(ANSICPP)
+#define TRANS(func) _XTrans##func
+#else
+#define TRANS(func) _XTrans/**/func
+#endif
+#ifdef XTRANSDEBUG
+static char* __xtransname = "_XTrans";
+#endif
+#endif /* !TRANS */
+
+
+/*
+ * Create a single address structure that can be used wherever
+ * an address structure is needed. struct sockaddr is not big enough
+ * to hold a sockadd_un, so we create this definition to have a single
+ * structure that is big enough for all the structures we might need.
+ *
+ * This structure needs to be independent of the socket/TLI interface used.
+ */
+
+#if defined(IPv6) && defined(AF_INET6)
+typedef struct sockaddr_storage Xtransaddr;
+#else
+#define XTRANS_MAX_ADDR_LEN 128 /* large enough to hold sun_path */
+
+typedef struct {
+ unsigned char addr[XTRANS_MAX_ADDR_LEN];
+} Xtransaddr;
+#endif
+
+#ifdef LONG64
+typedef int BytesReadable_t;
+#else
+typedef long BytesReadable_t;
+#endif
+
+
+#if defined(WIN32) || (defined(USG) && !defined(CRAY) && !defined(umips) && !defined(MOTOROLA) && !defined(uniosu) && !defined(__sxg__))
+
+/*
+ * TRANS(Readv) and TRANS(Writev) use struct iovec, normally found
+ * in Berkeley systems in <sys/uio.h>. See the readv(2) and writev(2)
+ * manual pages for details.
+ */
+
+struct iovec {
+ caddr_t iov_base;
+ int iov_len;
+};
+
+#else
+#ifndef Lynx
+#include <sys/uio.h>
+#else
+#include <uio.h>
+#endif
+#endif
+
+typedef struct _XtransConnInfo *XtransConnInfo;
+
+
+/*
+ * Transport Option definitions
+ */
+
+#define TRANS_NONBLOCKING 1
+#define TRANS_CLOSEONEXEC 2
+
+
+/*
+ * Return values of Connect (0 is success)
+ */
+
+#define TRANS_CONNECT_FAILED -1
+#define TRANS_TRY_CONNECT_AGAIN -2
+#define TRANS_IN_PROGRESS -3
+
+
+/*
+ * Return values of CreateListener (0 is success)
+ */
+
+#define TRANS_CREATE_LISTENER_FAILED -1
+#define TRANS_ADDR_IN_USE -2
+
+
+/*
+ * Return values of Accept (0 is success)
+ */
+
+#define TRANS_ACCEPT_BAD_MALLOC -1
+#define TRANS_ACCEPT_FAILED -2
+#define TRANS_ACCEPT_MISC_ERROR -3
+
+
+/*
+ * ResetListener return values
+ */
+
+#define TRANS_RESET_NOOP 1
+#define TRANS_RESET_NEW_FD 2
+#define TRANS_RESET_FAILURE 3
+
+
+/*
+ * Function prototypes for the exposed interface
+ */
+
+void TRANS(FreeConnInfo) (
+ XtransConnInfo /* ciptr */
+);
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo TRANS(OpenCOTSClient)(
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo TRANS(OpenCOTSServer)(
+ char * /* address */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+XtransConnInfo TRANS(OpenCLTSClient)(
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+XtransConnInfo TRANS(OpenCLTSServer)(
+ char * /* address */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_REOPEN
+
+XtransConnInfo TRANS(ReopenCOTSServer)(
+ int, /* trans_id */
+ int, /* fd */
+ char * /* port */
+);
+
+XtransConnInfo TRANS(ReopenCLTSServer)(
+ int, /* trans_id */
+ int, /* fd */
+ char * /* port */
+);
+
+int TRANS(GetReopenInfo)(
+ XtransConnInfo, /* ciptr */
+ int *, /* trans_id */
+ int *, /* fd */
+ char ** /* port */
+);
+
+#endif /* TRANS_REOPEN */
+
+
+int TRANS(SetOption)(
+ XtransConnInfo, /* ciptr */
+ int, /* option */
+ int /* arg */
+);
+
+#ifdef TRANS_SERVER
+
+int TRANS(CreateListener)(
+ XtransConnInfo, /* ciptr */
+ char *, /* port */
+ unsigned int /* flags */
+);
+
+int TRANS(NoListen) (
+ char* /* protocol*/
+);
+
+int TRANS(ResetListener)(
+ XtransConnInfo /* ciptr */
+);
+
+XtransConnInfo TRANS(Accept)(
+ XtransConnInfo, /* ciptr */
+ int * /* status */
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+int TRANS(Connect)(
+ XtransConnInfo, /* ciptr */
+ char * /* address */
+);
+
+#endif /* TRANS_CLIENT */
+
+int TRANS(BytesReadable)(
+ XtransConnInfo, /* ciptr */
+ BytesReadable_t * /* pend */
+);
+
+int TRANS(Read)(
+ XtransConnInfo, /* ciptr */
+ char *, /* buf */
+ int /* size */
+);
+
+int TRANS(Write)(
+ XtransConnInfo, /* ciptr */
+ char *, /* buf */
+ int /* size */
+);
+
+int TRANS(Readv)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* buf */
+ int /* size */
+);
+
+int TRANS(Writev)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* buf */
+ int /* size */
+);
+
+int TRANS(Disconnect)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(Close)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(CloseForCloning)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(IsLocal)(
+ XtransConnInfo /* ciptr */
+);
+
+int TRANS(GetMyAddr)(
+ XtransConnInfo, /* ciptr */
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+int TRANS(GetPeerAddr)(
+ XtransConnInfo, /* ciptr */
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+int TRANS(GetConnectionNumber)(
+ XtransConnInfo /* ciptr */
+);
+
+#ifdef TRANS_SERVER
+
+int TRANS(MakeAllCOTSServerListeners)(
+ char *, /* port */
+ int *, /* partial */
+ int *, /* count_ret */
+ XtransConnInfo ** /* ciptrs_ret */
+);
+
+int TRANS(MakeAllCLTSServerListeners)(
+ char *, /* port */
+ int *, /* partial */
+ int *, /* count_ret */
+ XtransConnInfo ** /* ciptrs_ret */
+);
+
+#endif /* TRANS_SERVER */
+
+
+/*
+ * Function Prototypes for Utility Functions.
+ */
+
+#ifdef X11_t
+
+int TRANS(ConvertAddress)(
+ int *, /* familyp */
+ int *, /* addrlenp */
+ Xtransaddr ** /* addrp */
+);
+
+#endif /* X11_t */
+
+#ifdef ICE_t
+
+char *
+TRANS(GetMyNetworkId)(
+ XtransConnInfo /* ciptr */
+);
+
+char *
+TRANS(GetPeerNetworkId)(
+ XtransConnInfo /* ciptr */
+);
+
+#endif /* ICE_t */
+
+int
+TRANS(GetHostname) (
+ char * /* buf */,
+ int /* maxlen */
+);
+
+#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+int TRANS(WSAStartup)();
+#endif
+
+#endif /* _XTRANS_H_ */
diff --git a/nx-X11/lib/xtrans/Xtransdnet.c b/nx-X11/lib/xtrans/Xtransdnet.c
new file mode 100644
index 000000000..ac91695c7
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtransdnet.c
@@ -0,0 +1,668 @@
+/* $Xorg: Xtransdnet.c,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtransdnet.c,v 3.7tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR and makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef WIN32
+#include <netdnet/dn.h>
+#include <netdnet/dnetdb.h>
+#include <sys/ioctl.h>
+#endif /* !WIN32 */
+
+#include <stdio.h>
+
+#ifdef WIN32
+#define _WILLWINSOCK_
+#define BOOL wBOOL
+#undef Status
+#define Status wStatus
+#include <prgpre.h> /* PATHWORKS header normally in %MSTOOLS%\h\pathwork */
+#undef Status
+#define Status int
+#undef BOOL
+#include <X11/Xw32defs.h>
+#undef close
+#define close closesocket
+#endif /* WIN32 */
+
+
+#if defined(X11_t)
+#define DNETOBJ "X$X"
+#endif
+#if defined(XIM_t)
+#define DNETOBJ "IMSERVER$"
+#endif
+#if defined(FS_t) || defined(FONT_t)
+#define DNETOBJ "X$FONT"
+#endif
+#if defined(ICE_t)
+#define DNETOBJ ""
+#endif
+#if defined(TEST_t)
+#define DNETOBJ "X$TEST"
+#endif
+
+
+/*
+ * This is the DNET implementation of the X Transport service layer
+ */
+
+/*
+ * This function gets the local address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(DNETGetAddr) (XtransConnInfo ciptr)
+
+{
+ struct sockaddr_dn sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (3,"DNETGetAddr(%x)\n", ciptr, 0, 0);
+
+ if (getsockname (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
+ {
+ PRMSG (1,"DNETGetAddr: getsockname() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "DNETGetAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->family = sockname.sdn_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(DNETGetPeerAddr) (XtransConnInfo ciptr)
+
+{
+ struct sockaddr_dn sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (3,"DNETGetPeerAddr(%x)\n", ciptr, 0, 0);
+
+ if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0)
+ {
+ PRMSG (1,"DNETGetPeerAddr: getpeername() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "DNETGetPeerAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(DNETOpenCOTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (2,"DNETOpenCOTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETOpenCOTSClient: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->index = 0; /* only one form of DECnet */
+
+ /* nothing else to do here */
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(DNETOpenCOTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (2,"DNETOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETOpenCOTSServer: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr->fd = socket (AF_DECnet, SOCK_STREAM, 0)) < 0)
+ {
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+ ciptr->index = 0; /* only one form of DECnet */
+
+ return (ciptr);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(DNETOpenCLTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (2,"DNETOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof (struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETOpenCLTSClient: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->index = 0; /* only one form of DECnet */
+
+ /* nothing else to do here */
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(DNETOpenCLTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ /* NEED TO IMPLEMENT */
+
+ PRMSG (2,"DNETOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
+ return NULL;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(DNETReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (2,"DNETReopenCOTSServer(%d,%s)\n", fd, port, 0);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETReopenCOTSServer: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+ ciptr->index = 0; /* only one form of DECnet */
+
+ return (ciptr);
+}
+
+static XtransConnInfo
+TRANS(DNETReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (2,"DNETReopenCLTSServer(%d,%s)\n", fd, port, 0);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETReopenCLTSServer: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+ ciptr->index = 0; /* only one form of DECnet */
+
+ return (ciptr);
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(DNETSetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG (2,"DNETSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
+ return -1;
+}
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(DNETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+ struct sockaddr_dn dnsock;
+ int fd = ciptr->fd;
+
+ PRMSG (3, "DNETCreateListener(%x,%d)\n", ciptr, fd, 0);
+
+ bzero ((char *) &dnsock, sizeof (dnsock));
+ dnsock.sdn_family = AF_DECnet;
+
+ if (port && *port )
+ sprintf (dnsock.sdn_objname, "%s%s", DNETOBJ, port);
+ else
+#ifdef X11_t
+ return -1;
+#else
+ sprintf (dnsock.sdn_objname, "%s%d", DNETOBJ, getpid ());
+#endif
+
+ dnsock.sdn_objnamel = strlen (dnsock.sdn_objname);
+
+ if (bind (fd, (struct sockaddr *) &dnsock, sizeof (dnsock)))
+ {
+ close (fd);
+ return -1;
+ }
+
+ if (listen (fd, 5))
+ {
+ close (fd);
+ return (-1);
+ }
+
+
+ /* Set a flag to indicate that this connection is a listener */
+
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+
+ return 0;
+}
+
+
+static XtransConnInfo
+TRANS(DNETAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_dn sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (2, "DNETAccept(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc(
+ 1, sizeof (struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "DNETAccept: malloc failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, &namelen)) < 0)
+ {
+ PRMSG (1, "DNETAccept: accept() failed\n", 0, 0, 0);
+
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ /*
+ * Get this address again because the transport may give a more
+ * specific address now that a connection is established.
+ */
+
+ if (TRANS(DNETGetAddr) (newciptr) < 0)
+ {
+ PRMSG(1,
+ "DNETAccept: ...DNETGetAddr() failed:\n", 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if (TRANS(DNETGetPeerAddr) (newciptr) < 0)
+ {
+ PRMSG(1,
+ "DNETAccept: ...DNETGetPeerAddr() failed:\n", 0, 0, 0);
+
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+#define OBJBUFSIZE 64
+
+static int
+TRANS(DNETConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ char objname[OBJBUFSIZE];
+
+ extern int dnet_conn();
+
+ PRMSG (2,"DNETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ short tmpport = (short) atoi (port);
+
+ sprintf (objname, "X$X%d", tmpport);
+ }
+ else
+#endif
+ strncpy(objname, port, OBJBUFSIZE);
+
+
+ /*
+ * Do the connect
+ */
+
+ if (!host) host = "0";
+
+ if ((ciptr->fd = dnet_conn (host, objname, SOCK_STREAM, 0, 0, 0, 0)) < 0)
+ {
+ return TRANS_CONNECT_FAILED;
+ }
+
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if (TRANS(DNETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "DNETConnect: ...DNETGetAddr() failed:\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if (TRANS(DNETGetPeerAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "DNETConnect: ...DNETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(DNETBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ PRMSG (2,"DNETBytesReadable(%x,%d,%x)\n", ciptr, ciptr->fd, pend);
+
+#ifdef WIN32
+ {
+ int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return ioctl(ciptr->fd, FIONREAD, (char *)pend);
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(DNETRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"DNETRead(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+#ifdef WIN32
+ {
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return read (ciptr->fd, buf, size);
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(DNETWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"DNETWrite(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+#ifdef WIN32
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return write (ciptr->fd, buf, size);
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(DNETReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"DNETReadv(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+ return READV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(DNETWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"DNETWritev(%d,%x,%d)\n", ciptr->fd, buf, size);
+
+ return WRITEV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(DNETDisconnect) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"DNETDisconnect(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = shutdown (ciptr->fd, 2);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
+#endif
+}
+
+
+static int
+TRANS(DNETClose) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"DNETClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = close (ciptr->fd);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return close (ciptr->fd);
+#endif
+}
+
+
+Xtransport TRANS(DNETFuncs) = {
+ /* DNET Interface */
+ "dnet",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(DNETOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(DNETOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(DNETOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(DNETOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(DNETReopenCOTSServer),
+ TRANS(DNETReopenCLTSServer),
+#endif /* TRANS_REOPEN */
+ TRANS(DNETSetOption),
+#ifdef TRANS_SERVER
+ TRANS(DNETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(DNETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(DNETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(DNETBytesReadable),
+ TRANS(DNETRead),
+ TRANS(DNETWrite),
+ TRANS(DNETReadv),
+ TRANS(DNETWritev),
+ TRANS(DNETDisconnect),
+ TRANS(DNETClose),
+ TRANS(DNETClose),
+};
diff --git a/nx-X11/lib/xtrans/Xtransint.h b/nx-X11/lib/xtrans/Xtransint.h
new file mode 100644
index 000000000..88d223074
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtransint.h
@@ -0,0 +1,485 @@
+/* $XdotOrg: xc/lib/xtrans/Xtransint.h,v 1.4 2005/11/08 06:33:26 jkj Exp $ */
+/* $Xorg: Xtransint.h,v 1.4 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtransint.h,v 3.41 2003/08/28 00:35:23 tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _XTRANSINT_H_
+#define _XTRANSINT_H_
+
+/*
+ * XTRANSDEBUG will enable the PRMSG() macros used in the X Transport
+ * Interface code. Each use of the PRMSG macro has a level associated with
+ * it. XTRANSDEBUG is defined to be a level. If the invocation level is =<
+ * the value of XTRANSDEBUG, then the message will be printed out to stderr.
+ * Recommended levels are:
+ *
+ * XTRANSDEBUG=1 Error messages
+ * XTRANSDEBUG=2 API Function Tracing
+ * XTRANSDEBUG=3 All Function Tracing
+ * XTRANSDEBUG=4 printing of intermediate values
+ * XTRANSDEBUG=5 really detailed stuff
+#define XTRANSDEBUG 2
+ *
+ * Defining XTRANSDEBUGTIMESTAMP will cause printing timestamps with each
+ * message.
+ */
+
+#ifndef XTRANSDEBUG
+# ifndef __UNIXOS2__
+# define XTRANSDEBUG 1
+# else
+# define XTRANSDEBUG 1
+# endif
+#endif
+
+#ifdef WIN32
+# define _WILLWINSOCK_
+#endif
+
+#include "Xtrans.h"
+
+#ifdef XTRANSDEBUG
+# include <stdio.h>
+#endif /* XTRANSDEBUG */
+
+#include <errno.h>
+
+#ifndef WIN32
+# ifndef Lynx
+# include <sys/socket.h>
+# else
+# include <socket.h>
+# endif
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# ifdef __UNIXOS2__
+# include <sys/ioctl.h>
+# endif
+
+/*
+ * Moved the setting of NEED_UTSNAME to this header file from Xtrans.c,
+ * to avoid a race condition. JKJ (6/5/97)
+ */
+
+# if (defined(_POSIX_SOURCE) && !defined(AIXV3) && !defined(__QNX__)) || defined(hpux) || defined(USG) || defined(SVR4) || defined(__SCO__)
+# ifndef NEED_UTSNAME
+# define NEED_UTSNAME
+# endif
+# include <sys/utsname.h>
+# endif
+
+/*
+ * makedepend screws up on #undef OPEN_MAX, so we define a new symbol
+ */
+
+# ifndef TRANS_OPEN_MAX
+
+# ifndef X_NOT_POSIX
+# ifdef _POSIX_SOURCE
+# include <limits.h>
+# else
+# define _POSIX_SOURCE
+# include <limits.h>
+# undef _POSIX_SOURCE
+# endif
+# endif
+# ifndef OPEN_MAX
+# if defined(_SC_OPEN_MAX) && !defined(__UNIXOS2__)
+# define OPEN_MAX (sysconf(_SC_OPEN_MAX))
+# else
+# ifdef SVR4
+# define OPEN_MAX 256
+# else
+# include <sys/param.h>
+# ifndef OPEN_MAX
+# ifdef __OSF1__
+# define OPEN_MAX 256
+# else
+# ifdef NOFILE
+# define OPEN_MAX NOFILE
+# else
+# if !defined(__UNIXOS2__) && !defined(__QNX__)
+# define OPEN_MAX NOFILES_MAX
+# else
+# define OPEN_MAX 256
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# if defined(_SC_OPEN_MAX)
+# define TRANS_OPEN_MAX OPEN_MAX
+# else /* !__GNU__ */
+# if OPEN_MAX > 256
+# define TRANS_OPEN_MAX 256
+# else
+# define TRANS_OPEN_MAX OPEN_MAX
+# endif
+# endif /*__GNU__*/
+
+# endif /* TRANS_OPEN_MAX */
+
+# ifdef __UNIXOS2__
+# define ESET(val)
+# else
+# define ESET(val) errno = val
+# endif
+# define EGET() errno
+
+#else /* WIN32 */
+
+# include <limits.h> /* for USHRT_MAX */
+
+# define ESET(val) WSASetLastError(val)
+# define EGET() WSAGetLastError()
+
+#endif /* WIN32 */
+
+#include <stddef.h>
+
+#ifdef X11_t
+#define X_TCP_PORT 6000
+#endif
+
+struct _XtransConnInfo {
+ struct _Xtransport *transptr;
+ int index;
+ char *priv;
+ int flags;
+ int fd;
+ char *port;
+ int family;
+ char *addr;
+ int addrlen;
+ char *peeraddr;
+ int peeraddrlen;
+};
+
+#define XTRANS_OPEN_COTS_CLIENT 1
+#define XTRANS_OPEN_COTS_SERVER 2
+#define XTRANS_OPEN_CLTS_CLIENT 3
+#define XTRANS_OPEN_CLTS_SERVER 4
+
+
+typedef struct _Xtransport {
+ char *TransName;
+ int flags;
+
+#ifdef TRANS_CLIENT
+
+ XtransConnInfo (*OpenCOTSClient)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+ char ** nolisten;
+ XtransConnInfo (*OpenCOTSServer)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+ XtransConnInfo (*OpenCLTSClient)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+ XtransConnInfo (*OpenCLTSServer)(
+ struct _Xtransport *, /* transport */
+ char *, /* protocol */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+ XtransConnInfo (*ReopenCOTSServer)(
+ struct _Xtransport *, /* transport */
+ int, /* fd */
+ char * /* port */
+ );
+
+ XtransConnInfo (*ReopenCLTSServer)(
+ struct _Xtransport *, /* transport */
+ int, /* fd */
+ char * /* port */
+ );
+
+#endif /* TRANS_REOPEN */
+
+
+ int (*SetOption)(
+ XtransConnInfo, /* connection */
+ int, /* option */
+ int /* arg */
+ );
+
+#ifdef TRANS_SERVER
+/* Flags */
+# define ADDR_IN_USE_ALLOWED 1
+
+ int (*CreateListener)(
+ XtransConnInfo, /* connection */
+ char *, /* port */
+ unsigned int /* flags */
+ );
+
+ int (*ResetListener)(
+ XtransConnInfo /* connection */
+ );
+
+ XtransConnInfo (*Accept)(
+ XtransConnInfo, /* connection */
+ int * /* status */
+ );
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+ int (*Connect)(
+ XtransConnInfo, /* connection */
+ char *, /* host */
+ char * /* port */
+ );
+
+#endif /* TRANS_CLIENT */
+
+ int (*BytesReadable)(
+ XtransConnInfo, /* connection */
+ BytesReadable_t * /* pend */
+ );
+
+ int (*Read)(
+ XtransConnInfo, /* connection */
+ char *, /* buf */
+ int /* size */
+ );
+
+ int (*Write)(
+ XtransConnInfo, /* connection */
+ char *, /* buf */
+ int /* size */
+ );
+
+ int (*Readv)(
+ XtransConnInfo, /* connection */
+ struct iovec *, /* buf */
+ int /* size */
+ );
+
+ int (*Writev)(
+ XtransConnInfo, /* connection */
+ struct iovec *, /* buf */
+ int /* size */
+ );
+
+ int (*Disconnect)(
+ XtransConnInfo /* connection */
+ );
+
+ int (*Close)(
+ XtransConnInfo /* connection */
+ );
+
+ int (*CloseForCloning)(
+ XtransConnInfo /* connection */
+ );
+
+} Xtransport;
+
+
+typedef struct _Xtransport_table {
+ Xtransport *transport;
+ int transport_id;
+} Xtransport_table;
+
+
+/*
+ * Flags for the flags member of Xtransport.
+ */
+
+#define TRANS_ALIAS (1<<0) /* record is an alias, don't create server */
+#define TRANS_LOCAL (1<<1) /* local transport */
+#define TRANS_DISABLED (1<<2) /* Don't open this one */
+#define TRANS_NOLISTEN (1<<3) /* Don't listen on this one */
+#define TRANS_NOUNLINK (1<<4) /* Dont unlink transport endpoints */
+
+/* Flags to preserve when setting others */
+#define TRANS_KEEPFLAGS (TRANS_NOUNLINK)
+
+/*
+ * readv() and writev() don't exist or don't work correctly on some
+ * systems, so they may be emulated.
+ */
+
+#if defined(CRAY) || (defined(SYSV) && defined(i386) && !defined(__SCO__)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
+
+#define READV(ciptr, iov, iovcnt) TRANS(ReadV)(ciptr, iov, iovcnt)
+
+static int TRANS(ReadV)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* iov */
+ int /* iovcnt */
+);
+
+#else
+
+#define READV(ciptr, iov, iovcnt) readv(ciptr->fd, iov, iovcnt)
+
+#endif /* CRAY || (SYSV && i386) || WIN32 || __sxg__ || */
+
+
+#if defined(CRAY) || (defined(SYSV) && defined(i386) && !defined(__SCO__)) || defined(WIN32) || defined(__sxg__) || defined(__UNIXOS2__)
+
+#define WRITEV(ciptr, iov, iovcnt) TRANS(WriteV)(ciptr, iov, iovcnt)
+
+static int TRANS(WriteV)(
+ XtransConnInfo, /* ciptr */
+ struct iovec *, /* iov */
+ int /* iovcnt */
+);
+
+#else
+
+#define WRITEV(ciptr, iov, iovcnt) writev(ciptr->fd, iov, iovcnt)
+
+#endif /* CRAY || WIN32 || __sxg__ */
+
+
+static int is_numeric (
+ char * /* str */
+);
+
+#ifdef TRANS_SERVER
+static int trans_mkdir (
+ char *, /* path */
+ int /* mode */
+);
+#endif
+
+/*
+ * Some XTRANSDEBUG stuff
+ */
+
+#if defined(XTRANSDEBUG)
+/* add hack to the format string to avoid warnings about extra arguments
+ * to fprintf.
+ */
+#ifdef XTRANSDEBUGTIMESTAMP
+#if defined(XSERV_t) && defined(TRANS_SERVER)
+/* Use ErrorF() for the X server */
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ struct timeval tp;\
+ gettimeofday(&tp,0); \
+ ErrorF(__xtransname); \
+ ErrorF(x+hack,a,b,c); \
+ ErrorF("timestamp (ms): %d\n",tp.tv_sec*1000+tp.tv_usec/1000); \
+ errno=saveerrno; \
+ } else ((void)0)
+#else
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ struct timeval tp;\
+ gettimeofday(&tp,0); \
+ fprintf(stderr, __xtransname); fflush(stderr); \
+ fprintf(stderr, x+hack,a,b,c); fflush(stderr); \
+ fprintf(stderr, "timestamp (ms): %d\n",tp.tv_sec*1000+tp.tv_usec/1000); \
+ fflush(stderr); \
+ errno=saveerrno; \
+ } else ((void)0)
+#endif /* XSERV_t && TRANS_SERVER */
+#else /* XTRANSDEBUGTIMESTAMP */
+#if defined(XSERV_t) && defined(TRANS_SERVER)
+/* Use ErrorF() for the X server */
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ ErrorF(__xtransname); \
+ ErrorF(x+hack,a,b,c); \
+ errno=saveerrno; \
+ } else ((void)0)
+#else
+#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \
+ int hack= 0, saveerrno=errno; \
+ fprintf(stderr, __xtransname); fflush(stderr); \
+ fprintf(stderr, x+hack,a,b,c); fflush(stderr); \
+ errno=saveerrno; \
+ } else ((void)0)
+#endif /* XSERV_t && TRANS_SERVER */
+#endif /* XTRANSDEBUGTIMESTAMP */
+#else
+#define PRMSG(lvl,x,a,b,c) ((void)0)
+#endif /* XTRANSDEBUG */
+
+#endif /* _XTRANSINT_H_ */
diff --git a/nx-X11/lib/xtrans/Xtranslcl.c b/nx-X11/lib/xtrans/Xtranslcl.c
new file mode 100644
index 000000000..6165d3658
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtranslcl.c
@@ -0,0 +1,2755 @@
+/* $Xorg: Xtranslcl.c,v 1.6 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranslcl.c,v 3.40tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ *
+ * The connection code/ideas in lib/X and server/os for SVR4/Intel
+ * environments was contributed by the following companies/groups:
+ *
+ * MetroLink Inc
+ * NCR
+ * Pittsburgh Powercomputing Corporation (PPc)/Quarterdeck Office Systems
+ * SGCS
+ * Unix System Laboratories (USL) / Novell
+ * XFree86
+ *
+ * The goal is to have common connection code among all SVR4/Intel vendors.
+ *
+ * ALL THE ABOVE COMPANIES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+ * IN NO EVENT SHALL THESE COMPANIES * BE LIABLE FOR ANY SPECIAL, INDIRECT
+ * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
+ * OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <errno.h>
+#include <ctype.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#if defined(SVR4)
+#if !defined(DGUX)
+#include <sys/filio.h>
+#else /* DGUX */
+#include <sys/stream.h>
+#include <sys/ptms.h>
+#endif
+#endif
+#include <sys/stropts.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+
+/*
+ * The local transports should be treated the same as a UNIX domain socket
+ * wrt authentication, etc. Because of this, we will use struct sockaddr_un
+ * for the address format. This will simplify the code in other places like
+ * The X Server.
+ */
+
+#include <sys/socket.h>
+#ifndef X_NO_SYS_UN
+#include <sys/un.h>
+#endif
+
+#if defined(ISC) && !defined(_POSIX_SOURCE)
+typedef unsigned short mode_t;
+/* POSIX needed for mode_t define in sys/types.h */
+#endif
+
+/*
+ * These functions actually implement the local connection mechanisms.
+ */
+
+/* Type Not Supported */
+
+static int
+TRANS(OpenFail)(XtransConnInfo ciptr, char *port)
+
+{
+ return -1;
+}
+
+#ifdef TRANS_REOPEN
+
+static int
+TRANS(ReopenFail)(XtransConnInfo ciptr, int fd, char *port)
+
+{
+ return 0;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+static int
+TRANS(FillAddrInfo)(XtransConnInfo ciptr, char *sun_path, char *peer_sun_path)
+
+{
+ struct sockaddr_un *sunaddr;
+ struct sockaddr_un *p_sunaddr;
+
+ ciptr->family = AF_UNIX;
+ ciptr->addrlen = sizeof (struct sockaddr_un);
+
+ if ((sunaddr = (struct sockaddr_un *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG(1,"FillAddrInfo: failed to allocate memory for addr\n", 0, 0, 0);
+ return 0;
+ }
+
+ sunaddr->sun_family = AF_UNIX;
+
+ if (strlen(sun_path) > sizeof(sunaddr->sun_path) - 1) {
+ PRMSG(1, "FillAddrInfo: path too long\n", 0, 0, 0);
+ return 0;
+ }
+ strcpy (sunaddr->sun_path, sun_path);
+#if defined(BSD44SOCKETS) && !defined(Lynx)
+ sunaddr->sun_len = strlen (sunaddr->sun_path);
+#endif
+
+ ciptr->addr = (char *) sunaddr;
+
+ ciptr->peeraddrlen = sizeof (struct sockaddr_un);
+
+ if ((p_sunaddr = (struct sockaddr_un *) xalloc (
+ ciptr->peeraddrlen)) == NULL)
+ {
+ PRMSG(1,
+ "FillAddrInfo: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ xfree ((char *) sunaddr);
+ ciptr->addr = NULL;
+
+ return 0;
+ }
+
+ p_sunaddr->sun_family = AF_UNIX;
+
+ if (strlen(peer_sun_path) > sizeof(p_sunaddr->sun_path) - 1) {
+ PRMSG(1, "FillAddrInfo: peer path too long\n", 0, 0, 0);
+ return 0;
+ }
+ strcpy (p_sunaddr->sun_path, peer_sun_path);
+#if defined(BSD44SOCKETS) && !defined(Lynx)
+ p_sunaddr->sun_len = strlen (p_sunaddr->sun_path);
+#endif
+
+ ciptr->peeraddr = (char *) p_sunaddr;
+
+ return 1;
+}
+
+
+
+/* PTS */
+
+#if defined(SYSV) && !defined(__SCO__) && !defined(ISC)
+#define SIGNAL_T int
+#else
+#define SIGNAL_T void
+#endif /* SYSV */
+
+typedef SIGNAL_T (*PFV)();
+
+extern PFV signal();
+
+extern char *ptsname(
+ int
+);
+
+static void _dummy(int sig)
+
+{
+}
+
+#ifndef sun
+#define X_STREAMS_DIR "/dev/X"
+#define DEV_SPX "/dev/spx"
+#else
+#ifndef X11_t
+#define X_STREAMS_DIR "/dev/X"
+#else
+#define X_STREAMS_DIR "/tmp/.X11-pipe"
+#endif
+#endif
+
+#ifdef _AIX
+#define DEV_PTMX "/dev/ptc"
+#else
+#define DEV_PTMX "/dev/ptmx"
+#endif
+
+#if defined(X11_t)
+
+#define PTSNODENAME "/dev/X/server."
+#ifndef sun
+#define NAMEDNODENAME "/dev/X/Nserver."
+#else
+#define NAMEDNODENAME "/tmp/.X11-pipe/X"
+#endif
+
+/*
+ * ISC is only defined for X11 since they are there for
+ * backwards binary compatability only.
+ */
+
+#define X_ISC_DIR "/dev/X/ISCCONN"
+#define ISCDEVNODENAME "/dev/X/ISCCONN/X%s"
+#define ISCTMPNODENAME "/tmp/.X11-unix/X%s"
+#define SCORNODENAME "/dev/X%1sR"
+#define SCOSNODENAME "/dev/X%1sS"
+#endif
+#if defined(XIM_t)
+#define PTSNODENAME "/dev/X/XIM."
+#define NAMEDNODENAME "/dev/X/NXIM."
+#define SCORNODENAME "/dev/XIM.%sR"
+#define SCOSNODENAME "/dev/XIM.%sS"
+#endif
+#if defined(FS_t) || defined (FONT_t)
+/*
+ * USL has already defined something here. We need to check with them
+ * and see if their choice is usable here.
+ */
+#define PTSNODENAME "/dev/X/fontserver."
+#define NAMEDNODENAME "/dev/X/Nfontserver."
+#define SCORNODENAME "/dev/fontserver.%sR"
+#define SCOSNODENAME "/dev/fontserver.%sS"
+#endif
+#if defined(ICE_t)
+#define PTSNODENAME "/dev/X/ICE."
+#define NAMEDNODENAME "/dev/X/NICE."
+#define SCORNODENAME "/dev/ICE.%sR"
+#define SCOSNODENAME "/dev/ICE.%sS"
+#endif
+#if defined(TEST_t)
+#define PTSNODENAME "/dev/X/transtest."
+#define NAMEDNODENAME "/dev/X/Ntranstest."
+#define SCORNODENAME "/dev/transtest.%sR"
+#define SCOSNODENAME "/dev/transtest.%sS"
+#endif
+
+
+
+#ifndef sun
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(PTSOpenClient)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef PTSNODENAME
+ int fd,server,exitval,alarm_time,ret;
+ char server_path[64];
+ char *slave, namelen;
+ char buf[20]; /* MAX_PATH_LEN?? */
+ PFV savef;
+ pid_t saved_pid;
+#endif
+
+ PRMSG(2,"PTSOpenClient(%s)\n", port, 0,0 );
+
+#if !defined(PTSNODENAME)
+ PRMSG(1,"PTSOpenClient: Protocol is not supported by a pts connection\n", 0,0,0);
+ return -1;
+#else
+ if (port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
+ }
+
+
+ /*
+ * Open the node the on which the server is listening.
+ */
+
+ if ((server = open (server_path, O_RDWR)) < 0) {
+ PRMSG(1,"PTSOpenClient: failed to open %s\n", server_path, 0,0);
+ return -1;
+ }
+
+
+ /*
+ * Open the streams based pipe that will be this connection.
+ */
+
+ if ((fd = open(DEV_PTMX, O_RDWR)) < 0) {
+ PRMSG(1,"PTSOpenClient: failed to open %s\n", DEV_PTMX, 0,0);
+ return(-1);
+ }
+
+ (void) grantpt(fd);
+ (void) unlockpt(fd);
+
+ slave = ptsname(fd); /* get name */
+
+ if( slave == NULL ) {
+ PRMSG(1,"PTSOpenClient: failed to get ptsname()\n", 0,0,0);
+ close(fd);
+ close(server);
+ return -1;
+ }
+
+ /*
+ * This is neccesary for the case where a program is setuid to non-root.
+ * grantpt() calls /usr/lib/pt_chmod which is set-uid root. This program will
+ * set the owner of the pt device incorrectly if the uid is not restored
+ * before it is called. The problem is that once it gets restored, it
+ * cannot be changed back to its original condition, hence the fork().
+ */
+
+ if(!(saved_pid=fork())) {
+ uid_t saved_euid;
+
+ saved_euid = geteuid();
+ /** sets the euid to the actual/real uid **/
+ if (setuid( getuid() ) == -1) {
+ exit(1);
+ }
+ if( chown( slave, saved_euid, -1 ) < 0 ) {
+ exit( 1 );
+ }
+
+ exit( 0 );
+ }
+
+ waitpid(saved_pid, &exitval, 0);
+ if (WIFEXITED(exitval) && WEXITSTATUS(exitval) != 0) {
+ close(fd);
+ close(server);
+ PRMSG(1, "PTSOpenClient: cannot set the owner of %s\n",
+ slave, 0, 0);
+ return(-1);
+ }
+ if (chmod(slave, 0666) < 0) {
+ close(fd);
+ close(server);
+ PRMSG(1,"PTSOpenClient: Cannot chmod %s\n", slave, 0,0);
+ return(-1);
+ }
+
+ /*
+ * write slave name to server
+ */
+
+ namelen = strlen(slave);
+ buf[0] = namelen;
+ (void) sprintf(&buf[1], slave);
+ (void) write(server, buf, namelen+1);
+ (void) close(server);
+
+ /*
+ * wait for server to respond
+ */
+
+ savef = signal(SIGALRM, _dummy);
+ alarm_time = alarm (30); /* CONNECT_TIMEOUT */
+
+ ret = read(fd, buf, 1);
+
+ (void) alarm(alarm_time);
+ (void) signal(SIGALRM, savef);
+
+ if (ret != 1) {
+ PRMSG(1,
+ "PTSOpenClient: failed to get acknoledgement from server\n", 0, 0, 0);
+ (void) close(fd);
+ fd = -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, slave, server_path) == 0)
+ {
+ PRMSG(1,"PTSOpenClient: failed to fill in addr info\n", 0, 0, 0);
+ close(fd);
+ return -1;
+ }
+
+ return(fd);
+
+#endif /* !PTSNODENAME */
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(PTSOpenServer)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef PTSNODENAME
+ int fd, server;
+ char server_path[64], *slave;
+ int mode;
+#endif
+
+ PRMSG(2,"PTSOpenServer(%s)\n", port, 0,0 );
+
+#if !defined(PTSNODENAME)
+ PRMSG(1,"PTSOpenServer: Protocol is not supported by a pts connection\n", 0,0,0);
+ return -1;
+#else
+ if (port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%d", PTSNODENAME, getpid());
+ }
+
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "PTSOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
+
+#if 0
+ if( (fd=open(server_path, O_RDWR)) >= 0 ) {
+ /*
+ * This doesn't prevent the server from starting up, and doesn't
+ * prevent clients from trying to connect to the in-use PTS (which
+ * is often in use by something other than another server).
+ */
+ PRMSG(1, "PTSOpenServer: A server is already running on port %s\n", port, 0,0 );
+ PRMSG(1, "PTSOpenServer: Remove %s if this is incorrect.\n", server_path, 0,0 );
+ close(fd);
+ return(-1);
+ }
+#else
+ /* Just remove the old path (which is what happens with UNIXCONN) */
+#endif
+
+ unlink(server_path);
+
+ if( (fd=open(DEV_PTMX, O_RDWR)) < 0) {
+ PRMSG(1, "PTSOpenServer: Unable to open %s\n", DEV_PTMX, 0,0 );
+ return(-1);
+ }
+
+ grantpt(fd);
+ unlockpt(fd);
+
+ if( (slave=ptsname(fd)) == NULL) {
+ PRMSG(1, "PTSOpenServer: Unable to get slave device name\n", 0,0,0 );
+ close(fd);
+ return(-1);
+ }
+
+ if( link(slave,server_path) < 0 ) {
+ PRMSG(1, "PTSOpenServer: Unable to link %s to %s\n", slave, server_path,0 );
+ close(fd);
+ return(-1);
+ }
+
+ if( chmod(server_path, 0666) < 0 ) {
+ PRMSG(1, "PTSOpenServer: Unable to chmod %s to 0666\n", server_path,0,0 );
+ close(fd);
+ return(-1);
+ }
+
+ if( (server=open(server_path, O_RDWR)) < 0 ) {
+ PRMSG(1, "PTSOpenServer: Unable to open server device %s\n", server_path,0,0 );
+ close(fd);
+ return(-1);
+ }
+
+ close(server);
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"PTSOpenServer: failed to fill in addr info\n", 0, 0, 0);
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+
+#endif /* !PTSNODENAME */
+}
+
+static int
+TRANS(PTSAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
+
+{
+ int newfd;
+ int in;
+ unsigned char length;
+ char buf[256];
+ struct sockaddr_un *sunaddr;
+
+ PRMSG(2,"PTSAccept(%x->%d)\n",ciptr,ciptr->fd,0);
+
+ if( (in=read(ciptr->fd,&length,1)) <= 0 ){
+ if( !in ) {
+ PRMSG(2,
+ "PTSAccept: Incoming connection closed\n",0,0,0);
+ }
+ else {
+ PRMSG(1,
+ "PTSAccept: Error reading incoming connection. errno=%d \n",
+ errno,0,0);
+ }
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return -1;
+ }
+
+ if( (in=read(ciptr->fd,buf,length)) <= 0 ){
+ if( !in ) {
+ PRMSG(2,
+ "PTSAccept: Incoming connection closed\n",0,0,0);
+ }
+ else {
+ PRMSG(1,
+"PTSAccept: Error reading device name for new connection. errno=%d \n",
+ errno,0,0);
+ }
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return -1;
+ }
+
+ buf[length] = '\0';
+
+ if( (newfd=open(buf,O_RDWR)) < 0 ) {
+ PRMSG(1, "PTSAccept: Failed to open %s\n",buf,0,0);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return -1;
+ }
+
+ write(newfd,"1",1);
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ newciptr->addrlen=ciptr->addrlen;
+ if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
+ PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ close(newfd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
+
+ newciptr->peeraddrlen=sizeof(struct sockaddr_un);
+ if( (sunaddr=(struct sockaddr_un *)xalloc(newciptr->peeraddrlen)) == NULL ) {
+ PRMSG(1,"PTSAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ xfree(newciptr->addr);
+ close(newfd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ sunaddr->sun_family=AF_UNIX;
+ strcpy(sunaddr->sun_path,buf);
+#if defined(BSD44SOCKETS) && !defined(Lynx)
+ sunaddr->sun_len=strlen(sunaddr->sun_path);
+#endif
+
+ newciptr->peeraddr=(char *)sunaddr;
+
+ *status = 0;
+
+ return newfd;
+}
+
+#endif /* TRANS_SERVER */
+#endif /* sun */
+
+
+#ifdef SVR4
+
+/* NAMED */
+
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(NAMEDOpenClient)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef NAMEDNODENAME
+ int fd;
+ char server_path[64];
+ struct stat filestat;
+ extern int isastream();
+#endif
+
+ PRMSG(2,"NAMEDOpenClient(%s)\n", port, 0,0 );
+
+#if !defined(NAMEDNODENAME)
+ PRMSG(1,"NAMEDOpenClient: Protocol is not supported by a NAMED connection\n", 0,0,0);
+ return -1;
+#else
+ if ( port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", NAMEDNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%ld", NAMEDNODENAME, (long)getpid());
+ }
+
+ if (stat(server_path, &filestat) < 0 ) {
+ PRMSG(1,"NAMEDOpenClient: No device %s for NAMED connection\n", server_path, 0,0 );
+ return -1;
+ }
+
+ if ((filestat.st_mode & S_IFMT) != S_IFIFO) {
+ PRMSG(1,"NAMEDOpenClient: Device %s is not a FIFO\n", server_path, 0,0 );
+ /* Is this really a failure? */
+ return -1;
+ }
+
+ if ((fd = open(server_path, O_RDWR)) < 0) {
+ PRMSG(1,"NAMEDOpenClient: Cannot open %s for NAMED connection\n", server_path, 0,0 );
+ return -1;
+ }
+
+ if (isastream(fd) <= 0) {
+ PRMSG(1,"NAMEDOpenClient: %s is not a streams device\n", server_path, 0,0 );
+ (void) close(fd);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"NAMEDOpenClient: failed to fill in addr info\n",
+ 0,0,0);
+ close(fd);
+ return -1;
+ }
+
+ return(fd);
+
+#endif /* !NAMEDNODENAME */
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(NAMEDOpenServer)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef NAMEDNODENAME
+ int fd, pipefd[2];
+ char server_path[64];
+ struct stat sbuf;
+ int mode;
+#endif
+
+ PRMSG(2,"NAMEDOpenServer(%s)\n", port, 0,0 );
+
+#if !defined(NAMEDNODENAME)
+ PRMSG(1,"NAMEDOpenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
+ return -1;
+#else
+ if ( port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", NAMEDNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%ld", NAMEDNODENAME, (long)getpid());
+ }
+
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "NAMEDOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
+
+ if(stat(server_path, &sbuf) != 0) {
+ if (errno == ENOENT) {
+ if ((fd = creat(server_path, (mode_t)0666)) == -1) {
+ PRMSG(1, "NAMEDOpenServer: Can't open %s\n", server_path, 0,0 );
+ return(-1);
+ }
+ close(fd);
+ if (chmod(server_path, (mode_t)0666) < 0) {
+ PRMSG(1, "NAMEDOpenServer: Can't open %s\n", server_path, 0,0 );
+ return(-1);
+ }
+ } else {
+ PRMSG(1, "NAMEDOpenServer: stat on %s failed\n", server_path, 0,0 );
+ return(-1);
+ }
+ }
+
+ if( pipe(pipefd) != 0) {
+ PRMSG(1, "NAMEDOpenServer: pipe() failed, errno=%d\n",errno, 0,0 );
+ return(-1);
+ }
+
+ if( ioctl(pipefd[0], I_PUSH, "connld") != 0) {
+ PRMSG(1, "NAMEDOpenServer: ioctl(I_PUSH,\"connld\") failed, errno=%d\n",errno, 0,0 );
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return(-1);
+ }
+
+ if( fattach(pipefd[0], server_path) != 0) {
+ PRMSG(1, "NAMEDOpenServer: fattach(%s) failed, errno=%d\n", server_path,errno, 0 );
+ close(pipefd[0]);
+ close(pipefd[1]);
+ return(-1);
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"NAMEDOpenServer: failed to fill in addr info\n", 0,0,0);
+ return -1;
+ }
+
+ return(pipefd[1]);
+
+#endif /* !NAMEDNODENAME */
+}
+
+static int
+TRANS(NAMEDAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
+
+{
+ struct strrecvfd str;
+
+ PRMSG(2,"NAMEDAccept(%x->%d)\n", ciptr, ciptr->fd, 0 );
+
+ if( ioctl(ciptr->fd, I_RECVFD, &str ) < 0 ) {
+ PRMSG(1, "NAMEDAccept: ioctl(I_RECVFD) failed, errno=%d\n", errno, 0,0 );
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return(-1);
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ newciptr->addrlen=ciptr->addrlen;
+ if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
+ PRMSG(1,
+ "NAMEDAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ close(str.fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
+
+ newciptr->peeraddrlen=newciptr->addrlen;
+ if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
+ PRMSG(1,
+ "NAMEDAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ xfree(newciptr->addr);
+ close(str.fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
+
+ *status = 0;
+
+ return str.fd;
+}
+
+#endif /* TRANS_SERVER */
+
+#endif /* SVR4 */
+
+
+
+#ifndef sun
+
+/*
+ * connect_spipe is used by the SCO and ISC connection types.
+ */
+static int
+connect_spipe(int fd1, int fd2)
+{
+ long temp;
+ struct strfdinsert sbuf;
+
+ sbuf.databuf.maxlen = -1;
+ sbuf.databuf.len = -1;
+ sbuf.databuf.buf = NULL;
+ sbuf.ctlbuf.maxlen = sizeof(long);
+ sbuf.ctlbuf.len = sizeof(long);
+ sbuf.ctlbuf.buf = (caddr_t)&temp;
+ sbuf.offset = 0;
+ sbuf.fildes = fd2;
+ sbuf.flags = 0;
+
+ if( ioctl(fd1, I_FDINSERT, &sbuf) < 0 )
+ return(-1);
+
+ return(0);
+}
+
+/*
+ * named_spipe is used by the SCO and ISC connection types.
+ */
+
+static int
+named_spipe(int fd, char *path)
+
+{
+ int oldUmask, ret;
+ struct stat sbuf;
+
+ oldUmask = umask(0);
+
+ (void) fstat(fd, &sbuf);
+ ret = mknod(path, 0020666, sbuf.st_rdev);
+
+ umask(oldUmask);
+
+ if (ret < 0) {
+ ret = -1;
+ } else {
+ ret = fd;
+ }
+
+ return(ret);
+}
+
+/* SCO doesnt use the ISC transport type - it causes problems */
+#if !defined(__SCO__) && !defined(__UNIXWARE__)
+
+
+/* ISC */
+
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(ISCOpenClient)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef ISCDEVNODENAME
+ int fd,fds,server;
+ char server_path[64];
+ char server_dev_path[64];
+ struct strfdinsert buf;
+ long temp;
+ mode_t spmode;
+ struct stat filestat;
+#endif
+
+ PRMSG(2,"ISCOpenClient(%s)\n", port, 0,0 );
+
+#if !defined(ISCDEVNODENAME)
+ PRMSG(1,"ISCOpenClient: Protocol is not supported by a ISC connection\n", 0,0,0);
+ return -1;
+#else
+ (void) sprintf(server_path, ISCTMPNODENAME, port);
+ (void) sprintf(server_dev_path, ISCDEVNODENAME, port);
+
+ fd = fds = server = -1;
+
+ if (stat(DEV_SPX, &filestat) == -1) {
+ PRMSG(1, "ISCOpenClient: stat(%s) failed, errno=%d\n", DEV_SPX, errno, 0 );
+ return(-1);
+ }
+
+ spmode = (filestat.st_mode & S_IFMT);
+
+ if (stat(server_path, &filestat) != -1) {
+ if ((filestat.st_mode & S_IFMT) == spmode) {
+ if ((server = open(server_path, O_RDWR)) < 0) {
+ PRMSG(1,"ISCOpenClient: failed to open %s\n",
+ server_path, 0,0 );
+ }
+ }
+ }
+
+ if (server < 0) {
+ /* try the alternate path */
+ if (stat(server_dev_path, &filestat) != -1) {
+ if ((filestat.st_mode & S_IFMT) == spmode) {
+ if ((server = open(server_dev_path, O_RDWR)) < 0) {
+ PRMSG(1,"ISCOpenClient: failed to open %s\n",
+ server_dev_path, 0,0 );
+ }
+ }
+ }
+ }
+
+ if (server < 0) {
+ PRMSG(1,"ISCOpenClient: can't open either device %s or %s\n",
+ server_path, server_dev_path, 0 );
+ return -1;
+ }
+
+ if ((fds = open(DEV_SPX, O_RDWR)) < 0 ||
+ (fd = open(DEV_SPX, O_RDWR)) < 0) {
+ /* Failed to open all of the devices */
+ PRMSG(1,"ISCOpenClient: can't open %s\n", DEV_SPX, 0,0 );
+ (void) close(server);
+ if (fds != -1)
+ (void) close(fds);
+ if (fd != -1)
+ (void) close(fd);
+ return -1;
+ }
+
+ /* make a STREAMS-pipe */
+
+ buf.databuf.maxlen = -1;
+ buf.databuf.len = -1;
+ buf.databuf.buf = NULL;
+ buf.ctlbuf.maxlen = sizeof(long);
+ buf.ctlbuf.len = sizeof(long);
+ buf.ctlbuf.buf = (caddr_t)&temp;
+ buf.offset = 0;
+ buf.fildes = fd;
+ buf.flags = 0;
+
+ if (ioctl(fds, I_FDINSERT, &buf) < 0 ||
+ ioctl(server, I_SENDFD, fds) < 0) {
+ PRMSG(1,"ISCOpenClient: ioctl(I_FDINSERT or I_SENDFD) failed\n",
+ 0,0,0 );
+ (void) close(server);
+ (void) close(fds);
+ (void) close(fd);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"ISCOpenClient: failed to fill in addr info\n", 0, 0, 0);
+ close(fd);
+ return -1;
+ }
+
+ return (fd);
+
+#endif /* !ISCDEVNODENAME */
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(ISCOpenServer)(XtransConnInfo ciptr, char *port)
+
+{
+#ifdef ISCDEVNODENAME
+ int fd = -1,fds = -1;
+ char server_path[64],server_unix_path[64];
+ unsigned int mode = 0;
+#endif
+
+ PRMSG(2,"ISCOpenServer(%s)\n", port, 0,0 );
+
+#if !defined(ISCDEVNODENAME)
+ PRMSG(1,"ISCOpenServer: Protocol is not supported by a ISC connection\n", 0,0,0);
+ return -1;
+#else
+ (void) sprintf(server_path, ISCDEVNODENAME, port);
+ (void) sprintf(server_unix_path, ISCTMPNODENAME, port);
+
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+
+ /* "/dev/X" */
+ if (trans_mkdir(X_STREAMS_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_STREAMS_DIR, errno, 0);
+ return(-1);
+ }
+ /* "/dev/X/ISCCONN" */
+ if (trans_mkdir(X_ISC_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_ISC_DIR, errno, 0);
+ return(-1);
+ }
+
+ unlink(server_path);
+
+ if( ((fds=open(DEV_SPX, O_RDWR)) < 0) ||
+ ((fd =open(DEV_SPX, O_RDWR)) < 0)) {
+ PRMSG(1,"ISCOpenServer: failed to open %s\n", DEV_SPX, 0,0 );
+ return -1;
+ }
+
+ if( (connect_spipe(fds, fd) < 0) ||
+ (named_spipe(fds, server_path) < 0)) {
+ PRMSG(1,"ISCOpenServer: failed connect pipes\n", 0,0,0 );
+ close(fd);
+ close(fds);
+ return -1;
+ }
+
+#if !defined(UNIXCONN)
+ /*
+ * If the UNIX Domain socket transport is not being used, then link this
+ * device to the path /tmp/.X11-unix/X path.
+ */
+#define X_UNIX_DIR "/tmp/.X11-unix"
+
+ if (trans_mkdir(X_UNIX_DIR, mode) == -1) {
+ PRMSG (1, "ISCOpenServer: mkdir(%s) failed, errno = %d\n",
+ X_UNIX_DIR, errno, 0);
+ return(-1);
+ }
+
+ unlink(server_unix_path);
+
+#ifdef SVR4
+ /* we prefer symbolic links because hard links can't cross file systems */
+ if( symlink(server_path, server_unix_path) < 0 )
+ PRMSG(1,"ISCOpenServer: failed to link %s to %s\n",
+ server_path, server_unix_path, 0 );
+ /*
+ * Don't make this failure fatal since the listener
+ * is already established, and this just for compatability
+ */
+#else
+#ifdef ISC40
+ /* catch SIGSYS on symlink for ISC40 compiled binaries running on ISC30 */
+ signal(SIGSYS,_dummy);
+#endif
+ if( link(server_path, server_unix_path) < 0 )
+#ifdef ISC40
+ if( symlink(server_path, server_unix_path) < 0 )
+#endif
+ PRMSG(1,"ISCOpenServer: failed to link %s to %s\n",
+ server_path, server_unix_path, 0 );
+ /*
+ * Don't make this failure fatal since the listener
+ * is already established, and this just for compatability
+ */
+#endif /* SVR4 */
+#endif /* !UNIXCONN */
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"ISCOpenServer: failed to fill in addr info\n", 0, 0, 0);
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+
+#endif /* !ISCDEVNODENAME */
+}
+
+static int
+TRANS(ISCAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
+
+{
+ struct strrecvfd str;
+
+ PRMSG(2,"ISCAccept(%d)\n", ciptr->fd, 0,0 );
+
+ while (ioctl(ciptr->fd, I_RECVFD, &str) < 0) {
+ if (errno != EAGAIN) {
+ PRMSG(1,"ISCAccept: Can't read fildes", 0,0,0 );
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return(-1);
+ }
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ newciptr->addrlen=ciptr->addrlen;
+ if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
+ PRMSG(1,
+ "ISCAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ close(str.fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
+
+ newciptr->peeraddrlen=newciptr->addrlen;
+ if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
+ PRMSG(1,
+ "ISCAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ xfree(newciptr->addr);
+ close(str.fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
+
+ *status = 0;
+
+ return(str.fd);
+}
+
+#endif /* TRANS_SERVER */
+#endif /* !__SCO__ && !__UNIXWARE__ */
+
+
+/* SCO */
+
+/*
+ * 2002-11-09 (jkj@sco.com)
+ *
+ * This code has been modified to match what is in the actual SCO X server.
+ * This greatly helps inter-operability between X11R6 and X11R5 (the native
+ * SCO server). Mainly, it relies on streams nodes existing in /dev, not
+ * creating them or unlinking them, which breaks the native X server.
+ *
+ * However, this is only for the X protocol. For all other protocols, we
+ * do in fact create the nodes, as only X11R6 will use them, and this makes
+ * it possible to have both types of clients running, otherwise we get all
+ * kinds of nasty errors on startup for anything that doesnt use the X
+ * protocol (like SM, when KDE starts up).
+ */
+
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(SCOOpenClient)(XtransConnInfo ciptr, char *port)
+{
+#ifdef SCORNODENAME
+ int fd, server, fl, ret;
+ char server_path[64];
+ struct strbuf ctlbuf;
+ unsigned long alarm_time;
+ void (*savef)();
+ long temp;
+ extern int getmsg(), putmsg();
+#endif
+
+ PRMSG(2,"SCOOpenClient(%s)\n", port, 0,0 );
+ if (!port || !port[0])
+ port = "0";
+
+#if !defined(SCORNODENAME)
+ PRMSG(2,"SCOOpenClient: Protocol is not supported by a SCO connection\n", 0,0,0);
+ return -1;
+#else
+ (void) sprintf(server_path, SCORNODENAME, port);
+
+ if ((server = open(server_path, O_RDWR)) < 0) {
+ PRMSG(1,"SCOOpenClient: failed to open %s\n", server_path, 0,0 );
+ return -1;
+ }
+
+ if ((fd = open(DEV_SPX, O_RDWR)) < 0) {
+ PRMSG(1,"SCOOpenClient: failed to open %s\n", DEV_SPX, 0,0 );
+ close(server);
+ return -1;
+ }
+
+ (void) write(server, &server, 1);
+ ctlbuf.len = 0;
+ ctlbuf.maxlen = sizeof(long);
+ ctlbuf.buf = (caddr_t)&temp;
+ fl = 0;
+
+ savef = signal(SIGALRM, _dummy);
+ alarm_time = alarm(10);
+
+ ret = getmsg(server, &ctlbuf, 0, &fl);
+
+ (void) alarm(alarm_time);
+ (void) signal(SIGALRM, savef);
+
+ if (ret < 0) {
+ PRMSG(1,"SCOOpenClient: error from getmsg\n", 0,0,0 );
+ close(fd);
+ close(server);
+ return -1;
+ }
+
+ /* The msg we got via getmsg is the result of an
+ * I_FDINSERT, so if we do a putmsg with whatever
+ * we recieved, we're doing another I_FDINSERT ...
+ */
+ (void) putmsg(fd, &ctlbuf, 0, 0);
+ (void) fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NDELAY);
+
+ (void) close(server);
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+#if defined(X11_t) && defined(__SCO__)
+ ciptr->flags |= TRANS_NOUNLINK;
+#endif
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"SCOOpenClient: failed to fill addr info\n", 0, 0, 0);
+ close(fd);
+ return -1;
+ }
+
+ return(fd);
+
+#endif /* !SCORNODENAME */
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(SCOOpenServer)(XtransConnInfo ciptr, char *port)
+{
+#ifdef SCORNODENAME
+ char serverR_path[64];
+ char serverS_path[64];
+ struct flock mylock;
+ int fdr = -1;
+ int fds = -1;
+#endif
+
+ PRMSG(2,"SCOOpenServer(%s)\n", port, 0,0 );
+ if (!port || !port[0])
+ port = "0";
+
+#if !defined(SCORNODENAME)
+ PRMSG(1,"SCOOpenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
+ return -1;
+#else
+ (void) sprintf(serverR_path, SCORNODENAME, port);
+ (void) sprintf(serverS_path, SCOSNODENAME, port);
+
+#if !defined(X11_t) || !defined(__SCO__)
+ unlink(serverR_path);
+ unlink(serverS_path);
+
+ if ((fds = open(DEV_SPX, O_RDWR)) < 0 ||
+ (fdr = open(DEV_SPX, O_RDWR)) < 0 ) {
+ PRMSG(1,"SCOOpenServer: failed to open %s\n", DEV_SPX, 0,0 );
+ return -1;
+ }
+
+ if (named_spipe (fds, serverS_path) == -1) {
+ PRMSG(1,"SCOOpenServer: failed to create %s\n", serverS_path, 0, 0);
+ close (fdr);
+ close (fds);
+ return -1;
+ }
+
+ if (named_spipe (fdr, serverR_path) == -1) {
+ PRMSG(1,"SCOOpenServer: failed to create %s\n", serverR_path, 0, 0);
+ close (fdr);
+ close (fds);
+ return -1;
+ }
+#else /* X11_t */
+
+ fds = open (serverS_path, O_RDWR | O_NDELAY);
+ if (fds < 0) {
+ PRMSG(1,"SCOOpenServer: failed to open %s\n", serverS_path, 0, 0);
+ return -1;
+ }
+
+ /*
+ * Lock the connection device for the duration of the server.
+ * This resolves multiple server starts especially on SMP machines.
+ */
+ mylock.l_type = F_WRLCK;
+ mylock.l_whence = 0;
+ mylock.l_start = 0;
+ mylock.l_len = 0;
+ if (fcntl (fds, F_SETLK, &mylock) < 0) {
+ PRMSG(1,"SCOOpenServer: failed to lock %s\n", serverS_path, 0, 0);
+ close (fds);
+ return -1;
+ }
+
+ fdr = open (serverR_path, O_RDWR | O_NDELAY);
+ if (fds < 0) {
+ PRMSG(1,"SCOOpenServer: failed to open %s\n", serverR_path, 0, 0);
+ close (fds);
+ return -1;
+ }
+#endif /* X11_t */
+
+ if (connect_spipe(fds, fdr)) {
+ PRMSG(1,"SCOOpenServer: ioctl(I_FDINSERT) failed on %s\n",
+ serverS_path, 0, 0);
+ close (fdr);
+ close (fds);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+#if defined(X11_t) && defined(__SCO__)
+ ciptr->flags |= TRANS_NOUNLINK;
+#endif
+ if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0) {
+ PRMSG(1,"SCOOpenServer: failed to fill in addr info\n", 0,0,0);
+ close(fds);
+ close(fdr);
+ return -1;
+ }
+
+ return(fds);
+
+#endif /* !SCORNODENAME */
+}
+
+static int
+TRANS(SCOAccept)(XtransConnInfo ciptr, XtransConnInfo newciptr, int *status)
+{
+ char c;
+ int fd;
+
+ PRMSG(2,"SCOAccept(%d)\n", ciptr->fd, 0,0 );
+
+ if (read(ciptr->fd, &c, 1) < 0) {
+ PRMSG(1,"SCOAccept: can't read from client\n",0,0,0);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return(-1);
+ }
+
+ if( (fd = open(DEV_SPX, O_RDWR)) < 0 ) {
+ PRMSG(1,"SCOAccept: can't open \"%s\"\n",DEV_SPX, 0,0 );
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return(-1);
+ }
+
+ if (connect_spipe (ciptr->fd, fd) < 0) {
+ PRMSG(1,"SCOAccept: ioctl(I_FDINSERT) failed\n", 0, 0, 0);
+ close (fd);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ newciptr->addrlen=ciptr->addrlen;
+ if( (newciptr->addr=(char *)xalloc(newciptr->addrlen)) == NULL ) {
+ PRMSG(1,
+ "SCOAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ close(fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->addr,ciptr->addr,newciptr->addrlen);
+#if defined(__SCO__)
+ newciptr->flags |= TRANS_NOUNLINK;
+#endif
+
+ newciptr->peeraddrlen=newciptr->addrlen;
+ if( (newciptr->peeraddr=(char *)xalloc(newciptr->peeraddrlen)) == NULL ) {
+ PRMSG(1,
+ "SCOAccept: failed to allocate memory for peer addr\n",
+ 0,0,0);
+ xfree(newciptr->addr);
+ close(fd);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return -1;
+ }
+
+ memcpy(newciptr->peeraddr,newciptr->addr,newciptr->peeraddrlen);
+
+ *status = 0;
+
+ return(fd);
+}
+
+#endif /* TRANS_SERVER */
+#endif /* sun */
+
+
+
+#ifdef TRANS_REOPEN
+#ifndef sun
+
+static int
+TRANS(PTSReopenServer)(XtransConnInfo ciptr, int fd, char *port)
+
+{
+#ifdef PTSNODENAME
+ char server_path[64];
+#endif
+
+ PRMSG(2,"PTSReopenServer(%d,%s)\n", fd, port, 0 );
+
+#if !defined(PTSNODENAME)
+ PRMSG(1,"PTSReopenServer: Protocol is not supported by a pts connection\n", 0,0,0);
+ return 0;
+#else
+ if (port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", PTSNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%ld", PTSNODENAME, (long)getpid());
+ }
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"PTSReopenServer: failed to fill in addr info\n",
+ 0,0,0);
+ return 0;
+ }
+
+ return 1;
+
+#endif /* !PTSNODENAME */
+}
+
+#endif /* !sun */
+
+static int
+TRANS(NAMEDReopenServer)(XtransConnInfo ciptr, int fd, char *port)
+
+{
+#ifdef NAMEDNODENAME
+ char server_path[64];
+#endif
+
+ PRMSG(2,"NAMEDReopenServer(%s)\n", port, 0,0 );
+
+#if !defined(NAMEDNODENAME)
+ PRMSG(1,"NAMEDReopenServer: Protocol is not supported by a NAMED connection\n", 0,0,0);
+ return 0;
+#else
+ if ( port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(server_path, "%s", port);
+ } else {
+ (void) sprintf(server_path, "%s%s", NAMEDNODENAME, port);
+ }
+ } else {
+ (void) sprintf(server_path, "%s%ld", NAMEDNODENAME, (long)getpid());
+ }
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1,"NAMEDReopenServer: failed to fill in addr info\n",
+ 0,0,0);
+ return 0;
+ }
+
+ return 1;
+
+#endif /* !NAMEDNODENAME */
+}
+
+#ifndef sun
+#if !defined(__SCO__) && !defined(__UNIXWARE__)
+static int
+TRANS(ISCReopenServer)(XtransConnInfo ciptr, int fd, char *port)
+
+{
+#ifdef ISCDEVNODENAME
+ char server_path[64], server_unix_path[64];
+#endif
+
+ PRMSG(2,"ISCReopenServer(%s)\n", port, 0,0 );
+
+#if !defined(ISCDEVNODENAME)
+ PRMSG(1,"ISCReopenServer: Protocol is not supported by a ISC connection\n", 0,0,0);
+ return 0;
+#else
+ (void) sprintf(server_path, ISCDEVNODENAME, port);
+ (void) sprintf(server_unix_path, ISCTMPNODENAME, port);
+
+ if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0)
+ {
+ PRMSG(1, "ISCReopenServer: failed to fill in addr info\n", 0,0,0);
+ return 0;
+ }
+
+ return 1;
+
+#endif /* !ISCDEVNODENAME */
+}
+#endif /* !__SCO__ && !__UNIXWARE__ */
+
+static int
+TRANS(SCOReopenServer)(XtransConnInfo ciptr, int fd, char *port)
+
+{
+#ifdef SCORNODENAME
+ char serverR_path[64], serverS_path[64];
+#endif
+
+ PRMSG(2,"SCOReopenServer(%s)\n", port, 0,0 );
+ if (!port || !port[0])
+ port = "0";
+
+#if !defined(SCORNODENAME)
+ PRMSG(2,"SCOReopenServer: Protocol is not supported by a SCO connection\n", 0,0,0);
+ return 0;
+#else
+ (void) sprintf(serverR_path, SCORNODENAME, port);
+ (void) sprintf(serverS_path, SCOSNODENAME, port);
+
+#if defined(X11_t) && defined(__SCO__)
+ ciptr->flags |= TRANS_NOUNLINK;
+#endif
+ if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0)
+ {
+ PRMSG(1, "SCOReopenServer: failed to fill in addr info\n", 0,0,0);
+ return 0;
+ }
+
+ return 1;
+
+#endif /* SCORNODENAME */
+}
+
+#endif /* !sun */
+
+#endif /* TRANS_REOPEN */
+
+
+
+/*
+ * This table contains all of the entry points for the different local
+ * connection mechanisms.
+ */
+
+typedef struct _LOCALtrans2dev {
+ char *transname;
+
+#ifdef TRANS_CLIENT
+
+ int (*devcotsopenclient)(
+ XtransConnInfo, char * /*port*/
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+ int (*devcotsopenserver)(
+ XtransConnInfo, char * /*port*/
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+ int (*devcltsopenclient)(
+ XtransConnInfo, char * /*port*/
+);
+
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+
+ int (*devcltsopenserver)(
+ XtransConnInfo, char * /*port*/
+);
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_REOPEN
+
+ int (*devcotsreopenserver)(
+ XtransConnInfo,
+ int, /* fd */
+ char * /* port */
+);
+
+ int (*devcltsreopenserver)(
+ XtransConnInfo,
+ int, /* fd */
+ char * /* port */
+);
+
+#endif /* TRANS_REOPEN */
+
+#ifdef TRANS_SERVER
+
+ int (*devaccept)(
+ XtransConnInfo, XtransConnInfo, int *
+);
+
+#endif /* TRANS_SERVER */
+
+} LOCALtrans2dev;
+
+static LOCALtrans2dev LOCALtrans2devtab[] = {
+#ifndef sun
+{"",
+#ifdef TRANS_CLIENT
+ TRANS(PTSOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(PTSOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(PTSReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(PTSAccept)
+#endif /* TRANS_SERVER */
+},
+
+{"local",
+#ifdef TRANS_CLIENT
+ TRANS(PTSOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(PTSOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(PTSReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(PTSAccept)
+#endif /* TRANS_SERVER */
+},
+
+{"pts",
+#ifdef TRANS_CLIENT
+ TRANS(PTSOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(PTSOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(PTSReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(PTSAccept)
+#endif /* TRANS_SERVER */
+},
+#else /* sun */
+{"",
+#ifdef TRANS_CLIENT
+ TRANS(NAMEDOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(NAMEDOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(NAMEDReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(NAMEDAccept)
+#endif /* TRANS_SERVER */
+},
+
+{"local",
+#ifdef TRANS_CLIENT
+ TRANS(NAMEDOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(NAMEDOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(NAMEDReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(NAMEDAccept)
+#endif /* TRANS_SERVER */
+},
+#endif /* sun */
+
+#ifdef SVR4
+{"named",
+#ifdef TRANS_CLIENT
+ TRANS(NAMEDOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(NAMEDOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(NAMEDReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(NAMEDAccept)
+#endif /* TRANS_SERVER */
+},
+#endif /* SVR4 */
+
+#ifndef sun
+#if !defined(__SCO__) && !defined(__UNIXWARE__)
+{"isc",
+#ifdef TRANS_CLIENT
+ TRANS(ISCOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(ISCOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(ISCReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(ISCAccept)
+#endif /* TRANS_SERVER */
+},
+#endif /* !__SCO__ && !__UNIXWARE__ */
+
+{"sco",
+#ifdef TRANS_CLIENT
+ TRANS(SCOOpenClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SCOOpenServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(OpenFail),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(OpenFail),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SCOReopenServer),
+ TRANS(ReopenFail),
+#endif
+#ifdef TRANS_SERVER
+ TRANS(SCOAccept)
+#endif /* TRANS_SERVER */
+},
+#endif /* sun */
+};
+
+#define NUMTRANSPORTS (sizeof(LOCALtrans2devtab)/sizeof(LOCALtrans2dev))
+
+static char *XLOCAL=NULL;
+static char *workingXLOCAL=NULL;
+static char *freeXLOCAL=NULL;
+
+#if defined(__SCO__)
+#define DEF_XLOCAL "SCO:UNIX:PTS"
+#elif defined(__UNIXWARE__)
+#define DEF_XLOCAL "UNIX:PTS:NAMED:SCO"
+#else
+#define DEF_XLOCAL "UNIX:PTS:NAMED:ISC:SCO"
+#endif
+
+static void
+TRANS(LocalInitTransports)(char *protocol)
+
+{
+ PRMSG(3,"LocalInitTransports(%s)\n", protocol, 0,0 );
+
+ if( strcmp(protocol,"local") && strcmp(protocol,"LOCAL") )
+ {
+ workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (protocol) + 1);
+ if (workingXLOCAL)
+ strcpy (workingXLOCAL, protocol);
+ }
+ else {
+ XLOCAL=(char *)getenv("XLOCAL");
+ if(XLOCAL==NULL)
+ XLOCAL=DEF_XLOCAL;
+ workingXLOCAL=freeXLOCAL=(char *)xalloc (strlen (XLOCAL) + 1);
+ if (workingXLOCAL)
+ strcpy (workingXLOCAL, XLOCAL);
+ }
+}
+
+static void
+TRANS(LocalEndTransports)(void)
+
+{
+ PRMSG(3,"LocalEndTransports()\n", 0,0,0 );
+ xfree(freeXLOCAL);
+}
+
+#define TYPEBUFSIZE 32
+
+#ifdef TRANS_CLIENT
+
+static LOCALtrans2dev *
+TRANS(LocalGetNextTransport)(void)
+
+{
+ int i,j;
+ char *typetocheck;
+ char typebuf[TYPEBUFSIZE];
+ PRMSG(3,"LocalGetNextTransport()\n", 0,0,0 );
+
+ while(1)
+ {
+ if( workingXLOCAL == NULL || *workingXLOCAL == '\0' )
+ return NULL;
+
+ typetocheck=workingXLOCAL;
+ workingXLOCAL=strchr(workingXLOCAL,':');
+ if(workingXLOCAL && *workingXLOCAL)
+ *workingXLOCAL++='\0';
+
+ for(i=0;i<NUMTRANSPORTS;i++)
+ {
+ /*
+ * This is equivilent to a case insensitive strcmp(),
+ * but should be more portable.
+ */
+ strncpy(typebuf,typetocheck,TYPEBUFSIZE);
+ for(j=0;j<TYPEBUFSIZE;j++)
+ if (isupper(typebuf[j]))
+ typebuf[j]=tolower(typebuf[j]);
+
+ /* Now, see if they match */
+ if(!strcmp(LOCALtrans2devtab[i].transname,typebuf))
+ return &LOCALtrans2devtab[i];
+ }
+ }
+#if 0
+ /*NOTREACHED*/
+ return NULL;
+#endif
+}
+
+#ifdef NEED_UTSNAME
+#include <sys/utsname.h>
+#endif
+
+/*
+ * Make sure 'host' is really local.
+ */
+
+static int
+HostReallyLocal (char *host)
+
+{
+ /*
+ * The 'host' passed to this function may have been generated
+ * by either uname() or gethostname(). We try both if possible.
+ */
+
+#ifdef NEED_UTSNAME
+ struct utsname name;
+#endif
+ char buf[256];
+
+#ifdef NEED_UTSNAME
+ if (uname (&name) >= 0 && strcmp (host, name.nodename) == 0)
+ return (1);
+#endif
+
+ buf[0] = '\0';
+ (void) gethostname (buf, 256);
+ buf[255] = '\0';
+
+ if (strcmp (host, buf) == 0)
+ return (1);
+
+ return (0);
+}
+
+
+static XtransConnInfo
+TRANS(LocalOpenClient)(int type, char *protocol, char *host, char *port)
+
+{
+ LOCALtrans2dev *transptr;
+ XtransConnInfo ciptr;
+ int index;
+
+ PRMSG(3,"LocalOpenClient()\n", 0,0,0 );
+
+ /*
+ * Make sure 'host' is really local. If not, we return failure.
+ * The reason we make this check is because a process may advertise
+ * a "local" address for which it can accept connections, but if a
+ * process on a remote machine tries to connect to this address,
+ * we know for sure it will fail.
+ */
+
+ if (strcmp (host, "unix") != 0 && !HostReallyLocal (host))
+ {
+ PRMSG (1,
+ "LocalOpenClient: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return NULL;
+ }
+
+
+#if defined(X11_t)
+ /*
+ * X has a well known port, that is transport dependant. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay(). Since that is what we want for the local transports,
+ * we don't have to do anything special.
+ */
+#endif /* X11_t */
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1,"LocalOpenClient: calloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+ ciptr->fd = -1;
+
+ TRANS(LocalInitTransports)(protocol);
+
+ index = 0;
+ for(transptr=TRANS(LocalGetNextTransport)();
+ transptr!=NULL;transptr=TRANS(LocalGetNextTransport)(), index++)
+ {
+ switch( type )
+ {
+ case XTRANS_OPEN_COTS_CLIENT:
+ ciptr->fd=transptr->devcotsopenclient(ciptr,port);
+ break;
+ case XTRANS_OPEN_CLTS_CLIENT:
+ ciptr->fd=transptr->devcltsopenclient(ciptr,port);
+ break;
+ case XTRANS_OPEN_COTS_SERVER:
+ case XTRANS_OPEN_CLTS_SERVER:
+ PRMSG(1,
+ "LocalOpenClient: Should not be opening a server with this function\n",
+ 0,0,0);
+ break;
+ default:
+ PRMSG(1,
+ "LocalOpenClient: Unknown Open type %d\n",
+ type, 0,0 );
+ }
+ if( ciptr->fd >= 0 )
+ break;
+ }
+
+ TRANS(LocalEndTransports)();
+
+ if( ciptr->fd < 0 )
+ {
+ xfree(ciptr);
+ return NULL;
+ }
+
+ ciptr->priv=(char *)transptr;
+ ciptr->index = index;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(LocalOpenServer)(int type, char *protocol, char *host, char *port)
+
+{
+ int i;
+ XtransConnInfo ciptr;
+
+ PRMSG(2,"LocalOpenServer(%d,%s,%s)\n", type, protocol, port);
+
+#if defined(X11_t)
+ /*
+ * For X11, the port will be in the format xserverN where N is the
+ * display number. All of the local connections just need to know
+ * the display number because they don't do any name resolution on
+ * the port. This just truncates port to the display portion.
+ */
+#endif /* X11_t */
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1,"LocalOpenServer: calloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+ for(i=1;i<NUMTRANSPORTS;i++)
+ {
+ if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 )
+ continue;
+ switch( type )
+ {
+ case XTRANS_OPEN_COTS_CLIENT:
+ case XTRANS_OPEN_CLTS_CLIENT:
+ PRMSG(1,
+ "LocalOpenServer: Should not be opening a client with this function\n",
+ 0,0,0);
+ break;
+ case XTRANS_OPEN_COTS_SERVER:
+ ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port);
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+ ciptr->fd=LOCALtrans2devtab[i].devcltsopenserver(ciptr,port);
+ break;
+ default:
+ PRMSG(1,"LocalOpenServer: Unknown Open type %d\n",
+ type ,0,0);
+ }
+ if( ciptr->fd >= 0 ) {
+ ciptr->priv=(char *)&LOCALtrans2devtab[i];
+ ciptr->index=i;
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+ return ciptr;
+ }
+ }
+
+ xfree(ciptr);
+ return NULL;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(LocalReopenServer)(int type, int index, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int stat = 0;
+
+ PRMSG(2,"LocalReopenServer(%d,%d,%d)\n", type, index, fd);
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1,"LocalReopenServer: calloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ switch( type )
+ {
+ case XTRANS_OPEN_COTS_SERVER:
+ stat = LOCALtrans2devtab[index].devcotsreopenserver(ciptr,fd,port);
+ break;
+ case XTRANS_OPEN_CLTS_SERVER:
+ stat = LOCALtrans2devtab[index].devcltsreopenserver(ciptr,fd,port);
+ break;
+ default:
+ PRMSG(1,"LocalReopenServer: Unknown Open type %d\n",
+ type ,0,0);
+ }
+
+ if( stat > 0 ) {
+ ciptr->priv=(char *)&LOCALtrans2devtab[index];
+ ciptr->index=index;
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+ return ciptr;
+ }
+
+ xfree(ciptr);
+ return NULL;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+/*
+ * This is the Local implementation of the X Transport service layer
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(LocalOpenCOTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ PRMSG(2,"LocalOpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
+
+ return TRANS(LocalOpenClient)(XTRANS_OPEN_COTS_CLIENT, protocol, host, port);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(LocalOpenCOTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ char *typetocheck = NULL;
+ int found = 0;
+ char typebuf[TYPEBUFSIZE];
+
+ PRMSG(2,"LocalOpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
+
+ /* Check if this local type is in the XLOCAL list */
+ TRANS(LocalInitTransports)("local");
+ typetocheck = workingXLOCAL;
+ while (typetocheck && !found) {
+ int j;
+
+ workingXLOCAL = strchr(workingXLOCAL, ':');
+ if (workingXLOCAL && *workingXLOCAL)
+ *workingXLOCAL++ = '\0';
+ strncpy(typebuf, typetocheck, TYPEBUFSIZE);
+ for (j = 0; j < TYPEBUFSIZE; j++)
+ if (isupper(typebuf[j]))
+ typebuf[j] = tolower(typebuf[j]);
+ if (!strcmp(thistrans->TransName, typebuf))
+ found = 1;
+ typetocheck = workingXLOCAL;
+ }
+ TRANS(LocalEndTransports)();
+
+ if (!found) {
+ PRMSG(3,"LocalOpenCOTSServer: disabling %s\n",thistrans->TransName,0,0);
+ thistrans->flags |= TRANS_DISABLED;
+ return NULL;
+ }
+
+ return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(LocalOpenCLTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ PRMSG(2,"LocalOpenCLTSClient(%s,%s,%s)\n",protocol,host,port);
+
+ return TRANS(LocalOpenClient)(XTRANS_OPEN_CLTS_CLIENT, protocol, host, port);
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(LocalOpenCLTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ PRMSG(2,"LocalOpenCLTSServer(%s,%s,%s)\n",protocol,host,port);
+
+ return TRANS(LocalOpenServer)(XTRANS_OPEN_CLTS_SERVER, protocol, host, port);
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(LocalReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
+
+{
+ int index;
+
+ PRMSG(2,"LocalReopenCOTSServer(%d,%s)\n", fd, port, 0);
+
+ for(index=1;index<NUMTRANSPORTS;index++)
+ {
+ if( strcmp(thistrans->TransName,
+ LOCALtrans2devtab[index].transname) == 0 )
+ break;
+ }
+
+ if (index >= NUMTRANSPORTS)
+ {
+ return (NULL);
+ }
+
+ return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER,
+ index, fd, port);
+}
+
+static XtransConnInfo
+TRANS(LocalReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
+
+{
+ int index;
+
+ PRMSG(2,"LocalReopenCLTSServer(%d,%s)\n", fd, port, 0);
+
+ for(index=1;index<NUMTRANSPORTS;index++)
+ {
+ if( strcmp(thistrans->TransName,
+ LOCALtrans2devtab[index].transname) == 0 )
+ break;
+ }
+
+ if (index >= NUMTRANSPORTS)
+ {
+ return (NULL);
+ }
+
+ return TRANS(LocalReopenServer)(XTRANS_OPEN_CLTS_SERVER,
+ index, fd, port);
+}
+
+#endif /* TRANS_REOPEN */
+
+
+
+static int
+TRANS(LocalSetOption)(XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG(2,"LocalSetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
+
+ return -1;
+}
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(LocalCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+ PRMSG(2,"LocalCreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port);
+
+ return 0;
+}
+
+static XtransConnInfo
+TRANS(LocalAccept)(XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ LOCALtrans2dev *transptr;
+
+ PRMSG(2,"LocalAccept(%x->%d)\n", ciptr, ciptr->fd,0);
+
+ transptr=(LOCALtrans2dev *)ciptr->priv;
+
+ if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL )
+ {
+ PRMSG(1,"LocalAccept: calloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ newciptr->fd=transptr->devaccept(ciptr,newciptr,status);
+
+ if( newciptr->fd < 0 )
+ {
+ xfree(newciptr);
+ return NULL;
+ }
+
+ newciptr->priv=(char *)transptr;
+ newciptr->index = ciptr->index;
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(LocalConnect)(XtransConnInfo ciptr, char *host, char *port)
+
+{
+ PRMSG(2,"LocalConnect(%x->%d,%s)\n", ciptr, ciptr->fd, port);
+
+ return 0;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(LocalBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend )
+
+{
+ PRMSG(2,"LocalBytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend);
+
+#if defined(ISC) || defined(SCO325)
+ return ioctl(ciptr->fd, I_NREAD, (char *)pend);
+#else
+ return ioctl(ciptr->fd, FIONREAD, (char *)pend);
+#endif
+}
+
+static int
+TRANS(LocalRead)(XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG(2,"LocalRead(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return read(ciptr->fd,buf,size);
+}
+
+static int
+TRANS(LocalWrite)(XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG(2,"LocalWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return write(ciptr->fd,buf,size);
+}
+
+static int
+TRANS(LocalReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG(2,"LocalReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return READV(ciptr,buf,size);
+}
+
+static int
+TRANS(LocalWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG(2,"LocalWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return WRITEV(ciptr,buf,size);
+}
+
+static int
+TRANS(LocalDisconnect)(XtransConnInfo ciptr)
+
+{
+ PRMSG(2,"LocalDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
+
+ return 0;
+}
+
+static int
+TRANS(LocalClose)(XtransConnInfo ciptr)
+
+{
+ struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr;
+ int ret;
+
+ PRMSG(2,"LocalClose(%x->%d)\n", ciptr, ciptr->fd ,0);
+
+ ret=close(ciptr->fd);
+
+ if(ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0] )
+ {
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ unlink(sockname->sun_path);
+ }
+
+ return ret;
+}
+
+static int
+TRANS(LocalCloseForCloning)(XtransConnInfo ciptr)
+
+{
+ int ret;
+
+ PRMSG(2,"LocalCloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0);
+
+ /* Don't unlink path */
+
+ ret=close(ciptr->fd);
+
+ return ret;
+}
+
+
+/*
+ * MakeAllCOTSServerListeners() will go through the entire Xtransports[]
+ * array defined in Xtrans.c and try to OpenCOTSServer() for each entry.
+ * We will add duplicate entries to that table so that the OpenCOTSServer()
+ * function will get called once for each type of local transport.
+ *
+ * The TransName is in lowercase, so it will never match during a normal
+ * call to SelectTransport() in Xtrans.c.
+ */
+
+#ifdef TRANS_SERVER
+static char * local_aliases[] = {
+# ifndef sun
+ "pts",
+# endif
+ "named",
+# ifndef sun
+# if !defined(__SCO__) && !defined(__UNIXWARE__)
+ "isc",
+# endif
+ "sco",
+# endif
+ NULL };
+#endif
+
+Xtransport TRANS(LocalFuncs) = {
+ /* Local Interface */
+ "local",
+ TRANS_ALIAS | TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ local_aliases,
+ TRANS(LocalOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(LocalOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(LocalReopenCOTSServer),
+ TRANS(LocalReopenCLTSServer),
+#endif
+ TRANS(LocalSetOption),
+#ifdef TRANS_SERVER
+ TRANS(LocalCreateListener),
+ NULL, /* ResetListener */
+ TRANS(LocalAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(LocalBytesReadable),
+ TRANS(LocalRead),
+ TRANS(LocalWrite),
+ TRANS(LocalReadv),
+ TRANS(LocalWritev),
+ TRANS(LocalDisconnect),
+ TRANS(LocalClose),
+ TRANS(LocalCloseForCloning),
+};
+
+#ifndef sun
+
+Xtransport TRANS(PTSFuncs) = {
+ /* Local Interface */
+ "pts",
+ TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(LocalOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(LocalOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(LocalReopenCOTSServer),
+ TRANS(LocalReopenCLTSServer),
+#endif
+ TRANS(LocalSetOption),
+#ifdef TRANS_SERVER
+ TRANS(LocalCreateListener),
+ NULL, /* ResetListener */
+ TRANS(LocalAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(LocalBytesReadable),
+ TRANS(LocalRead),
+ TRANS(LocalWrite),
+ TRANS(LocalReadv),
+ TRANS(LocalWritev),
+ TRANS(LocalDisconnect),
+ TRANS(LocalClose),
+ TRANS(LocalCloseForCloning),
+};
+
+#endif /* sun */
+
+Xtransport TRANS(NAMEDFuncs) = {
+ /* Local Interface */
+ "named",
+ TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(LocalOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(LocalOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(LocalReopenCOTSServer),
+ TRANS(LocalReopenCLTSServer),
+#endif
+ TRANS(LocalSetOption),
+#ifdef TRANS_SERVER
+ TRANS(LocalCreateListener),
+ NULL, /* ResetListener */
+ TRANS(LocalAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(LocalBytesReadable),
+ TRANS(LocalRead),
+ TRANS(LocalWrite),
+ TRANS(LocalReadv),
+ TRANS(LocalWritev),
+ TRANS(LocalDisconnect),
+ TRANS(LocalClose),
+ TRANS(LocalCloseForCloning),
+};
+
+#ifndef sun
+#if !defined(__SCO__) && !defined(__UNIXWARE__)
+Xtransport TRANS(ISCFuncs) = {
+ /* Local Interface */
+ "isc",
+ TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(LocalOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(LocalOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(LocalReopenCOTSServer),
+ TRANS(LocalReopenCLTSServer),
+#endif
+ TRANS(LocalSetOption),
+#ifdef TRANS_SERVER
+ TRANS(LocalCreateListener),
+ NULL, /* ResetListener */
+ TRANS(LocalAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(LocalBytesReadable),
+ TRANS(LocalRead),
+ TRANS(LocalWrite),
+ TRANS(LocalReadv),
+ TRANS(LocalWritev),
+ TRANS(LocalDisconnect),
+ TRANS(LocalClose),
+ TRANS(LocalCloseForCloning),
+};
+#endif /* !__SCO__ && !__UNIXWARE__ */
+Xtransport TRANS(SCOFuncs) = {
+ /* Local Interface */
+ "sco",
+ TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(LocalOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(LocalOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(LocalReopenCOTSServer),
+ TRANS(LocalReopenCLTSServer),
+#endif
+ TRANS(LocalSetOption),
+#ifdef TRANS_SERVER
+ TRANS(LocalCreateListener),
+ NULL, /* ResetListener */
+ TRANS(LocalAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(LocalConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(LocalBytesReadable),
+ TRANS(LocalRead),
+ TRANS(LocalWrite),
+ TRANS(LocalReadv),
+ TRANS(LocalWritev),
+ TRANS(LocalDisconnect),
+ TRANS(LocalClose),
+ TRANS(LocalCloseForCloning),
+};
+#endif /* sun */
diff --git a/nx-X11/lib/xtrans/Xtransos2.c b/nx-X11/lib/xtrans/Xtransos2.c
new file mode 100644
index 000000000..f4a6b036b
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtransos2.c
@@ -0,0 +1,887 @@
+/* $XFree86: xc/lib/xtrans/Xtransos2.c,v 3.9tsi Exp $ */
+
+/*
+ * (c) Copyright 1996 by Sebastien Marineau and Holger Veit
+ * <marineau@genie.uottawa.ca>
+ * <Holger.Veit@gmd.de>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * HOLGER VEIT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+ * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Except as contained in this notice, the name of Sebastien Marineau or Holger Veit shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from Holger Veit or Sebastien Marineau.
+ *
+ */
+
+/* Implementation of the OS/2 local pipe transport layer */
+
+#define INCL_DOSNMPIPES
+#define INCL_DOSPROCESS
+#define INCL_DOSERRORS
+#define INCL_DOSFILEMGR
+#undef BYTE
+#undef BOOL
+#include <os2.h>
+
+#ifdef XSERV_t
+extern HEV hPipeSem;
+BOOL init_server_pipes();
+#endif
+
+/*************************************************************************
+ * Independent Layer
+ *************************************************************************/
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(Os2OpenClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ APIRET rc;
+ HFILE hfd,hServer;
+ ULONG action,byteWritten,State;
+ char pipename[256],clientname[256];
+ char server_string[256];
+ struct sockaddr *addr_name;
+ unsigned char pipe_len;
+ XtransConnInfo ciptr;
+ static int unique_id=0;
+ int i,namelen,try;
+
+ PRMSG(2,"Os2OpenClient(%s,%s,%s)\n",protocol,host,port);
+
+ /* test, whether the host is really local, i.e. either
+ * "os2" or "local"
+ */
+ if (strcmp(protocol,"os2") && strcmp(protocol,"local")) {
+ PRMSG (1,
+ "Os2OpenClient: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return NULL;
+ }
+
+ /* make the pipename */
+
+ if (port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(pipename, "\\PIPE\\X\\%s,", port);
+ } else {
+ (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port);
+ }
+ } else {
+ (void) sprintf(pipename, "\\PIPE\\X\\xfree86"); }
+
+ PRMSG(5, "Os2OpenClient: Creating pipe %s\n",pipename, 0,0 );
+
+ /* make a connection entry */
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL ) {
+ PRMSG(1,"Os2OpenClient: calloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+ /* open the pipe. Try ten times before giving up at 500ms intervals*/
+ try = 0;
+ do {
+ rc = DosOpen(pipename,&hServer, &action, 0,
+ FILE_NORMAL, FILE_OPEN,
+ OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYWRITE,
+ (PEAOP2)NULL);
+ if(rc == 0) break;
+ if (try >=10) {
+ PRMSG(1,"Os2OpenClient: Open server pipe %s failed, rc=%d\n",
+ pipename,rc,0 );
+ PRMSG(1,"\tProbable causes: either the XServer is not running, or has not started properly,\n",
+ 0,0,0 );
+ PRMSG(1,"\tor the DISPLAY variable is set incorrectly.\n",
+ 0,0,0 );
+ xfree(ciptr);
+ return NULL;
+ }
+ try ++;
+ DosSleep(500);
+ } while (rc != 0);
+
+/* OK, now we are talking to the server. Generate a unique pipe name and pass it to
+ * the server. Make the pipe and wait for server to connect */
+
+ sprintf(clientname,"\\PIPE\\X\\%d.%d",getpid(),unique_id++);
+
+ rc = DosCreateNPipe (clientname, &hfd,
+ NP_NOINHERIT | NP_ACCESS_DUPLEX,
+ 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE,
+ 16384, 16384, 0);
+ if (rc != 0){
+ PRMSG(1, "Os2OpenClient: Unable to create pipe %s\n", pipename,0,0 );
+ DosClose(hfd);
+ pipe_len=0;
+ DosWrite(hServer,&pipe_len,1,&byteWritten);
+ DosClose(hServer);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ /* Connect to the pipe. */
+
+ rc = DosConnectNPipe (hfd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2OpenClient: Unable to connect to pipe %s\n", pipename,0,0 );
+ DosClose (hfd);
+ DosClose(hServer);
+ xfree(ciptr);
+ return (NULL);
+ }
+
+/* Now write name to server on hServer */
+ server_string[0]=(char) strlen(clientname)+1;
+ strcpy(&server_string[1],clientname);
+ rc = DosWrite(hServer,server_string,(ULONG)server_string[0]+1,&byteWritten);
+ if(rc != 0){ /* Could not write to server pipe? */
+ PRMSG(1, "Os2OpenClient: Error writing to server pipe, handle=%d, rc=%d, w=%d\n",
+ hServer,rc,byteWritten );
+ DosClose(hServer);
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ PRMSG (5, "Os2OpenCLient: Wrote pipename %s to server; len %d written %d \n",
+ &server_string[1],server_string[0]+1,byteWritten);
+
+
+/* The server will respond by opening the pipe. Wait for that for 30 secs */
+
+ i=0;
+ DosSleep(50); /* Give it time to catch up but minimize race condition*/
+ rc = DosConnectNPipe(hfd);
+ while((rc == ERROR_PIPE_NOT_CONNECTED)&&(i++<60)) {
+ DosSleep(500);
+ rc = DosConnectNPipe(hfd);
+ }
+
+ if(rc != 0){ /* Server has not responded! */
+ PRMSG(1, "Os2OpenClient: Timeout on wait for server response, handle=%d, rc=%d\n",hServer,rc,0 );
+ PRMSG(1, "\tProbable cause: the XServer has exited or crashed while the connection was being established\n",0,0,0 );
+ PRMSG(1, "\tor the XServer is too busy to respond.\n",0,0,0 );
+ DosClose(hServer);
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+/* OK, the server has connected! Fill-in the info and return */
+
+ DosClose(hServer);
+
+/* Last check: make sure client is connected! */
+
+ rc = DosQueryNPHState(hfd,&State);
+ if(rc != 0){ /* Client is not connected! */
+ PRMSG(1, "Os2OpenClient: Client pipe does not appear connected. rc=%d, h=%d\n",rc,hfd,0 );
+ PRMSG(1, "\tProbable cause: the XServer has just exited.\n",0,0,0 );
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ namelen=sizeof(struct sockaddr);
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2OpenClient: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+ ciptr->addrlen = namelen;
+ ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX;
+ strcpy(((struct sockaddr *)ciptr->addr)->sa_data, "local");
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2OpenCLient: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hfd);
+ xfree(ciptr->addr);
+ xfree(ciptr);
+ return(NULL);
+ }
+ ciptr->peeraddrlen = namelen;
+ ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX;
+ strcpy (((struct sockaddr *)ciptr->peeraddr)->sa_data,"local");
+
+ PRMSG (5, "Os2OpenCLient: Filled in struct: len %d %d name %s\n",
+ ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data);
+
+
+ ciptr->index=hfd;
+ ciptr->family=AF_UNIX;
+ if((ciptr->fd=_imphandle(hfd))<0){
+ PRMSG(1, "Os2OpenClient: Could not import the pipe handle into EMX\n",0,0,0 );
+ PRMSG(1, "\tProbable cause: EMX has run out of free file handles.\n",0,0,0 );
+ DosClose(hfd);
+ xfree(ciptr->addr);
+ xfree(ciptr->peeraddr);
+ xfree(ciptr);
+ return(NULL);
+ }
+ PRMSG(5, "Os2OpenClient: pipe handle %d EMX handle %d\n",ciptr->index,ciptr->fd,0 );
+ fcntl(ciptr->fd,F_SETFL,O_NDELAY);
+ fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
+ return ciptr;
+}
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(Os2OpenServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ APIRET rc;
+ HFILE hfd;
+ ULONG action;
+ char pipename[256];
+ struct sockaddr *addr_name;
+ XtransConnInfo ciptr;
+ int namelen;
+
+#ifdef XSERV_t
+ if (! init_server_pipes()) return(NULL);
+#endif
+
+ PRMSG(2,"Os2OpenServer(%s,%s,%s)\n",protocol,host,port);
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1,"Os2OpenServer: xcalloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+
+ if (port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) sprintf(pipename, "\\PIPE\\X\\%s", port);
+ } else {
+ (void) sprintf(pipename, "%s%s", "\\PIPE\\X\\xf86.", port);
+ }
+ } else {
+ (void) sprintf(pipename, "\\PIPE\\X\\xfree86");
+ }
+
+ PRMSG(5, "Os2OpenServer: Creating pipe %s\n",pipename, 0,0 );
+
+ rc = DosCreateNPipe (pipename, &hfd,
+ NP_NOINHERIT | NP_ACCESS_INBOUND,
+ 1 | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE,
+ 0, 8192, 0);
+ if (rc != 0){
+ PRMSG(1, "Os2OpenServer: Unable to create pipe %s, rc=%d\n", pipename,rc,0 );
+ PRMSG(1, "\tProbable cause: there is already another XServer running on display :%s\n",port,0,0 );
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ /* Connect to the pipe. */
+
+ rc = DosConnectNPipe (hfd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2OpenServer: Unable to connect to pipe %s\n", pipename,0,0 );
+ DosClose (hfd);
+ xfree(ciptr);
+ return (NULL);
+ }
+
+/* Pipe is now connected and waiting for client connect */
+
+/*** Put in info ***/
+
+ namelen=sizeof(struct sockaddr);
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hfd);
+ xfree(ciptr);
+ return(NULL);
+ }
+ ciptr->addrlen = namelen;
+ ((struct sockaddr *)ciptr->addr)->sa_family = AF_UNIX;
+ strcpy (((struct sockaddr *)ciptr->addr)->sa_data, "local");
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2OpenServer: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hfd);
+ xfree(ciptr->addr);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ ciptr->peeraddrlen = namelen;
+ ((struct sockaddr *)ciptr->peeraddr)->sa_family = AF_UNIX;
+ strcpy(((struct sockaddr *)ciptr->peeraddr)->sa_data,"local");
+
+ PRMSG (5, "Os2OpenServer: Filled in struct: len %d %d name %s\n",
+ ciptr->addrlen,ciptr->peeraddrlen,((struct sockaddr *)ciptr->peeraddr)->sa_data);
+
+ ciptr->index=hfd; /* Save this for later use in this unused member of struct */
+ ciptr->flags=1; /* Listener */
+ ciptr->family=AF_UNIX;
+
+ if((ciptr->fd=_imphandle(hfd))<0){
+ DosClose(hfd);
+ xfree(ciptr->addr);
+ xfree(ciptr->peeraddr);
+ xfree(ciptr);
+ return(NULL);
+ }
+ PRMSG(5, "Os2OpenServer: Pipe handle %d EMX handle %d",ciptr->index,ciptr->fd,0 );
+
+#ifdef XSERV_t
+/* Attach the pipe sem to the pipe. Use handle index as key */
+ rc = DosSetNPipeSem(ciptr->fd, (HSEM)hPipeSem, ciptr->fd);
+ if (rc){
+ PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n",
+ hPipeSem,ciptr->fd,rc);
+ DosClose(ciptr->fd);
+ xfree(ciptr->addr);
+ xfree(ciptr->peeraddr);
+ xfree(ciptr);
+ return(NULL);
+ }
+#endif
+
+ fcntl(ciptr->fd,F_SETFL,O_NDELAY);
+ fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
+ return(ciptr);
+}
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+static XtransConnInfo
+TRANS(Os2OpenCLTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ PRMSG(2,"Os2OpenCLTSClient(%s,%s,%s)\n",protocol,host,port);
+ return TRANS(Os2OpenClient)(thistrans, protocol, host, port);
+}
+#endif /* TRANS_CLIENT */
+
+#ifdef TRANS_CLIENT
+static XtransConnInfo
+TRANS(Os2OpenCOTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ PRMSG(2,"Os2OpenCOTSClient(%s,%s,%s)\n",protocol,host,port);
+ return TRANS(Os2OpenClient)(thistrans, protocol, host, port);
+}
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(Os2OpenCLTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ PRMSG(2,"Os2OpenCLTSServer(%s,%s,%s)\n",protocol,host,port);
+ return TRANS(Os2OpenServer)(thistrans, protocol, host, port);
+}
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_SERVER
+static XtransConnInfo
+TRANS(Os2OpenCOTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ PRMSG(2,"Os2OpenCOTSServer(%s,%s,%s)\n",protocol,host,port);
+ return TRANS(Os2OpenServer)(thistrans, protocol, host, port);
+}
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+static XtransConnInfo
+TRANS(Os2ReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
+{
+
+ XtransConnInfo ciptr;
+ char addr_name[256];
+ int namelen;
+
+ PRMSG(2,"Os2ReopenCOTSServer(%d,%s)\n", fd, port, 0);
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1,"Os2ReopenCOTSServer: xcalloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ return NULL;
+ }
+
+ strcpy(addr_name,"local");
+ namelen=sizeof(addr_name);
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, addr_name, ciptr->addrlen);
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2ReopenCOTSServer: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ xfree(ciptr);
+ return(NULL);
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr,addr_name, ciptr->addrlen);
+
+ ciptr->fd = fd;
+ ciptr->family=AF_UNIX;
+ ciptr->flags=1;
+ PRMSG(1,"Os2ReopenCOTSServer: Filled-in info for handle %d on port %s.\n", fd, port, 0);
+
+ return(ciptr);
+}
+
+static XtransConnInfo
+TRANS(Os2ReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
+{
+ PRMSG(2,"Os2ReopenCLTSServer(%d,%s)\n", fd, port, 0);
+ return TRANS(Os2ReopenCOTSServer)(thistrans, fd, port);
+}
+#endif
+
+static
+TRANS(Os2SetOption)(XtransConnInfo ciptr, int option, int arg)
+{
+ PRMSG(2,"Os2SetOption(%d,%d,%d)\n",ciptr->fd,option,arg);
+ return -1;
+}
+
+#ifdef TRANS_SERVER
+
+static
+TRANS(Os2CreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
+{
+ PRMSG(2,"Os2CreateListener(%x->%d,%s)\n",ciptr,ciptr->fd,port);
+ return 0;
+}
+
+static XtransConnInfo
+TRANS(Os2Accept)(XtransConnInfo ciptr, int *status)
+{
+ XtransConnInfo newciptr;
+ HFILE hClient;
+ unsigned char length;
+ ULONG action;
+ char clientname[256];
+ struct sockaddr *addr_name;
+ int in,namelen;
+ APIRET rc;
+
+
+ PRMSG(2,"Os2Accept(%x->%d)\n", ciptr, ciptr->fd,0);
+ if( (newciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo)))==NULL )
+ {
+ PRMSG(1,"Os2Accept: xcalloc(1,%d) failed\n",
+ sizeof(struct _XtransConnInfo),0,0 );
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+/* Read in length of client pipe name. If fails, then reset server pipe */
+ if((in=read(ciptr->fd,&length,1))<=0){
+ PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n",
+ in,errno,0 );
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ xfree(newciptr);
+ rc = DosDisConnectNPipe(ciptr->fd);
+ rc = DosConnectNPipe (ciptr->fd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
+ }
+ return NULL;
+ }
+ PRMSG(5, "Os2Accept: Bytes to read for name: %d\n",length,0,0 );
+
+
+/* Check length for valid length ?? */
+
+/* Now read in length bytes from pipe for client pipe name */
+ if((in=read(ciptr->fd,clientname,length))<=0){
+ PRMSG(2,"Os2Accept: Error reading incoming connection, in=%d, error=%d\n",
+ in,errno,0 );
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ xfree(newciptr);
+ rc = DosDisConnectNPipe(ciptr->fd);
+ rc = DosConnectNPipe (ciptr->fd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
+ }
+ return NULL;
+ }
+ clientname[length]='\0';
+ PRMSG(5, "Os2Accept: Server name %s length %d\n",clientname,length,0 );
+
+
+/* Now we have the client pipe name. Open it with DosOpen */
+
+ rc = DosOpen(clientname,&hClient, &action, 0,
+ FILE_NORMAL, FILE_OPEN,
+ OPEN_FLAGS_NOINHERIT | OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE,
+ (PEAOP2)NULL);
+
+ PRMSG(5, "Os2Accept: Open pipe %s, handle = %d, rc=%d\n",clientname,hClient,rc );
+
+ if (rc) {
+ PRMSG(1,"Os2Accept: Open pipe %s to client failed, rc=%d\n",
+ clientname,rc,0 );
+ PRMSG(1, "\tProbable cause: the client has exited or timed-out.\n",0,0,0 );
+ xfree(newciptr);
+ rc = DosDisConnectNPipe(ciptr->fd);
+ rc = DosConnectNPipe (ciptr->fd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
+ }
+ return NULL;
+ }
+
+ rc = DosSetNPHState (hClient, NP_NOWAIT | NP_READMODE_BYTE);
+ if (rc != 0)
+ {
+ PRMSG(1,"Os2Accept: Could not set pipe %s to non-blocking mode, rc=%d\n",
+ hClient,rc,0 );
+ xfree(newciptr);
+ rc = DosDisConnectNPipe(ciptr->fd);
+ rc = DosConnectNPipe (ciptr->fd);
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
+ }
+ return NULL;
+ }
+
+/* OK, we seem to be well connected to client. Now disconnect server pipe and put again in listen */
+
+ rc = DosDisConnectNPipe(ciptr->fd);
+ rc = DosConnectNPipe (ciptr->fd);
+ PRMSG(5, "Os2Accept: Reconnecting server pipe %d, rc = %d\n",ciptr->fd,rc,0 );
+
+ if (rc != 0 && rc != ERROR_PIPE_NOT_CONNECTED)
+ {
+ PRMSG(1, "Os2Accept: Unable to reconnect server pipe %d\n", ciptr->fd,0,0 );
+ } /* Consider this non-fatal for present connection */
+
+/* And finally fill-in info in newciptr */
+
+ namelen=sizeof(struct sockaddr);
+ if ((newciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2Accept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hClient);
+ xfree(newciptr);
+ return(NULL);
+ }
+
+ newciptr->addrlen = namelen;
+ ((struct sockaddr *)newciptr->addr)->sa_family = AF_UNIX;
+ strcpy (((struct sockaddr *)newciptr->addr)->sa_data, "local");
+
+ if ((newciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1, "Os2Accept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ DosClose(hClient);
+ xfree(ciptr->addr);
+ xfree(newciptr);
+ return(NULL);
+ }
+
+ newciptr->peeraddrlen = namelen;
+ ((struct sockaddr *)newciptr->peeraddr)->sa_family = AF_UNIX;
+ strcpy (((struct sockaddr *)newciptr->peeraddr)->sa_data, "local");
+
+ PRMSG (5, "Os2Accept: Filled in struct: len %d %d name %s\n",
+ newciptr->addrlen,newciptr->peeraddrlen,newciptr->peeraddr);
+
+
+ newciptr->index=hClient;
+ newciptr->family=AF_UNIX;
+ if((newciptr->fd=_imphandle(hClient))<0){
+ PRMSG(1,"Os2Accept: Could not import pipe %d into EMX, errno=%d\n",
+ hClient,errno,0 );
+ PRMSG(1, "\tProbable cause: EMX has run out of file handles.\n",0,0,0 );
+ DosClose(hClient);
+ xfree(newciptr->addr);
+ xfree(newciptr->peeraddr);
+ xfree(newciptr);
+ return(NULL);
+ }
+ PRMSG(5, "Os2Accept: Pipe handle %d EMX handle %d",newciptr->index,newciptr->fd,0 );
+
+#ifdef XSERV_t
+/* Attach the pipe sem to the pipe. Use handle index as key */
+ rc = DosSetNPipeSem(newciptr->fd, (HSEM)hPipeSem, newciptr->fd);
+ if (rc){
+ PRMSG(1, "Os2OpenCOTSServer: Could not attach sem %d to pipe %d, rc=%d\n",
+ hPipeSem,newciptr->fd,rc);
+ DosClose(newciptr->fd);
+ xfree(newciptr->addr);
+ xfree(newciptr->peeraddr);
+ xfree(newciptr);
+ return(NULL);
+ }
+#endif
+
+ fcntl(ciptr->fd,F_SETFL,O_NDELAY);
+ fcntl(ciptr->fd,F_SETFD,FD_CLOEXEC);
+ *status=0;
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+static
+TRANS(Os2Connect)(XtransConnInfo ciptr, char *host, char *port)
+{
+ PRMSG(2,"Os2Connect(%x->%d,%s)\n", ciptr, ciptr->fd, port);
+ return 0;
+}
+
+#endif /* TRANS_CLIENT */
+
+static int
+TRANS(Os2BytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend )
+{
+ ULONG rc, state, nread;
+ AVAILDATA avail;
+ char buffer;
+
+ PRMSG(2,"Os2BytesReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend);
+
+ rc = DosPeekNPipe (ciptr->fd, &buffer, 0, &nread, &avail, &state);
+ if (rc != 0)
+ {
+ errno = EPIPE;
+ *pend = 0;
+ return -1;
+ }
+ if (state == NP_STATE_CLOSING)
+ {
+ errno = EPIPE;
+ *pend = 0;
+ return -1;
+ }
+ errno = 0;
+ *pend = avail.cbpipe;
+ return 0;
+}
+
+static int
+TRANS(Os2Read)(XtransConnInfo ciptr, char *buf, int size)
+{
+ int ret;
+ APIRET rc;
+ ULONG ulRead;
+ PRMSG(2,"Os2Read(%d,%x,%d)\n", ciptr->fd, buf, size );
+ errno = 0;
+ rc = DosRead(ciptr->fd, buf, size, &ulRead);
+ if (rc == 0){
+ ret = ulRead;
+ }
+ else if ((rc == 232) || (rc == 231)){
+ errno = EAGAIN;
+ ret = -1;
+ }
+ else if (rc == 6){
+ errno = EBADF;
+ ret = -1;
+ }
+ else if ((rc == 109) || (rc == 230) || (rc == 233)){
+ errno = EPIPE;
+ ret = -1;
+ }
+ else {
+ PRMSG(2,"Os2Read: Unknown return code from DosRead, fd %d rc=%d\n", ciptr->fd,rc,0 );
+ errno = EINVAL;
+ ret = -1;
+ }
+ return (ret);
+}
+
+static int
+TRANS(Os2Write)(XtransConnInfo ciptr, char *buf, int size)
+{
+ int ret;
+ APIRET rc;
+ ULONG nWritten;
+ PRMSG(2,"Os2Write(%d,%x,%d)\n", ciptr->fd, buf, size );
+ rc = DosWrite(ciptr->fd, buf, size, &nWritten);
+ if (rc == 0){
+ ret = nWritten;
+ if(nWritten == 0) {
+ errno=EAGAIN;
+ ret = -1;
+ }
+ }
+ else if ((rc == 39) || (rc == 112)){
+ errno = EAGAIN;
+ ret = -1;
+ }
+ else if ((rc == 109) || (rc == 230) || (rc == 233)){
+ errno = EPIPE;
+ ret = -1;
+ }
+ else if (rc == 6){
+ errno=EBADF;
+ ret = -1;
+ }
+ else {
+ PRMSG(2,"(Os2Write)Unknown return code from DosWrite, fd %d rc=%d\n", ciptr->fd,rc,0 );
+ errno = EINVAL;
+ ret = -1;
+ }
+ return (ret);
+}
+
+static int
+TRANS(Os2Readv)(XtransConnInfo ciptr, struct iovec *buf, int size)
+{
+ int ret;
+ PRMSG(2,"Os2Readv(%d,%x,%d)\n", ciptr->fd, buf, size );
+ ret = READV(ciptr,buf,size);
+ if ((ret <0) && (errno == EINVAL)) errno = EPIPE;
+ return (ret);
+}
+
+static int
+TRANS(Os2Writev)(XtransConnInfo ciptr, struct iovec *buf, int size)
+{
+ int ret;
+ PRMSG(2,"Os2Writev(%d,%x,%d)\n", ciptr->fd, buf, size );
+ ret = WRITEV(ciptr,buf,size);
+ if ((ret <0) && (errno == EINVAL)) errno = EPIPE;
+ if ((ret <0) && (errno == ENOSPC)) errno = EAGAIN;
+ return (ret);
+}
+
+static int
+TRANS(Os2Disconnect)(XtransConnInfo ciptr)
+{
+ PRMSG(2,"Os2Disconnect(%x->%d)\n", ciptr, ciptr->fd, 0);
+ return 0;
+}
+
+static int
+TRANS(Os2Close)(XtransConnInfo ciptr)
+{
+ int ret;
+ PRMSG(2,"Os2Close(%x->%d)\n", ciptr, ciptr->fd ,0);
+ ret=close(ciptr->fd);
+ return ret;
+}
+
+static int
+TRANS(Os2CloseForCloning)(XtransConnInfo ciptr)
+{
+ int ret;
+
+ PRMSG(2,"Os2CloseForCloning(%x->%d)\n", ciptr, ciptr->fd ,0);
+ ret=close(ciptr->fd);
+ return ret;
+}
+
+
+Xtransport TRANS(OS2LocalFuncs) = {
+ /* Local Interface */
+ "local",
+ TRANS_LOCAL,
+#ifdef TRANS_CLIENT
+ TRANS(Os2OpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(Os2OpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(Os2OpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(Os2OpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(Os2ReopenCOTSServer),
+ TRANS(Os2ReopenCLTSServer),
+#endif
+ TRANS(Os2SetOption),
+#ifdef TRANS_SERVER
+ TRANS(Os2CreateListener),
+ NULL, /* ResetListener */
+ TRANS(Os2Accept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(Os2Connect),
+#endif /* TRANS_CLIENT */
+ TRANS(Os2BytesReadable),
+ TRANS(Os2Read),
+ TRANS(Os2Write),
+ TRANS(Os2Readv),
+ TRANS(Os2Writev),
+ TRANS(Os2Disconnect),
+ TRANS(Os2Close),
+ TRANS(Os2CloseForCloning),
+};
+
+#ifdef XSERV_t
+/* This function is used in the server to initialize the semaphore used with pipes */
+
+BOOL init_server_pipes()
+{
+ static BOOL first_time=TRUE;
+ ULONG rc;
+
+ if(first_time){
+ rc = DosCreateEventSem(NULL, &hPipeSem,DC_SEM_SHARED,FALSE);
+ if (rc){
+ PRMSG(1,"Os2OpenListener (init_server_pipes): Could not create pipe semaphore, rc=%d\n",
+ rc,0,0);
+ return(FALSE);
+ }
+ first_time=FALSE;
+ }
+return(TRUE);
+}
+#endif /* XSERV_t */
diff --git a/nx-X11/lib/xtrans/Xtranssock.c b/nx-X11/lib/xtrans/Xtranssock.c
new file mode 100644
index 000000000..8361157f9
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtranssock.c
@@ -0,0 +1,3417 @@
+/* $XdotOrg: xc/lib/xtrans/Xtranssock.c,v 1.11 2005/11/08 06:33:26 jkj Exp $ */
+/* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holders shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the copyright holders.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.68 2004/01/07 04:28:02 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NX-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of NoMachine S.r.l. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifdef NX_TRANS_SOCKET
+
+#ifdef NX_TRANS_DEBUG
+#define XTRANSDEBUG 5
+#endif
+
+#ifndef PF_LOCAL
+#define PF_LOCAL PF_UNIX
+#endif
+
+#endif
+
+#include <ctype.h>
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+
+#ifndef WIN32
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_NO_LOCKING
+#include <X11/Xos_r.h>
+#endif
+
+#ifdef UNIXCONN
+#ifndef X_NO_SYS_UN
+#ifndef Lynx
+#include <sys/un.h>
+#else
+#include <un.h>
+#endif
+#endif
+#include <sys/stat.h>
+#endif
+
+#if defined(hpux) || (defined(MOTOROLA) && defined(SYSV))
+#define NO_TCP_H
+#endif
+
+#ifndef NO_TCP_H
+#if defined(__osf__) || defined(linux) || defined(__GLIBC__) || defined(AIXV5)
+#include <sys/param.h>
+#endif /* osf */
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#include <machine/endian.h>
+#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
+#include <netinet/tcp.h>
+#endif /* !NO_TCP_H */
+
+#include <sys/ioctl.h>
+#if defined(SVR4) && !defined(DGUX) && !defined(_SEQUENT_)
+#include <sys/filio.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
+#include <net/errno.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_)
+#include <sys/stropts.h>
+#endif
+
+#else /* !WIN32 */
+
+#include <X11/Xwinsock.h>
+#include <X11/Xwindows.h>
+#include <X11/Xw32defs.h>
+#undef close
+#define close closesocket
+#define ECONNREFUSED WSAECONNREFUSED
+#define EADDRINUSE WSAEADDRINUSE
+#define EPROTOTYPE WSAEPROTOTYPE
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#undef EINTR
+#define EINTR WSAEINTR
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_MTSAFE_NETDBAPI
+#include <X11/Xos_r.h>
+#endif /* WIN32 */
+
+#if defined(SO_DONTLINGER) && defined(SO_LINGER)
+#undef SO_DONTLINGER
+#endif
+
+#if defined(__UNIXOS2__)
+#if defined(NOT_EMX09A)
+static int IBMsockInit = 0;
+#define SocketInitOnce()\
+ if (!IBMsockInit) {\
+ sock_init();\
+ IBMsockInit = 1;\
+ }
+#undef EINTR
+#define EINTR SOCEINTR
+#undef EINVAL
+#define EINVAL SOCEINVAL
+#undef errno
+#define errno sock_errno()
+#undef close
+#define close soclose
+#undef ioctl
+#define ioctl sockioctl
+#else
+#define SocketInitOnce() /**/
+#endif
+/* this is still not there */
+#define SOCKET int
+#else
+/* others don't need this */
+#define SocketInitOnce() /**/
+#endif
+
+#define MIN_BACKLOG 128
+#ifdef SOMAXCONN
+#if SOMAXCONN > MIN_BACKLOG
+#define BACKLOG SOMAXCONN
+#endif
+#endif
+#ifndef BACKLOG
+#define BACKLOG MIN_BACKLOG
+#endif
+/*
+ * This is the Socket implementation of the X Transport service layer
+ *
+ * This file contains the implementation for both the UNIX and INET domains,
+ * and can be built for either one, or both.
+ *
+ */
+
+typedef struct _Sockettrans2dev {
+ char *transname;
+ int family;
+ int devcotsname;
+ int devcltsname;
+ int protocol;
+} Sockettrans2dev;
+
+static Sockettrans2dev Sockettrans2devtab[] = {
+#ifdef TCPCONN
+ {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(IPv6) || !defined(AF_INET6)
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#else /* IPv6 */
+ {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
+ {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+#endif
+#endif /* TCPCONN */
+#ifdef UNIXCONN
+ {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(LOCALCONN)
+ {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#endif /* !LOCALCONN */
+#endif /* UNIXCONN */
+};
+
+#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
+
+#ifdef TCPCONN
+static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
+#endif
+
+#ifdef UNIXCONN
+
+#ifdef hpux
+
+#if defined(X11_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/usr/spool/sockets/XIM/"
+#define UNIX_DIR "/usr/spool/sockets/XIM"
+#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/usr/spool/sockets/fontserv/"
+#define UNIX_DIR "/usr/spool/sockets/fontserv"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/usr/spool/sockets/ICE/"
+#define UNIX_DIR "/usr/spool/sockets/ICE"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
+#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#endif
+
+#else /* !hpux */
+
+#if defined(X11_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/tmp/.XIM-unix/XIM"
+#define UNIX_DIR "/tmp/.XIM-unix"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/tmp/.font-unix/fs"
+#define UNIX_DIR "/tmp/.font-unix"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/tmp/.ICE-unix/"
+#define UNIX_DIR "/tmp/.ICE-unix"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/tmp/.Test-unix/test"
+#define UNIX_DIR "/tmp/.Test-unix"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif
+
+#endif /* hpux */
+
+#endif /* UNIXCONN */
+
+#define PORTBUFSIZE 32
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 255
+#endif
+
+/*
+ * This provides compatibility for apps linked against system libraries
+ * that don't have IPv6 support.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
+#pragma weak in6addr_any = local_in6addr_any
+#ifndef __USLC__
+#pragma weak getaddrinfo
+#endif
+static int haveIPv6 = 1;
+#endif
+
+#ifndef X11_t
+
+/*
+ * No NX changes if this is not
+ * compiled as a X11 transport.
+ */
+
+#undef NX_TRANS_SOCKET
+
+#endif
+
+#ifdef NX_TRANS_SOCKET
+
+#ifdef TRANS_CLIENT
+
+#include "NX.h"
+
+typedef struct
+{
+ XtransConnInfo info;
+ int local;
+ int remote;
+ int congestion;
+
+} _NXProxyConnInfo;
+
+#define NX_PROXY_CONN_LIMIT 256
+
+static _NXProxyConnInfo *_NXProxyConnInfoTab[NX_PROXY_CONN_LIMIT];
+
+#endif /* #ifdef TRANS_CLIENT */
+
+/*
+ * Override the UNIX_DIR and UNIX_PATH settings and
+ * make them configurable, based on the NX_TEMP or
+ * the TEMP environment.
+ *
+ * We must be careful as the same defines are used
+ * for different directories, based on the subsystem
+ * that is compiling this, while we want to override
+ * only the '/tmp/.X11-unix' and '/tmp/.X11-unix/X'
+ * settings.
+ */
+
+static char _NXUnixDir[1024];
+static char _NXUnixPath[1024];
+
+static char *_NXGetUnixDir(char *dir)
+{
+ const char *tempDir;
+
+ PRMSG (3, "_NXGetUnixDir(%s)\n", dir, 0, 0);
+
+ if (strcmp(dir, UNIX_DIR) != 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Returning other Unix directory [%s].\n", dir);
+#endif
+ return dir;
+ }
+
+ /*
+ * Check the environment only once.
+ */
+
+ if (*_NXUnixDir != '\0')
+ {
+ return _NXUnixDir;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Trying with the NX_TEMP environment.\n");
+#endif
+
+ tempDir = getenv("NX_TEMP");
+
+ if (tempDir == NULL || *tempDir == '\0')
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Trying with the TEMP environment.\n");
+#endif
+
+ tempDir = getenv("TEMP");
+ }
+
+ if (tempDir != NULL && *tempDir != '\0')
+ {
+ if (strlen(tempDir) + strlen("/.X11-unix") + 1 > 1024)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: WARNING! Maximum length of X11 Unix directory exceeded.\n");
+#endif
+ goto _NXGetUnixDirError;
+ }
+
+ strcpy(_NXUnixDir, tempDir);
+ strcat(_NXUnixDir, "/.X11-unix");
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Using X11 Unix directory [%s].\n", _NXUnixDir);
+#endif
+
+ return _NXUnixDir;
+ }
+
+_NXGetUnixDirError:
+
+ strcpy(_NXUnixDir, dir);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Returning default X11 Unix directory [%s].\n", _NXUnixDir);
+#endif
+
+ return _NXUnixDir;
+}
+
+static char *_NXGetUnixPath(char *path)
+{
+ const char *unixDir;
+
+ PRMSG (3, "_NXGetUnixPath(%s)\n", path, 0, 0);
+
+ if (strcmp(path, UNIX_PATH) != 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning other X11 Unix path [%s].\n", path);
+#endif
+ return path;
+ }
+
+ /*
+ * Check the environment only once.
+ */
+
+ if (*_NXUnixPath != '\0')
+ {
+ return _NXUnixPath;
+ }
+
+ unixDir = _NXGetUnixDir(UNIX_DIR);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Got X11 Unix directory [%s].\n", unixDir);
+#endif
+
+ if (strlen(unixDir) + strlen("/X") + 1 > 1024)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: WARNING! Maximum length of X11 Unix path exceeded.\n");
+#endif
+
+ goto _NXGetUnixPathError;
+ }
+
+ strcpy(_NXUnixPath, unixDir);
+ strcat(_NXUnixPath, "/X");
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning X11 Unix path [%s].\n", _NXUnixPath);
+#endif
+
+ return _NXUnixPath;
+
+_NXGetUnixPathError:
+
+ strcpy(_NXUnixPath, path);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning default X11 Unix path [%s].\n", _NXUnixPath);
+#endif
+
+ return _NXUnixPath;
+}
+
+#ifdef hpux
+
+static char *_NXGetOldUnixPath(char *path)
+{
+ PRMSG (3, "_NXGetOldUnixPath(%s)\n", path, 0, 0);
+
+ if (strcmp(path, OLD_UNIX_PATH) == 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetOldUnixPath: Returning X11 Unix path [%s].\n",
+ _NXGetUnixPath(path));
+#endif
+
+ return _NXGetUnixPath(path);
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetOldUnixPath: Returning other old X11 Unix path [%s].\n", path);
+#endif
+
+ return path;
+}
+
+#endif /* #ifdef hpux */
+
+/*
+ * Forcibly close any connection attempt on the
+ * listening socket. Need this to avoid loopback
+ * connections to the agent server.
+ */
+
+#ifdef TRANS_SERVER
+
+void TRANS(SocketRejectConnection) (XtransConnInfo ciptr)
+{
+ size_t sa_l = sizeof(struct sockaddr);
+ struct sockaddr sa;
+ fd_set fs;
+ struct timeval t;
+ int f;
+
+ PRMSG (3, "SocketRejectConnection(%x)\n", ciptr, 0, 0);
+
+ FD_ZERO(&fs);
+ FD_SET(ciptr -> fd, &fs);
+
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+
+ /*
+ * Check if there is an awaiting connection.
+ */
+
+ if (select(ciptr -> fd + 1, &fs, NULL, NULL, &t) == 1)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketRejectConnection: Accepting connection attempt on fd [%d].\n",
+ ciptr -> fd);
+#endif
+ /*
+ * If there is one, close it.
+ */
+
+ if ((f = accept(ciptr -> fd, &sa, &sa_l)) >= 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketRejectConnection: Closing connection attempt on fd [%d].\n",
+ ciptr -> fd);
+#endif
+ close(f);
+ }
+ }
+}
+
+#endif /* #ifdef TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+void *TRANS(SocketProxyConnInfo) (XtransConnInfo ciptr)
+{
+ if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
+ {
+ return ciptr->priv;
+ }
+
+ return NULL;
+}
+
+static XtransConnInfo TRANS(SocketCreateConnInfo) ()
+{
+ XtransConnInfo ciptr;
+
+ int fds[2];
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX connection info.\n");
+#endif
+
+ if ((ciptr = (XtransConnInfo) xcalloc (1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Create a pair of sockets. We'll communicate with
+ * the NX proxy by reading and writing to our end.
+ */
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX socketpair.\n");
+#endif
+
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0)
+ {
+ PRMSG (1, "SocketCreateConnInfo: socketpair() failed.\n", 0, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: X socket end is [%d] NX proxy end is [%d].\n",
+ fds[0], fds[1]);
+#endif
+
+ /*
+ * Save in _NXProxyConnInfoTab the local and remote end of
+ * the socketpair. The remote end will be used by the proxy.
+ * When the memory-to-memory transport is activated, the
+ * agent and the proxy don't read or write to the real des-
+ * criptors but the communication takes place by reading
+ * and writing to the proxy's buffers.
+ */
+
+ ciptr->fd = fds[0];
+
+ if (ciptr->fd >= NX_PROXY_CONN_LIMIT)
+ {
+ PRMSG (1, "SocketCreateConnInfo: No space for a new _NXProxyConnInfo for [%d].\n",
+ ciptr->fd, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: _NXProxyConnInfo for [%d] is not NULL. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+
+ _NXProxyConnInfoTab[ciptr->fd] = (_NXProxyConnInfo *) xcalloc(1, sizeof(_NXProxyConnInfo));
+
+ if (_NXProxyConnInfoTab[ciptr->fd] == NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: Alloc of _NXProxyConnInfo failed.\n", 0, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Allocated new _NXProxyConnInfo for [%d].\n",
+ ciptr->fd);
+#endif
+
+ _NXProxyConnInfoTab[ciptr->fd]->info = ciptr;
+ _NXProxyConnInfoTab[ciptr->fd]->local = fds[0];
+ _NXProxyConnInfoTab[ciptr->fd]->remote = fds[1];
+ _NXProxyConnInfoTab[ciptr->fd]->congestion = 0;
+
+ ciptr->priv = (char *) _NXProxyConnInfoTab[ciptr->fd];
+
+ return ciptr;
+}
+
+static int TRANS(SocketConnectConnInfo) (XtransConnInfo ciptr, char *host, char *port)
+{
+ int fds[2];
+ char display[1024];
+
+ _NXProxyConnInfo *proxy_conn;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Going to connect NX fd [%d] to host [%s] port [%s].\n",
+ ciptr->fd, host, port);
+#endif
+
+ /*
+ * We should have already created the socket pair.
+ */
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
+
+ exit(1);
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
+ 0, 0, 0);
+
+ exit(1);
+ }
+
+ if (strlen(host) + strlen(port) + 1 >= 1023)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Length of NX display string '%s:%s' would exceed %d characters.\n",
+ host, port, 1023);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+ sprintf(display, "%s:%s", host, port);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Setting close-on-exec flag on local NX descriptor [%d].\n",
+ proxy_conn -> local);
+#endif
+
+#ifdef F_SETFD
+#ifdef FD_CLOEXEC
+ if (fcntl(proxy_conn -> local, F_SETFD, FD_CLOEXEC) != 0)
+#else
+ if (fcntl(proxy_conn -> local, F_SETFD, 1) != 0)
+#endif
+#endif
+ {
+ PRMSG (1, "SocketConnectConnInfo: Cannot set close-on-exec on local NX descriptor [%d].\n",
+ proxy_conn -> local, 0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Creating the NX transport with display [%s].\n",
+ display);
+#endif
+
+ if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, display) < 0)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Cannot create the NX transport.\n",
+ 0, 0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Starting the NX agent with descriptor [%d].\n",
+ proxy_conn -> remote);
+#endif
+
+ fds[0] = proxy_conn -> local;
+ fds[1] = proxy_conn -> remote;
+
+ NXTransAgent(fds);
+
+ return 0;
+}
+
+static void TRANS(SocketCloseConnInfo) (XtransConnInfo ciptr)
+{
+ _NXProxyConnInfo *proxy_conn;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Going to close the NX fd [%d].\n", ciptr->fd);
+#endif
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
+
+ exit(1);
+ }
+ else if (ciptr->fd >= NX_PROXY_CONN_LIMIT ||
+ _NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] -> info != ciptr ||
+ _NXProxyConnInfoTab[ciptr->fd] -> local != ciptr->fd)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Invalid _NXProxyConnInfo structure for [%d]. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+ else if (proxy_conn->local < 0 || proxy_conn->remote < 0)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Invalid socket pair in NX connection for [%d]. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+
+ NXTransClose(ciptr->fd);
+
+ /*
+ * Get rid of the _NXProxyConnInfo structure.
+ */
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Freeing _NXProxyConnInfo structure for [%d].\n",
+ ciptr->fd);
+#endif
+
+ xfree((char *) _NXProxyConnInfoTab[ciptr->fd]);
+
+ _NXProxyConnInfoTab[ciptr->fd] = NULL;
+
+ ciptr->priv = NULL;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Should now close the local descriptor [%d].\n",
+ ciptr->fd);
+#endif
+}
+
+#endif /* #ifdef TRANS_CLIENT */
+
+#if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE)
+
+/*
+ * Check the congestion state of the NX transport
+ * and return 1 if there has been a change. This
+ * can be extended by adding a few counters track-
+ * ing the bandwidth usage of the X11 connection.
+ */
+
+int TRANS(SocketCongestionChange) (XtransConnInfo ciptr, int *state)
+{
+ int congestion;
+
+ _NXProxyConnInfo *proxy_conn;
+
+ PRMSG (3, "SocketCongestionChange(%x)\n", ciptr, 0, 0);
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketCongestionChange: Descriptor [%d] doesn't appear to be a NX connection.\n",
+ ciptr->fd);
+#endif
+ return 0;
+ }
+
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketCongestionChange: Checking congestion on fd [%d] with old state [%d].\n",
+ ciptr->fd, proxy_conn->congestion);
+#endif
+
+ congestion = NXTransCongestion(ciptr->fd);
+
+ if (congestion != proxy_conn->congestion)
+ {
+ proxy_conn->congestion = congestion;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCongestionChange: Change detected on fd [%d] with new state [%d].\n",
+ ciptr->fd, proxy_conn->congestion);
+#endif
+ return 1;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCongestionChange: No change on fd [%d] with current state [%d].\n",
+ ciptr->fd, congestion);
+#endif
+ return 0;
+}
+
+#endif /* #if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE) */
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
+/*
+ * These are some utility function used by the real interface function below.
+ */
+
+static int
+TRANS(SocketSelectFamily) (int first, char *family)
+
+{
+ int i;
+
+ PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
+
+ for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
+ {
+ if (!strcmp (family, Sockettrans2devtab[i].transname))
+ return i;
+ }
+
+ return (first == -1 ? -2 : -1);
+}
+
+
+/*
+ * This function gets the local address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+ PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
+ EGET(),0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
+ }
+ else
+#endif
+ {
+ ciptr->family = socknamev4.sin_family;
+ }
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && ciptr->family == AF_INET6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
+
+ if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+static XtransConnInfo
+TRANS(SocketOpen) (int i, int type)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+
+ if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
+ return NULL;
+#endif
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
+ Sockettrans2devtab[i].protocol)) < 0
+#ifndef WIN32
+#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
+ || ciptr->fd >= TRANS_OPEN_MAX
+#endif
+#endif
+ ) {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (2, "SocketOpen: socket() failed for %s\n",
+ Sockettrans2devtab[i].transname, 0, 0);
+
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopen) (int i, int type, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+/*
+ * These functions are the interface supplied in the Xtransport structure
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
+ char *host, char *port, int previndex)
+{
+ XtransConnInfo ciptr;
+ int i = previndex;
+
+ PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
+ protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
+ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
+ {
+ ciptr = TRANS(SocketCreateConnInfo) ();
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1, "SocketOpenCOTSClient: Unable to create the NX connection info for %s.\n",
+ transname, 0, 0);
+
+ return NULL;
+ }
+
+ ciptr->index = i;
+
+ return ciptr;
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
+ transname, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
+ transname, 0, 0);
+ return NULL;
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ ciptr->priv = NULL;
+
+#endif
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ return TRANS(SocketOpenCOTSClientBase)(
+ thistrans->TransName, protocol, host, port, -1);
+}
+
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Using this prevents the bind() check for an existing server listening
+ * on the same port, but it is required for other reasons.
+ */
+#ifdef SO_REUSEADDR
+
+ /*
+ * SO_REUSEADDR only applied to AF_INET && AF_INET6
+ */
+
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ int one = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &one, sizeof (int));
+ }
+#endif
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
+ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
+ {
+ ciptr = TRANS(SocketCreateConnInfo) ();
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1, "SocketOpenCLTSClient: Unable to create the NX connection info for %s.\n",
+ thistrans->TransName, 0, 0);
+
+ return NULL;
+ }
+
+ ciptr->index = i;
+
+ return ciptr;
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ ciptr->priv = NULL;
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketSetOption: WARNING! Not setting option [%d] with value [%d] on descriptor [%d].\n",
+ option, arg, ciptr -> fd);
+#endif
+
+ return -1;
+}
+
+#ifdef UNIXCONN
+static int
+set_sun_path(const char *port, const char *upath, char *path)
+{
+ struct sockaddr_un s;
+ int maxlen = sizeof(s.sun_path) - 1;
+
+ if (!port || !*port || !path)
+ return -1;
+
+ if (*port == '/') { /* a full pathname */
+ if (strlen(port) > maxlen)
+ return -1;
+ sprintf(path, "%s", port);
+ } else {
+ if (strlen(port) + strlen(upath) > maxlen)
+ return -1;
+ sprintf(path, "%s%s", upath, port);
+ }
+ return 0;
+}
+#endif
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(SocketCreateListener) (XtransConnInfo ciptr,
+ struct sockaddr *sockname,
+ int socknamelen, unsigned int flags)
+
+{
+ int namelen = socknamelen;
+ int fd = ciptr->fd;
+ int retry;
+
+ PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ )
+ retry = 20;
+ else
+ retry = 0;
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketCreateListener: Creating listener for ciptr at [%p] on path [%s].\n",
+ (void *) ciptr, ((struct sockaddr_un *) sockname)->sun_family == AF_UNIX ?
+ ((struct sockaddr_un *) sockname)->sun_path : "TCP");
+#endif
+ while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
+ {
+ if (errno == EADDRINUSE) {
+ if (flags & ADDR_IN_USE_ALLOWED)
+ break;
+ else
+ return TRANS_ADDR_IN_USE;
+ }
+
+ if (retry-- == 0) {
+ PRMSG (1, "SocketCreateListener: failed to bind listener\n",
+ 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#ifdef SO_REUSEADDR
+ sleep (1);
+#else
+ sleep (10);
+#endif /* SO_REUSEDADDR */
+ }
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ ) {
+#ifdef SO_DONTLINGER
+ setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
+#else
+#ifdef SO_LINGER
+ {
+ static int linger[2] = { 0, 0 };
+ setsockopt (fd, SOL_SOCKET, SO_LINGER,
+ (char *) linger, sizeof (linger));
+ }
+#endif
+#endif
+}
+
+ if (listen (fd, BACKLOG) < 0)
+ {
+ PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ /* Set a flag to indicate that this connection is a listener */
+
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketCreateListener: Set flags to [%d] for ciptr [%p].\n",
+ ciptr->flags, (void *) ciptr);
+#endif
+
+ return 0;
+}
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage sockname;
+#else
+ struct sockaddr_in sockname;
+#endif
+ unsigned short sport;
+ int namelen = sizeof(sockname);
+ int status;
+ long tmpport;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgetservbynameparams sparams;
+#endif
+ struct servent *servp;
+
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ /* fixup the server port address */
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf,"%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ if (port && *port)
+ {
+ /* Check to see if the port string is just a number (handles X11) */
+
+ if (!is_numeric (port))
+ {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: Unable to get service for %s\n",
+ port, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ /* we trust getservbyname to return a valid number */
+ sport = servp->s_port;
+ }
+ else
+ {
+ tmpport = strtol (port, (char**)NULL, 10);
+ /*
+ * check that somehow the port address isn't negative or in
+ * the range of reserved port addresses. This can happen and
+ * be very bad if the server is suid-root and the user does
+ * something (dumb) like `X :60049`.
+ */
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CREATE_LISTENER_FAILED;
+
+ sport = (unsigned short) tmpport;
+ }
+ }
+ else
+ sport = 0;
+
+ bzero(&sockname, sizeof(sockname));
+#if defined(IPv6) && defined(AF_INET6)
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ namelen = sizeof (struct sockaddr_in);
+#ifdef BSD44SOCKETS
+ ((struct sockaddr_in *)&sockname)->sin_len = namelen;
+#endif
+ ((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
+ ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ namelen = sizeof (struct sockaddr_in6);
+#ifdef SIN6_LEN
+ ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
+#endif
+ ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
+ ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
+ }
+#else
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (sockname);
+#endif
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (sport);
+ sockname.sin_addr.s_addr = htonl (INADDR_ANY);
+#endif
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ return status;
+ }
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
+ 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* SOCKCONN */
+
+
+#ifdef UNIXCONN
+
+static int
+TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
+ unsigned int flags)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+ int oldUmask;
+ int status;
+ unsigned int mode;
+
+ PRMSG (2, "SocketUNIXCreateListener(%s)\n",
+ port ? port : "NULL", 0, 0);
+
+ /* Make sure the directory is created */
+
+ oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+#ifdef NX_TRANS_SOCKET
+ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ _NXGetUnixDir(UNIX_DIR), errno, 0);
+#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+#endif
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#endif
+
+ sockname.sun_family = AF_UNIX;
+
+ if (port && *port) {
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
+#ifdef NX_TRANS_SOCKET
+ sprintf (sockname.sun_path, "%s%ld", _NXGetUnixPath(UNIX_PATH), (long)getpid());
+#else
+ sprintf (sockname.sun_path, "%s%ld", UNIX_PATH, (long)getpid());
+#endif
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen(sockname.sun_path);
+ namelen = SUN_LEN(&sockname);
+#else
+ namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
+#endif
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketUNIXCreateListener: Unlinking path [%s] for ciptr at [%p].\n",
+ sockname.sun_path, (void *) ciptr);
+#endif
+ unlink (sockname.sun_path);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return status;
+ }
+
+ /*
+ * Now that the listener is esablished, create the addr info for
+ * this connection. getpeername() doesn't work for UNIX Domain Sockets
+ * on some systems (hpux at least), so we will just do it manually, instead
+ * of calling something like TRANS(SocketUNIXGetAddr).
+ */
+
+ namelen = sizeof (sockname); /* this will always make it the same size */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ ciptr->family = sockname.sun_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ (void) umask (oldUmask);
+
+ return 0;
+}
+
+
+static int
+TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
+
+{
+ /*
+ * See if the unix domain socket has disappeared. If it has, recreate it.
+ */
+
+ struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
+ struct stat statb;
+ int status = TRANS_RESET_NOOP;
+ unsigned int mode;
+
+ PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if (stat (unsock->sun_path, &statb) == -1 ||
+ ((statb.st_mode & S_IFMT) !=
+#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
+ S_IFIFO))
+#else
+ S_IFSOCK))
+#endif
+ {
+ int oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+#ifdef NX_TRANS_SOCKET
+ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ _NXGetUnixDir(UNIX_DIR), errno, 0);
+#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+#endif
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+#endif
+
+ close (ciptr->fd);
+ unlink (unsock->sun_path);
+
+ if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (listen (ciptr->fd, BACKLOG) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ umask (oldUmask);
+
+ status = TRANS_RESET_NEW_FD;
+ }
+
+ return status;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+
+static XtransConnInfo
+TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_in sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ /*
+ * Get this address again because the transport may give a more
+ * specific address now that a connection is established.
+ */
+
+ if (TRANS(SocketINETGetAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static XtransConnInfo
+TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_un sockname;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+ PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ /*
+ * Get the socket name and the peer name from the listener socket,
+ * since this is unix domain.
+ */
+
+ if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+
+ newciptr->addrlen = ciptr->addrlen;
+ memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
+
+ if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ newciptr->peeraddrlen = ciptr->addrlen;
+ memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
+
+ newciptr->family = AF_UNIX;
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+#ifdef TCPCONN
+
+#if defined(IPv6) && defined(AF_INET6)
+struct addrlist {
+ struct addrinfo * addr;
+ struct addrinfo * firstaddr;
+ char port[PORTBUFSIZE];
+ char host[MAXHOSTNAMELEN];
+};
+static struct addrlist *addrlist = NULL;
+#endif
+
+
+static int
+TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr * socketaddr = NULL;
+ int socketaddrlen = 0;
+ int res;
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo hints;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ int resetonce = 0;
+#endif
+ struct sockaddr_in sockname;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+ _Xgetservbynameparams sparams;
+#endif
+ struct hostent *hostp;
+ struct servent *servp;
+ unsigned long tmpaddr;
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ long tmpport;
+ char hostnamebuf[256]; /* tmp space */
+
+ PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ if (!host)
+ {
+ hostnamebuf[0] = '\0';
+ (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+ host = hostnamebuf;
+ }
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf, "%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6) {
+ if (addrlist != NULL) {
+ if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
+ if (addrlist->firstaddr)
+ freeaddrinfo(addrlist->firstaddr);
+ addrlist->firstaddr = NULL;
+ }
+ } else {
+ addrlist = malloc(sizeof(struct addrlist));
+ addrlist->firstaddr = NULL;
+ }
+
+ if (addrlist->firstaddr == NULL) {
+ strncpy(addrlist->port, port, sizeof(addrlist->port));
+ addrlist->port[sizeof(addrlist->port) - 1] = '\0';
+ strncpy(addrlist->host, host, sizeof(addrlist->host));
+ addrlist->host[sizeof(addrlist->host) - 1] = '\0';
+
+ bzero(&hints,sizeof(hints));
+ hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
+
+ res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
+ if (res != 0) {
+ PRMSG (1, "SocketINETConnect() can't get address "
+ "for %s:%s: %s\n", host, port, gai_strerror(res));
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ for (res = 0, addrlist->addr = addrlist->firstaddr;
+ addrlist->addr ; res++) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
+ res = 0;
+ addrlist->addr = NULL;
+ }
+
+ while (socketaddr == NULL) {
+ if (addrlist->addr == NULL) {
+ if (resetonce) {
+ /* Already checked entire list - no usable addresses */
+ PRMSG (1, "SocketINETConnect() no usable address "
+ "for %s:%s\n", host, port, 0);
+ return TRANS_CONNECT_FAILED;
+ } else {
+ /* Go back to beginning of list */
+ resetonce = 1;
+ addrlist->addr = addrlist->firstaddr;
+ }
+ }
+
+ socketaddr = addrlist->addr->ai_addr;
+ socketaddrlen = addrlist->addr->ai_addrlen;
+
+ if (addrlist->addr->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
+ ntopbuf,sizeof(ntopbuf)), 0, 0);
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
+ ntohs(sin->sin_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Our socket is an IPv6 socket, but the address is
+ * IPv4. Close it and get an IPv4 socket. This is
+ * needed for IPv4 connections to work on platforms
+ * that don't allow IPv4 over IPv6 sockets.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, ciptr->index);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
+ " socketfor IPv4 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ } else {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
+ 0,0,0);
+ }
+ }
+ } else if (addrlist->addr->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,
+ &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
+ 0, 0);
+ PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
+ ntohs(sin6->sin6_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Close the IPv4 socket and try to open an IPv6 socket.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, -1);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET6) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
+ "socket for IPv6 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ }
+ else
+ {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
+ 0,0,0);
+ }
+ }
+ } else {
+ socketaddr = NULL; /* Unsupported address type */
+ }
+ if (socketaddr == NULL) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ }
+ } else
+#endif
+ {
+ /*
+ * Build the socket name.
+ */
+
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (struct sockaddr_in);
+#endif
+ sockname.sin_family = AF_INET;
+
+ /*
+ * fill in sin_addr
+ */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((in_addr_t) 0xffffffff)
+#endif
+
+ /* check for ww.xx.yy.zz host string */
+
+ if (isascii (host[0]) && isdigit (host[0])) {
+ tmpaddr = inet_addr (host); /* returns network byte order */
+ } else {
+ tmpaddr = INADDR_NONE;
+ }
+
+ PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
+
+ if (tmpaddr == INADDR_NONE) {
+ if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
+ host, 0, 0);
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ if (hostp->h_addrtype != AF_INET) { /* is IP host? */
+ PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
+ ESET(EPROTOTYPE);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ {
+ long t;
+ memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
+ sockname.sin_addr = t;
+ }
+#else
+ memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
+ sizeof (sockname.sin_addr));
+#endif /* CRAY and OLDTCP */
+
+ } else {
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ sockname.sin_addr = tmpaddr;
+#else
+ sockname.sin_addr.s_addr = tmpaddr;
+#endif /* CRAY and OLDTCP */
+ }
+
+ /*
+ * fill in sin_port
+ */
+
+ /* Check for number in the port string */
+
+ if (!is_numeric (port)) {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: can't get service for %s\n",
+ port, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ sockname.sin_port = htons (servp->s_port);
+ } else {
+ tmpport = strtol (port, (char**)NULL, 10);
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CONNECT_FAILED;
+ sockname.sin_port = htons (((unsigned short) tmpport));
+ }
+
+ PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
+ ntohs(sockname.sin_port), 0, 0);
+ socketaddr = (struct sockaddr *) &sockname;
+ socketaddrlen = sizeof(sockname);
+ }
+
+ /*
+ * Turn on socket keepalive so the client process will eventually
+ * be notified with a SIGPIPE signal if the display server fails
+ * to respond to a periodic transmission of messages
+ * on the connected socket.
+ * This is useful to avoid hung application processes when the
+ * processes are not spawned from the xdm session and
+ * the display server terminates abnormally.
+ * (Someone turned off the power switch.)
+ */
+
+ {
+ int tmp = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &tmp, sizeof (int));
+ }
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
+ {
+#ifdef WIN32
+ int olderrno = WSAGetLastError();
+#else
+ int olderrno = errno;
+#endif
+
+ /*
+ * If the error was ECONNREFUSED, the server may be overloaded
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ *
+ * If multiple addresses are found for a host then we should
+ * try to connect again with a different address for a larger
+ * number of errors that made us quit before, since those
+ * could be caused by trying to use an IPv6 address to contact
+ * a machine with an IPv4-only server or other reasons that
+ * only affect one of a set of addresses.
+ */
+
+ if (olderrno == ECONNREFUSED || olderrno == EINTR
+#if defined(IPv6) && defined(AF_INET6)
+ || (haveIPv6 && ((addrlist->addr->ai_next != NULL) ||
+ (addrlist->addr != addrlist->firstaddr)) &&
+ (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
+ olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
+#if defined(EHOSTDOWN)
+ || olderrno == EHOSTDOWN
+#endif
+ ))
+#endif
+ )
+ res = TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ res = TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
+ olderrno,0, 0);
+
+ res = TRANS_CONNECT_FAILED;
+ }
+ } else {
+ res = 0;
+
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+
+ else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && res != 0) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+#endif
+
+ return res;
+}
+
+#endif /* TCPCONN */
+
+
+
+#ifdef UNIXCONN
+
+/*
+ * Make sure 'host' is really local.
+ */
+
+static int
+UnixHostReallyLocal (char *host)
+
+{
+ char hostnamebuf[256];
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+#endif
+
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+
+ if (strcmp (hostnamebuf, host) == 0)
+ {
+ return (1);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (haveIPv6)
+ {
+ struct addrinfo *localhostaddr;
+ struct addrinfo *otherhostaddr;
+ struct addrinfo *i, *j;
+ int equiv = 0;
+
+ if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
+ return 0;
+ if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
+ freeaddrinfo(localhostaddr);
+ return 0;
+ }
+
+ for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
+ for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
+ if (i->ai_family == j->ai_family) {
+ if (i->ai_family == AF_INET) {
+ struct sockaddr_in *sinA
+ = (struct sockaddr_in *) i->ai_addr;
+ struct sockaddr_in *sinB
+ = (struct sockaddr_in *) j->ai_addr;
+ struct in_addr *A = &sinA->sin_addr;
+ struct in_addr *B = &sinB->sin_addr;
+
+ if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
+ equiv = 1;
+ }
+ } else if (i->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sinA
+ = (struct sockaddr_in6 *) i->ai_addr;
+ struct sockaddr_in6 *sinB
+ = (struct sockaddr_in6 *) j->ai_addr;
+ struct in6_addr *A = &sinA->sin6_addr;
+ struct in6_addr *B = &sinB->sin6_addr;
+
+ if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
+ equiv = 1;
+ }
+ }
+ }
+ }
+ }
+
+ freeaddrinfo(localhostaddr);
+ freeaddrinfo(otherhostaddr);
+ return equiv;
+ }
+#endif
+ else
+ {
+ /*
+ * A host may have more than one network address. If any of the
+ * network addresses of 'host' (specified to the connect call)
+ * match any of the network addresses of 'hostname' (determined
+ * by TRANS(GetHostname)), then the two hostnames are equivalent,
+ * and we know that 'host' is really a local host.
+ */
+ char specified_local_addr_list[10][4];
+ int scount, equiv, i, j;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ struct hostent *hostp;
+
+ if ((hostp = _XGethostbyname (host,hparams)) == NULL)
+ return (0);
+
+ scount = 0;
+ while (hostp->h_addr_list[scount] && scount <= 8)
+ {
+ /*
+ * The 2nd call to gethostname() overrides the data
+ * from the 1st call, so we must save the address list.
+ */
+
+ specified_local_addr_list[scount][0] =
+ hostp->h_addr_list[scount][0];
+ specified_local_addr_list[scount][1] =
+ hostp->h_addr_list[scount][1];
+ specified_local_addr_list[scount][2] =
+ hostp->h_addr_list[scount][2];
+ specified_local_addr_list[scount][3] =
+ hostp->h_addr_list[scount][3];
+ scount++;
+ }
+ if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
+ return (0);
+
+ equiv = 0;
+ i = 0;
+
+ while (i < scount && !equiv)
+ {
+ j = 0;
+
+ while (hostp->h_addr_list[j])
+ {
+ if ((specified_local_addr_list[i][0] ==
+ hostp->h_addr_list[j][0]) &&
+ (specified_local_addr_list[i][1] ==
+ hostp->h_addr_list[j][1]) &&
+ (specified_local_addr_list[i][2] ==
+ hostp->h_addr_list[j][2]) &&
+ (specified_local_addr_list[i][3] ==
+ hostp->h_addr_list[j][3]))
+ {
+ /* They're equal, so we're done */
+
+ equiv = 1;
+ break;
+ }
+
+ j++;
+ }
+
+ i++;
+ }
+ return (equiv);
+ }
+}
+
+static int
+TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+
+#if defined(hpux) && defined(X11_t)
+ struct sockaddr_un old_sockname;
+ int old_namelen;
+#endif
+
+
+ PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ /*
+ * Make sure 'host' is really local. If not, we return failure.
+ * The reason we make this check is because a process may advertise
+ * a "local" network ID for which it can accept connections, but if
+ * a process on a remote machine tries to connect to this network ID,
+ * we know for sure it will fail.
+ */
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+ if (strcmp(host, "unix") != 0 && strcasecmp(host, "nx") != 0 &&
+ strncasecmp(host, "nx,", 3) != 0 && !UnixHostReallyLocal (host))
+#else
+ if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
+#endif
+ {
+ PRMSG (1,
+ "SocketUNIXConnect: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+
+ /*
+ * Check the port.
+ */
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ /*
+ * Build the socket name.
+ */
+
+ sockname.sun_family = AF_UNIX;
+
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen (sockname.sun_path);
+ namelen = SUN_LEN (&sockname);
+#else
+ namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family);
+#endif
+
+
+#if defined(hpux) && defined(X11_t)
+ /*
+ * This is gross, but it was in Xlib
+ */
+ old_sockname.sun_family = AF_UNIX;
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetOldUnixPath(OLD_UNIX_PATH), old_sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ old_namelen = strlen (old_sockname.sun_path) +
+ sizeof (old_sockname.sun_family);
+#endif
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv != NULL)
+ {
+ if (TRANS(SocketConnectConnInfo) (ciptr, host, port) != 0)
+ {
+ return TRANS_CONNECT_FAILED;
+ }
+
+ goto SocketUNIXConnectPost;
+ }
+
+#endif
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
+ {
+ int olderrno = errno;
+ int connected = 0;
+
+#if defined(hpux) && defined(X11_t)
+ if (olderrno == ENOENT)
+ {
+ if (connect (ciptr->fd,
+ (struct sockaddr *) &old_sockname, old_namelen) >= 0)
+ {
+ connected = 1;
+ }
+ else
+ olderrno = errno;
+ }
+#endif
+ if (!connected)
+ {
+ errno = olderrno;
+
+ /*
+ * If the error was ENOENT, the server may be starting up
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ */
+
+ if (olderrno == ENOENT || olderrno == EINTR)
+ return TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ return TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
+ EGET(),0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+ }
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+SocketUNIXConnectPost:
+
+#endif
+
+ /*
+ * Get the socket name and the peer name from the connect socket,
+ * since this is unix domain.
+ */
+
+ if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
+ (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ ciptr->family = AF_UNIX;
+ ciptr->addrlen = namelen;
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
+ ciptr, ciptr->fd, pend);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ if (NXTransRunning(ciptr->fd) == 0)
+ {
+ /*
+ * Force the application to shut down the
+ * socket if the NX transport is gone. We
+ * may probably save this additional call.
+ */
+
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketBytesReadable: NX transport not running for descriptor [%d].\n",
+ ciptr->fd);
+#endif
+ ESET(EPIPE);
+
+ return -1;
+ }
+ else
+ {
+ /*
+ * Emulate BytesReadable. Some X applications may use the system
+ * select() in their main loop, instead of the _XSelect() that is
+ * replaced by NX. Still these applications use _XEventsQueued to
+ * poll events from the X connection, and _XEventsQueued uses the
+ * NX _XSelect(), so it is generally possible to let the client
+ * yield the control to NX and let it handle the I/O on the proxy
+ * descriptors even if the application is not explicitly designed
+ * to work as a NX agent.
+ */
+
+#ifdef NX_TRANS_DEBUG
+
+ int result;
+
+ result = NXTransReadable(ciptr->fd, (int *) pend);
+
+ fprintf(stderr, "SocketBytesReadable: Descriptor [%d] result [%d] readable [%ld].\n",
+ ciptr->fd, result, *pend);
+
+ return result;
+#else
+ return NXTransReadable(ciptr->fd, (int *) pend);
+#endif
+ }
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(QNX4)
+ *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
+#endif
+#ifdef WIN32
+ {
+ int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+#if (defined(i386) && defined(SYSV) && !defined(SCO325)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1)
+ return ioctl (ciptr->fd, I_NREAD, (char *) pend);
+#else
+#if defined(__UNIXOS2__)
+ return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
+#else
+ return ioctl (ciptr->fd, FIONREAD, (char *) pend);
+#endif /* __UNIXOS2__ */
+#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the read.
+ */
+
+ if (ciptr->priv)
+ {
+ int result;
+
+ result = NXTransRead(ciptr->fd, buf, size);
+
+#ifdef NX_TRANS_DEBUG
+ if (result < 0 && EGET() == EAGAIN)
+ {
+ fprintf(stderr, "SocketRead: Read from descriptor [%d] would block.\n",
+ ciptr->fd);
+ }
+ else
+ {
+ fprintf(stderr, "SocketRead: Read [%d] bytes from descriptor [%d].\n",
+ result, ciptr->fd);
+ }
+#endif
+ return result;
+ }
+ else
+ {
+ return read (ciptr->fd, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return read (ciptr->fd, buf, size);
+#endif /* WIN32 */
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the write.
+ */
+
+ if (ciptr->priv)
+ {
+ int result;
+
+ result = NXTransWrite(ciptr->fd, buf, size);
+
+#ifdef NX_TRANS_DEBUG
+ if (result < 0 && EGET() == EAGAIN)
+ {
+ fprintf(stderr, "SocketWrite: Write on descriptor [%d] would block.\n",
+ ciptr->fd);
+ }
+ else
+ {
+ fprintf(stderr, "SocketWrite: Written [%d] bytes on descriptor [%d].\n",
+ result, ciptr->fd);
+ }
+#endif
+ return result;
+ }
+ else
+ {
+ return write (ciptr->fd, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return write (ciptr->fd, buf, size);
+#endif /* WIN32 */
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the readv.
+ */
+
+ if (ciptr->priv)
+ {
+ return NXTransReadVector(ciptr->fd, buf, size);
+ }
+ else
+ {
+ return READV (ciptr, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ return READV (ciptr, buf, size);
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the writev.
+ */
+
+ if (ciptr->priv)
+ {
+ return NXTransWriteVector(ciptr->fd, buf, size);
+ }
+ else
+ {
+ return WRITEV (ciptr, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ return WRITEV (ciptr, buf, size);
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketDisconnect) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = shutdown (ciptr->fd, 2);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
+#endif
+}
+
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETClose) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = close (ciptr->fd);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return close (ciptr->fd);
+#endif
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static int
+TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
+
+{
+ /*
+ * If this is the server side, then once the socket is closed,
+ * it must be unlinked to completely close it
+ */
+
+ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
+ int ret;
+
+ PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ TRANS(SocketCloseConnInfo) (ciptr);
+ }
+
+#endif
+
+ ret = close(ciptr->fd);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketUNIXClose: Flags are [%d] for ciptr at [%p] check is [%d].\n",
+ ciptr->flags, (void *) ciptr, (ciptr->flags && sockname
+ && sockname->sun_family == AF_UNIX && sockname->sun_path[0]));
+#endif
+
+ if (ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0])
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ {
+ fprintf(stderr, "SocketUNIXClose: Unlinking path [%s] for ciptr at [%p].\n",
+ sockname->sun_path, (void *) ciptr);
+ unlink (sockname->sun_path);
+ }
+#else
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ unlink (sockname->sun_path);
+#endif
+ }
+
+ return ret;
+}
+
+static int
+TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
+
+{
+ /*
+ * Don't unlink path.
+ */
+
+ int ret;
+
+ PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
+ ciptr, ciptr->fd, 0);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ TRANS(SocketCloseConnInfo) (ciptr);
+ }
+
+#endif
+
+ ret = close(ciptr->fd);
+
+ return ret;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+# ifdef TRANS_SERVER
+static char* tcp_nolisten[] = {
+ "inet",
+#if defined(IPv6) && defined(AF_INET6)
+ "inet6",
+#endif
+ NULL
+};
+# endif
+
+Xtransport TRANS(SocketTCPFuncs) = {
+ /* Socket Interface */
+ "tcp",
+ TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ tcp_nolisten,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+Xtransport TRANS(SocketINETFuncs) = {
+ /* Socket Interface */
+ "inet",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+#if defined(IPv6) && defined(AF_INET6)
+Xtransport TRANS(SocketINET6Funcs) = {
+ /* Socket Interface */
+ "inet6",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+#endif /* IPv6 */
+#endif /* TCPCONN */
+
+#ifdef UNIXCONN
+#if !defined(LOCALCONN)
+Xtransport TRANS(SocketLocalFuncs) = {
+ /* Socket Interface */
+ "local",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+#endif /* !LOCALCONN */
+# ifdef TRANS_SERVER
+# if !defined(LOCALCONN)
+static char* unix_nolisten[] = { "local" , NULL };
+# endif
+# endif
+
+Xtransport TRANS(SocketUNIXFuncs) = {
+ /* Socket Interface */
+ "unix",
+#if !defined(LOCALCONN)
+ TRANS_ALIAS,
+#else
+ 0,
+#endif
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+#if !defined(LOCALCONN)
+ unix_nolisten,
+#else
+ NULL,
+#endif
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+
+#endif /* UNIXCONN */
diff --git a/nx-X11/lib/xtrans/Xtranssock.c.NX.original b/nx-X11/lib/xtrans/Xtranssock.c.NX.original
new file mode 100644
index 000000000..8361157f9
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtranssock.c.NX.original
@@ -0,0 +1,3417 @@
+/* $XdotOrg: xc/lib/xtrans/Xtranssock.c,v 1.11 2005/11/08 06:33:26 jkj Exp $ */
+/* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holders shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the copyright holders.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.68 2004/01/07 04:28:02 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NX-X11, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of NoMachine S.r.l. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#ifdef NX_TRANS_SOCKET
+
+#ifdef NX_TRANS_DEBUG
+#define XTRANSDEBUG 5
+#endif
+
+#ifndef PF_LOCAL
+#define PF_LOCAL PF_UNIX
+#endif
+
+#endif
+
+#include <ctype.h>
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+
+#ifndef WIN32
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_NO_LOCKING
+#include <X11/Xos_r.h>
+#endif
+
+#ifdef UNIXCONN
+#ifndef X_NO_SYS_UN
+#ifndef Lynx
+#include <sys/un.h>
+#else
+#include <un.h>
+#endif
+#endif
+#include <sys/stat.h>
+#endif
+
+#if defined(hpux) || (defined(MOTOROLA) && defined(SYSV))
+#define NO_TCP_H
+#endif
+
+#ifndef NO_TCP_H
+#if defined(__osf__) || defined(linux) || defined(__GLIBC__) || defined(AIXV5)
+#include <sys/param.h>
+#endif /* osf */
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#include <machine/endian.h>
+#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
+#include <netinet/tcp.h>
+#endif /* !NO_TCP_H */
+
+#include <sys/ioctl.h>
+#if defined(SVR4) && !defined(DGUX) && !defined(_SEQUENT_)
+#include <sys/filio.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
+#include <net/errno.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_)
+#include <sys/stropts.h>
+#endif
+
+#else /* !WIN32 */
+
+#include <X11/Xwinsock.h>
+#include <X11/Xwindows.h>
+#include <X11/Xw32defs.h>
+#undef close
+#define close closesocket
+#define ECONNREFUSED WSAECONNREFUSED
+#define EADDRINUSE WSAEADDRINUSE
+#define EPROTOTYPE WSAEPROTOTYPE
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#undef EINTR
+#define EINTR WSAEINTR
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_MTSAFE_NETDBAPI
+#include <X11/Xos_r.h>
+#endif /* WIN32 */
+
+#if defined(SO_DONTLINGER) && defined(SO_LINGER)
+#undef SO_DONTLINGER
+#endif
+
+#if defined(__UNIXOS2__)
+#if defined(NOT_EMX09A)
+static int IBMsockInit = 0;
+#define SocketInitOnce()\
+ if (!IBMsockInit) {\
+ sock_init();\
+ IBMsockInit = 1;\
+ }
+#undef EINTR
+#define EINTR SOCEINTR
+#undef EINVAL
+#define EINVAL SOCEINVAL
+#undef errno
+#define errno sock_errno()
+#undef close
+#define close soclose
+#undef ioctl
+#define ioctl sockioctl
+#else
+#define SocketInitOnce() /**/
+#endif
+/* this is still not there */
+#define SOCKET int
+#else
+/* others don't need this */
+#define SocketInitOnce() /**/
+#endif
+
+#define MIN_BACKLOG 128
+#ifdef SOMAXCONN
+#if SOMAXCONN > MIN_BACKLOG
+#define BACKLOG SOMAXCONN
+#endif
+#endif
+#ifndef BACKLOG
+#define BACKLOG MIN_BACKLOG
+#endif
+/*
+ * This is the Socket implementation of the X Transport service layer
+ *
+ * This file contains the implementation for both the UNIX and INET domains,
+ * and can be built for either one, or both.
+ *
+ */
+
+typedef struct _Sockettrans2dev {
+ char *transname;
+ int family;
+ int devcotsname;
+ int devcltsname;
+ int protocol;
+} Sockettrans2dev;
+
+static Sockettrans2dev Sockettrans2devtab[] = {
+#ifdef TCPCONN
+ {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(IPv6) || !defined(AF_INET6)
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#else /* IPv6 */
+ {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
+ {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+#endif
+#endif /* TCPCONN */
+#ifdef UNIXCONN
+ {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(LOCALCONN)
+ {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#endif /* !LOCALCONN */
+#endif /* UNIXCONN */
+};
+
+#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
+
+#ifdef TCPCONN
+static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
+#endif
+
+#ifdef UNIXCONN
+
+#ifdef hpux
+
+#if defined(X11_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/usr/spool/sockets/XIM/"
+#define UNIX_DIR "/usr/spool/sockets/XIM"
+#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/usr/spool/sockets/fontserv/"
+#define UNIX_DIR "/usr/spool/sockets/fontserv"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/usr/spool/sockets/ICE/"
+#define UNIX_DIR "/usr/spool/sockets/ICE"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
+#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#endif
+
+#else /* !hpux */
+
+#if defined(X11_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/tmp/.XIM-unix/XIM"
+#define UNIX_DIR "/tmp/.XIM-unix"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/tmp/.font-unix/fs"
+#define UNIX_DIR "/tmp/.font-unix"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/tmp/.ICE-unix/"
+#define UNIX_DIR "/tmp/.ICE-unix"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/tmp/.Test-unix/test"
+#define UNIX_DIR "/tmp/.Test-unix"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif
+
+#endif /* hpux */
+
+#endif /* UNIXCONN */
+
+#define PORTBUFSIZE 32
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 255
+#endif
+
+/*
+ * This provides compatibility for apps linked against system libraries
+ * that don't have IPv6 support.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
+#pragma weak in6addr_any = local_in6addr_any
+#ifndef __USLC__
+#pragma weak getaddrinfo
+#endif
+static int haveIPv6 = 1;
+#endif
+
+#ifndef X11_t
+
+/*
+ * No NX changes if this is not
+ * compiled as a X11 transport.
+ */
+
+#undef NX_TRANS_SOCKET
+
+#endif
+
+#ifdef NX_TRANS_SOCKET
+
+#ifdef TRANS_CLIENT
+
+#include "NX.h"
+
+typedef struct
+{
+ XtransConnInfo info;
+ int local;
+ int remote;
+ int congestion;
+
+} _NXProxyConnInfo;
+
+#define NX_PROXY_CONN_LIMIT 256
+
+static _NXProxyConnInfo *_NXProxyConnInfoTab[NX_PROXY_CONN_LIMIT];
+
+#endif /* #ifdef TRANS_CLIENT */
+
+/*
+ * Override the UNIX_DIR and UNIX_PATH settings and
+ * make them configurable, based on the NX_TEMP or
+ * the TEMP environment.
+ *
+ * We must be careful as the same defines are used
+ * for different directories, based on the subsystem
+ * that is compiling this, while we want to override
+ * only the '/tmp/.X11-unix' and '/tmp/.X11-unix/X'
+ * settings.
+ */
+
+static char _NXUnixDir[1024];
+static char _NXUnixPath[1024];
+
+static char *_NXGetUnixDir(char *dir)
+{
+ const char *tempDir;
+
+ PRMSG (3, "_NXGetUnixDir(%s)\n", dir, 0, 0);
+
+ if (strcmp(dir, UNIX_DIR) != 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Returning other Unix directory [%s].\n", dir);
+#endif
+ return dir;
+ }
+
+ /*
+ * Check the environment only once.
+ */
+
+ if (*_NXUnixDir != '\0')
+ {
+ return _NXUnixDir;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Trying with the NX_TEMP environment.\n");
+#endif
+
+ tempDir = getenv("NX_TEMP");
+
+ if (tempDir == NULL || *tempDir == '\0')
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Trying with the TEMP environment.\n");
+#endif
+
+ tempDir = getenv("TEMP");
+ }
+
+ if (tempDir != NULL && *tempDir != '\0')
+ {
+ if (strlen(tempDir) + strlen("/.X11-unix") + 1 > 1024)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: WARNING! Maximum length of X11 Unix directory exceeded.\n");
+#endif
+ goto _NXGetUnixDirError;
+ }
+
+ strcpy(_NXUnixDir, tempDir);
+ strcat(_NXUnixDir, "/.X11-unix");
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Using X11 Unix directory [%s].\n", _NXUnixDir);
+#endif
+
+ return _NXUnixDir;
+ }
+
+_NXGetUnixDirError:
+
+ strcpy(_NXUnixDir, dir);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixDir: Returning default X11 Unix directory [%s].\n", _NXUnixDir);
+#endif
+
+ return _NXUnixDir;
+}
+
+static char *_NXGetUnixPath(char *path)
+{
+ const char *unixDir;
+
+ PRMSG (3, "_NXGetUnixPath(%s)\n", path, 0, 0);
+
+ if (strcmp(path, UNIX_PATH) != 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning other X11 Unix path [%s].\n", path);
+#endif
+ return path;
+ }
+
+ /*
+ * Check the environment only once.
+ */
+
+ if (*_NXUnixPath != '\0')
+ {
+ return _NXUnixPath;
+ }
+
+ unixDir = _NXGetUnixDir(UNIX_DIR);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Got X11 Unix directory [%s].\n", unixDir);
+#endif
+
+ if (strlen(unixDir) + strlen("/X") + 1 > 1024)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: WARNING! Maximum length of X11 Unix path exceeded.\n");
+#endif
+
+ goto _NXGetUnixPathError;
+ }
+
+ strcpy(_NXUnixPath, unixDir);
+ strcat(_NXUnixPath, "/X");
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning X11 Unix path [%s].\n", _NXUnixPath);
+#endif
+
+ return _NXUnixPath;
+
+_NXGetUnixPathError:
+
+ strcpy(_NXUnixPath, path);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetUnixPath: Returning default X11 Unix path [%s].\n", _NXUnixPath);
+#endif
+
+ return _NXUnixPath;
+}
+
+#ifdef hpux
+
+static char *_NXGetOldUnixPath(char *path)
+{
+ PRMSG (3, "_NXGetOldUnixPath(%s)\n", path, 0, 0);
+
+ if (strcmp(path, OLD_UNIX_PATH) == 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetOldUnixPath: Returning X11 Unix path [%s].\n",
+ _NXGetUnixPath(path));
+#endif
+
+ return _NXGetUnixPath(path);
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "_NXGetOldUnixPath: Returning other old X11 Unix path [%s].\n", path);
+#endif
+
+ return path;
+}
+
+#endif /* #ifdef hpux */
+
+/*
+ * Forcibly close any connection attempt on the
+ * listening socket. Need this to avoid loopback
+ * connections to the agent server.
+ */
+
+#ifdef TRANS_SERVER
+
+void TRANS(SocketRejectConnection) (XtransConnInfo ciptr)
+{
+ size_t sa_l = sizeof(struct sockaddr);
+ struct sockaddr sa;
+ fd_set fs;
+ struct timeval t;
+ int f;
+
+ PRMSG (3, "SocketRejectConnection(%x)\n", ciptr, 0, 0);
+
+ FD_ZERO(&fs);
+ FD_SET(ciptr -> fd, &fs);
+
+ t.tv_sec = 0;
+ t.tv_usec = 0;
+
+ /*
+ * Check if there is an awaiting connection.
+ */
+
+ if (select(ciptr -> fd + 1, &fs, NULL, NULL, &t) == 1)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketRejectConnection: Accepting connection attempt on fd [%d].\n",
+ ciptr -> fd);
+#endif
+ /*
+ * If there is one, close it.
+ */
+
+ if ((f = accept(ciptr -> fd, &sa, &sa_l)) >= 0)
+ {
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketRejectConnection: Closing connection attempt on fd [%d].\n",
+ ciptr -> fd);
+#endif
+ close(f);
+ }
+ }
+}
+
+#endif /* #ifdef TRANS_SERVER */
+
+#ifdef TRANS_CLIENT
+
+void *TRANS(SocketProxyConnInfo) (XtransConnInfo ciptr)
+{
+ if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
+ {
+ return ciptr->priv;
+ }
+
+ return NULL;
+}
+
+static XtransConnInfo TRANS(SocketCreateConnInfo) ()
+{
+ XtransConnInfo ciptr;
+
+ int fds[2];
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX connection info.\n");
+#endif
+
+ if ((ciptr = (XtransConnInfo) xcalloc (1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Create a pair of sockets. We'll communicate with
+ * the NX proxy by reading and writing to our end.
+ */
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Going to create the NX socketpair.\n");
+#endif
+
+ if (socketpair(PF_LOCAL, SOCK_STREAM, 0, fds) < 0)
+ {
+ PRMSG (1, "SocketCreateConnInfo: socketpair() failed.\n", 0, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: X socket end is [%d] NX proxy end is [%d].\n",
+ fds[0], fds[1]);
+#endif
+
+ /*
+ * Save in _NXProxyConnInfoTab the local and remote end of
+ * the socketpair. The remote end will be used by the proxy.
+ * When the memory-to-memory transport is activated, the
+ * agent and the proxy don't read or write to the real des-
+ * criptors but the communication takes place by reading
+ * and writing to the proxy's buffers.
+ */
+
+ ciptr->fd = fds[0];
+
+ if (ciptr->fd >= NX_PROXY_CONN_LIMIT)
+ {
+ PRMSG (1, "SocketCreateConnInfo: No space for a new _NXProxyConnInfo for [%d].\n",
+ ciptr->fd, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] != NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: _NXProxyConnInfo for [%d] is not NULL. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+
+ _NXProxyConnInfoTab[ciptr->fd] = (_NXProxyConnInfo *) xcalloc(1, sizeof(_NXProxyConnInfo));
+
+ if (_NXProxyConnInfoTab[ciptr->fd] == NULL)
+ {
+ PRMSG (1, "SocketCreateConnInfo: Alloc of _NXProxyConnInfo failed.\n", 0, 0, 0);
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCreateConnInfo: Allocated new _NXProxyConnInfo for [%d].\n",
+ ciptr->fd);
+#endif
+
+ _NXProxyConnInfoTab[ciptr->fd]->info = ciptr;
+ _NXProxyConnInfoTab[ciptr->fd]->local = fds[0];
+ _NXProxyConnInfoTab[ciptr->fd]->remote = fds[1];
+ _NXProxyConnInfoTab[ciptr->fd]->congestion = 0;
+
+ ciptr->priv = (char *) _NXProxyConnInfoTab[ciptr->fd];
+
+ return ciptr;
+}
+
+static int TRANS(SocketConnectConnInfo) (XtransConnInfo ciptr, char *host, char *port)
+{
+ int fds[2];
+ char display[1024];
+
+ _NXProxyConnInfo *proxy_conn;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Going to connect NX fd [%d] to host [%s] port [%s].\n",
+ ciptr->fd, host, port);
+#endif
+
+ /*
+ * We should have already created the socket pair.
+ */
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
+
+ exit(1);
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
+ 0, 0, 0);
+
+ exit(1);
+ }
+
+ if (strlen(host) + strlen(port) + 1 >= 1023)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Length of NX display string '%s:%s' would exceed %d characters.\n",
+ host, port, 1023);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+ sprintf(display, "%s:%s", host, port);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Setting close-on-exec flag on local NX descriptor [%d].\n",
+ proxy_conn -> local);
+#endif
+
+#ifdef F_SETFD
+#ifdef FD_CLOEXEC
+ if (fcntl(proxy_conn -> local, F_SETFD, FD_CLOEXEC) != 0)
+#else
+ if (fcntl(proxy_conn -> local, F_SETFD, 1) != 0)
+#endif
+#endif
+ {
+ PRMSG (1, "SocketConnectConnInfo: Cannot set close-on-exec on local NX descriptor [%d].\n",
+ proxy_conn -> local, 0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Creating the NX transport with display [%s].\n",
+ display);
+#endif
+
+ if (NXTransCreate(NX_FD_ANY, NX_MODE_CLIENT, display) < 0)
+ {
+ PRMSG (1, "SocketConnectConnInfo: Cannot create the NX transport.\n",
+ 0, 0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketConnectConnInfo: Starting the NX agent with descriptor [%d].\n",
+ proxy_conn -> remote);
+#endif
+
+ fds[0] = proxy_conn -> local;
+ fds[1] = proxy_conn -> remote;
+
+ NXTransAgent(fds);
+
+ return 0;
+}
+
+static void TRANS(SocketCloseConnInfo) (XtransConnInfo ciptr)
+{
+ _NXProxyConnInfo *proxy_conn;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Going to close the NX fd [%d].\n", ciptr->fd);
+#endif
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Pointer to _NXProxyConnInfo is NULL. Exiting.\n", 0, 0, 0);
+
+ exit(1);
+ }
+ else if (ciptr->fd >= NX_PROXY_CONN_LIMIT ||
+ _NXProxyConnInfoTab[ciptr->fd] != (_NXProxyConnInfo *) ciptr->priv)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Can't find _NXProxyConnInfo in table. Exiting.\n",
+ 0, 0, 0);
+ exit(1);
+ }
+ else if (_NXProxyConnInfoTab[ciptr->fd] -> info != ciptr ||
+ _NXProxyConnInfoTab[ciptr->fd] -> local != ciptr->fd)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Invalid _NXProxyConnInfo structure for [%d]. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+ else if (proxy_conn->local < 0 || proxy_conn->remote < 0)
+ {
+ PRMSG (1, "SocketCloseConnInfo: Invalid socket pair in NX connection for [%d]. Exiting.\n",
+ ciptr->fd, 0, 0);
+ exit(1);
+ }
+
+ NXTransClose(ciptr->fd);
+
+ /*
+ * Get rid of the _NXProxyConnInfo structure.
+ */
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Freeing _NXProxyConnInfo structure for [%d].\n",
+ ciptr->fd);
+#endif
+
+ xfree((char *) _NXProxyConnInfoTab[ciptr->fd]);
+
+ _NXProxyConnInfoTab[ciptr->fd] = NULL;
+
+ ciptr->priv = NULL;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCloseConnInfo: Should now close the local descriptor [%d].\n",
+ ciptr->fd);
+#endif
+}
+
+#endif /* #ifdef TRANS_CLIENT */
+
+#if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE)
+
+/*
+ * Check the congestion state of the NX transport
+ * and return 1 if there has been a change. This
+ * can be extended by adding a few counters track-
+ * ing the bandwidth usage of the X11 connection.
+ */
+
+int TRANS(SocketCongestionChange) (XtransConnInfo ciptr, int *state)
+{
+ int congestion;
+
+ _NXProxyConnInfo *proxy_conn;
+
+ PRMSG (3, "SocketCongestionChange(%x)\n", ciptr, 0, 0);
+
+ proxy_conn = (_NXProxyConnInfo *) ciptr->priv;
+
+ if (proxy_conn == NULL)
+ {
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketCongestionChange: Descriptor [%d] doesn't appear to be a NX connection.\n",
+ ciptr->fd);
+#endif
+ return 0;
+ }
+
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketCongestionChange: Checking congestion on fd [%d] with old state [%d].\n",
+ ciptr->fd, proxy_conn->congestion);
+#endif
+
+ congestion = NXTransCongestion(ciptr->fd);
+
+ if (congestion != proxy_conn->congestion)
+ {
+ proxy_conn->congestion = congestion;
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCongestionChange: Change detected on fd [%d] with new state [%d].\n",
+ ciptr->fd, proxy_conn->congestion);
+#endif
+ return 1;
+ }
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketCongestionChange: No change on fd [%d] with current state [%d].\n",
+ ciptr->fd, congestion);
+#endif
+ return 0;
+}
+
+#endif /* #if defined(TRANS_CLIENT) && defined(NX_TRANS_CHANGE) */
+
+#endif /* #ifdef NX_TRANS_SOCKET */
+
+/*
+ * These are some utility function used by the real interface function below.
+ */
+
+static int
+TRANS(SocketSelectFamily) (int first, char *family)
+
+{
+ int i;
+
+ PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
+
+ for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
+ {
+ if (!strcmp (family, Sockettrans2devtab[i].transname))
+ return i;
+ }
+
+ return (first == -1 ? -2 : -1);
+}
+
+
+/*
+ * This function gets the local address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+ PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
+ EGET(),0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
+ }
+ else
+#endif
+ {
+ ciptr->family = socknamev4.sin_family;
+ }
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && ciptr->family == AF_INET6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
+
+ if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+static XtransConnInfo
+TRANS(SocketOpen) (int i, int type)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+
+ if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
+ return NULL;
+#endif
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
+ Sockettrans2devtab[i].protocol)) < 0
+#ifndef WIN32
+#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
+ || ciptr->fd >= TRANS_OPEN_MAX
+#endif
+#endif
+ ) {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (2, "SocketOpen: socket() failed for %s\n",
+ Sockettrans2devtab[i].transname, 0, 0);
+
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopen) (int i, int type, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+/*
+ * These functions are the interface supplied in the Xtransport structure
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
+ char *host, char *port, int previndex)
+{
+ XtransConnInfo ciptr;
+ int i = previndex;
+
+ PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
+ protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
+ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
+ {
+ ciptr = TRANS(SocketCreateConnInfo) ();
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1, "SocketOpenCOTSClient: Unable to create the NX connection info for %s.\n",
+ transname, 0, 0);
+
+ return NULL;
+ }
+
+ ciptr->index = i;
+
+ return ciptr;
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
+ transname, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
+ transname, 0, 0);
+ return NULL;
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ ciptr->priv = NULL;
+
+#endif
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ return TRANS(SocketOpenCOTSClientBase)(
+ thistrans->TransName, protocol, host, port, -1);
+}
+
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Using this prevents the bind() check for an existing server listening
+ * on the same port, but it is required for other reasons.
+ */
+#ifdef SO_REUSEADDR
+
+ /*
+ * SO_REUSEADDR only applied to AF_INET && AF_INET6
+ */
+
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ int one = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &one, sizeof (int));
+ }
+#endif
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if ((!strcmp(protocol, "local") || !strcmp(protocol, "nx")) &&
+ (!strcasecmp(host, "nx") || !strncasecmp(host, "nx,", 3)))
+ {
+ ciptr = TRANS(SocketCreateConnInfo) ();
+
+ if (ciptr == NULL)
+ {
+ PRMSG (1, "SocketOpenCLTSClient: Unable to create the NX connection info for %s.\n",
+ thistrans->TransName, 0, 0);
+
+ return NULL;
+ }
+
+ ciptr->index = i;
+
+ return ciptr;
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ ciptr->priv = NULL;
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
+#ifdef NX_TRANS_TEST
+ fprintf(stderr, "SocketSetOption: WARNING! Not setting option [%d] with value [%d] on descriptor [%d].\n",
+ option, arg, ciptr -> fd);
+#endif
+
+ return -1;
+}
+
+#ifdef UNIXCONN
+static int
+set_sun_path(const char *port, const char *upath, char *path)
+{
+ struct sockaddr_un s;
+ int maxlen = sizeof(s.sun_path) - 1;
+
+ if (!port || !*port || !path)
+ return -1;
+
+ if (*port == '/') { /* a full pathname */
+ if (strlen(port) > maxlen)
+ return -1;
+ sprintf(path, "%s", port);
+ } else {
+ if (strlen(port) + strlen(upath) > maxlen)
+ return -1;
+ sprintf(path, "%s%s", upath, port);
+ }
+ return 0;
+}
+#endif
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(SocketCreateListener) (XtransConnInfo ciptr,
+ struct sockaddr *sockname,
+ int socknamelen, unsigned int flags)
+
+{
+ int namelen = socknamelen;
+ int fd = ciptr->fd;
+ int retry;
+
+ PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ )
+ retry = 20;
+ else
+ retry = 0;
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketCreateListener: Creating listener for ciptr at [%p] on path [%s].\n",
+ (void *) ciptr, ((struct sockaddr_un *) sockname)->sun_family == AF_UNIX ?
+ ((struct sockaddr_un *) sockname)->sun_path : "TCP");
+#endif
+ while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
+ {
+ if (errno == EADDRINUSE) {
+ if (flags & ADDR_IN_USE_ALLOWED)
+ break;
+ else
+ return TRANS_ADDR_IN_USE;
+ }
+
+ if (retry-- == 0) {
+ PRMSG (1, "SocketCreateListener: failed to bind listener\n",
+ 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#ifdef SO_REUSEADDR
+ sleep (1);
+#else
+ sleep (10);
+#endif /* SO_REUSEDADDR */
+ }
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ ) {
+#ifdef SO_DONTLINGER
+ setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
+#else
+#ifdef SO_LINGER
+ {
+ static int linger[2] = { 0, 0 };
+ setsockopt (fd, SOL_SOCKET, SO_LINGER,
+ (char *) linger, sizeof (linger));
+ }
+#endif
+#endif
+}
+
+ if (listen (fd, BACKLOG) < 0)
+ {
+ PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ /* Set a flag to indicate that this connection is a listener */
+
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketCreateListener: Set flags to [%d] for ciptr [%p].\n",
+ ciptr->flags, (void *) ciptr);
+#endif
+
+ return 0;
+}
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage sockname;
+#else
+ struct sockaddr_in sockname;
+#endif
+ unsigned short sport;
+ int namelen = sizeof(sockname);
+ int status;
+ long tmpport;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgetservbynameparams sparams;
+#endif
+ struct servent *servp;
+
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ /* fixup the server port address */
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf,"%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ if (port && *port)
+ {
+ /* Check to see if the port string is just a number (handles X11) */
+
+ if (!is_numeric (port))
+ {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: Unable to get service for %s\n",
+ port, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ /* we trust getservbyname to return a valid number */
+ sport = servp->s_port;
+ }
+ else
+ {
+ tmpport = strtol (port, (char**)NULL, 10);
+ /*
+ * check that somehow the port address isn't negative or in
+ * the range of reserved port addresses. This can happen and
+ * be very bad if the server is suid-root and the user does
+ * something (dumb) like `X :60049`.
+ */
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CREATE_LISTENER_FAILED;
+
+ sport = (unsigned short) tmpport;
+ }
+ }
+ else
+ sport = 0;
+
+ bzero(&sockname, sizeof(sockname));
+#if defined(IPv6) && defined(AF_INET6)
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ namelen = sizeof (struct sockaddr_in);
+#ifdef BSD44SOCKETS
+ ((struct sockaddr_in *)&sockname)->sin_len = namelen;
+#endif
+ ((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
+ ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ namelen = sizeof (struct sockaddr_in6);
+#ifdef SIN6_LEN
+ ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
+#endif
+ ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
+ ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
+ }
+#else
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (sockname);
+#endif
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (sport);
+ sockname.sin_addr.s_addr = htonl (INADDR_ANY);
+#endif
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ return status;
+ }
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
+ 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* SOCKCONN */
+
+
+#ifdef UNIXCONN
+
+static int
+TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
+ unsigned int flags)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+ int oldUmask;
+ int status;
+ unsigned int mode;
+
+ PRMSG (2, "SocketUNIXCreateListener(%s)\n",
+ port ? port : "NULL", 0, 0);
+
+ /* Make sure the directory is created */
+
+ oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+#ifdef NX_TRANS_SOCKET
+ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ _NXGetUnixDir(UNIX_DIR), errno, 0);
+#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+#endif
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#endif
+
+ sockname.sun_family = AF_UNIX;
+
+ if (port && *port) {
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
+#ifdef NX_TRANS_SOCKET
+ sprintf (sockname.sun_path, "%s%ld", _NXGetUnixPath(UNIX_PATH), (long)getpid());
+#else
+ sprintf (sockname.sun_path, "%s%ld", UNIX_PATH, (long)getpid());
+#endif
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen(sockname.sun_path);
+ namelen = SUN_LEN(&sockname);
+#else
+ namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
+#endif
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketUNIXCreateListener: Unlinking path [%s] for ciptr at [%p].\n",
+ sockname.sun_path, (void *) ciptr);
+#endif
+ unlink (sockname.sun_path);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return status;
+ }
+
+ /*
+ * Now that the listener is esablished, create the addr info for
+ * this connection. getpeername() doesn't work for UNIX Domain Sockets
+ * on some systems (hpux at least), so we will just do it manually, instead
+ * of calling something like TRANS(SocketUNIXGetAddr).
+ */
+
+ namelen = sizeof (sockname); /* this will always make it the same size */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ ciptr->family = sockname.sun_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ (void) umask (oldUmask);
+
+ return 0;
+}
+
+
+static int
+TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
+
+{
+ /*
+ * See if the unix domain socket has disappeared. If it has, recreate it.
+ */
+
+ struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
+ struct stat statb;
+ int status = TRANS_RESET_NOOP;
+ unsigned int mode;
+
+ PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if (stat (unsock->sun_path, &statb) == -1 ||
+ ((statb.st_mode & S_IFMT) !=
+#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
+ S_IFIFO))
+#else
+ S_IFSOCK))
+#endif
+ {
+ int oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+#ifdef NX_TRANS_SOCKET
+ if (trans_mkdir(_NXGetUnixDir(UNIX_DIR), mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ _NXGetUnixDir(UNIX_DIR), errno, 0);
+#else
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+#endif
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+#endif
+
+ close (ciptr->fd);
+ unlink (unsock->sun_path);
+
+ if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (listen (ciptr->fd, BACKLOG) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ umask (oldUmask);
+
+ status = TRANS_RESET_NEW_FD;
+ }
+
+ return status;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+
+static XtransConnInfo
+TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_in sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ /*
+ * Get this address again because the transport may give a more
+ * specific address now that a connection is established.
+ */
+
+ if (TRANS(SocketINETGetAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static XtransConnInfo
+TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_un sockname;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+ PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ /*
+ * Get the socket name and the peer name from the listener socket,
+ * since this is unix domain.
+ */
+
+ if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+
+ newciptr->addrlen = ciptr->addrlen;
+ memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
+
+ if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ newciptr->peeraddrlen = ciptr->addrlen;
+ memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
+
+ newciptr->family = AF_UNIX;
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+#ifdef TCPCONN
+
+#if defined(IPv6) && defined(AF_INET6)
+struct addrlist {
+ struct addrinfo * addr;
+ struct addrinfo * firstaddr;
+ char port[PORTBUFSIZE];
+ char host[MAXHOSTNAMELEN];
+};
+static struct addrlist *addrlist = NULL;
+#endif
+
+
+static int
+TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr * socketaddr = NULL;
+ int socketaddrlen = 0;
+ int res;
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo hints;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ int resetonce = 0;
+#endif
+ struct sockaddr_in sockname;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+ _Xgetservbynameparams sparams;
+#endif
+ struct hostent *hostp;
+ struct servent *servp;
+ unsigned long tmpaddr;
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ long tmpport;
+ char hostnamebuf[256]; /* tmp space */
+
+ PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ if (!host)
+ {
+ hostnamebuf[0] = '\0';
+ (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+ host = hostnamebuf;
+ }
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf, "%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6) {
+ if (addrlist != NULL) {
+ if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
+ if (addrlist->firstaddr)
+ freeaddrinfo(addrlist->firstaddr);
+ addrlist->firstaddr = NULL;
+ }
+ } else {
+ addrlist = malloc(sizeof(struct addrlist));
+ addrlist->firstaddr = NULL;
+ }
+
+ if (addrlist->firstaddr == NULL) {
+ strncpy(addrlist->port, port, sizeof(addrlist->port));
+ addrlist->port[sizeof(addrlist->port) - 1] = '\0';
+ strncpy(addrlist->host, host, sizeof(addrlist->host));
+ addrlist->host[sizeof(addrlist->host) - 1] = '\0';
+
+ bzero(&hints,sizeof(hints));
+ hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
+
+ res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
+ if (res != 0) {
+ PRMSG (1, "SocketINETConnect() can't get address "
+ "for %s:%s: %s\n", host, port, gai_strerror(res));
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ for (res = 0, addrlist->addr = addrlist->firstaddr;
+ addrlist->addr ; res++) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
+ res = 0;
+ addrlist->addr = NULL;
+ }
+
+ while (socketaddr == NULL) {
+ if (addrlist->addr == NULL) {
+ if (resetonce) {
+ /* Already checked entire list - no usable addresses */
+ PRMSG (1, "SocketINETConnect() no usable address "
+ "for %s:%s\n", host, port, 0);
+ return TRANS_CONNECT_FAILED;
+ } else {
+ /* Go back to beginning of list */
+ resetonce = 1;
+ addrlist->addr = addrlist->firstaddr;
+ }
+ }
+
+ socketaddr = addrlist->addr->ai_addr;
+ socketaddrlen = addrlist->addr->ai_addrlen;
+
+ if (addrlist->addr->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
+ ntopbuf,sizeof(ntopbuf)), 0, 0);
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
+ ntohs(sin->sin_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Our socket is an IPv6 socket, but the address is
+ * IPv4. Close it and get an IPv4 socket. This is
+ * needed for IPv4 connections to work on platforms
+ * that don't allow IPv4 over IPv6 sockets.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, ciptr->index);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
+ " socketfor IPv4 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ } else {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
+ 0,0,0);
+ }
+ }
+ } else if (addrlist->addr->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,
+ &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
+ 0, 0);
+ PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
+ ntohs(sin6->sin6_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Close the IPv4 socket and try to open an IPv6 socket.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, -1);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET6) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
+ "socket for IPv6 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ }
+ else
+ {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
+ 0,0,0);
+ }
+ }
+ } else {
+ socketaddr = NULL; /* Unsupported address type */
+ }
+ if (socketaddr == NULL) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ }
+ } else
+#endif
+ {
+ /*
+ * Build the socket name.
+ */
+
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (struct sockaddr_in);
+#endif
+ sockname.sin_family = AF_INET;
+
+ /*
+ * fill in sin_addr
+ */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((in_addr_t) 0xffffffff)
+#endif
+
+ /* check for ww.xx.yy.zz host string */
+
+ if (isascii (host[0]) && isdigit (host[0])) {
+ tmpaddr = inet_addr (host); /* returns network byte order */
+ } else {
+ tmpaddr = INADDR_NONE;
+ }
+
+ PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
+
+ if (tmpaddr == INADDR_NONE) {
+ if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
+ host, 0, 0);
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ if (hostp->h_addrtype != AF_INET) { /* is IP host? */
+ PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
+ ESET(EPROTOTYPE);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ {
+ long t;
+ memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
+ sockname.sin_addr = t;
+ }
+#else
+ memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
+ sizeof (sockname.sin_addr));
+#endif /* CRAY and OLDTCP */
+
+ } else {
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ sockname.sin_addr = tmpaddr;
+#else
+ sockname.sin_addr.s_addr = tmpaddr;
+#endif /* CRAY and OLDTCP */
+ }
+
+ /*
+ * fill in sin_port
+ */
+
+ /* Check for number in the port string */
+
+ if (!is_numeric (port)) {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: can't get service for %s\n",
+ port, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ sockname.sin_port = htons (servp->s_port);
+ } else {
+ tmpport = strtol (port, (char**)NULL, 10);
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CONNECT_FAILED;
+ sockname.sin_port = htons (((unsigned short) tmpport));
+ }
+
+ PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
+ ntohs(sockname.sin_port), 0, 0);
+ socketaddr = (struct sockaddr *) &sockname;
+ socketaddrlen = sizeof(sockname);
+ }
+
+ /*
+ * Turn on socket keepalive so the client process will eventually
+ * be notified with a SIGPIPE signal if the display server fails
+ * to respond to a periodic transmission of messages
+ * on the connected socket.
+ * This is useful to avoid hung application processes when the
+ * processes are not spawned from the xdm session and
+ * the display server terminates abnormally.
+ * (Someone turned off the power switch.)
+ */
+
+ {
+ int tmp = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &tmp, sizeof (int));
+ }
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
+ {
+#ifdef WIN32
+ int olderrno = WSAGetLastError();
+#else
+ int olderrno = errno;
+#endif
+
+ /*
+ * If the error was ECONNREFUSED, the server may be overloaded
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ *
+ * If multiple addresses are found for a host then we should
+ * try to connect again with a different address for a larger
+ * number of errors that made us quit before, since those
+ * could be caused by trying to use an IPv6 address to contact
+ * a machine with an IPv4-only server or other reasons that
+ * only affect one of a set of addresses.
+ */
+
+ if (olderrno == ECONNREFUSED || olderrno == EINTR
+#if defined(IPv6) && defined(AF_INET6)
+ || (haveIPv6 && ((addrlist->addr->ai_next != NULL) ||
+ (addrlist->addr != addrlist->firstaddr)) &&
+ (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
+ olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
+#if defined(EHOSTDOWN)
+ || olderrno == EHOSTDOWN
+#endif
+ ))
+#endif
+ )
+ res = TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ res = TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
+ olderrno,0, 0);
+
+ res = TRANS_CONNECT_FAILED;
+ }
+ } else {
+ res = 0;
+
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+
+ else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && res != 0) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+#endif
+
+ return res;
+}
+
+#endif /* TCPCONN */
+
+
+
+#ifdef UNIXCONN
+
+/*
+ * Make sure 'host' is really local.
+ */
+
+static int
+UnixHostReallyLocal (char *host)
+
+{
+ char hostnamebuf[256];
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+#endif
+
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+
+ if (strcmp (hostnamebuf, host) == 0)
+ {
+ return (1);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (haveIPv6)
+ {
+ struct addrinfo *localhostaddr;
+ struct addrinfo *otherhostaddr;
+ struct addrinfo *i, *j;
+ int equiv = 0;
+
+ if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
+ return 0;
+ if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
+ freeaddrinfo(localhostaddr);
+ return 0;
+ }
+
+ for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
+ for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
+ if (i->ai_family == j->ai_family) {
+ if (i->ai_family == AF_INET) {
+ struct sockaddr_in *sinA
+ = (struct sockaddr_in *) i->ai_addr;
+ struct sockaddr_in *sinB
+ = (struct sockaddr_in *) j->ai_addr;
+ struct in_addr *A = &sinA->sin_addr;
+ struct in_addr *B = &sinB->sin_addr;
+
+ if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
+ equiv = 1;
+ }
+ } else if (i->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sinA
+ = (struct sockaddr_in6 *) i->ai_addr;
+ struct sockaddr_in6 *sinB
+ = (struct sockaddr_in6 *) j->ai_addr;
+ struct in6_addr *A = &sinA->sin6_addr;
+ struct in6_addr *B = &sinB->sin6_addr;
+
+ if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
+ equiv = 1;
+ }
+ }
+ }
+ }
+ }
+
+ freeaddrinfo(localhostaddr);
+ freeaddrinfo(otherhostaddr);
+ return equiv;
+ }
+#endif
+ else
+ {
+ /*
+ * A host may have more than one network address. If any of the
+ * network addresses of 'host' (specified to the connect call)
+ * match any of the network addresses of 'hostname' (determined
+ * by TRANS(GetHostname)), then the two hostnames are equivalent,
+ * and we know that 'host' is really a local host.
+ */
+ char specified_local_addr_list[10][4];
+ int scount, equiv, i, j;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ struct hostent *hostp;
+
+ if ((hostp = _XGethostbyname (host,hparams)) == NULL)
+ return (0);
+
+ scount = 0;
+ while (hostp->h_addr_list[scount] && scount <= 8)
+ {
+ /*
+ * The 2nd call to gethostname() overrides the data
+ * from the 1st call, so we must save the address list.
+ */
+
+ specified_local_addr_list[scount][0] =
+ hostp->h_addr_list[scount][0];
+ specified_local_addr_list[scount][1] =
+ hostp->h_addr_list[scount][1];
+ specified_local_addr_list[scount][2] =
+ hostp->h_addr_list[scount][2];
+ specified_local_addr_list[scount][3] =
+ hostp->h_addr_list[scount][3];
+ scount++;
+ }
+ if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
+ return (0);
+
+ equiv = 0;
+ i = 0;
+
+ while (i < scount && !equiv)
+ {
+ j = 0;
+
+ while (hostp->h_addr_list[j])
+ {
+ if ((specified_local_addr_list[i][0] ==
+ hostp->h_addr_list[j][0]) &&
+ (specified_local_addr_list[i][1] ==
+ hostp->h_addr_list[j][1]) &&
+ (specified_local_addr_list[i][2] ==
+ hostp->h_addr_list[j][2]) &&
+ (specified_local_addr_list[i][3] ==
+ hostp->h_addr_list[j][3]))
+ {
+ /* They're equal, so we're done */
+
+ equiv = 1;
+ break;
+ }
+
+ j++;
+ }
+
+ i++;
+ }
+ return (equiv);
+ }
+}
+
+static int
+TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+
+#if defined(hpux) && defined(X11_t)
+ struct sockaddr_un old_sockname;
+ int old_namelen;
+#endif
+
+
+ PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ /*
+ * Make sure 'host' is really local. If not, we return failure.
+ * The reason we make this check is because a process may advertise
+ * a "local" network ID for which it can accept connections, but if
+ * a process on a remote machine tries to connect to this network ID,
+ * we know for sure it will fail.
+ */
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+ if (strcmp(host, "unix") != 0 && strcasecmp(host, "nx") != 0 &&
+ strncasecmp(host, "nx,", 3) != 0 && !UnixHostReallyLocal (host))
+#else
+ if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
+#endif
+ {
+ PRMSG (1,
+ "SocketUNIXConnect: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+
+ /*
+ * Check the port.
+ */
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ /*
+ * Build the socket name.
+ */
+
+ sockname.sun_family = AF_UNIX;
+
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetUnixPath(UNIX_PATH), sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen (sockname.sun_path);
+ namelen = SUN_LEN (&sockname);
+#else
+ namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family);
+#endif
+
+
+#if defined(hpux) && defined(X11_t)
+ /*
+ * This is gross, but it was in Xlib
+ */
+ old_sockname.sun_family = AF_UNIX;
+#ifdef NX_TRANS_SOCKET
+ if (set_sun_path(port, _NXGetOldUnixPath(OLD_UNIX_PATH), old_sockname.sun_path) != 0) {
+#else
+ if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
+#endif
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ old_namelen = strlen (old_sockname.sun_path) +
+ sizeof (old_sockname.sun_family);
+#endif
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv != NULL)
+ {
+ if (TRANS(SocketConnectConnInfo) (ciptr, host, port) != 0)
+ {
+ return TRANS_CONNECT_FAILED;
+ }
+
+ goto SocketUNIXConnectPost;
+ }
+
+#endif
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
+ {
+ int olderrno = errno;
+ int connected = 0;
+
+#if defined(hpux) && defined(X11_t)
+ if (olderrno == ENOENT)
+ {
+ if (connect (ciptr->fd,
+ (struct sockaddr *) &old_sockname, old_namelen) >= 0)
+ {
+ connected = 1;
+ }
+ else
+ olderrno = errno;
+ }
+#endif
+ if (!connected)
+ {
+ errno = olderrno;
+
+ /*
+ * If the error was ENOENT, the server may be starting up
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ */
+
+ if (olderrno == ENOENT || olderrno == EINTR)
+ return TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ return TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
+ EGET(),0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+ }
+ }
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+SocketUNIXConnectPost:
+
+#endif
+
+ /*
+ * Get the socket name and the peer name from the connect socket,
+ * since this is unix domain.
+ */
+
+ if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
+ (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ ciptr->family = AF_UNIX;
+ ciptr->addrlen = namelen;
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
+ ciptr, ciptr->fd, pend);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ if (NXTransRunning(ciptr->fd) == 0)
+ {
+ /*
+ * Force the application to shut down the
+ * socket if the NX transport is gone. We
+ * may probably save this additional call.
+ */
+
+#ifdef NX_TRANS_DEBUG
+ fprintf(stderr, "SocketBytesReadable: NX transport not running for descriptor [%d].\n",
+ ciptr->fd);
+#endif
+ ESET(EPIPE);
+
+ return -1;
+ }
+ else
+ {
+ /*
+ * Emulate BytesReadable. Some X applications may use the system
+ * select() in their main loop, instead of the _XSelect() that is
+ * replaced by NX. Still these applications use _XEventsQueued to
+ * poll events from the X connection, and _XEventsQueued uses the
+ * NX _XSelect(), so it is generally possible to let the client
+ * yield the control to NX and let it handle the I/O on the proxy
+ * descriptors even if the application is not explicitly designed
+ * to work as a NX agent.
+ */
+
+#ifdef NX_TRANS_DEBUG
+
+ int result;
+
+ result = NXTransReadable(ciptr->fd, (int *) pend);
+
+ fprintf(stderr, "SocketBytesReadable: Descriptor [%d] result [%d] readable [%ld].\n",
+ ciptr->fd, result, *pend);
+
+ return result;
+#else
+ return NXTransReadable(ciptr->fd, (int *) pend);
+#endif
+ }
+ }
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(QNX4)
+ *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
+#endif
+#ifdef WIN32
+ {
+ int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+#if (defined(i386) && defined(SYSV) && !defined(SCO325)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1)
+ return ioctl (ciptr->fd, I_NREAD, (char *) pend);
+#else
+#if defined(__UNIXOS2__)
+ return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
+#else
+ return ioctl (ciptr->fd, FIONREAD, (char *) pend);
+#endif /* __UNIXOS2__ */
+#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the read.
+ */
+
+ if (ciptr->priv)
+ {
+ int result;
+
+ result = NXTransRead(ciptr->fd, buf, size);
+
+#ifdef NX_TRANS_DEBUG
+ if (result < 0 && EGET() == EAGAIN)
+ {
+ fprintf(stderr, "SocketRead: Read from descriptor [%d] would block.\n",
+ ciptr->fd);
+ }
+ else
+ {
+ fprintf(stderr, "SocketRead: Read [%d] bytes from descriptor [%d].\n",
+ result, ciptr->fd);
+ }
+#endif
+ return result;
+ }
+ else
+ {
+ return read (ciptr->fd, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return read (ciptr->fd, buf, size);
+#endif /* WIN32 */
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the write.
+ */
+
+ if (ciptr->priv)
+ {
+ int result;
+
+ result = NXTransWrite(ciptr->fd, buf, size);
+
+#ifdef NX_TRANS_DEBUG
+ if (result < 0 && EGET() == EAGAIN)
+ {
+ fprintf(stderr, "SocketWrite: Write on descriptor [%d] would block.\n",
+ ciptr->fd);
+ }
+ else
+ {
+ fprintf(stderr, "SocketWrite: Written [%d] bytes on descriptor [%d].\n",
+ result, ciptr->fd);
+ }
+#endif
+ return result;
+ }
+ else
+ {
+ return write (ciptr->fd, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return write (ciptr->fd, buf, size);
+#endif /* WIN32 */
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the readv.
+ */
+
+ if (ciptr->priv)
+ {
+ return NXTransReadVector(ciptr->fd, buf, size);
+ }
+ else
+ {
+ return READV (ciptr, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ return READV (ciptr, buf, size);
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ /*
+ * If we have a valid priv pointer then this
+ * is an internal connection to the proxy.
+ * In this case we should emulate the writev.
+ */
+
+ if (ciptr->priv)
+ {
+ return NXTransWriteVector(ciptr->fd, buf, size);
+ }
+ else
+ {
+ return WRITEV (ciptr, buf, size);
+ }
+
+#else /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+
+ return WRITEV (ciptr, buf, size);
+
+#endif /* #if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT) */
+}
+
+
+static int
+TRANS(SocketDisconnect) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = shutdown (ciptr->fd, 2);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
+#endif
+}
+
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETClose) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = close (ciptr->fd);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return close (ciptr->fd);
+#endif
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static int
+TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
+
+{
+ /*
+ * If this is the server side, then once the socket is closed,
+ * it must be unlinked to completely close it
+ */
+
+ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
+ int ret;
+
+ PRMSG (2,"SocketUNIXClose(%x,%d)\n", ciptr, ciptr->fd, 0);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ TRANS(SocketCloseConnInfo) (ciptr);
+ }
+
+#endif
+
+ ret = close(ciptr->fd);
+
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ fprintf(stderr, "SocketUNIXClose: Flags are [%d] for ciptr at [%p] check is [%d].\n",
+ ciptr->flags, (void *) ciptr, (ciptr->flags && sockname
+ && sockname->sun_family == AF_UNIX && sockname->sun_path[0]));
+#endif
+
+ if (ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0])
+ {
+#if defined(NX_TRANS_SOCKET) && defined(NX_TRANS_TEST)
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ {
+ fprintf(stderr, "SocketUNIXClose: Unlinking path [%s] for ciptr at [%p].\n",
+ sockname->sun_path, (void *) ciptr);
+ unlink (sockname->sun_path);
+ }
+#else
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ unlink (sockname->sun_path);
+#endif
+ }
+
+ return ret;
+}
+
+static int
+TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
+
+{
+ /*
+ * Don't unlink path.
+ */
+
+ int ret;
+
+ PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
+ ciptr, ciptr->fd, 0);
+
+#if defined(NX_TRANS_SOCKET) && defined(TRANS_CLIENT)
+
+ if (ciptr->priv)
+ {
+ TRANS(SocketCloseConnInfo) (ciptr);
+ }
+
+#endif
+
+ ret = close(ciptr->fd);
+
+ return ret;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+# ifdef TRANS_SERVER
+static char* tcp_nolisten[] = {
+ "inet",
+#if defined(IPv6) && defined(AF_INET6)
+ "inet6",
+#endif
+ NULL
+};
+# endif
+
+Xtransport TRANS(SocketTCPFuncs) = {
+ /* Socket Interface */
+ "tcp",
+ TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ tcp_nolisten,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+Xtransport TRANS(SocketINETFuncs) = {
+ /* Socket Interface */
+ "inet",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+#if defined(IPv6) && defined(AF_INET6)
+Xtransport TRANS(SocketINET6Funcs) = {
+ /* Socket Interface */
+ "inet6",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+#endif /* IPv6 */
+#endif /* TCPCONN */
+
+#ifdef UNIXCONN
+#if !defined(LOCALCONN)
+Xtransport TRANS(SocketLocalFuncs) = {
+ /* Socket Interface */
+ "local",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+#endif /* !LOCALCONN */
+# ifdef TRANS_SERVER
+# if !defined(LOCALCONN)
+static char* unix_nolisten[] = { "local" , NULL };
+# endif
+# endif
+
+Xtransport TRANS(SocketUNIXFuncs) = {
+ /* Socket Interface */
+ "unix",
+#if !defined(LOCALCONN)
+ TRANS_ALIAS,
+#else
+ 0,
+#endif
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+#if !defined(LOCALCONN)
+ unix_nolisten,
+#else
+ NULL,
+#endif
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+
+#endif /* UNIXCONN */
diff --git a/nx-X11/lib/xtrans/Xtranssock.c.X.original b/nx-X11/lib/xtrans/Xtranssock.c.X.original
new file mode 100644
index 000000000..0f3c6b46a
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtranssock.c.X.original
@@ -0,0 +1,2504 @@
+/* $XdotOrg: xc/lib/xtrans/Xtranssock.c,v 1.11 2005/11/08 06:33:26 jkj Exp $ */
+/* $Xorg: Xtranssock.c,v 1.11 2001/02/09 02:04:06 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the copyright holders shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the copyright holders.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.68 2004/01/07 04:28:02 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <ctype.h>
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+
+#ifndef WIN32
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif
+
+#if defined(TCPCONN) || defined(UNIXCONN)
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_NO_LOCKING
+#include <X11/Xos_r.h>
+#endif
+
+#ifdef UNIXCONN
+#ifndef X_NO_SYS_UN
+#ifndef Lynx
+#include <sys/un.h>
+#else
+#include <un.h>
+#endif
+#endif
+#include <sys/stat.h>
+#endif
+
+#if defined(hpux) || (defined(MOTOROLA) && defined(SYSV))
+#define NO_TCP_H
+#endif
+
+#ifndef NO_TCP_H
+#if defined(__osf__) || defined(linux) || defined(__GLIBC__) || defined(AIXV5)
+#include <sys/param.h>
+#endif /* osf */
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
+#include <sys/param.h>
+#include <machine/endian.h>
+#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ || __DragonFly__ */
+#include <netinet/tcp.h>
+#endif /* !NO_TCP_H */
+
+#include <sys/ioctl.h>
+#if defined(SVR4) && !defined(DGUX) && !defined(_SEQUENT_)
+#include <sys/filio.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && !defined(SCO325) && !defined(sun)
+#include <net/errno.h>
+#endif
+
+#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_)
+#include <sys/stropts.h>
+#endif
+
+#else /* !WIN32 */
+
+#include <X11/Xwinsock.h>
+#include <X11/Xwindows.h>
+#include <X11/Xw32defs.h>
+#undef close
+#define close closesocket
+#define ECONNREFUSED WSAECONNREFUSED
+#define EADDRINUSE WSAEADDRINUSE
+#define EPROTOTYPE WSAEPROTOTYPE
+#undef EWOULDBLOCK
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define EINPROGRESS WSAEINPROGRESS
+#undef EINTR
+#define EINTR WSAEINTR
+#define X_INCLUDE_NETDB_H
+#define XOS_USE_MTSAFE_NETDBAPI
+#include <X11/Xos_r.h>
+#endif /* WIN32 */
+
+#if defined(SO_DONTLINGER) && defined(SO_LINGER)
+#undef SO_DONTLINGER
+#endif
+
+#if defined(__UNIXOS2__)
+#if defined(NOT_EMX09A)
+static int IBMsockInit = 0;
+#define SocketInitOnce()\
+ if (!IBMsockInit) {\
+ sock_init();\
+ IBMsockInit = 1;\
+ }
+#undef EINTR
+#define EINTR SOCEINTR
+#undef EINVAL
+#define EINVAL SOCEINVAL
+#undef errno
+#define errno sock_errno()
+#undef close
+#define close soclose
+#undef ioctl
+#define ioctl sockioctl
+#else
+#define SocketInitOnce() /**/
+#endif
+/* this is still not there */
+#define SOCKET int
+#else
+/* others don't need this */
+#define SocketInitOnce() /**/
+#endif
+
+#define MIN_BACKLOG 128
+#ifdef SOMAXCONN
+#if SOMAXCONN > MIN_BACKLOG
+#define BACKLOG SOMAXCONN
+#endif
+#endif
+#ifndef BACKLOG
+#define BACKLOG MIN_BACKLOG
+#endif
+/*
+ * This is the Socket implementation of the X Transport service layer
+ *
+ * This file contains the implementation for both the UNIX and INET domains,
+ * and can be built for either one, or both.
+ *
+ */
+
+typedef struct _Sockettrans2dev {
+ char *transname;
+ int family;
+ int devcotsname;
+ int devcltsname;
+ int protocol;
+} Sockettrans2dev;
+
+static Sockettrans2dev Sockettrans2devtab[] = {
+#ifdef TCPCONN
+ {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(IPv6) || !defined(AF_INET6)
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0},
+#else /* IPv6 */
+ {"tcp",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+ {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, /* fallback */
+ {"inet6",AF_INET6,SOCK_STREAM,SOCK_DGRAM,0},
+#endif
+#endif /* TCPCONN */
+#ifdef UNIXCONN
+ {"unix",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#if !defined(LOCALCONN)
+ {"local",AF_UNIX,SOCK_STREAM,SOCK_DGRAM,0},
+#endif /* !LOCALCONN */
+#endif /* UNIXCONN */
+};
+
+#define NUMSOCKETFAMILIES (sizeof(Sockettrans2devtab)/sizeof(Sockettrans2dev))
+
+#ifdef TCPCONN
+static int TRANS(SocketINETClose) (XtransConnInfo ciptr);
+#endif
+
+#ifdef UNIXCONN
+
+#ifdef hpux
+
+#if defined(X11_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#define OLD_UNIX_PATH "/tmp/.X11-unix/X"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/usr/spool/sockets/XIM/"
+#define UNIX_DIR "/usr/spool/sockets/XIM"
+#define OLD_UNIX_PATH "/tmp/.XIM-unix/XIM"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/usr/spool/sockets/fontserv/"
+#define UNIX_DIR "/usr/spool/sockets/fontserv"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/usr/spool/sockets/ICE/"
+#define UNIX_DIR "/usr/spool/sockets/ICE"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/usr/spool/sockets/xtrans_test/"
+#define UNIX_DIR "/usr/spool/sockets/xtrans_test"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/usr/spool/sockets/X11/"
+#define UNIX_DIR "/usr/spool/sockets/X11"
+#endif
+
+#else /* !hpux */
+
+#if defined(X11_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif /* X11_t */
+#if defined(XIM_t)
+#define UNIX_PATH "/tmp/.XIM-unix/XIM"
+#define UNIX_DIR "/tmp/.XIM-unix"
+#endif /* XIM_t */
+#if defined(FS_t) || defined(FONT_t)
+#define UNIX_PATH "/tmp/.font-unix/fs"
+#define UNIX_DIR "/tmp/.font-unix"
+#endif /* FS_t || FONT_t */
+#if defined(ICE_t)
+#define UNIX_PATH "/tmp/.ICE-unix/"
+#define UNIX_DIR "/tmp/.ICE-unix"
+#endif /* ICE_t */
+#if defined(TEST_t)
+#define UNIX_PATH "/tmp/.Test-unix/test"
+#define UNIX_DIR "/tmp/.Test-unix"
+#endif
+#if defined(LBXPROXY_t)
+#define UNIX_PATH "/tmp/.X11-unix/X"
+#define UNIX_DIR "/tmp/.X11-unix"
+#endif
+
+#endif /* hpux */
+
+#endif /* UNIXCONN */
+
+#define PORTBUFSIZE 32
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 255
+#endif
+
+/*
+ * This provides compatibility for apps linked against system libraries
+ * that don't have IPv6 support.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+static const struct in6_addr local_in6addr_any = IN6ADDR_ANY_INIT;
+#pragma weak in6addr_any = local_in6addr_any
+#ifndef __USLC__
+#pragma weak getaddrinfo
+#endif
+static int haveIPv6 = 1;
+#endif
+
+/*
+ * These are some utility function used by the real interface function below.
+ */
+
+static int
+TRANS(SocketSelectFamily) (int first, char *family)
+
+{
+ int i;
+
+ PRMSG (3,"SocketSelectFamily(%s)\n", family, 0, 0);
+
+ for (i = first + 1; i < NUMSOCKETFAMILIES;i++)
+ {
+ if (!strcmp (family, Sockettrans2devtab[i].transname))
+ return i;
+ }
+
+ return (first == -1 ? -2 : -1);
+}
+
+
+/*
+ * This function gets the local address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+ PRMSG (3,"SocketINETGetAddr(%p)\n", ciptr, 0, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ if (getsockname (ciptr->fd,(struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n",
+ EGET(),0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6)
+ {
+ ciptr->family = ((struct sockaddr *)socknamePtr)->sa_family;
+ }
+ else
+#endif
+ {
+ ciptr->family = socknamev4.sin_family;
+ }
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, socknamePtr, ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(SocketINETGetPeerAddr) (XtransConnInfo ciptr)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage socknamev6;
+#endif
+ struct sockaddr_in socknamev4;
+ void *socknamePtr;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen;
+#else
+ int namelen;
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && ciptr->family == AF_INET6)
+ {
+ namelen = sizeof(socknamev6);
+ socknamePtr = &socknamev6;
+ }
+ else
+#endif
+ {
+ namelen = sizeof(socknamev4);
+ socknamePtr = &socknamev4;
+ }
+
+ PRMSG (3,"SocketINETGetPeerAddr(%p)\n", ciptr, 0, 0);
+
+ if (getpeername (ciptr->fd, (struct sockaddr *) socknamePtr,
+ (void *)&namelen) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n",
+ EGET(), 0, 0);
+ return -1;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETGetPeerAddr: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->peeraddr, socknamePtr, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+static XtransConnInfo
+TRANS(SocketOpen) (int i, int type)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0);
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+
+ if (!haveIPv6 && Sockettrans2devtab[i].family == AF_INET6)
+ return NULL;
+#endif
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type,
+ Sockettrans2devtab[i].protocol)) < 0
+#ifndef WIN32
+#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t)
+ || ciptr->fd >= TRANS_OPEN_MAX
+#endif
+#endif
+ ) {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (2, "SocketOpen: socket() failed for %s\n",
+ Sockettrans2devtab[i].transname, 0, 0);
+
+ xfree ((char *) ciptr);
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (ciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopen) (int i, int type, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG (3,"SocketReopen(%d,%d,%s)\n", type, fd, port);
+
+ if ((ciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0);
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+/*
+ * These functions are the interface supplied in the Xtransport structure
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClientBase) (char *transname, char *protocol,
+ char *host, char *port, int previndex)
+{
+ XtransConnInfo ciptr;
+ int i = previndex;
+
+ PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n",
+ protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, transname)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSClient: Unable to open socket for %s\n",
+ transname, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSClient: Unable to determine socket type for %s\n",
+ transname, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+{
+ return TRANS(SocketOpenCOTSClientBase)(
+ thistrans->TransName, protocol, host, port, -1);
+}
+
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCOTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /*
+ * Using this prevents the bind() check for an existing server listening
+ * on the same port, but it is required for other reasons.
+ */
+#ifdef SO_REUSEADDR
+
+ /*
+ * SO_REUSEADDR only applied to AF_INET && AF_INET6
+ */
+
+ if (Sockettrans2devtab[i].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[i].family == AF_INET6
+#endif
+ )
+ {
+ int one = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR,
+ (char *) &one, sizeof (int));
+ }
+#endif
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSClient) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSClient: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSClient: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(SocketOpenCLTSServer) (Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketOpen) (
+ i, Sockettrans2devtab[i].devcotsname)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketOpenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketOpenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+#ifdef IPV6_V6ONLY
+ if (Sockettrans2devtab[i].family == AF_INET6)
+ {
+ int one = 1;
+ setsockopt(ciptr->fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(int));
+ }
+#endif
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(SocketReopenCOTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCOTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCOTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+static XtransConnInfo
+TRANS(SocketReopenCLTSServer) (Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i = -1;
+
+ PRMSG (2,
+ "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0);
+
+ SocketInitOnce();
+
+ while ((i = TRANS(SocketSelectFamily) (i, thistrans->TransName)) >= 0) {
+ if ((ciptr = TRANS(SocketReopen) (
+ i, Sockettrans2devtab[i].devcotsname, fd, port)) != NULL)
+ break;
+ }
+ if (i < 0) {
+ if (i == -1)
+ PRMSG (1,"SocketReopenCLTSServer: Unable to open socket for %s\n",
+ thistrans->TransName, 0, 0);
+ else
+ PRMSG (1,"SocketReopenCLTSServer: Unable to determine socket type for %s\n",
+ thistrans->TransName, 0, 0);
+ return NULL;
+ }
+
+ /* Save the index for later use */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(SocketSetOption) (XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG (2,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg);
+
+ return -1;
+}
+
+#ifdef UNIXCONN
+static int
+set_sun_path(const char *port, const char *upath, char *path)
+{
+ struct sockaddr_un s;
+ int maxlen = sizeof(s.sun_path) - 1;
+
+ if (!port || !*port || !path)
+ return -1;
+
+ if (*port == '/') { /* a full pathname */
+ if (strlen(port) > maxlen)
+ return -1;
+ sprintf(path, "%s", port);
+ } else {
+ if (strlen(port) + strlen(upath) > maxlen)
+ return -1;
+ sprintf(path, "%s%s", upath, port);
+ }
+ return 0;
+}
+#endif
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(SocketCreateListener) (XtransConnInfo ciptr,
+ struct sockaddr *sockname,
+ int socknamelen, unsigned int flags)
+
+{
+ int namelen = socknamelen;
+ int fd = ciptr->fd;
+ int retry;
+
+ PRMSG (3, "SocketCreateListener(%x,%p)\n", ciptr, fd, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ )
+ retry = 20;
+ else
+ retry = 0;
+
+ while (bind (fd, (struct sockaddr *) sockname, namelen) < 0)
+ {
+ if (errno == EADDRINUSE) {
+ if (flags & ADDR_IN_USE_ALLOWED)
+ break;
+ else
+ return TRANS_ADDR_IN_USE;
+ }
+
+ if (retry-- == 0) {
+ PRMSG (1, "SocketCreateListener: failed to bind listener\n",
+ 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#ifdef SO_REUSEADDR
+ sleep (1);
+#else
+ sleep (10);
+#endif /* SO_REUSEDADDR */
+ }
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET
+#if defined(IPv6) && defined(AF_INET6)
+ || Sockettrans2devtab[ciptr->index].family == AF_INET6
+#endif
+ ) {
+#ifdef SO_DONTLINGER
+ setsockopt (fd, SOL_SOCKET, SO_DONTLINGER, (char *) NULL, 0);
+#else
+#ifdef SO_LINGER
+ {
+ static int linger[2] = { 0, 0 };
+ setsockopt (fd, SOL_SOCKET, SO_LINGER,
+ (char *) linger, sizeof (linger));
+ }
+#endif
+#endif
+}
+
+ if (listen (fd, BACKLOG) < 0)
+ {
+ PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0);
+ close (fd);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ /* Set a flag to indicate that this connection is a listener */
+
+ ciptr->flags = 1 | (ciptr->flags & TRANS_KEEPFLAGS);
+
+ return 0;
+}
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETCreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage sockname;
+#else
+ struct sockaddr_in sockname;
+#endif
+ unsigned short sport;
+ int namelen = sizeof(sockname);
+ int status;
+ long tmpport;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgetservbynameparams sparams;
+#endif
+ struct servent *servp;
+
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ /* fixup the server port address */
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf,"%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ if (port && *port)
+ {
+ /* Check to see if the port string is just a number (handles X11) */
+
+ if (!is_numeric (port))
+ {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: Unable to get service for %s\n",
+ port, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ /* we trust getservbyname to return a valid number */
+ sport = servp->s_port;
+ }
+ else
+ {
+ tmpport = strtol (port, (char**)NULL, 10);
+ /*
+ * check that somehow the port address isn't negative or in
+ * the range of reserved port addresses. This can happen and
+ * be very bad if the server is suid-root and the user does
+ * something (dumb) like `X :60049`.
+ */
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CREATE_LISTENER_FAILED;
+
+ sport = (unsigned short) tmpport;
+ }
+ }
+ else
+ sport = 0;
+
+ bzero(&sockname, sizeof(sockname));
+#if defined(IPv6) && defined(AF_INET6)
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ namelen = sizeof (struct sockaddr_in);
+#ifdef BSD44SOCKETS
+ ((struct sockaddr_in *)&sockname)->sin_len = namelen;
+#endif
+ ((struct sockaddr_in *)&sockname)->sin_family = AF_INET;
+ ((struct sockaddr_in *)&sockname)->sin_port = htons(sport);
+ ((struct sockaddr_in *)&sockname)->sin_addr.s_addr = htonl(INADDR_ANY);
+ } else {
+ namelen = sizeof (struct sockaddr_in6);
+#ifdef SIN6_LEN
+ ((struct sockaddr_in6 *)&sockname)->sin6_len = sizeof(sockname);
+#endif
+ ((struct sockaddr_in6 *)&sockname)->sin6_family = AF_INET6;
+ ((struct sockaddr_in6 *)&sockname)->sin6_port = htons(sport);
+ ((struct sockaddr_in6 *)&sockname)->sin6_addr = in6addr_any;
+ }
+#else
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (sockname);
+#endif
+ sockname.sin_family = AF_INET;
+ sockname.sin_port = htons (sport);
+ sockname.sin_addr.s_addr = htonl (INADDR_ANY);
+#endif
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ return status;
+ }
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETCreateListener: ...SocketINETGetAddr() failed\n",
+ 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ return 0;
+}
+
+#endif /* SOCKCONN */
+
+
+#ifdef UNIXCONN
+
+static int
+TRANS(SocketUNIXCreateListener) (XtransConnInfo ciptr, char *port,
+ unsigned int flags)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+ int oldUmask;
+ int status;
+ unsigned int mode;
+
+ PRMSG (2, "SocketUNIXCreateListener(%s)\n",
+ port ? port : "NULL", 0, 0);
+
+ /* Make sure the directory is created */
+
+ oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXCreateListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+#endif
+
+ sockname.sun_family = AF_UNIX;
+
+ if (port && *port) {
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXCreateListener: path too long\n", 0, 0, 0);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
+ sprintf (sockname.sun_path, "%s%ld", UNIX_PATH, (long)getpid());
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen(sockname.sun_path);
+ namelen = SUN_LEN(&sockname);
+#else
+ namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family);
+#endif
+
+ unlink (sockname.sun_path);
+
+ if ((status = TRANS(SocketCreateListener) (ciptr,
+ (struct sockaddr *) &sockname, namelen, flags)) < 0)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: ...SocketCreateListener() failed\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return status;
+ }
+
+ /*
+ * Now that the listener is esablished, create the addr info for
+ * this connection. getpeername() doesn't work for UNIX Domain Sockets
+ * on some systems (hpux at least), so we will just do it manually, instead
+ * of calling something like TRANS(SocketUNIXGetAddr).
+ */
+
+ namelen = sizeof (sockname); /* this will always make it the same size */
+
+ if ((ciptr->addr = (char *) xalloc (namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ (void) umask (oldUmask);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ ciptr->family = sockname.sun_family;
+ ciptr->addrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+
+ (void) umask (oldUmask);
+
+ return 0;
+}
+
+
+static int
+TRANS(SocketUNIXResetListener) (XtransConnInfo ciptr)
+
+{
+ /*
+ * See if the unix domain socket has disappeared. If it has, recreate it.
+ */
+
+ struct sockaddr_un *unsock = (struct sockaddr_un *) ciptr->addr;
+ struct stat statb;
+ int status = TRANS_RESET_NOOP;
+ unsigned int mode;
+
+ PRMSG (3, "SocketUNIXResetListener(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if (stat (unsock->sun_path, &statb) == -1 ||
+ ((statb.st_mode & S_IFMT) !=
+#if (defined (sun) && defined(SVR4)) || defined(NCR) || defined(SCO325) || !defined(S_IFSOCK)
+ S_IFIFO))
+#else
+ S_IFSOCK))
+#endif
+ {
+ int oldUmask = umask (0);
+
+#ifdef UNIX_DIR
+#ifdef HAS_STICKY_DIR_BIT
+ mode = 01777;
+#else
+ mode = 0777;
+#endif
+ if (trans_mkdir(UNIX_DIR, mode) == -1) {
+ PRMSG (1, "SocketUNIXResetListener: mkdir(%s) failed, errno = %d\n",
+ UNIX_DIR, errno, 0);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+#endif
+
+ close (ciptr->fd);
+ unlink (unsock->sun_path);
+
+ if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+ {
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (bind (ciptr->fd, (struct sockaddr *) unsock, ciptr->addrlen) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ return TRANS_RESET_FAILURE;
+ }
+
+ if (listen (ciptr->fd, BACKLOG) < 0)
+ {
+ close (ciptr->fd);
+ TRANS(FreeConnInfo) (ciptr);
+ (void) umask (oldUmask);
+ return TRANS_RESET_FAILURE;
+ }
+
+ umask (oldUmask);
+
+ status = TRANS_RESET_NEW_FD;
+ }
+
+ return status;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+
+static XtransConnInfo
+TRANS(SocketINETAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_in sockname;
+ int namelen = sizeof(sockname);
+
+ PRMSG (2, "SocketINETAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+#ifdef TCP_NODELAY
+ {
+ /*
+ * turn off TCP coalescence for INET sockets
+ */
+
+ int tmp = 1;
+ setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char *) &tmp, sizeof (int));
+ }
+#endif
+
+ /*
+ * Get this address again because the transport may give a more
+ * specific address now that a connection is established.
+ */
+
+ if (TRANS(SocketINETGetAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static XtransConnInfo
+TRANS(SocketUNIXAccept) (XtransConnInfo ciptr, int *status)
+
+{
+ XtransConnInfo newciptr;
+ struct sockaddr_un sockname;
+#if defined(SVR4) || defined(__SCO__)
+ size_t namelen = sizeof sockname;
+#else
+ int namelen = sizeof sockname;
+#endif
+
+ PRMSG (2, "SocketUNIXAccept(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ if ((newciptr = (XtransConnInfo) xcalloc (
+ 1, sizeof(struct _XtransConnInfo))) == NULL)
+ {
+ PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if ((newciptr->fd = accept (ciptr->fd,
+ (struct sockaddr *) &sockname, (void *)&namelen)) < 0)
+ {
+ PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ /*
+ * Get the socket name and the peer name from the listener socket,
+ * since this is unix domain.
+ */
+
+ if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+
+ newciptr->addrlen = ciptr->addrlen;
+ memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen);
+
+ if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXAccept: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ close (newciptr->fd);
+ if (newciptr->addr) xfree (newciptr->addr);
+ xfree (newciptr);
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ newciptr->peeraddrlen = ciptr->addrlen;
+ memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen);
+
+ newciptr->family = AF_UNIX;
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+#ifdef TCPCONN
+
+#if defined(IPv6) && defined(AF_INET6)
+struct addrlist {
+ struct addrinfo * addr;
+ struct addrinfo * firstaddr;
+ char port[PORTBUFSIZE];
+ char host[MAXHOSTNAMELEN];
+};
+static struct addrlist *addrlist = NULL;
+#endif
+
+
+static int
+TRANS(SocketINETConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr * socketaddr = NULL;
+ int socketaddrlen = 0;
+ int res;
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo hints;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ int resetonce = 0;
+#endif
+ struct sockaddr_in sockname;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+ _Xgetservbynameparams sparams;
+#endif
+ struct hostent *hostp;
+ struct servent *servp;
+ unsigned long tmpaddr;
+#ifdef X11_t
+ char portbuf[PORTBUFSIZE];
+#endif
+
+ long tmpport;
+ char hostnamebuf[256]; /* tmp space */
+
+ PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ if (!host)
+ {
+ hostnamebuf[0] = '\0';
+ (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+ host = hostnamebuf;
+ }
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf (portbuf, "%lu", tmpport);
+ port = portbuf;
+ }
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6) {
+ if (addrlist != NULL) {
+ if (strcmp(host,addrlist->host) || strcmp(port,addrlist->port)) {
+ if (addrlist->firstaddr)
+ freeaddrinfo(addrlist->firstaddr);
+ addrlist->firstaddr = NULL;
+ }
+ } else {
+ addrlist = malloc(sizeof(struct addrlist));
+ addrlist->firstaddr = NULL;
+ }
+
+ if (addrlist->firstaddr == NULL) {
+ strncpy(addrlist->port, port, sizeof(addrlist->port));
+ addrlist->port[sizeof(addrlist->port) - 1] = '\0';
+ strncpy(addrlist->host, host, sizeof(addrlist->host));
+ addrlist->host[sizeof(addrlist->host) - 1] = '\0';
+
+ bzero(&hints,sizeof(hints));
+ hints.ai_socktype = Sockettrans2devtab[ciptr->index].devcotsname;
+
+ res = getaddrinfo(host,port,&hints,&addrlist->firstaddr);
+ if (res != 0) {
+ PRMSG (1, "SocketINETConnect() can't get address "
+ "for %s:%s: %s\n", host, port, gai_strerror(res));
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ for (res = 0, addrlist->addr = addrlist->firstaddr;
+ addrlist->addr ; res++) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ PRMSG(4,"Got New Address list with %d addresses\n", res, 0, 0);
+ res = 0;
+ addrlist->addr = NULL;
+ }
+
+ while (socketaddr == NULL) {
+ if (addrlist->addr == NULL) {
+ if (resetonce) {
+ /* Already checked entire list - no usable addresses */
+ PRMSG (1, "SocketINETConnect() no usable address "
+ "for %s:%s\n", host, port, 0);
+ return TRANS_CONNECT_FAILED;
+ } else {
+ /* Go back to beginning of list */
+ resetonce = 1;
+ addrlist->addr = addrlist->firstaddr;
+ }
+ }
+
+ socketaddr = addrlist->addr->ai_addr;
+ socketaddrlen = addrlist->addr->ai_addrlen;
+
+ if (addrlist->addr->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,&sin->sin_addr,
+ ntopbuf,sizeof(ntopbuf)), 0, 0);
+
+ PRMSG (4,"SocketINETConnect() sockname.sin_port = %d\n",
+ ntohs(sin->sin_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET6) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Our socket is an IPv6 socket, but the address is
+ * IPv4. Close it and get an IPv4 socket. This is
+ * needed for IPv4 connections to work on platforms
+ * that don't allow IPv4 over IPv6 sockets.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, ciptr->index);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv4 "
+ " socketfor IPv4 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ } else {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect Skipping IPv4 address\n",
+ 0,0,0);
+ }
+ }
+ } else if (addrlist->addr->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) socketaddr;
+
+ PRMSG (4,"SocketINETConnect() sockname.sin6_addr = %s\n",
+ inet_ntop(addrlist->addr->ai_family,
+ &sin6->sin6_addr,ntopbuf,sizeof(ntopbuf)),
+ 0, 0);
+ PRMSG (4,"SocketINETConnect() sockname.sin6_port = %d\n",
+ ntohs(sin6->sin6_port), 0, 0);
+
+ if (Sockettrans2devtab[ciptr->index].family == AF_INET) {
+ if (strcmp(Sockettrans2devtab[ciptr->index].transname,
+ "tcp") == 0) {
+ XtransConnInfo newciptr;
+
+ /*
+ * Close the IPv4 socket and try to open an IPv6 socket.
+ */
+ TRANS(SocketINETClose)(ciptr);
+ newciptr = TRANS(SocketOpenCOTSClientBase)(
+ "tcp", "tcp", host, port, -1);
+ if (newciptr)
+ ciptr->fd = newciptr->fd;
+ if (!newciptr ||
+ Sockettrans2devtab[newciptr->index].family !=
+ AF_INET6) {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Cannot get IPv6 "
+ "socket for IPv6 address\n", 0,0,0);
+ }
+ if (newciptr)
+ xfree(newciptr);
+ }
+ else
+ {
+ socketaddr = NULL;
+ PRMSG (4,"SocketINETConnect() Skipping IPv6 address\n",
+ 0,0,0);
+ }
+ }
+ } else {
+ socketaddr = NULL; /* Unsupported address type */
+ }
+ if (socketaddr == NULL) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+ }
+ } else
+#endif
+ {
+ /*
+ * Build the socket name.
+ */
+
+#ifdef BSD44SOCKETS
+ sockname.sin_len = sizeof (struct sockaddr_in);
+#endif
+ sockname.sin_family = AF_INET;
+
+ /*
+ * fill in sin_addr
+ */
+
+#ifndef INADDR_NONE
+#define INADDR_NONE ((in_addr_t) 0xffffffff)
+#endif
+
+ /* check for ww.xx.yy.zz host string */
+
+ if (isascii (host[0]) && isdigit (host[0])) {
+ tmpaddr = inet_addr (host); /* returns network byte order */
+ } else {
+ tmpaddr = INADDR_NONE;
+ }
+
+ PRMSG (4,"SocketINETConnect() inet_addr(%s) = %x\n", host, tmpaddr, 0);
+
+ if (tmpaddr == INADDR_NONE) {
+ if ((hostp = _XGethostbyname(host,hparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: Can't get address for %s\n",
+ host, 0, 0);
+ ESET(EINVAL);
+ return TRANS_CONNECT_FAILED;
+ }
+ if (hostp->h_addrtype != AF_INET) { /* is IP host? */
+ PRMSG (1,"SocketINETConnect: not INET host%s\n", host, 0, 0);
+ ESET(EPROTOTYPE);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ {
+ long t;
+ memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t));
+ sockname.sin_addr = t;
+ }
+#else
+ memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr,
+ sizeof (sockname.sin_addr));
+#endif /* CRAY and OLDTCP */
+
+ } else {
+#if defined(CRAY) && defined(OLDTCP)
+ /* Only Cray UNICOS3 and UNICOS4 will define this */
+ sockname.sin_addr = tmpaddr;
+#else
+ sockname.sin_addr.s_addr = tmpaddr;
+#endif /* CRAY and OLDTCP */
+ }
+
+ /*
+ * fill in sin_port
+ */
+
+ /* Check for number in the port string */
+
+ if (!is_numeric (port)) {
+ if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) {
+ PRMSG (1,"SocketINETConnect: can't get service for %s\n",
+ port, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ sockname.sin_port = htons (servp->s_port);
+ } else {
+ tmpport = strtol (port, (char**)NULL, 10);
+ if (tmpport < 1024 || tmpport > USHRT_MAX)
+ return TRANS_CONNECT_FAILED;
+ sockname.sin_port = htons (((unsigned short) tmpport));
+ }
+
+ PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n",
+ ntohs(sockname.sin_port), 0, 0);
+ socketaddr = (struct sockaddr *) &sockname;
+ socketaddrlen = sizeof(sockname);
+ }
+
+ /*
+ * Turn on socket keepalive so the client process will eventually
+ * be notified with a SIGPIPE signal if the display server fails
+ * to respond to a periodic transmission of messages
+ * on the connected socket.
+ * This is useful to avoid hung application processes when the
+ * processes are not spawned from the xdm session and
+ * the display server terminates abnormally.
+ * (Someone turned off the power switch.)
+ */
+
+ {
+ int tmp = 1;
+ setsockopt (ciptr->fd, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) &tmp, sizeof (int));
+ }
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, socketaddr, socketaddrlen ) < 0)
+ {
+#ifdef WIN32
+ int olderrno = WSAGetLastError();
+#else
+ int olderrno = errno;
+#endif
+
+ /*
+ * If the error was ECONNREFUSED, the server may be overloaded
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ *
+ * If multiple addresses are found for a host then we should
+ * try to connect again with a different address for a larger
+ * number of errors that made us quit before, since those
+ * could be caused by trying to use an IPv6 address to contact
+ * a machine with an IPv4-only server or other reasons that
+ * only affect one of a set of addresses.
+ */
+
+ if (olderrno == ECONNREFUSED || olderrno == EINTR
+#if defined(IPv6) && defined(AF_INET6)
+ || (haveIPv6 && ((addrlist->addr->ai_next != NULL) ||
+ (addrlist->addr != addrlist->firstaddr)) &&
+ (olderrno == ENETUNREACH || olderrno == EAFNOSUPPORT ||
+ olderrno == EADDRNOTAVAIL || olderrno == ETIMEDOUT
+#if defined(EHOSTDOWN)
+ || olderrno == EHOSTDOWN
+#endif
+ ))
+#endif
+ )
+ res = TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ res = TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketINETConnect: Can't connect: errno = %d\n",
+ olderrno,0, 0);
+
+ res = TRANS_CONNECT_FAILED;
+ }
+ } else {
+ res = 0;
+
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if (TRANS(SocketINETGetAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+
+ else if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0)
+ {
+ PRMSG (1,
+ "SocketINETConnect: ...SocketINETGetPeerAddr() failed:\n",
+ 0, 0, 0);
+ res = TRANS_CONNECT_FAILED;
+ }
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (haveIPv6 && res != 0) {
+ addrlist->addr = addrlist->addr->ai_next;
+ }
+#endif
+
+ return res;
+}
+
+#endif /* TCPCONN */
+
+
+
+#ifdef UNIXCONN
+
+/*
+ * Make sure 'host' is really local.
+ */
+
+static int
+UnixHostReallyLocal (char *host)
+
+{
+ char hostnamebuf[256];
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (getaddrinfo == NULL)
+ haveIPv6 = 0;
+#endif
+
+ TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf));
+
+ if (strcmp (hostnamebuf, host) == 0)
+ {
+ return (1);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (haveIPv6)
+ {
+ struct addrinfo *localhostaddr;
+ struct addrinfo *otherhostaddr;
+ struct addrinfo *i, *j;
+ int equiv = 0;
+
+ if (getaddrinfo(hostnamebuf, NULL, NULL, &localhostaddr) != 0)
+ return 0;
+ if (getaddrinfo(host, NULL, NULL, &otherhostaddr) != 0) {
+ freeaddrinfo(localhostaddr);
+ return 0;
+ }
+
+ for (i = localhostaddr; i != NULL && equiv == 0; i = i->ai_next) {
+ for (j = otherhostaddr; j != NULL && equiv == 0; j = j->ai_next) {
+ if (i->ai_family == j->ai_family) {
+ if (i->ai_family == AF_INET) {
+ struct sockaddr_in *sinA
+ = (struct sockaddr_in *) i->ai_addr;
+ struct sockaddr_in *sinB
+ = (struct sockaddr_in *) j->ai_addr;
+ struct in_addr *A = &sinA->sin_addr;
+ struct in_addr *B = &sinB->sin_addr;
+
+ if (memcmp(A,B,sizeof(struct in_addr)) == 0) {
+ equiv = 1;
+ }
+ } else if (i->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sinA
+ = (struct sockaddr_in6 *) i->ai_addr;
+ struct sockaddr_in6 *sinB
+ = (struct sockaddr_in6 *) j->ai_addr;
+ struct in6_addr *A = &sinA->sin6_addr;
+ struct in6_addr *B = &sinB->sin6_addr;
+
+ if (memcmp(A,B,sizeof(struct in6_addr)) == 0) {
+ equiv = 1;
+ }
+ }
+ }
+ }
+ }
+
+ freeaddrinfo(localhostaddr);
+ freeaddrinfo(otherhostaddr);
+ return equiv;
+ }
+#endif
+ else
+ {
+ /*
+ * A host may have more than one network address. If any of the
+ * network addresses of 'host' (specified to the connect call)
+ * match any of the network addresses of 'hostname' (determined
+ * by TRANS(GetHostname)), then the two hostnames are equivalent,
+ * and we know that 'host' is really a local host.
+ */
+ char specified_local_addr_list[10][4];
+ int scount, equiv, i, j;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ struct hostent *hostp;
+
+ if ((hostp = _XGethostbyname (host,hparams)) == NULL)
+ return (0);
+
+ scount = 0;
+ while (hostp->h_addr_list[scount] && scount <= 8)
+ {
+ /*
+ * The 2nd call to gethostname() overrides the data
+ * from the 1st call, so we must save the address list.
+ */
+
+ specified_local_addr_list[scount][0] =
+ hostp->h_addr_list[scount][0];
+ specified_local_addr_list[scount][1] =
+ hostp->h_addr_list[scount][1];
+ specified_local_addr_list[scount][2] =
+ hostp->h_addr_list[scount][2];
+ specified_local_addr_list[scount][3] =
+ hostp->h_addr_list[scount][3];
+ scount++;
+ }
+ if ((hostp = _XGethostbyname (hostnamebuf,hparams)) == NULL)
+ return (0);
+
+ equiv = 0;
+ i = 0;
+
+ while (i < scount && !equiv)
+ {
+ j = 0;
+
+ while (hostp->h_addr_list[j])
+ {
+ if ((specified_local_addr_list[i][0] ==
+ hostp->h_addr_list[j][0]) &&
+ (specified_local_addr_list[i][1] ==
+ hostp->h_addr_list[j][1]) &&
+ (specified_local_addr_list[i][2] ==
+ hostp->h_addr_list[j][2]) &&
+ (specified_local_addr_list[i][3] ==
+ hostp->h_addr_list[j][3]))
+ {
+ /* They're equal, so we're done */
+
+ equiv = 1;
+ break;
+ }
+
+ j++;
+ }
+
+ i++;
+ }
+ return (equiv);
+ }
+}
+
+static int
+TRANS(SocketUNIXConnect) (XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct sockaddr_un sockname;
+ int namelen;
+
+#if defined(hpux) && defined(X11_t)
+ struct sockaddr_un old_sockname;
+ int old_namelen;
+#endif
+
+
+ PRMSG (2,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port);
+
+ /*
+ * Make sure 'host' is really local. If not, we return failure.
+ * The reason we make this check is because a process may advertise
+ * a "local" network ID for which it can accept connections, but if
+ * a process on a remote machine tries to connect to this network ID,
+ * we know for sure it will fail.
+ */
+
+ if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host))
+ {
+ PRMSG (1,
+ "SocketUNIXConnect: Cannot connect to non-local host %s\n",
+ host, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+
+ /*
+ * Check the port.
+ */
+
+ if (!port || !*port)
+ {
+ PRMSG (1,"SocketUNIXConnect: Missing port specification\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ /*
+ * Build the socket name.
+ */
+
+ sockname.sun_family = AF_UNIX;
+
+ if (set_sun_path(port, UNIX_PATH, sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+#if (defined(BSD44SOCKETS) || defined(__UNIXWARE__)) && !defined(Lynx)
+ sockname.sun_len = strlen (sockname.sun_path);
+ namelen = SUN_LEN (&sockname);
+#else
+ namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family);
+#endif
+
+
+#if defined(hpux) && defined(X11_t)
+ /*
+ * This is gross, but it was in Xlib
+ */
+ old_sockname.sun_family = AF_UNIX;
+ if (set_sun_path(port, OLD_UNIX_PATH, old_sockname.sun_path) != 0) {
+ PRMSG (1, "SocketUNIXConnect: path too long\n", 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+ old_namelen = strlen (old_sockname.sun_path) +
+ sizeof (old_sockname.sun_family);
+#endif
+
+
+ /*
+ * Do the connect()
+ */
+
+ if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0)
+ {
+ int olderrno = errno;
+ int connected = 0;
+
+#if defined(hpux) && defined(X11_t)
+ if (olderrno == ENOENT)
+ {
+ if (connect (ciptr->fd,
+ (struct sockaddr *) &old_sockname, old_namelen) >= 0)
+ {
+ connected = 1;
+ }
+ else
+ olderrno = errno;
+ }
+#endif
+ if (!connected)
+ {
+ errno = olderrno;
+
+ /*
+ * If the error was ENOENT, the server may be starting up
+ * and we should try again.
+ *
+ * If the error was EWOULDBLOCK or EINPROGRESS then the socket
+ * was non-blocking and we should poll using select
+ *
+ * If the error was EINTR, the connect was interrupted and we
+ * should try again.
+ */
+
+ if (olderrno == ENOENT || olderrno == EINTR)
+ return TRANS_TRY_CONNECT_AGAIN;
+ else if (olderrno == EWOULDBLOCK || olderrno == EINPROGRESS)
+ return TRANS_IN_PROGRESS;
+ else
+ {
+ PRMSG (2,"SocketUNIXConnect: Can't connect: errno = %d\n",
+ EGET(),0, 0);
+
+ return TRANS_CONNECT_FAILED;
+ }
+ }
+ }
+
+ /*
+ * Get the socket name and the peer name from the connect socket,
+ * since this is unix domain.
+ */
+
+ if ((ciptr->addr = (char *) xalloc(namelen)) == NULL ||
+ (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL)
+ {
+ PRMSG (1,
+ "SocketUNIXCreateListener: Can't allocate space for the addr\n",
+ 0, 0, 0);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ ciptr->family = AF_UNIX;
+ ciptr->addrlen = namelen;
+ ciptr->peeraddrlen = namelen;
+ memcpy (ciptr->addr, &sockname, ciptr->addrlen);
+ memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen);
+
+ return 0;
+}
+
+#endif /* UNIXCONN */
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(SocketBytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ PRMSG (2,"SocketBytesReadable(%p,%d,%p)\n",
+ ciptr, ciptr->fd, pend);
+#if defined(QNX4)
+ *pend = 0L; /* FIONREAD only returns a short. Zero out upper bits */
+#endif
+#ifdef WIN32
+ {
+ int ret = ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+#if (defined(i386) && defined(SYSV) && !defined(SCO325)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1)
+ return ioctl (ciptr->fd, I_NREAD, (char *) pend);
+#else
+#if defined(__UNIXOS2__)
+ return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int));
+#else
+ return ioctl (ciptr->fd, FIONREAD, (char *) pend);
+#endif /* __UNIXOS2__ */
+#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(SocketRead) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketRead(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = recv ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return read (ciptr->fd, buf, size);
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(SocketWrite) (XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG (2,"SocketWrite(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+#if defined(WIN32) || defined(__UNIXOS2__)
+ {
+ int ret = send ((SOCKET)ciptr->fd, buf, size, 0);
+#ifdef WIN32
+ errno = WSAGetLastError();
+#endif
+ return ret;
+ }
+#else
+ return write (ciptr->fd, buf, size);
+#endif /* WIN32 */
+}
+
+
+static int
+TRANS(SocketReadv) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketReadv(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+ return READV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(SocketWritev) (XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG (2,"SocketWritev(%d,%p,%d)\n", ciptr->fd, buf, size);
+
+ return WRITEV (ciptr, buf, size);
+}
+
+
+static int
+TRANS(SocketDisconnect) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketDisconnect(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = shutdown (ciptr->fd, 2);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return shutdown (ciptr->fd, 2); /* disallow further sends and receives */
+#endif
+}
+
+
+#ifdef TCPCONN
+static int
+TRANS(SocketINETClose) (XtransConnInfo ciptr)
+
+{
+ PRMSG (2,"SocketINETClose(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+#ifdef WIN32
+ {
+ int ret = close (ciptr->fd);
+ errno = WSAGetLastError();
+ return ret;
+ }
+#else
+ return close (ciptr->fd);
+#endif
+}
+
+#endif /* TCPCONN */
+
+
+#ifdef UNIXCONN
+static int
+TRANS(SocketUNIXClose) (XtransConnInfo ciptr)
+
+{
+ /*
+ * If this is the server side, then once the socket is closed,
+ * it must be unlinked to completely close it
+ */
+
+ struct sockaddr_un *sockname = (struct sockaddr_un *) ciptr->addr;
+ int ret;
+
+ PRMSG (2,"SocketUNIXClose(%p,%d)\n", ciptr, ciptr->fd, 0);
+
+ ret = close(ciptr->fd);
+
+ if (ciptr->flags
+ && sockname
+ && sockname->sun_family == AF_UNIX
+ && sockname->sun_path[0])
+ {
+ if (!(ciptr->flags & TRANS_NOUNLINK))
+ unlink (sockname->sun_path);
+ }
+
+ return ret;
+}
+
+static int
+TRANS(SocketUNIXCloseForCloning) (XtransConnInfo ciptr)
+
+{
+ /*
+ * Don't unlink path.
+ */
+
+ int ret;
+
+ PRMSG (2,"SocketUNIXCloseForCloning(%p,%d)\n",
+ ciptr, ciptr->fd, 0);
+
+ ret = close(ciptr->fd);
+
+ return ret;
+}
+
+#endif /* UNIXCONN */
+
+
+#ifdef TCPCONN
+# ifdef TRANS_SERVER
+static char* tcp_nolisten[] = {
+ "inet",
+#if defined(IPv6) && defined(AF_INET6)
+ "inet6",
+#endif
+ NULL
+};
+# endif
+
+Xtransport TRANS(SocketTCPFuncs) = {
+ /* Socket Interface */
+ "tcp",
+ TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ tcp_nolisten,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+Xtransport TRANS(SocketINETFuncs) = {
+ /* Socket Interface */
+ "inet",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+
+#if defined(IPv6) && defined(AF_INET6)
+Xtransport TRANS(SocketINET6Funcs) = {
+ /* Socket Interface */
+ "inet6",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(SocketINETAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketINETClose),
+ TRANS(SocketINETClose),
+ };
+#endif /* IPv6 */
+#endif /* TCPCONN */
+
+#ifdef UNIXCONN
+#if !defined(LOCALCONN)
+Xtransport TRANS(SocketLocalFuncs) = {
+ /* Socket Interface */
+ "local",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+#endif /* !LOCALCONN */
+# ifdef TRANS_SERVER
+# if !defined(LOCALCONN)
+static char* unix_nolisten[] = { "local" , NULL };
+# endif
+# endif
+
+Xtransport TRANS(SocketUNIXFuncs) = {
+ /* Socket Interface */
+ "unix",
+#if !defined(LOCALCONN)
+ TRANS_ALIAS,
+#else
+ 0,
+#endif
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+#if !defined(LOCALCONN)
+ unix_nolisten,
+#else
+ NULL,
+#endif
+ TRANS(SocketOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(SocketOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(SocketReopenCOTSServer),
+ TRANS(SocketReopenCLTSServer),
+#endif
+ TRANS(SocketSetOption),
+#ifdef TRANS_SERVER
+ TRANS(SocketUNIXCreateListener),
+ TRANS(SocketUNIXResetListener),
+ TRANS(SocketUNIXAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(SocketUNIXConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(SocketBytesReadable),
+ TRANS(SocketRead),
+ TRANS(SocketWrite),
+ TRANS(SocketReadv),
+ TRANS(SocketWritev),
+ TRANS(SocketDisconnect),
+ TRANS(SocketUNIXClose),
+ TRANS(SocketUNIXCloseForCloning),
+ };
+
+#endif /* UNIXCONN */
diff --git a/nx-X11/lib/xtrans/Xtranstli.c b/nx-X11/lib/xtrans/Xtranstli.c
new file mode 100644
index 000000000..d8b5db83b
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtranstli.c
@@ -0,0 +1,1422 @@
+/* $Xorg: Xtranstli.c,v 1.4 2001/02/09 02:04:07 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtranstli.c,v 3.12tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/un.h>
+#include <stropts.h>
+#include <poll.h>
+#include <tiuser.h>
+
+#include <netdir.h>
+#include <netconfig.h>
+
+
+/*
+ * This is the TLI implementation of the X Transport service layer
+ */
+
+typedef struct _TLItrans2dev {
+ char *transname;
+ char *protofamily;
+ char *devcotsname;
+ char *devcltsname;
+ int family;
+} TLItrans2dev;
+
+static TLItrans2dev TLItrans2devtab[] = {
+ {"inet","inet","/dev/tcp","/dev/udp",AF_INET},
+ {"tcp","inet","/dev/tcp","/dev/udp",AF_INET},
+ {"tli","loopback","/dev/ticots","/dev/ticlts",AF_UNIX},
+};
+
+#define NUMTLIFAMILIES (sizeof(TLItrans2devtab)/sizeof(TLItrans2dev))
+
+/*
+ * The local TLI connection, is a form of a local connection, so use a
+ * sockaddr_un for the address so that it will be treated just like the other
+ * local transports such as UNIX domain sockets, pts, and named.
+ */
+
+#if defined(X11_t)
+#define TLINODENAME "TLI:xserver"
+#endif
+
+#if defined(XIM_t)
+#define TLINODENAME "TLI:xim"
+#endif
+
+#if defined(FS_t) || defined(FONT_t)
+#define TLINODENAME "TLI:fontserver"
+#endif
+
+#if defined(ICE_t)
+#define TLINODENAME "TLI:ICE"
+#endif
+
+#if defined(TEST_t)
+#define TLINODENAME "TLI:test"
+#endif
+
+#ifndef PORTBUFSIZE
+#ifdef TRANS_SERVER
+#define PORTBUFSIZE 64
+#else
+#ifdef TRANS_CLIENT
+#define PORTBUFSIZE 64
+#endif
+#endif
+#endif
+
+
+/*
+ * These are some utility function used by the real interface function below.
+ */
+
+static int
+TRANS(TLISelectFamily)(char *family)
+
+{
+ int i;
+
+ PRMSG(3,"TLISelectFamily(%s)\n", family, 0,0 );
+
+ for(i=0;i<NUMTLIFAMILIES;i++)
+ {
+ if( !strcmp(family,TLItrans2devtab[i].transname) )
+ return i;
+ }
+ return -1;
+}
+
+
+/*
+ * This function gets the local address of the transport and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(TLIGetAddr)(XtransConnInfo ciptr)
+
+{
+ Xtransaddr sockname;
+ struct netbuf netbuf;
+
+ PRMSG(3,"TLIGetAddr(%x)\n", ciptr, 0,0 );
+
+ netbuf.buf=(char *)&sockname;
+ netbuf.len=sizeof(sockname);
+ netbuf.maxlen=sizeof(sockname);
+
+ if( t_getname(ciptr->fd,&netbuf,LOCALNAME) < 0 )
+ {
+ PRMSG(1,"TLIGetAddr: t_getname(LOCALNAME) failed: %d\n",
+ errno, 0,0 );
+ return -1;
+ }
+
+ PRMSG(4,"TLIGetAddr: got family %d len %d\n",
+ ((struct sockaddr *) &sockname)->sa_family ,netbuf.len, 0 );
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if( ciptr->addr )
+ xfree(ciptr->addr);
+
+ if( (ciptr->addr=(char *)xalloc(netbuf.len)) == NULL )
+ {
+ PRMSG(1, "TLIGetAddr: Can't allocate space for the addr\n",
+ 0,0,0);
+ return -1;
+ }
+
+ ciptr->family=((struct sockaddr *) &sockname)->sa_family;
+ ciptr->addrlen=netbuf.len;
+ memcpy(ciptr->addr,&sockname,ciptr->addrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function gets the remote address of the socket and stores it in the
+ * XtransConnInfo structure for the connection.
+ */
+
+static int
+TRANS(TLIGetPeerAddr)(XtransConnInfo ciptr)
+
+{
+ Xtransaddr sockname;
+ struct netbuf netbuf;
+
+ PRMSG(3,"TLIGetPeerAddr(%x)\n", ciptr, 0,0 );
+
+ netbuf.buf=(char *)&sockname;
+ netbuf.len=sizeof(sockname);
+ netbuf.maxlen=sizeof(sockname);
+
+ if( t_getname(ciptr->fd,&netbuf,REMOTENAME) < 0 )
+ {
+ PRMSG(1,"TLIGetPeerAddr: t_getname(REMOTENAME) failed: %d\n",
+ errno, 0,0 );
+ return -1;
+ }
+
+ PRMSG(4,"TLIGetPeerAddr: got family %d len %d\n",
+ ((struct sockaddr *) &sockname)->sa_family ,netbuf.len, 0 );
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if( ciptr->peeraddr )
+ xfree(ciptr->peeraddr);
+
+ if( (ciptr->peeraddr=(char *)xalloc(netbuf.len)) == NULL )
+ {
+ PRMSG(1,
+ "TLIGetPeerAddr: Can't allocate space for the addr\n",
+ 0,0,0);
+ return -1;
+ }
+
+ ciptr->peeraddrlen=netbuf.len;
+ memcpy(ciptr->peeraddr,&sockname,ciptr->peeraddrlen);
+
+ return 0;
+}
+
+
+/*
+ * This function will establish a local name for the transport. This function
+ * do extra work for the local tli connection. It must create a sockaddr_un
+ * format address so that it will look like an AF_UNIX connection to the
+ * higher layer.
+ *
+ * This function will only be called by the OPENC?TSClient() functions since
+ * the local address is set up in the CreateListner() for the server ends.
+ */
+
+static int
+TRANS(TLITLIBindLocal)(int fd, int family, char *port)
+
+{
+ struct sockaddr_un *sunaddr=NULL;
+ struct t_bind *req=NULL;
+
+ PRMSG(2, "TLITLIBindLocal(%d,%d,%s)\n", fd, family, port);
+
+ if( family == AF_UNIX )
+ {
+ if( (req=(struct t_bind *)t_alloc(fd,T_BIND,0)) == NULL )
+ {
+ PRMSG(1,
+ "TLITLIBindLocal() failed to allocate a t_bind\n",
+ 0,0,0 );
+ return -1;
+ }
+
+ if( (sunaddr=(struct sockaddr_un *)
+ malloc(sizeof(struct sockaddr_un))) == NULL )
+ {
+ PRMSG(1,
+ "TLITLIBindLocal: failed to allocate a sockaddr_un\n",
+ 0,0,0 );
+ t_free((char *)req,T_BIND);
+ return -1;
+ }
+
+ sunaddr->sun_family=AF_UNIX;
+
+#ifdef nuke
+ if( *port == '/' ) { /* A full pathname */
+ (void) strcpy(sunaddr->sun_path, port);
+ } else {
+ (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
+ }
+#endif /*NUKE*/
+
+ (void) sprintf(sunaddr->sun_path,"%s%d",
+ TLINODENAME, getpid()^time(NULL) );
+
+ PRMSG(4, "TLITLIBindLocal: binding to %s\n",
+ sunaddr->sun_path, 0,0);
+
+ req->addr.buf=(char *)sunaddr;
+ req->addr.len=sizeof(*sunaddr);
+ req->addr.maxlen=sizeof(*sunaddr);
+ }
+
+ if( t_bind(fd, req, NULL) < 0 )
+ {
+ PRMSG(1,
+ "TLIBindLocal: Unable to bind TLI device to %s\n",
+ port, 0,0 );
+ if (sunaddr)
+ free((char *) sunaddr);
+ if (req)
+ t_free((char *)req,T_BIND);
+ return -1;
+ }
+ return 0;
+}
+
+static XtransConnInfo
+TRANS(TLIOpen)(char *device)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG(3,"TLIOpen(%s)\n", device, 0,0 );
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1, "TLIOpen: calloc failed\n", 0,0,0 );
+ return NULL;
+ }
+
+ if( (ciptr->fd=t_open( device, O_RDWR, NULL )) < 0 )
+ {
+ PRMSG(1, "TLIOpen: t_open failed for %s\n", device, 0,0 );
+ free(ciptr);
+ return NULL;
+ }
+
+ return ciptr;
+}
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(TLIReopen)(char *device, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+
+ PRMSG(3,"TLIReopen(%s,%d, %s)\n", device, fd, port );
+
+ if (t_sync (fd) < 0)
+ {
+ PRMSG(1, "TLIReopen: t_sync failed\n", 0,0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=(XtransConnInfo)xcalloc(1,sizeof(struct _XtransConnInfo))) == NULL )
+ {
+ PRMSG(1, "TLIReopen: calloc failed\n", 0,0,0 );
+ return NULL;
+ }
+
+ ciptr->fd = fd;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(TLIAddrToNetbuf)(int tlifamily, char *host, char *port,
+ struct netbuf *netbufp)
+
+{
+ struct netconfig *netconfigp;
+ struct nd_hostserv nd_hostserv;
+ struct nd_addrlist *nd_addrlistp = NULL;
+ void *handlep;
+ long lport;
+
+ PRMSG(3,"TLIAddrToNetbuf(%d,%s,%s)\n", tlifamily, host, port );
+
+ if( (handlep=setnetconfig()) == NULL )
+ return -1;
+
+ lport = strtol (port, (char**)NULL, 10);
+ if (lport < 1024 || lport > USHRT_MAX)
+ return -1;
+
+ nd_hostserv.h_host = host;
+ if( port && *port ) {
+ nd_hostserv.h_serv = port;
+ } else {
+ nd_hostserv.h_serv = NULL;
+ }
+
+ while( (netconfigp=getnetconfig(handlep)) != NULL )
+ {
+ if( strcmp(netconfigp->nc_protofmly,
+ TLItrans2devtab[tlifamily].protofamily) != 0 )
+ continue;
+ PRMSG(5,"TLIAddrToNetbuf: Trying to resolve %s.%s for %s\n",
+ host, port, TLItrans2devtab[tlifamily].protofamily );
+ if( netdir_getbyname(netconfigp,&nd_hostserv, &nd_addrlistp) == 0 )
+ {
+ /* we have at least one address to use */
+
+ PRMSG(5, "TLIAddrToNetbuf: found address for %s.%s\n", host, port, 0 );
+ PRMSG(5, "TLIAddrToNetbuf: %s\n",taddr2uaddr(netconfigp,nd_addrlistp->n_addrs),
+ 0,0 );
+
+ memcpy(netbufp->buf,nd_addrlistp->n_addrs->buf,
+ nd_addrlistp->n_addrs->len);
+ netbufp->len=nd_addrlistp->n_addrs->len;
+ endnetconfig(handlep);
+ return 0;
+ }
+ }
+ endnetconfig(handlep);
+
+ return -1;
+}
+
+/*
+ * These functions are the interface supplied in the Xtransport structure
+ */
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(TLIOpenCOTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIOpenCOTSClient(%s,%s,%s)\n", protocol, host, port );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,"TLIOpenCOTSClient: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
+ {
+ PRMSG(1,"TLIOpenCOTSClient: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCOTSClient: ...TLITLIBindLocal() failed: %d\n",
+ errno, 0,0 );
+ t_close(ciptr->fd);
+ xfree(ciptr);
+ return NULL;
+ }
+
+ if( TRANS(TLIGetAddr)(ciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCOTSClient: ...TLIGetAddr() failed: %d\n",
+ errno, 0,0 );
+ t_close(ciptr->fd);
+ xfree(ciptr);
+ return NULL;
+ }
+
+ /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(TLIOpenCOTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIOpenCOTSServer(%s,%s,%s)\n", protocol, host, port );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCOTSServer: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
+ {
+ PRMSG(1,
+ "TLIOpenCOTSServer: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ /* Set the family type */
+
+ ciptr->family = TLItrans2devtab[i].family;
+
+
+ /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static XtransConnInfo
+TRANS(TLIOpenCLTSClient)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIOpenCLTSClient(%s,%s,%s)\n", protocol, host, port );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSClient: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSClient: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( TRANS(TLITLIBindLocal)(ciptr->fd,TLItrans2devtab[i].family,port) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSClient: ...TLITLIBindLocal() failed: %d\n",
+ errno, 0,0 );
+ t_close(ciptr->fd);
+ xfree(ciptr);
+ return NULL;
+ }
+
+ if( TRANS(TLIGetAddr)(ciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSClient: ...TLIGetPeerAddr() failed: %d\n",
+ errno, 0,0 );
+ t_close(ciptr->fd);
+ xfree(ciptr);
+ return NULL;
+ }
+
+ return ciptr;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+#ifdef TRANS_SERVER
+
+static XtransConnInfo
+TRANS(TLIOpenCLTSServer)(Xtransport *thistrans, char *protocol,
+ char *host, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIOpenCLTSServer(%s,%s,%s)\n", protocol, host, port );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSServer: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL )
+ {
+ PRMSG(1,
+ "TLIOpenCLTSServer: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ return ciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_REOPEN
+
+static XtransConnInfo
+TRANS(TLIReopenCOTSServer)(Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIReopenCOTSServer(%d, %s)\n", fd, port, 0 );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,
+ "TLIReopenCOTSServer: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIReopen)(
+ TLItrans2devtab[i].devcotsname, fd, port)) == NULL )
+ {
+ PRMSG(1,
+ "TLIReopenCOTSServer: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ /* Save the TLIFamily for later use in TLIAddrToNetbuf() lookups */
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+
+static XtransConnInfo
+TRANS(TLIReopenCLTSServer)(Xtransport *thistrans, int fd, char *port)
+
+{
+ XtransConnInfo ciptr;
+ int i;
+
+ PRMSG(2,"TLIReopenCLTSServer(%d, %s)\n", fd, port, 0 );
+
+ if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 )
+ {
+ PRMSG(1,
+ "TLIReopenCLTSServer: Unable to determine device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ if( (ciptr=TRANS(TLIReopen)(
+ TLItrans2devtab[i].devcltsname, fd, port)) == NULL )
+ {
+ PRMSG(1,
+ "TLIReopenCLTSServer: Unable to open device for %s\n",
+ thistrans->TransName, 0,0 );
+ return NULL;
+ }
+
+ ciptr->index = i;
+
+ return ciptr;
+}
+
+#endif /* TRANS_REOPEN */
+
+
+static int
+TRANS(TLISetOption)(XtransConnInfo ciptr, int option, int arg)
+
+{
+ PRMSG(2,"TLISetOption(%d,%d,%d)\n", ciptr->fd, option, arg );
+
+ return -1;
+}
+
+
+#ifdef TRANS_SERVER
+
+static int
+TRANS(TLICreateListener)(XtransConnInfo ciptr, struct t_bind *req)
+
+{
+ struct t_bind *ret;
+
+ PRMSG(2,"TLICreateListener(%x->%d,%x)\n", ciptr, ciptr->fd, req );
+
+ if( (ret=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
+ {
+ PRMSG(1, "TLICreateListener: failed to allocate a t_bind\n",
+ 0,0,0 );
+ t_free((char *)req,T_BIND);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ if( t_bind(ciptr->fd, req, ret) < 0 )
+ {
+ PRMSG(1, "TLICreateListener: t_bind failed\n", 0,0,0 );
+ t_free((char *)req,T_BIND);
+ t_free((char *)ret,T_BIND);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ if( memcmp(req->addr.buf,ret->addr.buf,req->addr.len) != 0 )
+ {
+ PRMSG(1, "TLICreateListener: unable to bind to %x\n",
+ req, 0,0 );
+ t_free((char *)req,T_BIND);
+ t_free((char *)ret,T_BIND);
+ return TRANS_ADDR_IN_USE;
+ }
+
+ /*
+ * Everything looks good: fill in the XtransConnInfo structure.
+ */
+
+ if( (ciptr->addr=(char *)xalloc(ret->addr.len)) == NULL )
+ {
+ PRMSG(1,
+ "TLICreateListener: Unable to allocate space for the address\n",
+ 0,0,0 );
+ t_free((char *)req,T_BIND);
+ t_free((char *)ret, T_BIND);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ ciptr->addrlen=ret->addr.len;
+ memcpy(ciptr->addr,ret->addr.buf,ret->addr.len);
+
+ t_free((char *)req,T_BIND);
+ t_free((char *)ret, T_BIND);
+
+ return 0;
+}
+
+
+static int
+TRANS(TLIINETCreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+ char portbuf[PORTBUFSIZE];
+ struct t_bind *req;
+ struct sockaddr_in *sinaddr;
+ long tmpport;
+
+ PRMSG(2,"TLIINETCreateListener(%x->%d,%s)\n", ciptr,
+ ciptr->fd, port ? port : "NULL" );
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependent. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf(portbuf,"%u", tmpport);
+ port = portbuf;
+ }
+#endif
+
+ if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_ALL)) == NULL )
+ {
+ PRMSG(1,
+ "TLIINETCreateListener: failed to allocate a t_bind\n",
+ 0,0,0 );
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ if( port && *port ) {
+ if(TRANS(TLIAddrToNetbuf)(ciptr->index,HOST_SELF,port,&(req->addr)) < 0)
+ {
+ PRMSG(1,
+ "TLIINETCreateListener: can't resolve name:HOST_SELF.%s\n",
+ port, 0,0 );
+ t_free((char *)req,T_BIND);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+ } else {
+ sinaddr=(struct sockaddr_in *) req->addr.buf;
+ sinaddr->sin_family=AF_INET;
+ sinaddr->sin_port=htons(0);
+ sinaddr->sin_addr.s_addr=0;
+ }
+
+ /* Set the qlen */
+
+ req->qlen=1;
+
+ return TRANS(TLICreateListener)(ciptr, req);
+}
+
+
+static int
+TRANS(TLITLICreateListener)(XtransConnInfo ciptr, char *port, unsigned int flags)
+
+{
+ struct t_bind *req;
+ struct sockaddr_un *sunaddr;
+ int ret_value;
+
+ PRMSG(2,"TLITLICreateListener(%x->%d,%s)\n", ciptr, ciptr->fd,
+ port ? port : "NULL");
+
+ if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,0)) == NULL )
+ {
+ PRMSG(1,
+ "TLITLICreateListener: failed to allocate a t_bind\n",
+ 0,0,0 );
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ if( (sunaddr=(struct sockaddr_un *)
+ malloc(sizeof(struct sockaddr_un))) == NULL )
+ {
+ PRMSG(1,
+ "TLITLICreateListener: failed to allocate a sockaddr_un\n",
+ 0,0,0 );
+ t_free((char *)req,T_BIND);
+ return TRANS_CREATE_LISTENER_FAILED;
+ }
+
+ sunaddr->sun_family=AF_UNIX;
+ if( port && *port ) {
+ if( *port == '/' ) { /* A full pathname */
+ (void) strcpy(sunaddr->sun_path, port);
+ } else {
+ (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
+ }
+ } else {
+ (void) sprintf(sunaddr->sun_path,"%s%d", TLINODENAME, getpid());
+ }
+
+ req->addr.buf=(char *)sunaddr;
+ req->addr.len=sizeof(*sunaddr);
+ req->addr.maxlen=sizeof(*sunaddr);
+
+ /* Set the qlen */
+
+ req->qlen=1;
+
+ ret_value = TRANS(TLICreateListener)(ciptr, req);
+
+ free((char *) sunaddr);
+
+ return ret_value;
+}
+
+
+static XtransConnInfo
+TRANS(TLIAccept)(XtransConnInfo ciptr, int *status)
+
+{
+ struct t_call *call;
+ XtransConnInfo newciptr;
+ int i;
+
+ PRMSG(2,"TLIAccept(%x->%d)\n", ciptr, ciptr->fd, 0 );
+
+ if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
+ {
+ PRMSG(1, "TLIAccept() failed to allocate a t_call\n", 0,0,0 );
+ *status = TRANS_ACCEPT_BAD_MALLOC;
+ return NULL;
+ }
+
+ if( t_listen(ciptr->fd,call) < 0 )
+ {
+ extern char *t_errlist[];
+ extern int t_errno;
+ PRMSG(1, "TLIAccept() t_listen() failed\n", 0,0,0 );
+ PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
+ t_free((char *)call,T_CALL);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ /*
+ * Now we need to set up the new endpoint for the incoming connection.
+ */
+
+ i=ciptr->index; /* Makes the next line more readable */
+
+ if( (newciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL )
+ {
+ PRMSG(1, "TLIAccept() failed to open a new endpoint\n", 0,0,0 );
+ t_free((char *)call,T_CALL);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if( TRANS(TLITLIBindLocal)(newciptr->fd,TLItrans2devtab[i].family,"") < 0 )
+ {
+ PRMSG(1,
+ "TLIAccept: TRANS(TLITLIBindLocal)() failed: %d\n",
+ errno, 0,0 );
+ t_free((char *)call,T_CALL);
+ t_close(newciptr->fd);
+ xfree(newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+
+ if( t_accept(ciptr->fd,newciptr->fd,call) < 0 )
+ {
+ extern char *t_errlist[];
+ extern int t_errno;
+ PRMSG(1, "TLIAccept() t_accept() failed\n", 0,0,0 );
+ PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
+ if( t_errno == TLOOK )
+ {
+ int evtype = t_look(ciptr->fd);
+ PRMSG(1, "TLIAccept() t_look() returned %d\n", evtype,0,0 );
+ switch( evtype )
+ {
+ case T_DISCONNECT:
+ if( t_rcvdis(ciptr->fd, NULL) < 0 )
+ {
+ PRMSG(1, "TLIAccept() t_rcvdis() failed\n", 0,0,0 );
+ PRMSG(1, "TLIAccept: %s\n", t_errlist[t_errno], 0,0 );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ t_free((char *)call,T_CALL);
+ t_close(newciptr->fd);
+ free(newciptr);
+ *status = TRANS_ACCEPT_FAILED;
+ return NULL;
+ }
+
+ t_free((char *)call,T_CALL);
+
+ if( TRANS(TLIGetAddr)(newciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
+ errno, 0,0 );
+ t_close(newciptr->fd);
+ xfree(newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if( TRANS(TLIGetPeerAddr)(newciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIAccept: TRANS(TLIGetPeerAddr)() failed: %d\n",
+ errno, 0,0 );
+ t_close(newciptr->fd);
+ xfree(newciptr->addr);
+ xfree(newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if( ioctl(newciptr->fd, I_POP,"timod") < 0 )
+ {
+ PRMSG(1, "TLIAccept() ioctl(I_POP, \"timod\") failed %d\n",
+ errno,0,0 );
+ t_close(newciptr->fd);
+ xfree(newciptr->addr);
+ xfree(newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 )
+ {
+ PRMSG(1, "TLIAccept() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
+ errno,0,0 );
+ t_close(newciptr->fd);
+ xfree(newciptr->addr);
+ xfree(newciptr);
+ *status = TRANS_ACCEPT_MISC_ERROR;
+ return NULL;
+ }
+
+ *status = 0;
+
+ return newciptr;
+}
+
+#endif /* TRANS_SERVER */
+
+
+#ifdef TRANS_CLIENT
+
+static int
+TRANS(TLIConnect)(XtransConnInfo ciptr, struct t_call *sndcall )
+
+{
+ PRMSG(2, "TLIConnect(%x->%d,%x)\n", ciptr, ciptr->fd, sndcall);
+
+ if( t_connect(ciptr->fd,sndcall,NULL) < 0 )
+ {
+ extern char *t_errlist[];
+ extern int t_errno;
+ PRMSG(1, "TLIConnect() t_connect() failed\n", 0,0,0 );
+ PRMSG(1, "TLIConnect: %s\n", t_errlist[t_errno], 0,0 );
+ t_free((char *)sndcall,T_CALL);
+ if (t_errno == TLOOK && t_look(ciptr->fd) == T_DISCONNECT)
+ {
+ t_rcvdis(ciptr->fd,NULL);
+ return TRANS_TRY_CONNECT_AGAIN;
+ }
+ else
+ return TRANS_CONNECT_FAILED;
+ }
+
+ t_free((char *)sndcall,T_CALL);
+
+ /*
+ * Sync up the address fields of ciptr.
+ */
+
+ if( TRANS(TLIGetAddr)(ciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIConnect: ...TLIGetAddr() failed: %d\n",
+ errno, 0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if( TRANS(TLIGetPeerAddr)(ciptr) < 0 )
+ {
+ PRMSG(1,
+ "TLIConnect: ...TLIGetPeerAddr() failed: %d\n",
+ errno, 0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if( ioctl(ciptr->fd, I_POP,"timod") < 0 )
+ {
+ PRMSG(1, "TLIConnect() ioctl(I_POP,\"timod\") failed %d\n",
+ errno,0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if( ioctl(ciptr->fd, I_PUSH,"tirdwr") < 0 )
+ {
+ PRMSG(1, "TLIConnect() ioctl(I_PUSH,\"tirdwr\") failed %d\n",
+ errno,0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ return 0;
+}
+
+
+static int
+TRANS(TLIINETConnect)(XtransConnInfo ciptr, char *host, char *port)
+
+{
+ char portbuf[PORTBUFSIZE];
+ struct t_call *sndcall;
+ long tmpport;
+
+ PRMSG(2, "TLIINETConnect(%s,%s)\n", host, port, 0);
+
+#ifdef X11_t
+ /*
+ * X has a well known port, that is transport dependant. It is easier
+ * to handle it here, than try and come up with a transport independent
+ * representation that can be passed in and resolved the usual way.
+ *
+ * The port that is passed here is really a string containing the idisplay
+ * from ConnectDisplay().
+ */
+
+ if (is_numeric (port))
+ {
+ tmpport = X_TCP_PORT + strtol (port, (char**)NULL, 10);
+ sprintf(portbuf,"%u", tmpport );
+ port = portbuf;
+ }
+#endif
+
+ if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL )
+ {
+ PRMSG(1, "TLIINETConnect() failed to allocate a t_call\n", 0,0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if( TRANS(TLIAddrToNetbuf)(ciptr->index, host, port, &(sndcall->addr) ) < 0 )
+ {
+ PRMSG(1, "TLIINETConnect() unable to resolve name:%s.%s\n",
+ host, port, 0 );
+ t_free((char *)sndcall,T_CALL);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ return TRANS(TLIConnect)(ciptr, sndcall );
+}
+
+
+static int
+TRANS(TLITLIConnect)(XtransConnInfo ciptr, char *host, char *port)
+
+{
+ struct t_call *sndcall;
+ struct sockaddr_un *sunaddr;
+ int ret_value;
+
+ PRMSG(2, "TLITLIConnect(%s,%s)\n", host, port, 0);
+
+ if( (sndcall=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_OPT|T_UDATA)) == NULL )
+ {
+ PRMSG(1, "TLITLIConnect() failed to allocate a t_call\n", 0,0,0 );
+ return TRANS_CONNECT_FAILED;
+ }
+
+ if( (sunaddr=(struct sockaddr_un *)
+ malloc(sizeof(struct sockaddr_un))) == NULL )
+ {
+ PRMSG(1,
+ "TLITLIConnect: failed to allocate a sockaddr_un\n",
+ 0,0,0 );
+ t_free((char *)sndcall,T_CALL);
+ return TRANS_CONNECT_FAILED;
+ }
+
+ sunaddr->sun_family=AF_UNIX;
+ if( *port == '/' ||
+ strncmp (port, TLINODENAME, strlen (TLINODENAME)) == 0) {
+ /* Use the port as is */
+ (void) strcpy(sunaddr->sun_path, port);
+ } else {
+ (void) sprintf(sunaddr->sun_path,"%s%s", TLINODENAME, port );
+ }
+
+ sndcall->addr.buf=(char *)sunaddr;
+ sndcall->addr.len=sizeof(*sunaddr);
+ sndcall->addr.maxlen=sizeof(*sunaddr);
+
+ ret_value = TRANS(TLIConnect)(ciptr, sndcall );
+
+ free((char *) sunaddr);
+
+ return ret_value;
+}
+
+#endif /* TRANS_CLIENT */
+
+
+static int
+TRANS(TLIBytesReadable)(XtransConnInfo ciptr, BytesReadable_t *pend)
+
+{
+ int ret;
+ struct pollfd filedes;
+
+ PRMSG(2, "TLIByteReadable(%x->%d,%x)\n", ciptr, ciptr->fd, pend );
+
+ /*
+ * This function should detect hangup conditions. Use poll to check
+ * if no data is present. On SVR4, the M_HANGUP message sits on the
+ * streams head, and ioctl(N_READ) keeps returning 0 because there is
+ * no data available. The hangup goes undetected, and the client hangs.
+ */
+
+ ret=ioctl(ciptr->fd, I_NREAD, (char *)pend);
+
+ if( ret != 0 )
+ return ret; /* Data present or error */
+
+
+ /* Zero data, or POLLHUP message */
+
+ filedes.fd=ciptr->fd;
+ filedes.events=POLLIN;
+
+ ret=poll(&filedes, 1, 0);
+
+ if( ret == 0 ) {
+ *pend=0;
+ return 0; /* Really, no data */
+ }
+
+ if( ret < 0 )
+ return -1; /* just pass back the error */
+
+ if( filedes.revents & (POLLHUP|POLLERR) ) /* check for hangup */
+ return -1;
+
+ /* Should only get here if data arrived after the first ioctl() */
+ return ioctl(ciptr->fd, I_NREAD, (char *)pend);
+}
+
+
+static int
+TRANS(TLIRead)(XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG(2, "TLIRead(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return read(ciptr->fd,buf,size);
+}
+
+
+static int
+TRANS(TLIWrite)(XtransConnInfo ciptr, char *buf, int size)
+
+{
+ PRMSG(2, "TLIWrite(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return write(ciptr->fd,buf,size);
+}
+
+
+static int
+TRANS(TLIReadv)(XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG(2, "TLIReadv(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return READV(ciptr,buf,size);
+}
+
+
+static int
+TRANS(TLIWritev)(XtransConnInfo ciptr, struct iovec *buf, int size)
+
+{
+ PRMSG(2, "TLIWritev(%d,%x,%d)\n", ciptr->fd, buf, size );
+
+ return WRITEV(ciptr,buf,size);
+}
+
+
+static int
+TRANS(TLIDisconnect)(XtransConnInfo ciptr)
+
+{
+ PRMSG(2, "TLIDisconnect(%x->%d)\n", ciptr, ciptr->fd, 0 );
+
+ /*
+ * Restore the TLI modules so that the connection can be properly shutdown.
+ * This avoids the situation where a connection goes into the TIME_WAIT
+ * state, and the address remains unavailable for a while.
+ */
+ ioctl(ciptr->fd, I_POP,"tirdwr");
+ ioctl(ciptr->fd, I_PUSH,"timod");
+
+ t_snddis(ciptr->fd,NULL);
+
+ return 0;
+}
+
+
+static int
+TRANS(TLIClose)(XtransConnInfo ciptr)
+
+{
+ PRMSG(2, "TLIClose(%x->%d)\n", ciptr, ciptr->fd, 0 );
+
+ t_unbind(ciptr->fd);
+
+ return (t_close(ciptr->fd));
+}
+
+
+static int
+TRANS(TLICloseForCloning)(XtransConnInfo ciptr)
+
+{
+ /*
+ * Don't unbind.
+ */
+
+ PRMSG(2, "TLICloseForCloning(%x->%d)\n", ciptr, ciptr->fd, 0 );
+
+ return (t_close(ciptr->fd));
+}
+
+
+Xtransport TRANS(TLITCPFuncs) = {
+ /* TLI Interface */
+ "tcp",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(TLIOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(TLIOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(TLIReopenCOTSServer),
+ TRANS(TLIReopenCLTSServer),
+#endif
+ TRANS(TLISetOption),
+#ifdef TRANS_SERVER
+ TRANS(TLIINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(TLIAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLIINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(TLIBytesReadable),
+ TRANS(TLIRead),
+ TRANS(TLIWrite),
+ TRANS(TLIReadv),
+ TRANS(TLIWritev),
+ TRANS(TLIDisconnect),
+ TRANS(TLIClose),
+ TRANS(TLICloseForCloning),
+};
+
+#ifdef TRANS_SERVER
+static char * inet_aliases[] = { "tcp", NULL };
+#endif
+Xtransport TRANS(TLIINETFuncs) = {
+ /* TLI Interface */
+ "inet",
+ TRANS_ALIAS,
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ inet_aliases,
+ TRANS(TLIOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(TLIOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(TLIReopenCOTSServer),
+ TRANS(TLIReopenCLTSServer),
+#endif
+ TRANS(TLISetOption),
+#ifdef TRANS_SERVER
+ TRANS(TLIINETCreateListener),
+ NULL, /* ResetListener */
+ TRANS(TLIAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLIINETConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(TLIBytesReadable),
+ TRANS(TLIRead),
+ TRANS(TLIWrite),
+ TRANS(TLIReadv),
+ TRANS(TLIWritev),
+ TRANS(TLIDisconnect),
+ TRANS(TLIClose),
+ TRANS(TLICloseForCloning),
+};
+
+Xtransport TRANS(TLITLIFuncs) = {
+ /* TLI Interface */
+ "tli",
+ 0,
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCOTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ NULL,
+ TRANS(TLIOpenCOTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLIOpenCLTSClient),
+#endif /* TRANS_CLIENT */
+#ifdef TRANS_SERVER
+ TRANS(TLIOpenCLTSServer),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_REOPEN
+ TRANS(TLIReopenCOTSServer),
+ TRANS(TLIReopenCLTSServer),
+#endif
+ TRANS(TLISetOption),
+#ifdef TRANS_SERVER
+ TRANS(TLITLICreateListener),
+ NULL, /* ResetListener */
+ TRANS(TLIAccept),
+#endif /* TRANS_SERVER */
+#ifdef TRANS_CLIENT
+ TRANS(TLITLIConnect),
+#endif /* TRANS_CLIENT */
+ TRANS(TLIBytesReadable),
+ TRANS(TLIRead),
+ TRANS(TLIWrite),
+ TRANS(TLIReadv),
+ TRANS(TLIWritev),
+ TRANS(TLIDisconnect),
+ TRANS(TLIClose),
+ TRANS(TLICloseForCloning),
+};
diff --git a/nx-X11/lib/xtrans/Xtransutil.c b/nx-X11/lib/xtrans/Xtransutil.c
new file mode 100644
index 000000000..253e8b099
--- /dev/null
+++ b/nx-X11/lib/xtrans/Xtransutil.c
@@ -0,0 +1,691 @@
+/* $Xorg: Xtransutil.c,v 1.4 2001/02/09 02:04:07 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/Xtransutil.c,v 3.26 2003/07/09 15:27:30 tsi Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCRS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * These are some utility functions created for convenience or to provide
+ * an interface that is similar to an existing interface. These are built
+ * only using the Transport Independant API, and have no knowledge of
+ * the internal implementation.
+ */
+
+#ifdef XTHREADS
+#include <X11/Xthreads.h>
+#endif
+
+#ifdef X11_t
+
+/*
+ * These values come from X.h and Xauth.h, and MUST match them. Some
+ * of these values are also defined by the ChangeHost protocol message.
+ */
+
+#define FamilyInternet 0 /* IPv4 */
+#define FamilyDECnet 1
+#define FamilyChaos 2
+#define FamilyInternet6 6
+#define FamilyAmoeba 33
+#define FamilyLocalHost 252
+#define FamilyKrb5Principal 253
+#define FamilyNetname 254
+#define FamilyLocal 256
+#define FamilyWild 65535
+
+/*
+ * TRANS(ConvertAddress) converts a sockaddr based address to an
+ * X authorization based address. Some of this is defined as part of
+ * the ChangeHost protocol. The rest is just done in a consistent manner.
+ */
+
+int
+TRANS(ConvertAddress)(int *familyp, int *addrlenp, Xtransaddr **addrp)
+
+{
+
+ PRMSG(2,"ConvertAddress(%d,%d,%x)\n",*familyp,*addrlenp,*addrp);
+
+ switch( *familyp )
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+ {
+ /*
+ * Check for the BSD hack localhost address 127.0.0.1.
+ * In this case, we are really FamilyLocal.
+ */
+
+ struct sockaddr_in saddr;
+#ifdef CRAY
+#ifdef OLDTCP
+ int len = sizeof(saddr.sin_addr);
+#else
+ int len = SIZEOF_in_addr;
+#endif /* OLDTCP */
+ char *cp = (char *) &saddr.sin_addr;
+#else /* else not CRAY */
+ int len = sizeof(saddr.sin_addr.s_addr);
+ char *cp = (char *) &saddr.sin_addr.s_addr;
+#endif /* CRAY */
+
+ memcpy (&saddr, *addrp, sizeof (struct sockaddr_in));
+
+ if ((len == 4) && (cp[0] == 127) && (cp[1] == 0) &&
+ (cp[2] == 0) && (cp[3] == 1))
+ {
+ *familyp=FamilyLocal;
+ }
+ else
+ {
+ *familyp=FamilyInternet;
+ *addrlenp=len;
+ memcpy(*addrp,&saddr.sin_addr,len);
+ }
+ break;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 saddr6;
+
+ memcpy (&saddr6, *addrp, sizeof (struct sockaddr_in6));
+
+ if (IN6_IS_ADDR_LOOPBACK(&saddr6.sin6_addr))
+ {
+ *familyp=FamilyLocal;
+ }
+ else if (IN6_IS_ADDR_V4MAPPED(&(saddr6.sin6_addr))) {
+ char *cp = (char *) &saddr6.sin6_addr.s6_addr[12];
+
+ if ((cp[0] == 127) && (cp[1] == 0) &&
+ (cp[2] == 0) && (cp[3] == 1))
+ {
+ *familyp=FamilyLocal;
+ }
+ else
+ {
+ *familyp=FamilyInternet;
+ *addrlenp = sizeof (struct in_addr);
+ memcpy(*addrp,cp,*addrlenp);
+ }
+ }
+ else
+ {
+ *familyp=FamilyInternet6;
+ *addrlenp=sizeof(saddr6.sin6_addr);
+ memcpy(*addrp,&saddr6.sin6_addr,sizeof(saddr6.sin6_addr));
+ }
+ break;
+ }
+#endif /* IPv6 */
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ struct sockaddr_dn saddr;
+
+ memcpy (&saddr, *addrp, sizeof (struct sockaddr_dn));
+
+ *familyp=FamilyDECnet;
+ *addrlenp=sizeof(struct dn_naddr);
+ memcpy(*addrp,&saddr.sdn_add,*addrlenp);
+
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+#if defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ *familyp=FamilyLocal;
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)*/
+
+#if (defined(__SCO__) || defined(__UNIXWARE__)) && defined(LOCALCONN)
+ case 0:
+ {
+ *familyp=FamilyLocal;
+ break;
+ }
+#endif
+
+ default:
+ PRMSG(1,"ConvertAddress: Unknown family type %d\n",
+ *familyp, 0,0 );
+ return -1;
+ }
+
+
+ if (*familyp == FamilyLocal)
+ {
+ /*
+ * In the case of a local connection, we need to get the
+ * host name for authentication.
+ */
+
+ char hostnamebuf[256];
+ int len = TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf);
+
+ if (len > 0) {
+ if (*addrp && *addrlenp < (len + 1))
+ {
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ }
+ if (!*addrp)
+ *addrp = (Xtransaddr *) xalloc (len + 1);
+ if (*addrp) {
+ strcpy ((char *) *addrp, hostnamebuf);
+ *addrlenp = len;
+ } else {
+ *addrlenp = 0;
+ }
+ }
+ else
+ {
+ if (*addrp)
+ xfree ((char *) *addrp);
+ *addrp = NULL;
+ *addrlenp = 0;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* X11_t */
+
+#ifdef ICE_t
+
+#include <signal.h>
+
+char *
+TRANS(GetMyNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *addr = ciptr->addr;
+ char hostnamebuf[256];
+ char *networkId = NULL;
+ char *transName = ciptr->transptr->TransName;
+
+ if (gethostname (hostnamebuf, sizeof (hostnamebuf)) < 0)
+ {
+ return (NULL);
+ }
+
+ switch (family)
+ {
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ struct sockaddr_un *saddr = (struct sockaddr_un *) addr;
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (saddr->sun_path));
+ sprintf (networkId, "%s/%s:%s", transName,
+ hostnamebuf, saddr->sun_path);
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+#endif
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) addr;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) addr;
+#endif
+ int portnum;
+ char portnumbuf[10];
+
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == AF_INET6)
+ portnum = ntohs (saddr6->sin6_port);
+ else
+#endif
+ portnum = ntohs (saddr->sin_port);
+
+ sprintf (portnumbuf, "%d", portnum);
+ networkId = (char *) xalloc (3 + strlen (transName) +
+ strlen (hostnamebuf) + strlen (portnumbuf));
+ sprintf (networkId, "%s/%s:%s", transName, hostnamebuf, portnumbuf);
+ break;
+ }
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ struct sockaddr_dn *saddr = (struct sockaddr_dn *) addr;
+
+ networkId = (char *) xalloc (
+ 13 + strlen (hostnamebuf) + saddr->sdn_objnamel);
+ sprintf (networkId, "dnet/%s::%s",
+ hostnamebuf, saddr->sdn_objname);
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+ default:
+ break;
+ }
+
+ return (networkId);
+}
+
+#include <setjmp.h>
+static jmp_buf env;
+
+#ifdef SIGALRM
+static volatile int nameserver_timedout = 0;
+
+static
+#ifdef RETSIGTYPE /* set by autoconf AC_TYPE_SIGNAL */
+RETSIGTYPE
+#else /* Imake */
+#ifdef SIGNALRETURNSINT
+int
+#else
+void
+#endif
+#endif
+nameserver_lost(int sig)
+{
+ nameserver_timedout = 1;
+ longjmp (env, -1);
+ /* NOTREACHED */
+#ifdef SIGNALRETURNSINT
+ return -1; /* for picky compilers */
+#endif
+}
+#endif /* SIGALARM */
+
+
+char *
+TRANS(GetPeerNetworkId) (XtransConnInfo ciptr)
+
+{
+ int family = ciptr->family;
+ char *peer_addr = ciptr->peeraddr;
+ char *hostname;
+ char addrbuf[256];
+ const char *addr = NULL;
+
+ switch (family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN)
+ case AF_UNIX:
+ {
+ if (gethostname (addrbuf, sizeof (addrbuf)) == 0)
+ addr = addrbuf;
+ break;
+ }
+#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) || defined(OS2PIPECONN) */
+
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ case AF_INET:
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+#endif
+ {
+ struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) peer_addr;
+#endif
+ char *address;
+ int addresslen;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ struct hostent * volatile hostp = NULL;
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == AF_INET6)
+ {
+ address = (char *) &saddr6->sin6_addr;
+ addresslen = sizeof (saddr6->sin6_addr);
+ }
+ else
+#endif
+ {
+ address = (char *) &saddr->sin_addr;
+ addresslen = sizeof (saddr->sin_addr);
+ }
+
+#ifdef SIGALRM
+ /*
+ * gethostbyaddr can take a LONG time if the host does not exist.
+ * Assume that if it does not respond in NAMESERVER_TIMEOUT seconds
+ * that something is wrong and do not make the user wait.
+ * gethostbyaddr will continue after a signal, so we have to
+ * jump out of it.
+ */
+
+ nameserver_timedout = 0;
+ signal (SIGALRM, nameserver_lost);
+ alarm (4);
+ if (setjmp(env) == 0) {
+#endif
+ hostp = _XGethostbyaddr (address, addresslen, family, hparams);
+#ifdef SIGALRM
+ }
+ alarm (0);
+#endif
+ if (hostp != NULL)
+ addr = hostp->h_name;
+ else
+#if defined(IPv6) && defined(AF_INET6)
+ addr = inet_ntop (family, address, addrbuf, sizeof (addrbuf));
+#else
+ addr = inet_ntoa (saddr->sin_addr);
+#endif
+ break;
+ }
+
+#endif /* defined(TCPCONN) || defined(STREAMSCONN) */
+
+#if defined(DNETCONN)
+ case AF_DECnet:
+ {
+ struct sockaddr_dn *saddr = (struct sockaddr_dn *) peer_addr;
+ struct nodeent *np;
+
+ if (np = getnodebyaddr(saddr->sdn_add.a_addr,
+ saddr->sdn_add.a_len, AF_DECnet)) {
+ sprintf(addrbuf, "%s:", np->n_name);
+ } else {
+ sprintf(addrbuf, "%s:", dnet_htoa(&saddr->sdn_add));
+ }
+ addr = addrbuf;
+ break;
+ }
+#endif /* defined(DNETCONN) */
+
+ default:
+ return (NULL);
+ }
+
+
+ hostname = (char *) xalloc (
+ strlen (ciptr->transptr->TransName) + strlen (addr) + 2);
+ strcpy (hostname, ciptr->transptr->TransName);
+ strcat (hostname, "/");
+ if (addr)
+ strcat (hostname, addr);
+
+ return (hostname);
+}
+
+#endif /* ICE_t */
+
+
+#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+int
+TRANS(WSAStartup) (void)
+{
+ static WSADATA wsadata;
+
+ PRMSG (2,"WSAStartup()\n", 0, 0, 0);
+
+ if (!wsadata.wVersion && WSAStartup(0x0101, &wsadata))
+ return 1;
+ return 0;
+}
+#endif
+
+
+static int
+is_numeric (char *str)
+
+{
+ int i;
+
+ for (i = 0; i < (int) strlen (str); i++)
+ if (!isdigit (str[i]))
+ return (0);
+
+ return (1);
+}
+
+#ifdef TRANS_SERVER
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#if !defined(S_IFLNK) && !defined(S_ISLNK)
+#undef lstat
+#define lstat(a,b) stat(a,b)
+#endif
+
+#define FAIL_IF_NOMODE 1
+#define FAIL_IF_NOT_ROOT 2
+#define WARN_NO_ACCESS 4
+
+/*
+ * We make the assumption that when the 'sticky' (t) bit is requested
+ * it's not save if the directory has non-root ownership or the sticky
+ * bit cannot be set and fail.
+ */
+static int
+trans_mkdir(char *path, int mode)
+{
+ struct stat buf;
+
+ if (lstat(path, &buf) != 0) {
+ if (errno != ENOENT) {
+ PRMSG(1, "mkdir: ERROR: (l)stat failed for %s (%d)\n",
+ path, errno, 0);
+ return -1;
+ }
+ /* Dir doesn't exist. Try to create it */
+
+#ifndef WIN32
+ /*
+ * 'sticky' bit requested: assume application makes
+ * certain security implications. If effective user ID
+ * is != 0: fail as we may not be able to meet them.
+ */
+ if (geteuid() != 0) {
+ if (mode & 01000) {
+ PRMSG(1, "mkdir: ERROR: euid != 0,"
+ "directory %s will not be created.\n",
+ path, 0, 0);
+#ifdef FAIL_HARD
+ return -1;
+#endif
+ } else {
+ PRMSG(1, "mkdir: Cannot create %s with root ownership\n",
+ path, 0, 0);
+ }
+ }
+#endif
+
+#ifndef WIN32
+ if (mkdir(path, mode) == 0) {
+ if (chmod(path, mode)) {
+ PRMSG(1, "mkdir: ERROR: Mode of %s should be set to %04o\n",
+ path, mode, 0);
+#ifdef FAIL_HARD
+ return -1;
+#endif
+ }
+#else
+ if (mkdir(path) == 0) {
+#endif
+ } else {
+ PRMSG(1, "mkdir: ERROR: Cannot create %s\n",
+ path, 0, 0);
+ return -1;
+ }
+
+ return 0;
+
+ } else {
+ if (S_ISDIR(buf.st_mode)) {
+ int updateOwner = 0;
+ int updateMode = 0;
+ int updatedOwner = 0;
+ int updatedMode = 0;
+ int status = 0;
+ /* Check if the directory's ownership is OK. */
+ if (buf.st_uid != 0)
+ updateOwner = 1;
+
+ /*
+ * Check if the directory's mode is OK. An exact match isn't
+ * required, just a mode that isn't more permissive than the
+ * one requested.
+ */
+ if ((~mode) & 0077 & buf.st_mode)
+ updateMode = 1;
+
+ /*
+ * If the directory is not writeable not everybody may
+ * be able to create sockets. Therefore warn if mode
+ * cannot be fixed.
+ */
+ if ((~buf.st_mode) & 0022 & mode) {
+ updateMode = 1;
+ status |= WARN_NO_ACCESS;
+ }
+
+ /*
+ * If 'sticky' bit is requested fail if owner isn't root
+ * as we assume the caller makes certain security implications
+ */
+ if (mode & 01000) {
+ status |= FAIL_IF_NOT_ROOT;
+ if (!(buf.st_mode & 01000)) {
+ status |= FAIL_IF_NOMODE;
+ updateMode = 1;
+ }
+ }
+
+#ifdef HAS_FCHOWN
+ /*
+ * If fchown(2) and fchmod(2) are available, try to correct the
+ * directory's owner and mode. Otherwise it isn't safe to attempt
+ * to do this.
+ */
+ if (updateMode || updateOwner) {
+ int fd = -1;
+ struct stat fbuf;
+ if ((fd = open(path, O_RDONLY)) != -1) {
+ if (fstat(fd, &fbuf) == -1) {
+ PRMSG(1, "mkdir: ERROR: fstat failed for %s (%d)\n",
+ path, errno, 0);
+ return -1;
+ }
+ /*
+ * Verify that we've opened the same directory as was
+ * checked above.
+ */
+ if (!S_ISDIR(fbuf.st_mode) ||
+ buf.st_dev != fbuf.st_dev ||
+ buf.st_ino != fbuf.st_ino) {
+ PRMSG(1, "mkdir: ERROR: inode for %s changed\n",
+ path, 0, 0);
+ return -1;
+ }
+ if (updateOwner && fchown(fd, 0, 0) == 0)
+ updatedOwner = 1;
+ if (updateMode && fchmod(fd, mode) == 0)
+ updatedMode = 1;
+ close(fd);
+ }
+ }
+#endif
+
+ if (updateOwner && !updatedOwner) {
+#ifdef FAIL_HARD
+ if (status & FAIL_IF_NOT_ROOT) {
+ PRMSG(1, "mkdir: ERROR: Owner of %s must be set to root\n",
+ path, 0, 0);
+ return -1;
+ }
+#endif
+ PRMSG(1, "mkdir: Owner of %s should be set to root\n",
+ path, 0, 0);
+ }
+
+ if (updateMode && !updatedMode) {
+#ifdef FAIL_HARD
+ if (status & FAIL_IF_NOMODE) {
+ PRMSG(1, "mkdir: ERROR: Mode of %s must be set to %04o\n",
+ path, mode, 0);
+ return -1;
+ }
+#endif
+ PRMSG(1, "mkdir: Mode of %s should be set to %04o\n",
+ path, mode, 0);
+ if (status & WARN_NO_ACCESS) {
+ PRMSG(1, "mkdir: this may cause subsequent errors\n",
+ 0, 0, 0);
+ }
+ }
+ return 0;
+ }
+ return -1;
+ }
+
+ /* In all other cases, fail */
+ return -1;
+}
+
+#endif /* TRANS_SERVER */
diff --git a/nx-X11/lib/xtrans/transport.c b/nx-X11/lib/xtrans/transport.c
new file mode 100644
index 000000000..ff460c257
--- /dev/null
+++ b/nx-X11/lib/xtrans/transport.c
@@ -0,0 +1,86 @@
+/* $Xorg: transport.c,v 1.4 2001/02/09 02:04:07 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 1994, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+/* $XFree86: xc/lib/xtrans/transport.c,v 3.9 2002/05/31 18:45:51 dawes Exp $ */
+
+/* Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA
+ *
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name NCR not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCR makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef __UNIXOS2__
+#define I_NEED_OS2_H
+#endif
+
+#ifdef XSERV_t
+#include "os.h"
+#else
+#include <stdlib.h>
+#define xalloc(_size) malloc(_size)
+#define xcalloc(_num,_size) calloc(_num,_size)
+#define xrealloc(_ptr,_size) realloc(_ptr,_size)
+#define xfree(_ptr) free(_ptr)
+#endif
+
+#include "Xtransint.h"
+
+#ifdef DNETCONN
+#include "Xtransdnet.c"
+#endif
+#ifdef LOCALCONN
+#include "Xtranslcl.c"
+#endif
+#ifdef OS2PIPECONN
+#include "Xtransos2.c"
+#endif
+#if defined(TCPCONN) || defined(UNIXCONN)
+#include "Xtranssock.c"
+#endif
+#ifdef STREAMSCONN
+#include "Xtranstli.c"
+#endif
+#include "Xtrans.c"
+#include "Xtransutil.c"