diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/lib/xtrans | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-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/Imakefile | 24 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtrans.c | 1402 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtrans.h | 490 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtransdnet.c | 668 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtransint.h | 485 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtranslcl.c | 2755 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtransos2.c | 887 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtranssock.c | 3417 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtranssock.c.NX.original | 3417 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtranssock.c.X.original | 2504 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtranstli.c | 1422 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/Xtransutil.c | 691 | ||||
-rw-r--r-- | nx-X11/lib/xtrans/transport.c | 86 |
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" |