From 26781c4f009a4b448dca3ab4912cbf01182e3d92 Mon Sep 17 00:00:00 2001 From: Kaleb Keithley Date: Fri, 14 Nov 2003 15:54:40 +0000 Subject: R6.6 is the Xorg base-line --- Xtrans.c | 1415 ++++++++++++++++++++++++++++++ Xtrans.h | 489 +++++++++++ Xtransdnet.c | 704 +++++++++++++++ Xtransint.h | 432 ++++++++++ Xtranslcl.c | 2715 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Xtranssock.c | 1993 ++++++++++++++++++++++++++++++++++++++++++ Xtranstli.c | 1494 ++++++++++++++++++++++++++++++++ Xtransutil.c | 462 ++++++++++ transport.c | 71 ++ 9 files changed, 9775 insertions(+) create mode 100644 Xtrans.c create mode 100644 Xtrans.h create mode 100644 Xtransdnet.c create mode 100644 Xtransint.h create mode 100644 Xtranslcl.c create mode 100644 Xtranssock.c create mode 100644 Xtranstli.c create mode 100644 Xtransutil.c create mode 100644 transport.c diff --git a/Xtrans.c b/Xtrans.c new file mode 100644 index 0000000..3a1cacf --- /dev/null +++ b/Xtrans.c @@ -0,0 +1,1415 @@ +/* $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. + +*/ + +/* 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 + +/* + * 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_AMOEBA_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, + &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(LOCALCONN) + &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX, +#ifndef sun + &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX, +#endif /* sun */ + &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX, +#ifndef sun + &TRANS(ISCFuncs), TRANS_LOCAL_ISC_INDEX, + &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX, +#endif /* sun */ +#endif /* LOCALCONN */ +#if defined(AMRPCCONN) || defined(AMTCPCONN) + &TRANS(AmConnFuncs), TRANS_AMOEBA_INDEX, +#endif /* AMRPCCONN || AMTCPCONN */ +}; + +#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) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (3,"TRANS(FreeConnInfo) (%x)\n", ciptr, 0, 0); + + if (ciptr->addr) + free (ciptr->addr); + + if (ciptr->peeraddr) + free (ciptr->peeraddr); + + if (ciptr->port) + free (ciptr->port); + + free ((char *) ciptr); +} + + +#define PROTOBUFSIZE 20 + +static Xtransport * +TRANS(SelectTransport) (protocol) + +char *protocol; + +{ + char protobuf[PROTOBUFSIZE]; + int i; + + PRMSG (3,"TRANS(SelectTransport) (%s)\n", protocol, 0, 0); + + /* + * Force Protocol to be lowercase as a way of doing + * a case insensitive match. + */ + + strncpy (protobuf, protocol, PROTOBUFSIZE); + + 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) (address, protocol, host, port) + +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 INET. + * 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]; + + PRMSG (3,"TRANS(ParseAddress) (%s)\n", address, 0, 0); + + /* Copy the string so it can be changed */ + + tmpptr = mybuf = (char *) malloc (strlen (address) + 1); + strcpy (mybuf, address); + + /* Parse the string to get each component */ + + /* Get the protocol part */ + + _protocol = mybuf; + + if ((mybuf = strpbrk (mybuf,"/:")) == NULL) + { + /* adress is in a bad format */ + *protocol = NULL; + *host = NULL; + *port = NULL; + free (tmpptr); + return 0; + } + + if (*mybuf == ':') + { + /* + * If there is a hostname, then assume inet, otherwise + * it must be local. + */ + if (mybuf == tmpptr) + { + /* There is neither a protocol or host specified */ + _protocol = "local"; + } + else + { + /* Ther is a hostname specified */ + _protocol = "inet"; + 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 inet, otherwise + * it must be local. + */ + if (*mybuf != ':') + _protocol = "inet"; + else + _protocol = "local"; + } + } + + /* Get the host part */ + + _host = mybuf; + + if ((mybuf = strchr (mybuf,':')) == NULL) + { + *protocol = NULL; + *host = NULL; + *port = NULL; + free (tmpptr); + return 0; + } + + *mybuf ++= '\0'; + + if (strlen(_host) == 0) + { + TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); + _host = hostnamebuf; + } + + /* Check for DECnet */ + + if (*mybuf == ':') + { + _protocol = "dnet"; + mybuf++; + } + + /* Get the port */ + +get_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 *) malloc(strlen (_protocol) + 1)) == NULL) + { + /* Malloc failed */ + *port = NULL; + *host = NULL; + *protocol = NULL; + free (tmpptr); + return 0; + } + else + strcpy (*protocol, _protocol); + + if ((*host = (char *) malloc (strlen (_host) + 1)) == NULL) + { + /* Malloc failed */ + *port = NULL; + *host = NULL; + free (*protocol); + *protocol = NULL; + free (tmpptr); + return 0; + } + else + strcpy (*host, _host); + + if ((*port = (char *) malloc (strlen (_port) + 1)) == NULL) + { + /* Malloc failed */ + *port = NULL; + free (*host); + *host = NULL; + free (*protocol); + *protocol = NULL; + free (tmpptr); + return 0; + } + else + strcpy (*port, _port); + + free (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) (type, address) + +int type; +char *address; + +{ + char *protocol = NULL, *host = NULL, *port = NULL; + XtransConnInfo ciptr = NULL; + Xtransport *thistrans; + + PRMSG (2,"TRANS(Open) (%d,%s)\n", type, address, 0); + +#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN)) + if (TRANS(WSAStartup)()) + { + PRMSG (1,"TRANS(Open): WSAStartup failed\n", 0, 0, 0); + return NULL; + } +#endif + + /* Parse the Address */ + + if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) + { + PRMSG (1,"TRANS(Open): Unable to Parse address %s\n", address, 0, 0); + return NULL; + } + + /* Determine the transport type */ + + if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) + { + PRMSG (1,"TRANS(Open): Unable to find transport for %s\n", + protocol, 0, 0); + + free (protocol); + free (host); + free (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,"TRANS(Open): Unknown Open type %d\n", type, 0, 0); + } + + if (ciptr == NULL) + { + PRMSG (1,"TRANS(Open): transport open failed for %s/%s:%s\n", + protocol, host, port); + free (protocol); + free (host); + free (port); + return NULL; + } + + ciptr->transptr = thistrans; + ciptr->port = port; /* We need this for TRANS(Reopen) */ + + free (protocol); + free (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) (type, trans_id, fd, port) + +int type; +int trans_id; +int fd; +char *port; + +{ + XtransConnInfo ciptr = NULL; + Xtransport *thistrans = NULL; + char *save_port; + int i; + + PRMSG (2,"TRANS(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,"TRANS(Reopen): Unable to find transport id %d\n", + trans_id, 0, 0); + + return NULL; + } + + if ((save_port = (char *) malloc (strlen (port) + 1)) == NULL) + { + PRMSG (1,"TRANS(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,"TRANS(Reopen): Bad Open type %d\n", type, 0, 0); + } + + if (ciptr == NULL) + { + PRMSG (1,"TRANS(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) (address) + +char *address; + +{ + PRMSG (2,"TRANS(OpenCOTSClient) (%s)\n", address, 0, 0); + return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); +} + +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER + +XtransConnInfo +TRANS(OpenCOTSServer) (address) + +char *address; + +{ + PRMSG (2,"TRANS(OpenCOTSServer) (%s)\n", address, 0, 0); + return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +XtransConnInfo +TRANS(OpenCLTSClient) (address) + +char *address; +{ + PRMSG (2,"TRANS(OpenCLTSClient) (%s)\n", address, 0, 0); + return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address); +} + +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER + +XtransConnInfo +TRANS(OpenCLTSServer) (address) + +char *address; + +{ + PRMSG (2,"TRANS(OpenCLTSServer) (%s)\n", address, 0, 0); + return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address); +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN + +XtransConnInfo +TRANS(ReopenCOTSServer) (trans_id, fd, port) + +int trans_id; +int fd; +char *port; + +{ + PRMSG (2,"TRANS(ReopenCOTSServer) (%d, %d, %s)\n", trans_id, fd, port); + return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); +} + +XtransConnInfo +TRANS(ReopenCLTSServer) (trans_id, fd, port) + +int trans_id; +int fd; +char *port; + +{ + PRMSG (2,"TRANS(ReopenCLTSServer) (%d, %d, %s)\n", trans_id, fd, port); + return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port); +} + + +int +TRANS(GetReopenInfo) (ciptr, trans_id, fd, port) + +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 *) malloc (strlen (ciptr->port) + 1)) == NULL) + return 0; + else + { + strcpy (*port, ciptr->port); + return 1; + } + } + + return 0; +} + +#endif /* TRANS_REOPEN */ + + +int +TRANS(SetOption) (ciptr, option, arg) + +XtransConnInfo ciptr; +int option; +int arg; + +{ + int fd = ciptr->fd; + int ret = 0; + + PRMSG (2,"TRANS(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)) + 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(FIONBIO) + { + int arg; + arg = 1; + ret = ioctl (fd, FIONBIO, &arg); + } +#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) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + return ciptr->transptr->CreateListener (ciptr, port); +} + + +int +TRANS(ResetListener) (ciptr) + +XtransConnInfo ciptr; + +{ + if (ciptr->transptr->ResetListener) + return ciptr->transptr->ResetListener (ciptr); + else + return TRANS_RESET_NOOP; +} + + +XtransConnInfo +TRANS(Accept) (ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + + PRMSG (2,"TRANS(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) (ciptr, address) + +XtransConnInfo ciptr; +char *address; + +{ + char *protocol; + char *host; + char *port; + int ret; + + PRMSG (2,"TRANS(Connect) (%d,%s)\n", ciptr->fd, address, 0); + + if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) + { + PRMSG (1,"TRANS(Connect): Unable to Parse address %s\n", + address, 0, 0); + return -1; + } + + if (!port || !*port) + { + PRMSG (1,"TRANS(Connect): Missing port specification in %s\n", + address, 0, 0); + if (protocol) free (protocol); + if (host) free (host); + return -1; + } + + ret = ciptr->transptr->Connect (ciptr, host, port); + + if (protocol) free (protocol); + if (host) free (host); + if (port) free (port); + + return ret; +} + +#endif /* TRANS_CLIENT */ + + +int +TRANS(BytesReadable) (ciptr, pend) + +XtransConnInfo ciptr; +BytesReadable_t *pend; + +{ + return ciptr->transptr->BytesReadable (ciptr, pend); +} + +int +TRANS(Read) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + return ciptr->transptr->Read (ciptr, buf, size); +} + +int +TRANS(Write) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + return ciptr->transptr->Write (ciptr, buf, size); +} + +int +TRANS(Readv) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; +{ + return ciptr->transptr->Readv (ciptr, buf, size); +} + +int +TRANS(Writev) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + return ciptr->transptr->Writev (ciptr, buf, size); +} + +int +TRANS(Disconnect) (ciptr) + +XtransConnInfo ciptr; + +{ + return ciptr->transptr->Disconnect (ciptr); +} + +int +TRANS(Close) (ciptr) + +XtransConnInfo ciptr; + +{ + int ret; + + PRMSG (2,"TRANS(Close) (%d)\n", ciptr->fd, 0, 0); + + ret = ciptr->transptr->Close (ciptr); + + TRANS(FreeConnInfo) (ciptr); + + return ret; +} + +int +TRANS(CloseForCloning) (ciptr) + +XtransConnInfo ciptr; + +{ + int ret; + + PRMSG (2,"TRANS(CloseForCloning) (%d)\n", ciptr->fd, 0, 0); + + ret = ciptr->transptr->CloseForCloning (ciptr); + + TRANS(FreeConnInfo) (ciptr); + + return ret; +} + +int +TRANS(IsLocal) (ciptr) + +XtransConnInfo ciptr; + +{ + return (ciptr->family == AF_UNIX); +} + + +int +TRANS(GetMyAddr) (ciptr, familyp, addrlenp, addrp) + +XtransConnInfo ciptr; +int *familyp; +int *addrlenp; +Xtransaddr **addrp; + +{ + PRMSG (2,"TRANS(GetMyAddr) (%d)\n", ciptr->fd, 0, 0); + + *familyp = ciptr->family; + *addrlenp = ciptr->addrlen; + + if ((*addrp = (Xtransaddr *) malloc (ciptr->addrlen)) == NULL) + { + PRMSG (1,"TRANS(GetMyAddr) malloc failed\n", 0, 0, 0); + return -1; + } + memcpy(*addrp, ciptr->addr, ciptr->addrlen); + + return 0; +} + +int +TRANS(GetPeerAddr) (ciptr, familyp, addrlenp, addrp) + +XtransConnInfo ciptr; +int *familyp; +int *addrlenp; +Xtransaddr **addrp; + +{ + PRMSG (2,"TRANS(GetPeerAddr) (%d)\n", ciptr->fd, 0, 0); + + *familyp = ciptr->family; + *addrlenp = ciptr->peeraddrlen; + + if ((*addrp = (Xtransaddr *) malloc (ciptr->peeraddrlen)) == NULL) + { + PRMSG (1,"TRANS(GetPeerAddr) malloc failed\n", 0, 0, 0); + return -1; + } + memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); + + return 0; +} + + +int +TRANS(GetConnectionNumber) (ciptr) + +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. + */ + +static int +complete_network_count () + +{ + 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) + continue; + + if (Xtransports[i].transport->flags & TRANS_LOCAL) + found_local = 1; + else + count++; + } + + return (count + found_local); +} + + +#ifdef TRANS_SERVER + +int +TRANS(MakeAllCOTSServerListeners) (port, partial, count_ret, ciptrs_ret) + +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,"TRANS(MakeAllCOTSServerListeners) (%s,%x)\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) + continue; + + sprintf(buffer,"%s/:%s", trans->TransName, port ? port : ""); + + PRMSG (5,"TRANS(MakeAllCOTSServerListeners) opening %s\n", + buffer, 0, 0); + + if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) + { + PRMSG (1, + "TRANS(MakeAllCOTSServerListeners) failed to open listener for %s\n", + trans->TransName, 0, 0); + continue; + } + + if ((status = TRANS(CreateListener (ciptr, port))) < 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, + "TRANS(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, + "TRANS(MakeAllCOTSServerListeners) failed to create listener for %s\n", + trans->TransName, 0, 0); + + continue; + } + } + + PRMSG (5, + "TRANS(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, + "TRANS(MakeAllCLTSServerListeners) partial=%d, actual=%d, complete=%d \n", + *partial, *count_ret, complete_network_count()); + + if (*count_ret > 0) + { + if ((*ciptrs_ret = (XtransConnInfo *) malloc ( + *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) (port, partial, count_ret, ciptrs_ret) + +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,"TRANS(MakeAllCLTSServerListeners) (%s,%x)\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) + continue; + + sprintf(buffer,"%s/:%s", trans->TransName, port ? port : ""); + + PRMSG (5,"TRANS(MakeAllCLTSServerListeners) opening %s\n", + buffer, 0, 0); + + if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL) + { + PRMSG (1, + "TRANS(MakeAllCLTSServerListeners) failed to open listener for %s\n", + trans->TransName, 0, 0); + continue; + } + + if ((status = TRANS(CreateListener (ciptr, port))) < 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, + "TRANS(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, + "TRANS(MakeAllCLTSServerListeners) failed to create listener for %s\n", + trans->TransName, 0, 0); + + continue; + } + } + + PRMSG (5, + "TRANS(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, + "TRANS(MakeAllCLTSServerListeners) partial=%d, actual=%d, complete=%d \n", + *partial, *count_ret, complete_network_count()); + + if (*count_ret > 0) + { + if ((*ciptrs_ret = (XtransConnInfo *) malloc ( + *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) (ciptr, iov, iovcnt) + +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) (ciptr, iov, iovcnt) + +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(WIN32) || defined(__sxg__) || defined(SCO) + +/* + * emulate readv + */ + +static int TRANS(ReadV) (ciptr, iov, iovcnt) + +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 && SYSV386 || WIN32 || __sxg__ || SCO */ + +#if defined(WIN32) || defined(__sxg__) || defined(SCO) + +/* + * emulate writev + */ + +static int TRANS(WriteV) (ciptr, iov, iovcnt) + +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 /* WIN32 || __sxg__ || SCO */ + + +#if (defined(_POSIX_SOURCE) && !defined(AIXV3)) || defined(hpux) || defined(USG) || defined(SVR4) +#define NEED_UTSNAME +#include +#endif + +/* + * TRANS(GetHostname) - similar to gethostname but allows special processing. + */ + +int TRANS(GetHostname) (buf, maxlen) + +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/Xtrans.h b/Xtrans.h new file mode 100644 index 0000000..cdba474 --- /dev/null +++ b/Xtrans.h @@ -0,0 +1,489 @@ +/* $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. + +*/ + +/* 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 +#include + + +/* + * Set the functions names according to where this code is being compiled. + */ + +#ifdef X11_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _X11Trans##func +#else +#define TRANS(func) _X11Trans/**/func +#endif +#endif /* X11_t */ + +#ifdef XSERV_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _XSERVTrans##func +#else +#define TRANS(func) _XSERVTrans/**/func +#endif +#define X11_t +#endif /* X11_t */ + +#ifdef XIM_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _XimXTrans##func +#else +#define TRANS(func) _XimXTrans/**/func +#endif +#endif /* XIM_t */ + +#ifdef FS_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _FSTrans##func +#else +#define TRANS(func) _FSTrans/**/func +#endif +#endif /* FS_t */ + +#ifdef FONT_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _FontTrans##func +#else +#define TRANS(func) _FontTrans/**/func +#endif +#endif /* FONT_t */ + +#ifdef ICE_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _IceTrans##func +#else +#define TRANS(func) _IceTrans/**/func +#endif +#endif /* ICE_t */ + +#ifdef TEST_t +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _TESTTrans##func +#else +#define TRANS(func) _TESTTrans/**/func +#endif +#endif /* TEST_t */ + +#ifdef LBXPROXY_t +#if (defined(__STDC__) && !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 */ +#endif /* LBXPROXY_t */ + +#if !defined(TRANS) +#if (defined(__STDC__) && !defined(UNIXCPP)) || defined(ANSICPP) +#define TRANS(func) _XTrans##func +#else +#define TRANS(func) _XTrans/**/func +#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. + */ + +#define XTRANS_MAX_ADDR_LEN 128 /* large enough to hold sun_path */ + +typedef struct { + unsigned char addr[XTRANS_MAX_ADDR_LEN]; +} Xtransaddr; + + +#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 . See the readv(2) and writev(2) + * manual pages for details. + */ + +struct iovec { + caddr_t iov_base; + int iov_len; +}; + +#else +#include +#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 + + +/* + * 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 + */ + +#ifdef TRANS_CLIENT + +XtransConnInfo TRANS(OpenCOTSClient)( +#if NeedFunctionPrototypes + char * /* address */ +#endif +); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + +XtransConnInfo TRANS(OpenCOTSServer)( +#if NeedFunctionPrototypes + char * /* address */ +#endif +); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + +XtransConnInfo TRANS(OpenCLTSClient)( +#if NeedFunctionPrototypes + char * /* address */ +#endif +); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + +XtransConnInfo TRANS(OpenCLTSServer)( +#if NeedFunctionPrototypes + char * /* address */ +#endif +); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_REOPEN + +XtransConnInfo TRANS(ReopenCOTSServer)( +#if NeedFunctionPrototypes + int, /* trans_id */ + int, /* fd */ + char * /* port */ +#endif +); + +XtransConnInfo TRANS(ReopenCLTSServer)( +#if NeedFunctionPrototypes + int, /* trans_id */ + int, /* fd */ + char * /* port */ +#endif +); + +int TRANS(GetReopenInfo)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + int *, /* trans_id */ + int *, /* fd */ + char ** /* port */ +#endif +); + +#endif /* TRANS_REOPEN */ + + +int TRANS(SetOption)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + int, /* option */ + int /* arg */ +#endif +); + +#ifdef TRANS_SERVER + +int TRANS(CreateListener)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + char * /* port */ +#endif +); + +int TRANS(ResetListener)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +XtransConnInfo TRANS(Accept)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + int * /* status */ +#endif +); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + +int TRANS(Connect)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + char * /* address */ +#endif +); + +#endif /* TRANS_CLIENT */ + +int TRANS(BytesReadable)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + BytesReadable_t * /* pend */ +#endif +); + +int TRANS(Read)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + char *, /* buf */ + int /* size */ +#endif +); + +int TRANS(Write)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + char *, /* buf */ + int /* size */ +#endif +); + +int TRANS(Readv)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + struct iovec *, /* buf */ + int /* size */ +#endif +); + +int TRANS(Writev)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + struct iovec *, /* buf */ + int /* size */ +#endif +); + +int TRANS(Disconnect)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +int TRANS(Close)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +int TRANS(CloseForCloning)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +int TRANS(IsLocal)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +int TRANS(GetMyAddr)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + int *, /* familyp */ + int *, /* addrlenp */ + Xtransaddr ** /* addrp */ +#endif +); + +int TRANS(GetPeerAddr)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + int *, /* familyp */ + int *, /* addrlenp */ + Xtransaddr ** /* addrp */ +#endif +); + +int TRANS(GetConnectionNumber)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +#ifdef TRANS_SERVER + +int TRANS(MakeAllCOTSServerListeners)( +#if NeedFunctionPrototypes + char *, /* port */ + int *, /* partial */ + int *, /* count_ret */ + XtransConnInfo ** /* ciptrs_ret */ +#endif +); + +int TRANS(MakeAllCLTSServerListeners)( +#if NeedFunctionPrototypes + char *, /* port */ + int *, /* partial */ + int *, /* count_ret */ + XtransConnInfo ** /* ciptrs_ret */ +#endif +); + +#endif /* TRANS_SERVER */ + + +/* + * Function Prototypes for Utility Functions. + */ + +#ifdef X11_t + +int TRANS(ConvertAddress)( +#if NeedFunctionPrototypes + int *, /* familyp */ + int *, /* addrlenp */ + Xtransaddr ** /* addrp */ +#endif +); + +#endif /* X11_t */ + +#ifdef ICE_t + +char * +TRANS(GetMyNetworkId)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +char * +TRANS(GetPeerNetworkId)( +#if NeedFunctionPrototypes + XtransConnInfo /* ciptr */ +#endif +); + +#endif /* ICE_t */ + +#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN)) +int TRANS(WSAStartup)(); +#endif + +#endif /* _XTRANS_H_ */ diff --git a/Xtransdnet.c b/Xtransdnet.c new file mode 100644 index 0000000..55a618c --- /dev/null +++ b/Xtransdnet.c @@ -0,0 +1,704 @@ +/* $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. + +*/ + +/* 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 +#include +#include +#endif /* !WIN32 */ + +#include + +#ifdef WIN32 +#define _WILLWINSOCK_ +#define BOOL wBOOL +#undef Status +#define Status wStatus +#include /* PATHWORKS header normally in %MSTOOLS%\h\pathwork */ +#undef Status +#define Status int +#undef BOOL +#include +#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) (ciptr) + +XtransConnInfo ciptr; + +{ + struct sockaddr_dn sockname; + int namelen = sizeof(sockname); + + PRMSG (3,"TRANS(DNETGetAddr) (%x)\n", ciptr, 0, 0); + + if (getsockname (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"TRANS(DNETGetAddr): getsockname() failed: %d\n", + EGET(), 0, 0); + return -1; + } + + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->addr = (char *) malloc (namelen)) == NULL) + { + PRMSG (1, "TRANS(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) (ciptr) + +XtransConnInfo ciptr; + +{ + struct sockaddr_dn sockname; + int namelen = sizeof(sockname); + + PRMSG (3,"TRANS(DNETGetPeerAddr) (%x)\n", ciptr, 0, 0); + + if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"TRANS(DNETGetPeerAddr): getpeername() failed: %d\n", + EGET(), 0, 0); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->peeraddr = (char *) malloc (namelen)) == NULL) + { + PRMSG (1, + "TRANS(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) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (2,"TRANS(DNETOpenCOTSClient) (%s,%s,%s)\n", protocol, host, port); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (2,"TRANS(DNETOpenCOTSServer) (%s,%s,%s)\n", protocol, host, port); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(DNETOpenCOTSServer): malloc failed\n", 0, 0, 0); + return NULL; + } + + if ((ciptr->fd = socket (AF_DECnet, SOCK_STREAM, 0)) < 0) + { + free ((char *) ciptr); + return NULL; + } + + ciptr->index = 0; /* only one form of DECnet */ + + return (ciptr); +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(DNETOpenCLTSClient) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (2,"TRANS(DNETOpenCLTSClient) (%s,%s,%s)\n", protocol, host, port); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof (struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + /* NEED TO IMPLEMENT */ + + PRMSG (2,"TRANS(DNETOpenCLTSServer) (%s,%s,%s)\n", protocol, host, port); + return NULL; +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN + +static XtransConnInfo +TRANS(DNETReopenCOTSServer) (thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (2,"TRANS(DNETReopenCOTSServer) (%d, %s)\n", fd, port, 0); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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) (thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (2,"TRANS(DNETReopenCLTSServer) (%d, %s)\n", fd, port, 0); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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) (ciptr, option, arg) + +XtransConnInfo ciptr; +int option; +int arg; + +{ + PRMSG (2,"TRANS(DNETSetOption) (%d,%d,%d)\n", ciptr->fd, option, arg); + + return -1; +} + + +#ifdef TRANS_SERVER + +static int +TRANS(DNETCreateListener) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct sockaddr_dn dnsock; + int fd = ciptr->fd; + + PRMSG (3, "TRANS(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; + + return 0; +} + + +static XtransConnInfo +TRANS(DNETAccept) (ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + struct sockaddr_dn sockname; + int namelen = sizeof(sockname); + + PRMSG (2, "TRANS(DNETAccept) (%x,%d)\n", ciptr, ciptr->fd, 0); + + if ((newciptr = (XtransConnInfo) calloc( + 1, sizeof (struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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, "TRANS(DNETAccept): accept() failed\n", 0, 0, 0); + + free (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, + "TRANS(DNETAccept): TRANS(DNETGetAddr)() failed:\n", 0, 0, 0); + close (newciptr->fd); + free (newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if (TRANS(DNETGetPeerAddr) (newciptr) < 0) + { + PRMSG(1, + "TRANS(DNETAccept): TRANS(DNETGetPeerAddr)() failed:\n", 0, 0, 0); + + close (newciptr->fd); + if (newciptr->addr) free (newciptr->addr); + free (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) (ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + char objname[OBJBUFSIZE]; + + extern int dnet_conn(); + + PRMSG (2,"TRANS(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, + "TRANS(DNETConnect): TRANS(DNETGetAddr) () failed:\n", 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + if (TRANS(DNETGetPeerAddr) (ciptr) < 0) + { + PRMSG (1, + "TRANS(DNETConnect): TRANS(DNETGetPeerAddr) () failed:\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + return 0; +} + +#endif /* TRANS_CLIENT */ + + +static int +TRANS(DNETBytesReadable) (ciptr, pend) + +XtransConnInfo ciptr; +BytesReadable_t *pend; + +{ + PRMSG (2,"TRANS(DNETBytesReadable) (%x,%d,%x)\n", ciptr, ciptr->fd, pend); + +#ifdef WIN32 + return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); +#else + return ioctl(ciptr->fd, FIONREAD, (char *)pend); +#endif /* WIN32 */ +} + + +static int +TRANS(DNETRead) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG (2,"TRANS(DNETRead) (%d,%x,%d)\n", ciptr->fd, buf, size); + +#ifdef WIN32 + return recv ((SOCKET)ciptr->fd, buf, size, 0); +#else + return read (ciptr->fd, buf, size); +#endif /* WIN32 */ +} + + +static int +TRANS(DNETWrite) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG (2,"TRANS(DNETWrite) (%d,%x,%d)\n", ciptr->fd, buf, size); + +#ifdef WIN32 + return send ((SOCKET)ciptr->fd, buf, size, 0); +#else + return write (ciptr->fd, buf, size); +#endif /* WIN32 */ +} + + +static int +TRANS(DNETReadv) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG (2,"TRANS(DNETReadv) (%d,%x,%d)\n", ciptr->fd, buf, size); + + return READV (ciptr, buf, size); +} + + +static int +TRANS(DNETWritev) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG (2,"TRANS(DNETWritev) (%d,%x,%d)\n", ciptr->fd, buf, size); + + return WRITEV (ciptr, buf, size); +} + + +static int +TRANS(DNETDisconnect) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (2,"TRANS(DNETDisconnect) (%x,%d)\n", ciptr, ciptr->fd, 0); + + return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ +} + + +static int +TRANS(DNETClose) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (2,"TRANS(DNETClose) (%x,%d)\n", ciptr, ciptr->fd, 0); + + return close (ciptr->fd); +} + + +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/Xtransint.h b/Xtransint.h new file mode 100644 index 0000000..29c8522 --- /dev/null +++ b/Xtransint.h @@ -0,0 +1,432 @@ +/* $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. + +*/ + +/* 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. + */ + +/* + * 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 + */ + +#ifndef _XTRANSINT_H_ +#define _XTRANSINT_H_ + +#ifdef WIN32 +#define _WILLWINSOCK_ +#endif + +#include "Xtrans.h" + +#ifdef XTRANSDEBUG +#include +#endif /* XTRANSDEBUG */ + +#include +#ifdef X_NOT_STDC_ENV +extern int errno; /* Internal system error number. */ +#endif + +#ifndef WIN32 +#include + +/* + * 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 +#else +#define _POSIX_SOURCE +#include +#undef _POSIX_SOURCE +#endif +#endif +#ifndef OPEN_MAX +#ifdef SVR4 +#define OPEN_MAX 256 +#else +#include +#ifndef OPEN_MAX +#ifdef __OSF1__ +#define OPEN_MAX 256 +#else +#ifdef NOFILE +#define OPEN_MAX NOFILE +#else +#define OPEN_MAX NOFILES_MAX +#endif +#endif +#endif +#endif +#endif + +#if OPEN_MAX > 256 +#define TRANS_OPEN_MAX 256 +#else +#define TRANS_OPEN_MAX OPEN_MAX +#endif + +#endif /* TRANS_OPEN_MAX */ + + +#define ESET(val) errno = val +#define EGET() errno + +#else /* WIN32 */ + +#include /* for USHRT_MAX */ + +#define ESET(val) WSASetLastError(val) +#define EGET() WSAGetLastError() + +#endif /* WIN32 */ + +#ifndef NULL +#define NULL 0 +#endif + +#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)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + char *, /* protocol */ + char *, /* host */ + char * /* port */ +#endif + ); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + + XtransConnInfo (*OpenCOTSServer)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + char *, /* protocol */ + char *, /* host */ + char * /* port */ +#endif + ); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + + XtransConnInfo (*OpenCLTSClient)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + char *, /* protocol */ + char *, /* host */ + char * /* port */ +#endif + ); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + + XtransConnInfo (*OpenCLTSServer)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + char *, /* protocol */ + char *, /* host */ + char * /* port */ +#endif + ); + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN + + XtransConnInfo (*ReopenCOTSServer)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + int, /* fd */ + char * /* port */ +#endif + ); + + XtransConnInfo (*ReopenCLTSServer)( +#if NeedNestedPrototypes + struct _Xtransport *, /* transport */ + int, /* fd */ + char * /* port */ +#endif + ); + +#endif /* TRANS_REOPEN */ + + + int (*SetOption)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + int, /* option */ + int /* arg */ +#endif + ); + +#ifdef TRANS_SERVER + + int (*CreateListener)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + char * /* port */ +#endif + ); + + int (*ResetListener)( +#if NeedNestedPrototypes + XtransConnInfo /* connection */ +#endif + ); + + XtransConnInfo (*Accept)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + int * /* status */ +#endif + ); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + + int (*Connect)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + char *, /* host */ + char * /* port */ +#endif + ); + +#endif /* TRANS_CLIENT */ + + int (*BytesReadable)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + BytesReadable_t * /* pend */ +#endif + ); + + int (*Read)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + char *, /* buf */ + int /* size */ +#endif + ); + + int (*Write)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + char *, /* buf */ + int /* size */ +#endif + ); + + int (*Readv)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + struct iovec *, /* buf */ + int /* size */ +#endif + ); + + int (*Writev)( +#if NeedNestedPrototypes + XtransConnInfo, /* connection */ + struct iovec *, /* buf */ + int /* size */ +#endif + ); + + int (*Disconnect)( +#if NeedNestedPrototypes + XtransConnInfo /* connection */ +#endif + ); + + int (*Close)( +#if NeedNestedPrototypes + XtransConnInfo /* connection */ +#endif + ); + + int (*CloseForCloning)( +#if NeedNestedPrototypes + XtransConnInfo /* connection */ +#endif + ); + +} 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 */ + + +/* + * 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(SYSV386)) || defined(WIN32) || defined(__sxg__) || defined(sco324) + +#define READV(ciptr, iov, iovcnt) TRANS(ReadV)(ciptr, iov, iovcnt) + +static int TRANS(ReadV)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + struct iovec *, /* iov */ + int /* iovcnt */ +#endif +); + +#else + +#define READV(ciptr, iov, iovcnt) readv(ciptr->fd, iov, iovcnt) + +#endif /* CRAY || (SYSV && SYSV386) || WIN32 || __sxg__ || sco324 */ + + +#if defined(CRAY) || defined(WIN32) || defined(__sxg__) || defined(sco324) + +#define WRITEV(ciptr, iov, iovcnt) TRANS(WriteV)(ciptr, iov, iovcnt) + +static int TRANS(WriteV)( +#if NeedFunctionPrototypes + XtransConnInfo, /* ciptr */ + struct iovec *, /* iov */ + int /* iovcnt */ +#endif +); + +#else + +#define WRITEV(ciptr, iov, iovcnt) writev(ciptr->fd, iov, iovcnt) + +#endif /* CRAY || WIN32 || __sxg__ || sco324 */ + + +static int is_numeric ( +#if NeedFunctionPrototypes + char * /* str */ +#endif +); + + +/* + * Some XTRANSDEBUG stuff + */ + +#if defined(XTRANSDEBUG) +#define PRMSG(lvl,x,a,b,c) if (lvl <= XTRANSDEBUG){ \ + int saveerrno=errno; \ + fprintf(stderr, x,a,b,c); fflush(stderr); \ + errno=saveerrno; \ + } +#else +#define PRMSG(lvl,x,a,b,c) +#endif /* XTRANSDEBUG */ + +#endif /* _XTRANSINT_H_ */ diff --git a/Xtranslcl.c b/Xtranslcl.c new file mode 100644 index 0000000..1dde90f --- /dev/null +++ b/Xtranslcl.c @@ -0,0 +1,2715 @@ +/* $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. + +*/ + +/* 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 +#include +#include +#include +#include +#if 0 +#include /* Maybe for SVR4 only?? */ +#endif +#ifdef SVR4 +#include +#endif +#include +#include +#include + +/* + * 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 +#include + + +/* + * These functions actually implement the local connection mechanisms. + */ + +/* Type Not Supported */ + +static int +TRANS(OpenFail)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + return -1; +} + +#ifdef TRANS_REOPEN + +static int +TRANS(ReopenFail)(ciptr, fd, port) + +XtransConnInfo ciptr; +int fd; +char *port; + +{ + return 0; +} + +#endif /* TRANS_REOPEN */ + + + +static int +TRANS(FillAddrInfo)(ciptr, sun_path, peer_sun_path) + +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 *) malloc (ciptr->addrlen)) == NULL) + { + PRMSG(1,"TRANS(FillAddrInfo)() failed to allocate memory for addr\n", + 0,0,0); + return 0; + } + + sunaddr->sun_family = AF_UNIX; + + strcpy (sunaddr->sun_path, sun_path); +#ifdef BSD44SOCKETS + sunaddr->sun_len = strlen (sunaddr->sun_path); +#endif + + ciptr->addr = (char *) sunaddr; + + ciptr->peeraddrlen = sizeof (struct sockaddr_un); + + if ((p_sunaddr = (struct sockaddr_un *) malloc ( + ciptr->peeraddrlen)) == NULL) + { + PRMSG(1, + "TRANS(FillAddrInfo)() failed to allocate memory for peer addr\n", + 0,0,0); + free ((char *) sunaddr); + ciptr->addr = NULL; + + return 0; + } + + p_sunaddr->sun_family = AF_UNIX; + + strcpy (p_sunaddr->sun_path, peer_sun_path); +#ifdef BSD44SOCKETS + p_sunaddr->sun_len = strlen (p_sunaddr->sun_path); +#endif + + ciptr->peeraddr = (char *) p_sunaddr; + + return 1; +} + + + +/* PTS */ + +#if defined(SYSV) && !defined(sco) +#define SIGNAL_T int +#else +#define SIGNAL_T void +#endif /* SYSV */ + +typedef SIGNAL_T (*PFV)(); + +extern PFV signal(); + +extern char *ptsname( +#if NeedFunctionPrototypes + int +#endif +); + +static void _dummy(sig) + +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 +#define DEV_PTMX "/dev/ptmx" + +#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 and SCO are only defined for X11 since they are there for + * backwards binary compatability only. + */ + +#define X_ISC_DIR "/dev/X" +#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." +#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." +#endif +#if defined(ICE_t) +#define PTSNODENAME "/dev/X/ICE." +#define NAMEDNODENAME "/dev/X/NICE." +#endif +#if defined(TEST_t) +#define PTSNODENAME "/dev/X/transtest." +#define NAMEDNODENAME "/dev/X/Ntranstest." +#endif + + + +#ifndef sun +#ifdef TRANS_CLIENT + +static int +TRANS(PTSOpenClient)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + 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; + + PRMSG(2,"TRANS(PTSOpenClient)(%s)\n", port, 0,0 ); + +#if !defined(PTSNODENAME) + PRMSG(1,"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,"TRANS(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,"TRANS(PTSOpenClient)() failed to open /dev/ptmx\n", 0,0,0); + return -1; + } + + (void) grantpt(fd); + (void) unlockpt(fd); + + slave = ptsname(fd); /* get name */ + + if( slave == NULL ) { + PRMSG(1,"TRANS(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(); + setuid( getuid() ); /** sets the euid to the actual/real uid **/ + if( chown( slave, saved_euid, -1 ) < 0 ) { + exit( 1 ); + } + + exit( 0 ); + } + + waitpid(saved_pid, &exitval, 0); + + if (chmod(slave, 0666) < 0) { + close(fd); + close(server); + PRMSG(1,"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, + "TRANS(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,"TRANS(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)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd, server; + char server_path[64], *slave; + + PRMSG(2,"TRANS(PTSOpenServer)(%s)\n", port, 0,0 ); + +#if !defined(PTSNODENAME) + PRMSG(1,"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 + mkdir(X_STREAMS_DIR, 01777); + chmod(X_STREAMS_DIR, 01777); +#else + mkdir(X_STREAMS_DIR, 0777); + chmod(X_STREAMS_DIR, 0777); +#endif + + if( (fd=open(server_path, O_RDWR)) >= 0 ) { + PRMSG(1, "A server is already running on port %s\n", port, 0,0 ); + PRMSG(1, "Remove %s if this is incorrect.\n", server_path, 0,0 ); + close(fd); + return(-1); + } + + unlink(server_path); + + if( (fd=open(DEV_PTMX, O_RDWR)) < 0) { + PRMSG(1, "Unable to open %s\n", DEV_PTMX, 0,0 ); + return(-1); + } + + grantpt(fd); + unlockpt(fd); + + if( (slave=ptsname(fd)) == NULL) { + PRMSG(1, "Unable to get slave device name\n", 0,0,0 ); + close(fd); + return(-1); + } + + if( link(slave,server_path) < 0 ) { + PRMSG(1, "Unable to link %s to %s\n", slave, server_path,0 ); + close(fd); + return(-1); + } + + if( chmod(server_path, 0666) < 0 ) { + PRMSG(1, "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, "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,"TRANS(PTSOpenServer)() failed to fill in addr info\n", + 0,0,0); + close(fd); + return -1; + } + + return fd; + +#endif /* !PTSNODENAME */ +} + +static int +TRANS(PTSAccept)(ciptr, newciptr, status) + +XtransConnInfo ciptr; +XtransConnInfo newciptr; +int *status; + +{ + int newfd; + int in; + unsigned char length; + char buf[256]; + struct sockaddr_un *sunaddr; + + PRMSG(2,"TRANS(PTSAccept)(%x->%d)\n",ciptr,ciptr->fd,0); + + if( (in=read(ciptr->fd,&length,1)) <= 0 ){ + if( !in ) { + PRMSG(1, + "TRANS(PTSAccept)() Incoming connection closed\n",0,0,0); + } + else { + PRMSG(1, + "TRANS(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(1, + "TRANS(PTSAccept)() Incoming connection closed\n",0,0,0); + } + else { + PRMSG(1, +"TRANS(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, "TRANS(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 *)malloc(newciptr->addrlen)) == NULL ) { + PRMSG(1,"TRANS(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 *)malloc(newciptr->peeraddrlen)) == NULL ) { + PRMSG(1,"TRANS(PTSAccept)() failed to allocate memory for peer addr\n", + 0,0,0); + free(newciptr->addr); + close(newfd); + *status = TRANS_ACCEPT_BAD_MALLOC; + return -1; + } + + sunaddr->sun_family=AF_UNIX; + strcpy(sunaddr->sun_path,buf); +#ifdef BSD44SOCKETS + 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)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd; + char server_path[64]; + struct stat filestat; + extern int isastream(); + + PRMSG(2,"TRANS(NAMEDOpenClient)(%s)\n", port, 0,0 ); + +#if !defined(NAMEDNODENAME) + PRMSG(1,"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%d", NAMEDNODENAME, getpid()); + } + + if (stat(server_path, &filestat) < 0 ) { + PRMSG(1,"No device %s for NAMED connection\n", server_path, 0,0 ); + return -1; + } + + if ((filestat.st_mode & S_IFMT) != S_IFIFO) { + PRMSG(1,"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,"Cannot open %s for NAMED connection\n", server_path, 0,0 ); + return -1; + } + + if (isastream(fd) <= 0) { + PRMSG(1,"%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,"TRANS(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)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd, pipefd[2]; + char server_path[64]; + struct stat sbuf; + + PRMSG(2,"TRANS(NAMEDOpenServer)(%s)\n", port, 0,0 ); + +#if !defined(NAMEDNODENAME) + PRMSG(1,"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%d", NAMEDNODENAME, getpid()); + } + +#ifdef HAS_STICKY_DIR_BIT + mkdir(X_STREAMS_DIR, 01777); + chmod(X_STREAMS_DIR, 01777); +#else + mkdir(X_STREAMS_DIR, 0777); + chmod(X_STREAMS_DIR, 0777); +#endif + + if(stat(server_path, &sbuf) != 0) { + if (errno == ENOENT) { + if ((fd = creat(server_path, (mode_t)0666)) == -1) { + PRMSG(1, "Can't open %s\n", server_path, 0,0 ); + return(-1); + } + close(fd); + if (chmod(server_path, (mode_t)0666) < 0) { + PRMSG(1, "Can't open %s\n", server_path, 0,0 ); + return(-1); + } + } else { + PRMSG(1, "stat on %s failed\n", server_path, 0,0 ); + return(-1); + } + } + + if( pipe(pipefd) != 0) { + PRMSG(1, "pipe() failed, errno=%d\n",errno, 0,0 ); + return(-1); + } + + if( ioctl(pipefd[0], I_PUSH, "connld") != 0) { + PRMSG(1, "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, "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,"TRANS(NAMEDOpenServer)() failed to fill in addr info\n", + 0,0,0); + close(fd); + return -1; + } + + return(pipefd[1]); + +#endif /* !NAMEDNODENAME */ +} + +static int +TRANS(NAMEDAccept)(ciptr, newciptr, status) + +XtransConnInfo ciptr; +XtransConnInfo newciptr; +int *status; + +{ + struct strrecvfd str; + + PRMSG(2,"TRANS(NAMEDAccept)(%x->%d)\n", ciptr, ciptr->fd, 0 ); + + if( ioctl(ciptr->fd, I_RECVFD, &str ) < 0 ) { + PRMSG(1, "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 *)malloc(newciptr->addrlen)) == NULL ) { + PRMSG(1, + "TRANS(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 *)malloc(newciptr->peeraddrlen)) == NULL ) { + PRMSG(1, + "TRANS(NAMEDAccept)() failed to allocate memory for peer addr\n", + 0,0,0); + free(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 both the SCO and ISC connection types. + */ +static int +connect_spipe(fd1, fd2) + +int fd1, 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); +} + +/* + * connect_spipe is used by both the SCO and ISC connection types. + */ + +static int +named_spipe(fd, path) + +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); +} + + +/* ISC */ + +#ifdef TRANS_CLIENT + +static int +TRANS(ISCOpenClient)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd,fds,server; + char server_path[64]; + char server_dev_path[64]; + struct strfdinsert buf; + long temp; + mode_t spmode; + struct stat filestat; + + PRMSG(2,"TRANS(ISCOpenClient)(%s)\n", port, 0,0 ); + +#if !defined(ISCDEVNODENAME) + PRMSG(1,"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, "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,"TRANS(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,"TRANS(ISCOpenClient): failed to open %s\n", + server_dev_path, 0,0 ); + } + } + } + } + + if (server < 0) { + PRMSG(1,"TRANS(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,"TRANS(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,"TRANS(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,"TRANS(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)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd = -1,fds = -1; + char server_path[64],server_unix_path[64]; + + PRMSG(2,"TRANS(ISCOpenServer)(%s)\n", port, 0,0 ); + +#if !defined(ISCDEVNODENAME) + PRMSG(1,"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 + mkdir(X_STREAMS_DIR, 01777); /* "/dev/X" */ + chmod(X_STREAMS_DIR, 01777); + mkdir(X_ISC_DIR, 01777); /* "/dev/X/ISCCONN" */ + chmod(X_ISC_DIR, 01777); +#else + mkdir(X_STREAMS_DIR, 0777); /* "/dev/X" */ + chmod(X_STREAMS_DIR, 0777); + mkdir(X_ISC_DIR, 0777); /* "/dev/X/ISCCONN" */ + chmod(X_ISC_DIR, 0777); +#endif + + unlink(server_path); + + if( ((fds=open(DEV_SPX, O_RDWR)) < 0) || + ((fd =open(DEV_SPX, O_RDWR)) < 0)) { + PRMSG(1,"TRANS(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,"TRANS(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" + +#ifdef HAS_STICKY_DIR_BIT + if (!mkdir(X_UNIX_DIR, 01777)) + chmod(X_UNIX_DIR, 01777); +#else + if (!mkdir(X_UNIX_DIR, 0777)) + chmod(X_UNIX_DIR, 0777); +#endif + + 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,"TRANS(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 + if( link(server_path, server_unix_path) < 0 ) + PRMSG(1,"TRANS(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,"TRANS(ISCOpenServer)() failed to fill in addr info\n", + 0,0,0); + close(fd); + return -1; + } + + return fd; + +#endif /* !ISCDEVNODENAME */ +} + +static int +TRANS(ISCAccept)(ciptr, newciptr, status) + +XtransConnInfo ciptr; +XtransConnInfo newciptr; +int *status; + +{ + struct strrecvfd str; + + PRMSG(2,"TRANS(ISCAccept)(%d)\n", ciptr->fd, 0,0 ); + + while (ioctl(ciptr->fd, I_RECVFD, &str) < 0) { + if (errno != EAGAIN) { + PRMSG(1,"TRANS(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 *)malloc(newciptr->addrlen)) == NULL ) { + PRMSG(1, + "TRANS(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 *)malloc(newciptr->peeraddrlen)) == NULL ) { + PRMSG(1, + "TRANS(ISCAccept)() failed to allocate memory for peer addr\n", + 0,0,0); + free(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 */ + + + + +/* SCO */ + +#ifdef TRANS_CLIENT + +static int +TRANS(SCOOpenClient)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + int fd, server, fl, ret; + char server_path[64]; + struct strbuf ctlbuf; + unsigned long alarm_time; + void (*savef)(); + long temp; + extern int getmsg(), putmsg(); + + PRMSG(2,"TRANS(SCOOpenClient)(%s)\n", port, 0,0 ); + +#if !defined(SCORNODENAME) + PRMSG(1,"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,"TRANS(SCOOpenClient) failed to open %s\n", server_path, 0,0 ); + return -1; + } + + if ((fd = open(DEV_SPX, O_RDWR)) < 0) { + PRMSG(1,"TRANS(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,"TRANS(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 (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0) + { + PRMSG(1,"TRANS(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)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + char serverR_path[64]; + char serverS_path[64]; + int fdr = -1; + int fds = -1; + + PRMSG(2,"TRANS(SCOOpenServer)(%s)\n", port, 0,0 ); + +#if !defined(SCORNODENAME) + PRMSG(1,"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); + + unlink(serverR_path); + unlink(serverS_path); + + if ((fds = open(DEV_SPX, O_RDWR)) < 0 || + (fdr = open(DEV_SPX, O_RDWR)) < 0 ) { + PRMSG(2,"TRANS(SCOOpenServer) failed to open %s\n", DEV_SPX, 0,0 ); + return -1; + } + + if (connect_spipe(fds, fdr) != -1 && + named_spipe(fds, serverS_path) != -1 && + named_spipe(fdr, serverR_path) != -1) { + PRMSG(2,"TRANS(SCOOpenServer) connect pipes\n", 0,0,0 ); + } else { + PRMSG(2,"TRANS(SCOOpenServer) failed to connect pipes\n", 0,0,0 ); + close(fds); + close(fdr); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0) + { + PRMSG(1,"TRANS(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)(ciptr, newciptr, status) + +XtransConnInfo ciptr; +XtransConnInfo newciptr; +int *status; + +{ + char c; + int fd; + + PRMSG(2,"TRANS(SCOAccept)(%d)\n", ciptr->fd, 0,0 ); + + if (read(ciptr->fd, &c, 1) < 0) { + PRMSG(1,"TRANS(SCOAccept): can't read from client",0,0,0); + *status = TRANS_ACCEPT_MISC_ERROR; + return(-1); + } + + if( (fd = open(DEV_SPX, O_RDWR)) < 0 ) { + PRMSG(1,"TRANS(SCOAccept)(): can't open \"%s\"",DEV_SPX, 0,0 ); + *status = TRANS_ACCEPT_MISC_ERROR; + return(-1); + } + + if (connect_spipe(ciptr->fd, fd) < 0) { + PRMSG(1,"TRANS(SCOAccept)(): can't connect pipes", 0,0,0 ); + (void) 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 *)malloc(newciptr->addrlen)) == NULL ) { + PRMSG(1, + "TRANS(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); + + newciptr->peeraddrlen=newciptr->addrlen; + if( (newciptr->peeraddr=(char *)malloc(newciptr->peeraddrlen)) == NULL ) { + PRMSG(1, + "TRANS(SCOAccept)() failed to allocate memory for peer addr\n", + 0,0,0); + free(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 + +static int +TRANS(PTSReopenServer)(ciptr, fd, port) + +XtransConnInfo ciptr; +int fd; +char *port; +{ + char server_path[64]; + + PRMSG(2,"TRANS(PTSReopenServer)(%d,%s)\n", fd, port, 0 ); + +#if !defined(PTSNODENAME) + PRMSG(1,"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%d", PTSNODENAME, getpid()); + } + + if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0) + { + PRMSG(1,"TRANS(PTSReopenServer)() failed to fill in addr info\n", + 0,0,0); + return 0; + } + + return 1; + +#endif /* !PTSNODENAME */ +} + + +static int +TRANS(NAMEDReopenServer)(ciptr, fd, port) + +XtransConnInfo ciptr; +int fd; +char *port; + +{ + char server_path[64]; + + PRMSG(2,"TRANS(NAMEDReopenServer)(%s)\n", port, 0,0 ); + +#if !defined(NAMEDNODENAME) + PRMSG(1,"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%d", NAMEDNODENAME, getpid()); + } + + if (TRANS(FillAddrInfo) (ciptr, server_path, server_path) == 0) + { + PRMSG(1,"TRANS(NAMEDReopenServer)() failed to fill in addr info\n", + 0,0,0); + return 0; + } + + return 1; + +#endif /* !NAMEDNODENAME */ +} + + +static int +TRANS(ISCReopenServer)(ciptr, fd, port) + +XtransConnInfo ciptr; +int fd; +char *port; + +{ + char server_path[64],server_unix_path[64]; + + PRMSG(2,"TRANS(ISCReopenServer)(%s)\n", port, 0,0 ); + +#if !defined(ISCDEVNODENAME) + PRMSG(1,"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,"TRANS(ISCReopenServer)() failed to fill in addr info\n", + 0,0,0); + return 0; + } + + return 1; + +#endif /* !ISCDEVNODENAME */ +} + + +static int +TRANS(SCOReopenServer)(ciptr, fd, port) + +XtransConnInfo ciptr; +int fd; +char *port; + +{ + char serverR_path[64]; + char serverS_path[64]; + + PRMSG(2,"TRANS(SCOReopenServer)(%s)\n", port, 0,0 ); + +#if !defined(SCORNODENAME) + PRMSG(1,"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 (TRANS(FillAddrInfo) (ciptr, serverS_path, serverR_path) == 0) + { + PRMSG(1,"TRANS(SCOReopenServer)() failed to fill in addr info\n", + 0,0,0); + return 0; + } + + return 1; + +#endif /* SCORNODENAME */ +} + +#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)( +#if NeedFunctionPrototypes + XtransConnInfo, char * /*port*/ +#endif +); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + + int (*devcotsopenserver)( +#if NeedFunctionPrototypes + XtransConnInfo, char * /*port*/ +#endif +); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_CLIENT + + int (*devcltsopenclient)( +#if NeedFunctionPrototypes + XtransConnInfo, char * /*port*/ +#endif +); + +#endif /* TRANS_CLIENT */ + +#ifdef TRANS_SERVER + + int (*devcltsopenserver)( +#if NeedFunctionPrototypes + XtransConnInfo, char * /*port*/ +#endif +); + +#endif /* TRANS_SERVER */ + +#ifdef TRANS_REOPEN + + int (*devcotsreopenserver)( +#if NeedFunctionPrototypes + XtransConnInfo, + int, /* fd */ + char * /* port */ +#endif +); + + int (*devcltsreopenserver)( +#if NeedFunctionPrototypes + XtransConnInfo, + int, /* fd */ + char * /* port */ +#endif +); + +#endif /* TRANS_REOPEN */ + +#ifdef TRANS_SERVER + + int (*devaccept)( +#if NeedFunctionPrototypes + XtransConnInfo, XtransConnInfo, int * +#endif + +); + +#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 +{"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 */ +}, + +{"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; + +#ifdef sco +#define DEF_XLOCAL "UNIX:SCO:PTS:NAMED:ISC" +#else +#define DEF_XLOCAL "UNIX:PTS:NAMED:ISC:SCO" +#endif + +static void +TRANS(LocalInitTransports)(protocol) + +char *protocol; + +{ + PRMSG(3,"TRANS(LocalInitTransports)(%s)\n", protocol, 0,0 ); + + if( strcmp(protocol,"local") && strcmp(protocol,"LOCAL") ) + { + workingXLOCAL=freeXLOCAL=(char *)malloc (strlen (protocol) + 1); + if (workingXLOCAL) + strcpy (workingXLOCAL, protocol); + } + else { + XLOCAL=(char *)getenv("XLOCAL"); + if(XLOCAL==NULL) + XLOCAL=DEF_XLOCAL; + workingXLOCAL=freeXLOCAL=(char *)malloc (strlen (XLOCAL) + 1); + if (workingXLOCAL) + strcpy (workingXLOCAL, XLOCAL); + } +} + +static void +TRANS(LocalEndTransports)() + +{ + PRMSG(3,"TRANS(LocalEndTransports)()\n", 0,0,0 ); + free(freeXLOCAL); +} + +static LOCALtrans2dev * +TRANS(LocalGetNextTransport)() + +{ + int i,j; + char *typetocheck; +#define TYPEBUFSIZE 32 + char typebuf[TYPEBUFSIZE]; + PRMSG(3,"TRANS(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 +#endif + +/* + * Make sure 'host' is really local. + */ + +static int +HostReallyLocal (host) + +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)(type, protocol, host, port) + +int type; +char *protocol; +char *host; +char *port; + +{ + int fd = -1; + LOCALtrans2dev *transptr; + XtransConnInfo ciptr; + int index; + + PRMSG(3,"TRANS(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, + "TRANS(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)calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"TRANS(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, + "TRANS(LocalOpenClient): Should not be opening a server with this function\n", + 0,0,0); + break; + default: + PRMSG(1, + "TRANS(LocalOpenClient): Unknown Open type %d\n", + type, 0,0 ); + } + if( ciptr->fd >= 0 ) + break; + } + + TRANS(LocalEndTransports)(); + + if( ciptr->fd < 0 ) + { + free(ciptr); + return NULL; + } + + ciptr->priv=(char *)transptr; + ciptr->index = index; + + return ciptr; +} + +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER + +static XtransConnInfo +TRANS(LocalOpenServer)(type, protocol, host, port) + +int type; +char *protocol; +char *host; +char *port; + +{ + int i,fd = -1; + XtransConnInfo ciptr; + + PRMSG(2,"TRANS(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)calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"TRANS(LocalOpenServer)() calloc(1,%d) failed\n", + sizeof(struct _XtransConnInfo),0,0 ); + return NULL; + } + + for(i=1;ifd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port); + break; + case XTRANS_OPEN_CLTS_SERVER: + ciptr->fd=LOCALtrans2devtab[i].devcltsopenserver(ciptr,port); + break; + default: + PRMSG(1,"TRANS(LocalOpenServer): Unknown Open type %d\n", + type ,0,0); + } + if( ciptr->fd >= 0 ) { + ciptr->priv=(char *)&LOCALtrans2devtab[i]; + ciptr->index=i; + ciptr->flags=1; + return ciptr; + } + } + + free(ciptr); + return NULL; +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN + +static XtransConnInfo +TRANS(LocalReopenServer)(type, index, fd, port) + +int type; +int index; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + int stat; + + PRMSG(2,"TRANS(LocalReopenServer)(%d,%d,%d)\n", type, index, fd); + + if( (ciptr=(XtransConnInfo)calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1,"TRANS(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,"TRANS(LocalReopenServer): Unknown Open type %d\n", + type ,0,0); + } + + if( stat > 0 ) { + ciptr->priv=(char *)&LOCALtrans2devtab[index]; + ciptr->index=index; + ciptr->flags=1; + return ciptr; + } + + free(ciptr); + return NULL; +} + +#endif /* TRANS_REOPEN */ + + + +/* + * This is the Local implementation of the X Transport service layer + */ + +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(LocalOpenCOTSClient)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + PRMSG(2,"TRANS(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)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + PRMSG(2,"TRANS(LocalOpenCOTSServer)(%s,%s,%s)\n",protocol,host,port); + + return TRANS(LocalOpenServer)(XTRANS_OPEN_COTS_SERVER, protocol, host, port); +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(LocalOpenCLTSClient)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + PRMSG(2,"TRANS(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)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + PRMSG(2,"TRANS(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)(thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + int index; + + PRMSG(2,"TRANS(LocalReopenCOTSServer)(%d,%s)\n", fd, port, 0); + + for(index=1;indexTransName, + LOCALtrans2devtab[index].transname) == 0 ) + break; + } + + if (index >= NUMTRANSPORTS) + { + return (NULL); + } + + return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER, + index, fd, port); +} + +static XtransConnInfo +TRANS(LocalReopenCLTSServer)(thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + int index; + + PRMSG(2,"TRANS(LocalReopenCLTSServer)(%d,%s)\n", fd, port, 0); + + for(index=1;indexTransName, + LOCALtrans2devtab[index].transname) == 0 ) + break; + } + + if (index >= NUMTRANSPORTS) + { + return (NULL); + } + + return TRANS(LocalReopenServer)(XTRANS_OPEN_CLTS_SERVER, + index, fd, port); +} + +#endif /* TRANS_REOPEN */ + + + +static +TRANS(LocalSetOption)(ciptr, option, arg) + +XtransConnInfo ciptr; +int option; +int arg; + +{ + PRMSG(2,"TRANS(LocalSetOption)(%d,%d,%d)\n",ciptr->fd,option,arg); + + return -1; +} + + +#ifdef TRANS_SERVER + +static +TRANS(LocalCreateListener)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + PRMSG(2,"TRANS(LocalCreateListener)(%x->%d,%s)\n",ciptr,ciptr->fd,port); + + return 0; +} + +static XtransConnInfo +TRANS(LocalAccept)(ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + LOCALtrans2dev *transptr; + + PRMSG(2,"TRANS(LocalAccept)(%x->%d)\n", ciptr, ciptr->fd,0); + + transptr=(LOCALtrans2dev *)ciptr->priv; + + if( (newciptr=(XtransConnInfo)calloc(1,sizeof(struct _XtransConnInfo)))==NULL ) + { + PRMSG(1,"TRANS(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 ) + { + free(newciptr); + return NULL; + } + + newciptr->priv=(char *)transptr; + newciptr->index = ciptr->index; + + *status = 0; + + return newciptr; +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +static +TRANS(LocalConnect)(ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + PRMSG(2,"TRANS(LocalConnect)(%x->%d,%s)\n", ciptr, ciptr->fd, port); + + return 0; +} + +#endif /* TRANS_CLIENT */ + + +static int +TRANS(LocalBytesReadable)(ciptr, pend ) + +XtransConnInfo ciptr; +BytesReadable_t *pend; + +{ + PRMSG(2,"TRANS(LocalBytesReadable)(%x->%d,%x)\n", ciptr, ciptr->fd, pend); + +#ifdef sco + return ioctl(ciptr->fd, I_NREAD, (char *)pend); +#else + return ioctl(ciptr->fd, FIONREAD, (char *)pend); +#endif +} + +static int +TRANS(LocalRead)(ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG(2,"TRANS(LocalRead)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return read(ciptr->fd,buf,size); +} + +static int +TRANS(LocalWrite)(ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG(2,"TRANS(LocalWrite)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return write(ciptr->fd,buf,size); +} + +static int +TRANS(LocalReadv)(ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG(2,"TRANS(LocalReadv)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return READV(ciptr,buf,size); +} + +static int +TRANS(LocalWritev)(ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG(2,"TRANS(LocalWritev)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return WRITEV(ciptr,buf,size); +} + +static int +TRANS(LocalDisconnect)(ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG(2,"TRANS(LocalDisconnect)(%x->%d)\n", ciptr, ciptr->fd, 0); + + return 0; +} + +static int +TRANS(LocalClose)(ciptr) + +XtransConnInfo ciptr; + +{ + struct sockaddr_un *sockname=(struct sockaddr_un *) ciptr->addr; + char path[200]; /* > sizeof sun_path +1 */ + int ret; + + PRMSG(2,"TRANS(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] ) + { + strncpy(path,sockname->sun_path, + ciptr->addrlen-sizeof(sockname->sun_family)); + unlink(path); + } + + return ret; +} + +static int +TRANS(LocalCloseForCloning)(ciptr) + +XtransConnInfo ciptr; + +{ + int ret; + + PRMSG(2,"TRANS(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. + */ + +Xtransport TRANS(LocalFuncs) = { + /* Local Interface */ + "local", + TRANS_ALIAS | TRANS_LOCAL, +#ifdef TRANS_CLIENT + TRANS(LocalOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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 + 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 + 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(ISCFuncs) = { + /* Local Interface */ + "isc", + TRANS_LOCAL, +#ifdef TRANS_CLIENT + TRANS(LocalOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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), +}; +Xtransport TRANS(SCOFuncs) = { + /* Local Interface */ + "sco", + TRANS_LOCAL, +#ifdef TRANS_CLIENT + TRANS(LocalOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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/Xtranssock.c b/Xtranssock.c new file mode 100644 index 0000000..62033c9 --- /dev/null +++ b/Xtranssock.c @@ -0,0 +1,1993 @@ +/* $Xorg: Xtranssock.c,v 1.11 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. + +*/ + +/* 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 +#ifdef XTHREADS +#include +#endif + +#ifndef WIN32 + +#if defined(TCPCONN) || defined(UNIXCONN) +#include +#else +#ifdef ESIX +#include +#endif +#endif + +#if defined(TCPCONN) || defined(UNIXCONN) +#define X_INCLUDE_NETDB_H +#define XOS_USE_NO_LOCKING +#include +#endif + +#ifdef UNIXCONN +#include +#include +#endif + +#if defined(hpux) || defined(__EMX__) || (defined(MOTOROLA) && defined(SYSV)) +#define NO_TCP_H +#endif + +#ifndef NO_TCP_H +#ifdef __osf__ +#include +#endif /* osf */ +#if defined(__NetBSD__) || defined(__FreeBSD__) +#include +#endif /* __NetBSD__ || __FreeBSD__ */ +#include +#endif /* !NO_TCP_H */ + +#include + +#if defined (SVR4) && !defined(SCO325) && !defined(_SEQUENT_) +#include +#endif + +#if (defined(i386) && defined(SYSV)) && !defined(ESIX) && !defined(sco) +#include +#endif + +#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_) +#include +#endif + +#else /* !WIN32 */ + +#include +#include +#undef close +#define close closesocket +#define ECONNREFUSED WSAECONNREFUSED +#define EADDRINUSE WSAEADDRINUSE +#define EPROTOTYPE WSAEPROTOTYPE +#undef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINTR +#define EINTR WSAEINTR +#define X_INCLUDE_NETDB_H +#define XOS_USE_MTSAFE_NETDBAPI +#include +#endif /* WIN32 */ + +#if defined(SO_DONTLINGER) && defined(SO_LINGER) +#undef SO_DONTLINGER +#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}, + {"tcp",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, +#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 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 + +/* + * These are some utility function used by the real interface function below. + */ + +static int +TRANS(SocketSelectFamily) (family) + +char *family; + +{ + int i; + + PRMSG (3,"TRANS(SocketSelectFamily) (%s)\n", family, 0, 0); + + for (i = 0; i < NUMSOCKETFAMILIES;i++) + { + if (!strcmp (family, Sockettrans2devtab[i].transname)) + return i; + } + + return -1; +} + + +/* + * This function gets the local address of the socket and stores it in the + * XtransConnInfo structure for the connection. + */ + +static int +TRANS(SocketINETGetAddr) (ciptr) + +XtransConnInfo ciptr; + +{ + struct sockaddr_in sockname; + int namelen = sizeof sockname; + + PRMSG (3,"TRANS(SocketINETGetAddr) (%x)\n", ciptr, 0, 0); + + if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"TRANS(SocketINETGetAddr): getsockname() failed: %d\n", + EGET(),0, 0); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->addr = (char *) malloc (namelen)) == NULL) + { + PRMSG (1, + "TRANS(SocketINETGetAddr): Can't allocate space for the addr\n", + 0, 0, 0); + return -1; + } + + ciptr->family = sockname.sin_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(SocketINETGetPeerAddr) (ciptr) + +XtransConnInfo ciptr; + +{ + struct sockaddr_in sockname; + int namelen = sizeof(sockname); + + PRMSG (3,"TRANS(SocketINETGetPeerAddr) (%x)\n", ciptr, 0, 0); + + if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"TRANS(SocketINETGetPeerAddr): getpeername() failed: %d\n", + EGET(), 0, 0); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->peeraddr = (char *) malloc (namelen)) == NULL) + { + PRMSG (1, + "TRANS(SocketINETGetPeerAddr): Can't allocate space for the addr\n", + 0, 0, 0); + return -1; + } + + ciptr->peeraddrlen = namelen; + memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); + + return 0; +} + + +static XtransConnInfo +TRANS(SocketOpen) (i, type) + +int i; +int type; + +{ + XtransConnInfo ciptr; + + PRMSG (3,"TRANS(SocketOpen) (%d,%d)\n", i, type, 0); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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 + ) { + PRMSG (1, "TRANS(SocketOpen): socket() failed for %s\n", + Sockettrans2devtab[i].transname, 0, 0); + + free ((char *) ciptr); + return NULL; + } + +#ifdef TCP_NODELAY + if (Sockettrans2devtab[i].family == AF_INET) + { + /* + * 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) (i, type, fd, port) + +int i; +int type; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG (3,"TRANS(SocketReopen) (%d,%d,%s)\n", type, fd, port); + + if ((ciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(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(SocketOpenCOTSClient) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2, "TRANS(SocketOpenCOTSClient) (%s,%s,%s)\n", + protocol, host, port); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketOpenCOTSClient): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) == NULL) + { + PRMSG (1,"TRANS(SocketOpenCOTSClient): Unable to open socket 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(SocketOpenCOTSServer) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2,"TRANS(SocketOpenCOTSServer) (%s,%s,%s)\n", protocol, host, port); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketOpenCOTSServer): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) == NULL) + { + PRMSG (1,"TRANS(SocketOpenCOTSServer): Unable to open socket for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + +#ifdef SO_REUSEADDR + + /* + * SO_REUSEADDR only applied to AF_INET + */ + + if (Sockettrans2devtab[i].family == AF_INET) + { + int one = 1; + setsockopt (ciptr->fd, SOL_SOCKET, SO_REUSEADDR, + (char *) &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) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2,"TRANS(SocketOpenCLTSClient) (%s,%s,%s)\n", protocol, host, port); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketOpenCLTSClient): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) == NULL) + { + PRMSG (1,"TRANS(SocketOpenCLTSClient): Unable to open socket 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) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2,"TRANS(SocketOpenCLTSServer) (%s,%s,%s)\n", protocol, host, port); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketOpenCLTSServer): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketOpen) ( + i, Sockettrans2devtab[i].devcotsname)) == NULL) + { + PRMSG (1,"TRANS(SocketOpenCLTSServer): Unable to open socket for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + /* Save the index for later use */ + + ciptr->index = i; + + return ciptr; +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_REOPEN + +static XtransConnInfo +TRANS(SocketReopenCOTSServer) (thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2, + "TRANS(SocketReopenCOTSServer) (%d, %s)\n", fd, port, 0); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketReopenCOTSServer): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketReopen) ( + i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL) + { + PRMSG (1, + "TRANS(SocketReopenCOTSServer): Unable to reopen socket for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + /* Save the index for later use */ + + ciptr->index = i; + + return ciptr; +} + +static XtransConnInfo +TRANS(SocketReopenCLTSServer) (thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + + PRMSG (2, + "TRANS(SocketReopenCLTSServer) (%d, %s)\n", fd, port, 0); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "TRANS(SocketReopenCLTSServer): Unable to determine socket type for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + if ((ciptr = TRANS(SocketReopen) ( + i, Sockettrans2devtab[i].devcotsname, fd, port)) == NULL) + { + PRMSG (1, + "TRANS(SocketReopenCLTSServer): Unable to reopen socket 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) (ciptr, option, arg) + +XtransConnInfo ciptr; +int option; +int arg; + +{ + PRMSG (2,"TRANS(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 /* UNIXCONN */ + +#ifdef TRANS_SERVER + +static int +TRANS(SocketCreateListener) (ciptr, sockname, socknamelen) + +XtransConnInfo ciptr; +struct sockaddr *sockname; +int socknamelen; + +{ + int namelen = socknamelen; + int fd = ciptr->fd; + int retry; + + PRMSG (3, "TRANS(SocketCreateListener) (%x,%d)\n", ciptr, fd, 0); + + if (Sockettrans2devtab[ciptr->index].family == AF_INET) + retry = 20; + else + retry = 0; + + while (bind (fd, (struct sockaddr *) sockname, namelen) < 0) + { + if (errno == EADDRINUSE) + return TRANS_ADDR_IN_USE; + + if (retry-- == 0) { + PRMSG (1, "TRANS(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) { +#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, 5) < 0) + { + PRMSG (1, "TRANS(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; + + return 0; +} + +#ifdef TCPCONN +static int +TRANS(SocketINETCreateListener) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct sockaddr_in sockname; + int namelen = sizeof(sockname); + int status; + long tmpport; + _Xgetservbynameparams sparams; + struct servent *servp; + + + char portbuf[PORTBUFSIZE]; + + PRMSG (2, "TRANS(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,"%u", 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, + "TRANS(SocketINETCreateListener): Unable to get service for %s\n", + port, 0, 0); + return TRANS_CREATE_LISTENER_FAILED; + } + /* we trust getservbyname to return a valid number */ + sockname.sin_port = htons (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; + + sockname.sin_port = htons (((unsigned short) tmpport)); + } + } + else + sockname.sin_port = htons (0); + +#ifdef BSD44SOCKETS + sockname.sin_len = sizeof (sockname); +#endif + sockname.sin_family = AF_INET; + sockname.sin_addr.s_addr = htonl (INADDR_ANY); + + if ((status = TRANS(SocketCreateListener) (ciptr, + (struct sockaddr *) &sockname, namelen)) < 0) + { + PRMSG (1, + "TRANS(SocketINETCreateListener): TRANS(SocketCreateListener) () failed\n", + 0, 0, 0); + return status; + } + + if (TRANS(SocketINETGetAddr) (ciptr) < 0) + { + PRMSG (1, + "TRANS(SocketINETCreateListener): TRANS(SocketINETGetAddr) () failed\n", + 0, 0, 0); + return TRANS_CREATE_LISTENER_FAILED; + } + + return 0; +} + +#endif /* SOCKCONN */ + + +#ifdef UNIXCONN + +static +TRANS(SocketUNIXCreateListener) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct sockaddr_un sockname; + int namelen; + int oldUmask; + int status; + + PRMSG (2, "TRANS(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 + if (!mkdir (UNIX_DIR, 01777)) + chmod (UNIX_DIR, 01777); +# else + if (!mkdir (UNIX_DIR, 0777)) + chmod (UNIX_DIR, 0777); +# endif +#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%d", UNIX_PATH, getpid()); + } + +#ifdef BSD44SOCKETS + 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)) < 0) + { + PRMSG (1, + "TRANS(SocketUNIXCreateListener): TRANS(SocketCreateListener) () failed\n", + 0, 0, 0); + 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 *) malloc (namelen)) == NULL) + { + PRMSG (1, + "TRANS(SocketUNIXCreateListener): Can't allocate space for the addr\n", + 0, 0, 0); + 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 +TRANS(SocketUNIXResetListener) (ciptr) + +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; + void TRANS(FreeConnInfo) (); + + PRMSG (3, "TRANS(SocketUNIXResetListener) (%x,%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(sco) + S_IFIFO)) +#else + S_IFSOCK)) +#endif + { + int oldUmask = umask (0); + +#ifdef UNIX_DIR +# ifdef HAS_STICKY_DIR_BIT + if (!mkdir (UNIX_DIR, 01777)) + chmod (UNIX_DIR, 01777); +# else + if (!mkdir (UNIX_DIR, 0777)) + chmod (UNIX_DIR, 0777); +# endif +#endif + + close (ciptr->fd); + unlink (unsock->sun_path); + + if ((ciptr->fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + TRANS(FreeConnInfo) (ciptr); + 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, 5) < 0) + { + close (ciptr->fd); + TRANS(FreeConnInfo) (ciptr); + return TRANS_RESET_FAILURE; + } + + umask (oldUmask); + + status = TRANS_RESET_NEW_FD; + } + + return status; +} + +#endif /* UNIXCONN */ + + +#ifdef TCPCONN + +static XtransConnInfo +TRANS(SocketINETAccept) (ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + struct sockaddr_in sockname; + int namelen = sizeof(sockname); + + PRMSG (2, "TRANS(SocketINETAccept) (%x,%d)\n", ciptr, ciptr->fd, 0); + + if ((newciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(SocketINETAccept): 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, "TRANS(SocketINETAccept): accept() failed\n", 0, 0, 0); + free (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, + "TRANS(SocketINETAccept): TRANS(SocketINETGetAddr) () failed:\n", + 0, 0, 0); + close (newciptr->fd); + free (newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) + { + PRMSG (1, + "TRANS(SocketINETAccept): TRANS(SocketINETGetPeerAddr) () failed:\n", + 0, 0, 0); + close (newciptr->fd); + if (newciptr->addr) free (newciptr->addr); + free (newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + *status = 0; + + return newciptr; +} + +#endif /* TCPCONN */ + + +#ifdef UNIXCONN +static XtransConnInfo +TRANS(SocketUNIXAccept) (ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + struct sockaddr_un sockname; + int namelen = sizeof(sockname); + + PRMSG (2, "TRANS(SocketUNIXAccept) (%x,%d)\n", ciptr, ciptr->fd, 0); + + if ((newciptr = (XtransConnInfo) calloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "TRANS(SocketUNIXAccept): 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, "TRANS(SocketUNIXAccept): accept() failed\n", 0, 0, 0); + free (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 *) malloc (ciptr->addrlen)) == NULL) + { + PRMSG (1, + "TRANS(SocketUNIXAccept): Can't allocate space for the addr\n", + 0, 0, 0); + close (newciptr->fd); + free (newciptr); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + + + newciptr->addrlen = ciptr->addrlen; + memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); + + if ((newciptr->peeraddr = (char *) malloc (ciptr->addrlen)) == NULL) + { + PRMSG (1, + "TRANS(SocketUNIXAccept): Can't allocate space for the addr\n", + 0, 0, 0); + close (newciptr->fd); + if (newciptr->addr) free (newciptr->addr); + free (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 +static int +TRANS(SocketINETConnect) (ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + struct sockaddr_in sockname; + int namelen = sizeof(sockname); + _Xgethostbynameparams hparams; + _Xgetservbynameparams sparams; + struct hostent *hostp; + struct servent *servp; + + char portbuf[PORTBUFSIZE]; + + long tmpport; + unsigned long tmpaddr; + char hostnamebuf[256]; /* tmp space */ + + PRMSG (2,"TRANS(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, "%u", tmpport); + port = portbuf; + } +#endif + + /* + * Build the socket name. + */ + +#ifdef BSD44SOCKETS + sockname.sin_len = sizeof (struct sockaddr_in); +#endif + sockname.sin_family = AF_INET; + + /* + * fill in sin_addr + */ + + /* 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 = -1; + } + + PRMSG (4,"TRANS(SocketINETConnect) inet_addr(%s) = %x\n", + host, tmpaddr, 0); + + if (tmpaddr == -1) + { + if ((hostp = _XGethostbyname(host,hparams)) == NULL) + { + PRMSG (1,"TRANS(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,"TRANS(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,"TRANS(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,"TRANS(SocketINETConnect) sockname.sin_port = %d\n", + ntohs(sockname.sin_port), 0, 0); + + /* + * 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, (struct sockaddr *) &sockname, namelen) < 0) + { +#ifdef WIN32 + int olderrno = WSAGetLastError(); +#else + int olderrno = errno; +#endif + + PRMSG (1,"TRANS(SocketINETConnect) () can't connect: errno = %d\n", + EGET(),0, 0); + + /* + * If the error was ECONNREFUSED, the server may be overloaded + * and we should try again. + * + * If the error was EINTR, the connect was interrupted and we + * should try again. + */ + + if (olderrno == ECONNREFUSED || olderrno == EINTR) + return TRANS_TRY_CONNECT_AGAIN; + else + return TRANS_CONNECT_FAILED; + } + + + /* + * Sync up the address fields of ciptr. + */ + + if (TRANS(SocketINETGetAddr) (ciptr) < 0) + { + PRMSG (1, + "TRANS(SocketINETConnect): TRANS(SocketINETGetAddr) () failed:\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) + { + PRMSG (1, + "TRANS(SocketINETConnect): TRANS(SocketINETGetPeerAddr) () failed:\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + return 0; +} + +#endif /* TCPCONN */ + + + +#ifdef UNIXCONN + +/* + * Make sure 'host' is really local. + */ + +static int +UnixHostReallyLocal (host) + +char *host; + +{ + char hostnamebuf[256]; + + TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); + + if (strcmp (hostnamebuf, host) == 0) + { + return (1); + } + 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; + _Xgethostbynameparams hparams; + 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) (ciptr, host, port) + +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,"TRANS(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, + "TRANS(SocketUNIXConnect): Cannot connect to non-local host %s\n", + host, 0, 0); + return TRANS_CONNECT_FAILED; + } + + + /* + * Check the port. + */ + + if (!port || !*port) + { + PRMSG (1,"TRANS(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; + } + +#ifdef BSD44SOCKETS + 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 (*port == '/') { /* a full pathname */ + sprintf (old_sockname.sun_path, "%s", port); + } else { + sprintf (old_sockname.sun_path, "%s%s", OLD_UNIX_PATH, port); + } + 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; + + PRMSG (1,"TRANS(SocketUNIXConnect) () can't connect: errno = %d\n", + EGET(),0, 0); + + if (olderrno == ENOENT || olderrno == EINTR) + return TRANS_TRY_CONNECT_AGAIN; + else + 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 *) malloc(namelen)) == NULL || + (ciptr->peeraddr = (char *) malloc(namelen)) == NULL) + { + PRMSG (1, + "TRANS(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) (ciptr, pend) + +XtransConnInfo ciptr; +BytesReadable_t *pend; + +{ + PRMSG (2,"TRANS(SocketBytesReadable) (%x,%d,%x)\n", + ciptr, ciptr->fd, pend); + +#ifdef WIN32 + return ioctlsocket ((SOCKET) ciptr->fd, FIONREAD, (u_long *) pend); +#else +#if (defined(i386) && defined(SYSV) && !defined(sco)) || (defined(_SEQUENT_) && _SOCKET_VERSION == 1) + return ioctl (ciptr->fd, I_NREAD, (char *) pend); +#else + return ioctl (ciptr->fd, FIONREAD, (char *) pend); +#endif /* i386 && SYSV || _SEQUENT_ && _SOCKET_VERSION == 1 */ +#endif /* WIN32 */ +} + + +static int +TRANS(SocketRead) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG (2,"TRANS(SocketRead) (%d,%x,%d)\n", ciptr->fd, buf, size); + +#ifdef WIN32 + return recv ((SOCKET)ciptr->fd, buf, size, 0); +#else + return read (ciptr->fd, buf, size); +#endif /* WIN32 */ +} + + +static int +TRANS(SocketWrite) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG (2,"TRANS(SocketWrite) (%d,%x,%d)\n", ciptr->fd, buf, size); + +#ifdef WIN32 + return send ((SOCKET)ciptr->fd, buf, size, 0); +#else + return write (ciptr->fd, buf, size); +#endif /* WIN32 */ +} + + +static int +TRANS(SocketReadv) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG (2,"TRANS(SocketReadv) (%d,%x,%d)\n", ciptr->fd, buf, size); + + return READV (ciptr, buf, size); +} + + +static int +TRANS(SocketWritev) (ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG (2,"TRANS(SocketWritev) (%d,%x,%d)\n", ciptr->fd, buf, size); + + return WRITEV (ciptr, buf, size); +} + + +static int +TRANS(SocketDisconnect) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (2,"TRANS(SocketDisconnect) (%x,%d)\n", ciptr, ciptr->fd, 0); + + return shutdown (ciptr->fd, 2); /* disallow further sends and receives */ +} + + +#ifdef TCPCONN +static int +TRANS(SocketINETClose) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (2,"TRANS(SocketINETClose) (%x,%d)\n", ciptr, ciptr->fd, 0); + + return close (ciptr->fd); +} + +#endif /* TCPCONN */ + + +#ifdef UNIXCONN +static int +TRANS(SocketUNIXClose) (ciptr) + +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; + char path[200]; /* > sizeof sun_path +1 */ + int ret; + + PRMSG (2,"TRANS(SocketUNIXClose) (%x,%d)\n", ciptr, ciptr->fd, 0); + + ret = close(ciptr->fd); + + if (ciptr->flags + && sockname + && sockname->sun_family == AF_UNIX + && sockname->sun_path[0]) + { + strncpy (path, sockname->sun_path, + ciptr->addrlen - sizeof (sockname->sun_family)); + unlink (path); + } + + return ret; +} + +static int +TRANS(SocketUNIXCloseForCloning) (ciptr) + +XtransConnInfo ciptr; + +{ + /* + * Don't unlink path. + */ + + int ret; + + PRMSG (2,"TRANS(SocketUNIXCloseForCloning) (%x,%d)\n", + ciptr, ciptr->fd, 0); + + ret = close(ciptr->fd); + + return ret; +} + +#endif /* UNIXCONN */ + + +#ifdef TCPCONN +Xtransport TRANS(SocketTCPFuncs) = { + /* Socket Interface */ + "tcp", + 0, +#ifdef TRANS_CLIENT + TRANS(SocketOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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", + TRANS_ALIAS, +#ifdef TRANS_CLIENT + TRANS(SocketOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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 /* TCPCONN */ + +#ifdef UNIXCONN +#if !defined(LOCALCONN) +Xtransport TRANS(SocketLocalFuncs) = { + /* Socket Interface */ + "local", + 0, +#ifdef TRANS_CLIENT + TRANS(SocketOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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 */ + +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 + 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/Xtranstli.c b/Xtranstli.c new file mode 100644 index 0000000..b7daf70 --- /dev/null +++ b/Xtranstli.c @@ -0,0 +1,1494 @@ +/* $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. + +*/ + +/* 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 +#include +#include +#include + +#include +#include + + +/* + * 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)(family) + +char *family; + +{ + int i; + + PRMSG(3,"TRANS(TLISelectFamily)(%s)\n", family, 0,0 ); + + for(i=0;ifd,&netbuf,LOCALNAME) < 0 ) + { + PRMSG(1,"TRANS(TLIGetAddr): t_getname(LOCALNAME) failed: %d\n", + errno, 0,0 ); + return -1; + } + + PRMSG(4,"TRANS(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 ) + free(ciptr->addr); + + if( (ciptr->addr=(char *)malloc(netbuf.len)) == NULL ) + { + PRMSG(1, "TRANS(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)(ciptr) + +XtransConnInfo ciptr; + +{ + Xtransaddr sockname; + struct netbuf netbuf; + + PRMSG(3,"TRANS(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,"TRANS(TLIGetPeerAddr): t_getname(REMOTENAME) failed: %d\n", + errno, 0,0 ); + return -1; + } + + PRMSG(4,"TRANS(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 ) + free(ciptr->peeraddr); + + if( (ciptr->peeraddr=(char *)malloc(netbuf.len)) == NULL ) + { + PRMSG(1, + "TRANS(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)(fd,family,port) + +int fd; +int family; +char *port; + +{ + struct sockaddr_un *sunaddr=NULL; + struct t_bind *req=NULL; + + PRMSG(2, "TRANS(TLITLIBindLocal)(%d,%d,%s)\n", fd, family, port); + + if( family == AF_UNIX ) + { + if( (req=(struct t_bind *)t_alloc(fd,T_BIND,T_OPT|T_UDATA)) == NULL ) + { + PRMSG(1, + "TRANS(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, + "TRANS(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, "TRANS(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, + "TRANS(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)(device) + +char *device; + +{ + XtransConnInfo ciptr; + + PRMSG(3,"TRANS(TLIOpen)(%s)\n", device, 0,0 ); + + if( (ciptr=(XtransConnInfo)calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1, "TRANS(TLIOpen): calloc failed\n", 0,0,0 ); + return NULL; + } + + if( (ciptr->fd=t_open( device, O_RDWR, NULL )) < 0 ) + { + PRMSG(1, "TRANS(TLIOpen): t_open failed for %s\n", device, 0,0 ); + free(ciptr); + return NULL; + } + + return ciptr; +} + + +#ifdef TRANS_REOPEN + +static XtransConnInfo +TRANS(TLIReopen)(device, fd, port) + +char *device; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + + PRMSG(3,"TRANS(TLIReopen)(%s,%d, %s)\n", device, fd, port ); + + if (t_sync (fd) < 0) + { + PRMSG(1, "TRANS(TLIReopen): t_sync failed\n", 0,0,0 ); + return NULL; + } + + if( (ciptr=(XtransConnInfo)calloc(1,sizeof(struct _XtransConnInfo))) == NULL ) + { + PRMSG(1, "TRANS(TLIReopen): calloc failed\n", 0,0,0 ); + return NULL; + } + + ciptr->fd = fd; + + return ciptr; +} + +#endif /* TRANS_REOPEN */ + + +static int +TRANS(TLIAddrToNetbuf)(tlifamily, host, port, netbufp) + +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,"TRANS(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,"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, "found address for %s.%s\n", host, port, 0 ); + PRMSG(5, "%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)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIOpenCOTSClient)(%s,%s,%s)\n", protocol, host, port ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1,"TRANS(TLIOpenCOTSClient): Unable to determine device for %s\n", + thistrans->TransName, 0,0 ); + return NULL; + } + + if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL ) + { + PRMSG(1,"TRANS(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, + "TRANS(TLIOpenCOTSClient): TRANS(TLITLIBindLocal)() failed: %d\n", + errno, 0,0 ); + t_close(ciptr->fd); + free(ciptr); + return NULL; + } + + if( TRANS(TLIGetAddr)(ciptr) < 0 ) + { + PRMSG(1, + "TRANS(TLIOpenCOTSClient): TRANS(TLIGetAddr)() failed: %d\n", + errno, 0,0 ); + t_close(ciptr->fd); + free(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)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIOpenCOTSServer)(%s,%s,%s)\n", protocol, host, port ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1, + "TRANS(TLIOpenCOTSServer): Unable to determine device for %s\n", + thistrans->TransName, 0,0 ); + return NULL; + } + + if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcotsname)) == NULL ) + { + PRMSG(1, + "TRANS(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)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIOpenCLTSClient)(%s,%s,%s)\n", protocol, host, port ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1, + "TRANS(TLIOpenCLTSClient): Unable to determine device for %s\n", + thistrans->TransName, 0,0 ); + return NULL; + } + + if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL ) + { + PRMSG(1, + "TRANS(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, + "TRANS(TLIOpenCLTSClient): TRANS(TLITLIBindLocal)() failed: %d\n", + errno, 0,0 ); + t_close(ciptr->fd); + free(ciptr); + return NULL; + } + + if( TRANS(TLIGetAddr)(ciptr) < 0 ) + { + PRMSG(1, + "TRANS(TLIOpenCLTSClient): TRANS(TLIGetPeerAddr)() failed: %d\n", + errno, 0,0 ); + t_close(ciptr->fd); + free(ciptr); + return NULL; + } + + return ciptr; +} + +#endif /* TRANS_CLIENT */ + + +#ifdef TRANS_SERVER + +static XtransConnInfo +TRANS(TLIOpenCLTSServer)(thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIOpenCLTSServer)(%s,%s,%s)\n", protocol, host, port ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1, + "TRANS(TLIOpenCLTSServer): Unable to determine device for %s\n", + thistrans->TransName, 0,0 ); + return NULL; + } + + if( (ciptr=TRANS(TLIOpen)(TLItrans2devtab[i].devcltsname)) == NULL ) + { + PRMSG(1, + "TRANS(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)(thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIReopenCOTSServer)(%d, %s)\n", fd, port, 0 ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1, + "TRANS(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, + "TRANS(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)(thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG(2,"TRANS(TLIReopenCLTSServer)(%d, %s)\n", fd, port, 0 ); + + if( (i=TRANS(TLISelectFamily)(thistrans->TransName)) < 0 ) + { + PRMSG(1, + "TRANS(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, + "TRANS(TLIReopenCLTSServer): Unable to open device for %s\n", + thistrans->TransName, 0,0 ); + return NULL; + } + + ciptr->index = i; + + return ciptr; +} + +#endif /* TRANS_REOPEN */ + + +static +TRANS(TLISetOption)(ciptr, option, arg) + +XtransConnInfo ciptr; +int option; +int arg; + +{ + PRMSG(2,"TRANS(TLISetOption)(%d,%d,%d)\n", ciptr->fd, option, arg ); + + return -1; +} + + +#ifdef TRANS_SERVER + +static +TRANS(TLICreateListener)(ciptr, req) + +XtransConnInfo ciptr; +struct t_bind *req; + +{ + struct t_bind *ret; + + PRMSG(2,"TRANS(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, "TRANS(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, "TRANS(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, "TRANS(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 *)malloc(ret->addr.len)) == NULL ) + { + PRMSG(1, + "TRANS(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 +TRANS(TLIINETCreateListener)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + char portbuf[PORTBUFSIZE]; + struct t_bind *req; + struct sockaddr_in *sinaddr; + long tmpport; + + PRMSG(2,"TRANS(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, + "TRANS(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, + "TRANS(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 +TRANS(TLITLICreateListener)(ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct t_bind *req; + struct sockaddr_un *sunaddr; + int ret_value; + + PRMSG(2,"TRANS(TLITLICreateListener)(%x->%d,%s)\n", ciptr, ciptr->fd, + port ? port : "NULL"); + + if( (req=(struct t_bind *)t_alloc(ciptr->fd,T_BIND,T_OPT|T_UDATA)) == NULL ) + { + PRMSG(1, + "TRANS(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, + "TRANS(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)(ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + struct t_call *call; + XtransConnInfo newciptr; + int i; + + PRMSG(2,"TRANS(TLIAccept)(%x->%d)\n", ciptr, ciptr->fd, 0 ); + + if( (call=(struct t_call *)t_alloc(ciptr->fd,T_CALL,T_ALL)) == NULL ) + { + PRMSG(1, "TRANS(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, "TRANS(TLIAccept)() t_listen() failed\n", 0,0,0 ); + PRMSG(1, "%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, "TRANS(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, + "TRANS(TLIAccept): TRANS(TLITLIBindLocal)() failed: %d\n", + errno, 0,0 ); + t_free((char *)call,T_CALL); + t_close(newciptr->fd); + free(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, "TRANS(TLIAccept)() t_accept() failed\n", 0,0,0 ); + PRMSG(1, "%s\n", t_errlist[t_errno], 0,0 ); + 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, + "TRANS(TLIAccept): TRANS(TLIGetAddr)() failed: %d\n", + errno, 0,0 ); + t_close(newciptr->fd); + free(newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if( TRANS(TLIGetPeerAddr)(newciptr) < 0 ) + { + PRMSG(1, + "TRANS(TLIAccept): TRANS(TLIGetPeerAddr)() failed: %d\n", + errno, 0,0 ); + t_close(newciptr->fd); + free(newciptr->addr); + free(newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if( ioctl(newciptr->fd, I_POP,"timod") < 0 ) + { + PRMSG(1, "TRANS(TLIAccept)() ioctl(I_POP, \"timod\") failed %d\n", + errno,0,0 ); + t_close(newciptr->fd); + free(newciptr->addr); + free(newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if( ioctl(newciptr->fd, I_PUSH,"tirdwr") < 0 ) + { + PRMSG(1, "TRANS(TLIAccept)() ioctl(I_PUSH,\"tirdwr\") failed %d\n", + errno,0,0 ); + t_close(newciptr->fd); + free(newciptr->addr); + free(newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + *status = 0; + + return newciptr; +} + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +static +TRANS(TLIConnect)(ciptr, sndcall ) + +XtransConnInfo ciptr; +struct t_call *sndcall; + +{ + PRMSG(2, "TRANS(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, "TRANS(TLIConnect)() t_connect() failed\n", 0,0,0 ); + PRMSG(1, "%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, + "TRANS(TLIConnect): TRANS(TLIGetAddr)() failed: %d\n", + errno, 0,0 ); + return TRANS_CONNECT_FAILED; + } + + if( TRANS(TLIGetPeerAddr)(ciptr) < 0 ) + { + PRMSG(1, + "TRANS(TLIConnect): TRANS(TLIGetPeerAddr)() failed: %d\n", + errno, 0,0 ); + return TRANS_CONNECT_FAILED; + } + + if( ioctl(ciptr->fd, I_POP,"timod") < 0 ) + { + PRMSG(1, "TRANS(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, "TRANS(TLIConnect)() ioctl(I_PUSH,\"tirdwr\") failed %d\n", + errno,0,0 ); + return TRANS_CONNECT_FAILED; + } + + return 0; +} + + +static +TRANS(TLIINETConnect)(ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + char portbuf[PORTBUFSIZE]; + struct t_call *sndcall; + long tmpport; + + PRMSG(2, "TRANS(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, "TRANS(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, "TRANS(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 +TRANS(TLITLIConnect)(ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + struct t_call *sndcall; + struct sockaddr_un *sunaddr; + int ret_value; + + PRMSG(2, "TRANS(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, "TRANS(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, + "TRANS(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 +TRANS(TLIBytesReadable)(ciptr, pend) + +XtransConnInfo ciptr; +BytesReadable_t *pend; + +{ + int ret; + struct pollfd filedes; + + PRMSG(2, "TRANS(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 +TRANS(TLIRead)(ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG(2, "TRANS(TLIRead)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return read(ciptr->fd,buf,size); +} + + +static +TRANS(TLIWrite)(ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG(2, "TRANS(TLIWrite)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return write(ciptr->fd,buf,size); +} + + +static +TRANS(TLIReadv)(ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG(2, "TRANS(TLIReadv)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return READV(ciptr,buf,size); +} + + +static +TRANS(TLIWritev)(ciptr, buf, size) + +XtransConnInfo ciptr; +struct iovec *buf; +int size; + +{ + PRMSG(2, "TRANS(TLIWritev)(%d,%x,%d)\n", ciptr->fd, buf, size ); + + return WRITEV(ciptr,buf,size); +} + + +static +TRANS(TLIDisconnect)(ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG(2, "TRANS(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 +TRANS(TLIClose)(ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG(2, "TRANS(TLIClose)(%x->%d)\n", ciptr, ciptr->fd, 0 ); + + t_unbind(ciptr->fd); + + return (t_close(ciptr->fd)); +} + + +static +TRANS(TLICloseForCloning)(ciptr) + +XtransConnInfo ciptr; + +{ + /* + * Don't unbind. + */ + + PRMSG(2, "TRANS(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 + 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(TLIINETFuncs) = { + /* TLI Interface */ + "inet", + TRANS_ALIAS, +#ifdef TRANS_CLIENT + TRANS(TLIOpenCOTSClient), +#endif /* TRANS_CLIENT */ +#ifdef TRANS_SERVER + 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 + 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/Xtransutil.c b/Xtransutil.c new file mode 100644 index 0000000..e2809b3 --- /dev/null +++ b/Xtransutil.c @@ -0,0 +1,462 @@ +/* $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. + +*/ + +/* 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 +#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 +#define FamilyDECnet 1 +#define FamilyChaos 2 +#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 doen in a consistent manner. + */ + +int +TRANS(ConvertAddress)(familyp,addrlenp,addrp) +int *familyp; +int *addrlenp; +Xtransaddr **addrp; +{ + + PRMSG(2,"TRANS(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; + } +#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) + case AF_UNIX: + { + *familyp=FamilyLocal; + break; + } +#endif /* defined(UNIXCONN) || defined(LOCALCONN) */ + +#if defined(AMRPCCONN) + case AF_AMOEBA: + { + *familyp=FamilyAmoeba; + break; + } +#endif +#if defined(AMTCPCONN) && !(defined(TCPCONN) || defined(STREAMSCONN)) + case AF_INET: + { + *familyp=FamilyInternet; + break; + } +#endif + + default: + PRMSG(1,"TRANS(ConvertFamily) 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)) + { + free ((char *) *addrp); + *addrp = NULL; + } + if (!*addrp) + *addrp = (Xtransaddr *) malloc (len + 1); + if (*addrp) { + strcpy ((char *) *addrp, hostnamebuf); + *addrlenp = len; + } else { + *addrlenp = 0; + } + } + else + { + if (*addrp) + free ((char *) *addrp); + *addrp = NULL; + *addrlenp = 0; + } + } + + return 0; +} + +#endif /* X11_t */ + +#ifdef ICE_t + +#include + +char * +TRANS(GetMyNetworkId) (ciptr) + +XtransConnInfo ciptr; + +{ + int family = ciptr->family; + int addrlen = ciptr->addrlen; + 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) + case AF_UNIX: + { + struct sockaddr_un *saddr = (struct sockaddr_un *) addr; + networkId = (char *) malloc (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) */ + +#if defined(TCPCONN) || defined(STREAMSCONN) + case AF_INET: + { + struct sockaddr_in *saddr = (struct sockaddr_in *) addr; + char portnumbuf[10]; + + sprintf (portnumbuf, "%d", ntohs (saddr->sin_port)); + networkId = (char *) malloc (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 *) malloc ( + 13 + strlen (hostnamebuf) + saddr->sdn_objnamel); + sprintf (networkId, "dnet/%s::%s", + hostnamebuf, saddr->sdn_objname); + break; + } +#endif /* defined(DNETCONN) */ + + default: + break; + } + + return (networkId); +} + +#include +static jmp_buf env; + +#ifdef SIGALRM +static int nameserver_timedout = 0; + +static +#ifdef SIGNALRETURNSINT +int +#else +void +#endif +nameserver_lost(sig) +{ + nameserver_timedout = 1; + longjmp (env, -1); + /* NOTREACHED */ +#ifdef SIGNALRETURNSINT + return -1; /* for picky compilers */ +#endif +} +#endif /* SIGALARM */ + + +char * +TRANS(GetPeerNetworkId) (ciptr) + +XtransConnInfo ciptr; + +{ + int family = ciptr->family; + int peer_addrlen = ciptr->peeraddrlen; + char *peer_addr = ciptr->peeraddr; + char *hostname; + char *networkId = NULL; + char addrbuf[256]; + char *addr = NULL; + + switch (family) + { + case AF_UNSPEC: +#if defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) + case AF_UNIX: + { + if (gethostname (addrbuf, sizeof (addrbuf)) == 0) + addr = addrbuf; + break; + } +#endif /* defined(UNIXCONN) || defined(STREAMSCONN) || defined(LOCALCONN) */ + +#if defined(TCPCONN) || defined(STREAMSCONN) + case AF_INET: + { + struct sockaddr_in *saddr = (struct sockaddr_in *) peer_addr; + _Xgethostbynameparams hparams; + struct hostent * hostp; + +#ifndef WIN32 + char *inet_ntoa(); +#endif + +#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 ((char *) &saddr->sin_addr, + sizeof (saddr->sin_addr), AF_INET, hparams); +#ifdef SIGALRM + } + alarm (0); +#endif + if (hostp != NULL) + addr = hostp->h_name; + else + addr = inet_ntoa (saddr->sin_addr); + 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) */ + +#if defined(AMRPCCONN) + case AF_AMOEBA: + { + addr = "Amoeba"; /* not really used */ + break; + } +#endif +#if defined(AMTCPCONN) && !(defined(TCPCONN) || defined(STREAMSCONN)) + case AF_INET: + { + if (gethostname (addrbuf, sizeof (addrbuf)) == 0) { + addr = addrbuf; + } else { + addr = ""; + } + break; + } +#endif + + default: + return (NULL); + } + + + hostname = (char *) malloc ( + 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) () +{ + static WSADATA wsadata; + + PRMSG (2,"TRANS(WSAStartup)()\n", 0, 0, 0); + + if (!wsadata.wVersion && WSAStartup(MAKEWORD(1,1), &wsadata)) + return 1; + return 0; +} +#endif + + +static int +is_numeric (str) + +char *str; + +{ + int i; + + for (i = 0; i < (int) strlen (str); i++) + if (!isdigit (str[i])) + return (0); + + return (1); +} diff --git a/transport.c b/transport.c new file mode 100644 index 0000000..be46eca --- /dev/null +++ b/transport.c @@ -0,0 +1,71 @@ +/* $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. + +*/ + +/* 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 "Xtransint.h" + +#ifdef DNETCONN +#include "Xtransdnet.c" +#endif +#ifdef LOCALCONN +#include "Xtranslcl.c" +#endif +#if defined(TCPCONN) || defined(UNIXCONN) +#include "Xtranssock.c" +#endif +#ifdef STREAMSCONN +#include "Xtranstli.c" +#endif +#if defined(AMRPCCONN) || defined(AMTCPCONN) +#include "Xtransam.c" +#endif +#include "Xtrans.c" +#include "Xtransutil.c" -- cgit v1.2.3