summaryrefslogtreecommitdiff
path: root/Xtranssock.c
diff options
context:
space:
mode:
Diffstat (limited to 'Xtranssock.c')
-rw-r--r--Xtranssock.c1993
1 files changed, 1993 insertions, 0 deletions
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 */