diff options
-rw-r--r-- | Xtrans.c | 1415 | ||||
-rw-r--r-- | Xtrans.h | 489 | ||||
-rw-r--r-- | Xtransdnet.c | 704 | ||||
-rw-r--r-- | Xtransint.h | 432 | ||||
-rw-r--r-- | Xtranslcl.c | 2715 | ||||
-rw-r--r-- | Xtranssock.c | 1993 | ||||
-rw-r--r-- | Xtranstli.c | 1494 | ||||
-rw-r--r-- | Xtransutil.c | 462 | ||||
-rw-r--r-- | transport.c | 71 |
9 files changed, 9775 insertions, 0 deletions
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 <ctype.h> + +/* + * The transport table contains a definition for every transport (protocol) + * family. All operations that can be made on the transport go through this + * table. + * + * Each transport is assigned a unique transport id. + * + * New transports can be added by adding an entry in this table. + * For compatiblity, the transport ids should never be renumbered. + * Always add to the end of the list. + */ + +#define TRANS_TLI_INET_INDEX 1 +#define TRANS_TLI_TCP_INDEX 2 +#define TRANS_TLI_TLI_INDEX 3 +#define TRANS_SOCKET_UNIX_INDEX 4 +#define TRANS_SOCKET_LOCAL_INDEX 5 +#define TRANS_SOCKET_INET_INDEX 6 +#define TRANS_SOCKET_TCP_INDEX 7 +#define TRANS_DNET_INDEX 8 +#define TRANS_LOCAL_LOCAL_INDEX 9 +#define TRANS_LOCAL_PTS_INDEX 10 +#define TRANS_LOCAL_NAMED_INDEX 11 +#define TRANS_LOCAL_ISC_INDEX 12 +#define TRANS_LOCAL_SCO_INDEX 13 +#define TRANS_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 <sys/utsname.h> +#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 <X11/Xfuncproto.h> +#include <X11/Xos.h> + + +/* + * 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 <sys/uio.h>. See the readv(2) and writev(2) + * manual pages for details. + */ + +struct iovec { + caddr_t iov_base; + int iov_len; +}; + +#else +#include <sys/uio.h> +#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 <netdnet/dn.h> +#include <netdnet/dnetdb.h> +#include <sys/ioctl.h> +#endif /* !WIN32 */ + +#include <stdio.h> + +#ifdef WIN32 +#define _WILLWINSOCK_ +#define BOOL wBOOL +#undef Status +#define Status wStatus +#include <prgpre.h> /* PATHWORKS header normally in %MSTOOLS%\h\pathwork */ +#undef Status +#define Status int +#undef BOOL +#include <X11/Xw32defs.h> +#undef close +#define close closesocket +#endif /* WIN32 */ + + +#if defined(X11_t) +#define DNETOBJ "X$X" +#endif +#if defined(XIM_t) +#define DNETOBJ "IMSERVER$" +#endif +#if defined(FS_t) || defined(FONT_t) +#define DNETOBJ "X$FONT" +#endif +#if defined(ICE_t) +#define DNETOBJ "" +#endif +#if defined(TEST_t) +#define DNETOBJ "X$TEST" +#endif + + +/* + * This is the DNET implementation of the X Transport service layer + */ + +/* + * This function gets the local address of the socket and stores it in the + * XtransConnInfo structure for the connection. + */ + +static int +TRANS(DNETGetAddr) (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 <stdio.h> +#endif /* XTRANSDEBUG */ + +#include <errno.h> +#ifdef X_NOT_STDC_ENV +extern int errno; /* Internal system error number. */ +#endif + +#ifndef WIN32 +#include <sys/socket.h> + +/* + * makedepend screws up on #undef OPEN_MAX, so we define a new symbol + */ + +#ifndef TRANS_OPEN_MAX + +#ifndef X_NOT_POSIX +#ifdef _POSIX_SOURCE +#include <limits.h> +#else +#define _POSIX_SOURCE +#include <limits.h> +#undef _POSIX_SOURCE +#endif +#endif +#ifndef OPEN_MAX +#ifdef SVR4 +#define OPEN_MAX 256 +#else +#include <sys/param.h> +#ifndef OPEN_MAX +#ifdef __OSF1__ +#define OPEN_MAX 256 +#else +#ifdef NOFILE +#define OPEN_MAX NOFILE +#else +#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 <limits.h> /* 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 <errno.h> +#include <ctype.h> +#include <sys/signal.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#if 0 +#include <sys/ptms.h> /* Maybe for SVR4 only?? */ +#endif +#ifdef SVR4 +#include <sys/filio.h> +#endif +#include <sys/stropts.h> +#include <sys/wait.h> +#include <sys/types.h> + +/* + * The local transports should be treated the same as a UNIX domain socket + * wrt authentication, etc. Because of this, we will use struct sockaddr_un + * for the address format. This will simplify the code in other places like + * The X Server. + */ + +#include <sys/socket.h> +#include <sys/un.h> + + +/* + * 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<NUMTRANSPORTS;i++) + { + /* + * This is equivilent to a case insensitive strcmp(), + * but should be more portable. + */ + strncpy(typebuf,typetocheck,TYPEBUFSIZE); + for(j=0;j<TYPEBUFSIZE;j++) + if (isupper(typebuf[j])) + typebuf[j]=tolower(typebuf[j]); + + /* Now, see if they match */ + if(!strcmp(LOCALtrans2devtab[i].transname,typebuf)) + return &LOCALtrans2devtab[i]; + } + } + /*NOTREACHED*/ + return NULL; +} + +#ifdef TRANS_CLIENT + +#ifdef NEED_UTSNAME +#include <sys/utsname.h> +#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;i<NUMTRANSPORTS;i++) + { + if( strcmp(protocol,LOCALtrans2devtab[i].transname) != 0 ) + continue; + switch( type ) + { + case XTRANS_OPEN_COTS_CLIENT: + case XTRANS_OPEN_CLTS_CLIENT: + PRMSG(1, + "TRANS(LocalOpenServer): Should not be opening a client with this function\n", + 0,0,0); + break; + case XTRANS_OPEN_COTS_SERVER: + ciptr->fd=LOCALtrans2devtab[i].devcotsopenserver(ciptr,port); + break; + case XTRANS_OPEN_CLTS_SERVER: + ciptr->fd=LOCALtrans2devtab[i].devcltsopenserver(ciptr,port); + break; + default: + PRMSG(1,"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;index<NUMTRANSPORTS;index++) + { + if( strcmp(thistrans->TransName, + LOCALtrans2devtab[index].transname) == 0 ) + break; + } + + if (index >= NUMTRANSPORTS) + { + return (NULL); + } + + return TRANS(LocalReopenServer)(XTRANS_OPEN_COTS_SERVER, + index, fd, port); +} + +static XtransConnInfo +TRANS(LocalReopenCLTSServer)(thistrans, fd, port) + +Xtransport *thistrans; +int fd; +char *port; + +{ + int index; + + PRMSG(2,"TRANS(LocalReopenCLTSServer)(%d,%s)\n", fd, port, 0); + + for(index=1;index<NUMTRANSPORTS;index++) + { + if( strcmp(thistrans->TransName, + LOCALtrans2devtab[index].transname) == 0 ) + break; + } + + if (index >= NUMTRANSPORTS) + { + return (NULL); + } + + return TRANS(LocalReopenServer)(XTRANS_OPEN_CLTS_SERVER, + index, fd, port); +} + +#endif /* TRANS_REOPEN */ + + + +static +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 <ctype.h> +#ifdef XTHREADS +#include <X11/Xthreads.h> +#endif + +#ifndef WIN32 + +#if defined(TCPCONN) || defined(UNIXCONN) +#include <netinet/in.h> +#else +#ifdef ESIX +#include <lan/in.h> +#endif +#endif + +#if defined(TCPCONN) || defined(UNIXCONN) +#define X_INCLUDE_NETDB_H +#define XOS_USE_NO_LOCKING +#include <X11/Xos_r.h> +#endif + +#ifdef UNIXCONN +#include <sys/un.h> +#include <sys/stat.h> +#endif + +#if defined(hpux) || defined(__EMX__) || (defined(MOTOROLA) && defined(SYSV)) +#define NO_TCP_H +#endif + +#ifndef NO_TCP_H +#ifdef __osf__ +#include <sys/param.h> +#endif /* osf */ +#if defined(__NetBSD__) || defined(__FreeBSD__) +#include <machine/endian.h> +#endif /* __NetBSD__ || __FreeBSD__ */ +#include <netinet/tcp.h> +#endif /* !NO_TCP_H */ + +#include <sys/ioctl.h> + +#if defined (SVR4) && !defined(SCO325) && !defined(_SEQUENT_) +#include <sys/filio.h> +#endif + +#if (defined(i386) && defined(SYSV)) && !defined(ESIX) && !defined(sco) +#include <net/errno.h> +#endif + +#if (defined(i386) && defined(SYSV)) && (!defined(ISC) || !defined(I_NREAD) || defined(SCO325)) || defined(_SEQUENT_) +#include <sys/stropts.h> +#endif + +#else /* !WIN32 */ + +#include <X11/Xwinsock.h> +#include <X11/Xw32defs.h> +#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 <X11/Xos_r.h> +#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 <sys/un.h> +#include <stropts.h> +#include <poll.h> +#include <tiuser.h> + +#include <netdir.h> +#include <netconfig.h> + + +/* + * This is the TLI implementation of the X Transport service layer + */ + +typedef struct _TLItrans2dev { + char *transname; + char *protofamily; + char *devcotsname; + char *devcltsname; + int family; +} TLItrans2dev; + +static TLItrans2dev TLItrans2devtab[] = { + {"inet","inet","/dev/tcp","/dev/udp",AF_INET}, + {"tcp","inet","/dev/tcp","/dev/udp",AF_INET}, + {"tli","loopback","/dev/ticots","/dev/ticlts",AF_UNIX}, +}; + +#define NUMTLIFAMILIES (sizeof(TLItrans2devtab)/sizeof(TLItrans2dev)) + +/* + * The local TLI connection, is a form of a local connection, so use a + * sockaddr_un for the address so that it will be treated just like the other + * local transports such as UNIX domain sockets, pts, and named. + */ + +#if defined(X11_t) +#define TLINODENAME "TLI:xserver" +#endif + +#if defined(XIM_t) +#define TLINODENAME "TLI:xim" +#endif + +#if defined(FS_t) || defined(FONT_t) +#define TLINODENAME "TLI:fontserver" +#endif + +#if defined(ICE_t) +#define TLINODENAME "TLI:ICE" +#endif + +#if defined(TEST_t) +#define TLINODENAME "TLI:test" +#endif + +#ifndef PORTBUFSIZE +#ifdef TRANS_SERVER +#define PORTBUFSIZE 64 +#else +#ifdef TRANS_CLIENT +#define PORTBUFSIZE 64 +#endif +#endif +#endif + + +/* + * These are some utility function used by the real interface function below. + */ + +static int +TRANS(TLISelectFamily)(family) + +char *family; + +{ + int i; + + PRMSG(3,"TRANS(TLISelectFamily)(%s)\n", family, 0,0 ); + + for(i=0;i<NUMTLIFAMILIES;i++) + { + if( !strcmp(family,TLItrans2devtab[i].transname) ) + return i; + } + return -1; +} + + +/* + * This function gets the local address of the transport and stores it in the + * XtransConnInfo structure for the connection. + */ + +static int +TRANS(TLIGetAddr)(ciptr) + +XtransConnInfo ciptr; + +{ + Xtransaddr sockname; + struct netbuf netbuf; + + PRMSG(3,"TRANS(TLIGetAddr)(%x)\n", ciptr, 0,0 ); + + netbuf.buf=(char *)&sockname; + netbuf.len=sizeof(sockname); + netbuf.maxlen=sizeof(sockname); + + if( t_getname(ciptr->fd,&netbuf,LOCALNAME) < 0 ) + { + PRMSG(1,"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 <X11/Xthreads.h> +#endif + +#ifdef X11_t + +/* + * These values come from X.h and Xauth.h, and MUST match them. Some + * of these values are also defined by the ChangeHost protocol message. + */ + +#define FamilyInternet 0 +#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 <signal.h> + +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 <setjmp.h> +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" |