X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Flib%2Fxtrans%2FXtranssock.c;fp=Xserver%2Flib%2Fxtrans%2FXtranssock.c;h=40696aaa1c5e3c5f27753d5aa91b61aebb19edff;hp=0000000000000000000000000000000000000000;hb=b6e6afccf37f4ad0515ef2a698f714fdf1bf23b3;hpb=e3340a110a3b01756b8e67531395a33b40a17d37 diff --git a/Xserver/lib/xtrans/Xtranssock.c b/Xserver/lib/xtrans/Xtranssock.c new file mode 100644 index 0000000..40696aa --- /dev/null +++ b/Xserver/lib/xtrans/Xtranssock.c @@ -0,0 +1,2012 @@ +/* $XConsortium: Xtranssock.c /main/58 1996/12/04 10:22:50 lehors $ */ +/* $XFree86: xc/lib/xtrans/Xtranssock.c,v 3.25.2.4 1998/02/01 16:04:34 robin Exp $ */ +/* + +Copyright (c) 1993, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM 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 X Consortium 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 X Consortium. + +*/ + +/* Copyright (c) 1993, 1994 NCR Corporation - Dayton, Ohio, USA + * + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, provided + * that the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name NCR not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. NCR makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN + * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#ifdef XTHREADS +#include +#endif +#ifndef WIN32 + +#if defined(TCPCONN) || defined(UNIXCONN) +#include +#else +#ifdef ESIX +#include +#endif +#endif +#if defined(TCPCONN) || defined(UNIXCONN) +#define X_INCLUDE_NETDB_H +#define XOS_USE_NO_LOCKING +#include +#endif + +#ifdef UNIXCONN +#ifndef X_NO_SYS_UN +#ifndef Lynx +#include +#else +#include +#endif +#endif +#include +#endif + +#if defined(hpux) || defined(__EMX__) +#define NO_TCP_H +#endif /* hpux */ +#ifdef MOTOROLA +#ifdef SYSV +#define NO_TCP_H +#endif /* SYSV */ +#endif /* MOTOROLA */ +#ifndef NO_TCP_H +#ifdef __osf__ +#include +#endif /* osf */ +#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) +#include +#endif /* __NetBSD__ || __OpenBSD__ || __FreeBSD__ */ +#include +#endif /* !NO_TCP_H */ +#include +#if defined(SVR4) && !defined(SCO325) +#include +#endif +#if (defined(i386) && defined(SYSV)) || defined(_SEQUENT_) +#if !defined(_SEQUENT_) && !defined(ESIX) && !defined(sco) +#include +#endif /* _SEQUENT_ || ESIX || SCO */ +#if !defined(ISC) || !defined(I_NREAD) || defined(SCO325) +#include +#endif +#endif /* i386 && SYSV || _SEQUENT_ */ + +#else /* !WIN32 */ + +#include +#include +#undef close +#define close closesocket +#define ECONNREFUSED WSAECONNREFUSED +#define EADDRINUSE WSAEADDRINUSE +#define EPROTOTYPE WSAEPROTOTYPE +#undef EWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINTR +#define EINTR WSAEINTR +#define X_INCLUDE_NETDB_H +#define XOS_USE_MTSAFE_NETDBAPI +#include +#endif /* WIN32 */ + +#if defined(SO_DONTLINGER) && defined(SO_LINGER) +#undef SO_DONTLINGER +#endif + +#if defined(__EMX__) +#if defined(NOT_EMX09A) +static int IBMsockInit = 0; +#define SocketInitOnce()\ + if (!IBMsockInit) {\ + sock_init();\ + IBMsockInit = 1;\ + } +#undef EINTR +#define EINTR SOCEINTR +#undef EINVAL +#define EINVAL SOCEINVAL +#undef errno +#define errno sock_errno() +#undef close +#define close soclose +#undef ioctl +#define ioctl sockioctl +#else +#define SocketInitOnce() /**/ +#endif +/* this is still not there */ +#define SOCKET int +#else +/* others don't need this */ +#define SocketInitOnce() /**/ +#endif + +#define MIN_BACKLOG 128 +#ifdef SOMAXCONN +#if SOMAXCONN > MIN_BACKLOG +#define BACKLOG SOMAXCONN +#endif +#endif +#ifndef BACKLOG +#define BACKLOG MIN_BACKLOG +#endif +/* + * This is the Socket implementation of the X Transport service layer + * + * This file contains the implementation for both the UNIX and INET domains, + * and can be built for either one, or both. + * + */ + +typedef struct _Sockettrans2dev { + char *transname; + int family; + int devcotsname; + int devcltsname; + int protocol; +} Sockettrans2dev; + +static Sockettrans2dev Sockettrans2devtab[] = { +#ifdef TCPCONN + {"inet",AF_INET,SOCK_STREAM,SOCK_DGRAM,0}, + {"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 + +#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 + +#endif /* hpux */ + +#endif /* UNIXCONN */ + + +/* + * These are some utility function used by the real interface function below. + */ + +static int +TRANS(SocketSelectFamily) (family) + +char *family; + +{ + int i; + + PRMSG (3,"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; +#if defined(SVR4) || defined(SCO325) + size_t namelen = sizeof sockname; +#else + int namelen = sizeof sockname; +#endif + + PRMSG (3,"SocketINETGetAddr(%x)\n", ciptr, 0, 0); + + if (getsockname (ciptr->fd,(struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"SocketINETGetAddr: getsockname() failed: %d\n", + EGET(),0, 0); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->addr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, + "SocketINETGetAddr: Can't allocate space for the addr\n", + 0, 0, 0); + return -1; + } + + 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; +#if defined(SVR4) || defined(SCO325) + size_t namelen = sizeof sockname; +#else + int namelen = sizeof sockname; +#endif + + PRMSG (3,"SocketINETGetPeerAddr(%x)\n", ciptr, 0, 0); + + if (getpeername (ciptr->fd, (struct sockaddr *) &sockname, &namelen) < 0) + { + PRMSG (1,"SocketINETGetPeerAddr: getpeername() failed: %d\n", + EGET(), 0, 0); + return -1; + } + + /* + * Everything looks good: fill in the XtransConnInfo structure. + */ + + if ((ciptr->peeraddr = (char *) xalloc (namelen)) == NULL) + { + PRMSG (1, + "SocketINETGetPeerAddr: Can't allocate space for the addr\n", + 0, 0, 0); + return -1; + } + + ciptr->peeraddrlen = namelen; + memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); + + return 0; +} + + +static XtransConnInfo +TRANS(SocketOpen) (i, type) + +int i; +int type; + +{ + XtransConnInfo ciptr; + + PRMSG (3,"SocketOpen(%d,%d)\n", i, type, 0); + + if ((ciptr = (XtransConnInfo) xcalloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "SocketOpen: malloc failed\n", 0, 0, 0); + return NULL; + } + + if ((ciptr->fd = socket(Sockettrans2devtab[i].family, type, + Sockettrans2devtab[i].protocol)) < 0 +#ifndef WIN32 +#if (defined(X11_t) && !defined(USE_POLL)) || defined(FS_t) || defined(FONT_t) + || ciptr->fd >= TRANS_OPEN_MAX +#endif +#endif + ) { + PRMSG (1, "SocketOpen: socket() failed for %s\n", + Sockettrans2devtab[i].transname, 0, 0); + + xfree ((char *) ciptr); + return NULL; + } + +#ifdef TCP_NODELAY + if (Sockettrans2devtab[i].family == AF_INET) + { + /* + * 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,"SocketReopen(%d,%d,%s)\n", type, fd, port); + + if ((ciptr = (XtransConnInfo) xcalloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "SocketReopen: malloc failed\n", 0, 0, 0); + return NULL; + } + + ciptr->fd = fd; + + return ciptr; +} + +#endif /* TRANS_REOPEN */ + + +/* + * These functions are the interface supplied in the Xtransport structure + */ + +#ifdef TRANS_CLIENT + +static XtransConnInfo +TRANS(SocketOpenCOTSClient) (thistrans, protocol, host, port) + +Xtransport *thistrans; +char *protocol; +char *host; +char *port; + +{ + XtransConnInfo ciptr; + int i; + + PRMSG (2, "SocketOpenCOTSClient(%s,%s,%s)\n", + protocol, host, port); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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,"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,"SocketOpenCOTSServer(%s,%s,%s)\n", protocol, host, port); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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,"SocketOpenCOTSServer: Unable to open socket for %s\n", + thistrans->TransName, 0, 0); + return NULL; + } + + /* + * Using this prevents the bind() check for an existing server listening + * on the same port, but it is required for other reasons. + */ +#ifdef SO_REUSEADDR + + /* + * SO_REUSEADDR only applied to AF_INET + */ + + 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,"SocketOpenCLTSClient(%s,%s,%s)\n", protocol, host, port); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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,"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,"SocketOpenCLTSServer(%s,%s,%s)\n", protocol, host, port); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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,"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, + "SocketReopenCOTSServer(%d, %s)\n", fd, port, 0); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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, + "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, + "SocketReopenCLTSServer(%d, %s)\n", fd, port, 0); + + SocketInitOnce(); + + if ((i = TRANS(SocketSelectFamily) (thistrans->TransName)) < 0) + { + PRMSG (1, + "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, + "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,"SocketSetOption(%d,%d,%d)\n", ciptr->fd, option, arg); + + return -1; +} + + +#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, "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, "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, BACKLOG) < 0) + { + PRMSG (1, "SocketCreateListener: listen() failed\n", 0, 0, 0); + close (fd); + return TRANS_CREATE_LISTENER_FAILED; + } + + /* Set a flag to indicate that this connection is a listener */ + + ciptr->flags = 1; + + return 0; +} + + +#ifdef TCPCONN +static int +TRANS(SocketINETCreateListener) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct sockaddr_in sockname; + int namelen = sizeof(sockname); + int status; + short tmpport; + _Xgetservbynameparams sparams; + struct servent *servp; + +#define PORTBUFSIZE 64 /* what is a real size for this? */ + + char portbuf[PORTBUFSIZE]; + + PRMSG (2, "SocketINETCreateListener(%s)\n", port, 0, 0); + +#ifdef X11_t + /* + * X has a well known port, that is transport dependent. It is easier + * to handle it here, than try and come up with a transport independent + * representation that can be passed in and resolved the usual way. + * + * The port that is passed here is really a string containing the idisplay + * from ConnectDisplay(). + */ + + if (is_numeric (port)) + { + tmpport = (short) atoi (port); + + sprintf (portbuf,"%d", X_TCP_PORT+tmpport); + } + else + strncpy (portbuf, port, PORTBUFSIZE); + + port = portbuf; +#endif + + if (port && *port) + { + /* Check to see if the port string is just a number (handles X11) */ + + if (!is_numeric (port)) + { + if ((servp = _XGetservbyname (port,"tcp",sparams)) == NULL) + { + PRMSG (1, + "SocketINETCreateListener: Unable to get service for %s\n", + port, 0, 0); + return TRANS_CREATE_LISTENER_FAILED; + } + sockname.sin_port = servp->s_port; + } + else + { + tmpport = (short) atoi (port); + sockname.sin_port = htons (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, + "SocketINETCreateListener: ...SocketCreateListener() failed\n", + 0, 0, 0); + return status; + } + + if (TRANS(SocketINETGetAddr) (ciptr) < 0) + { + PRMSG (1, + "SocketINETCreateListener: ...SocketINETGetAddr() failed\n", + 0, 0, 0); + return TRANS_CREATE_LISTENER_FAILED; + } + + return 0; +} + +#endif /* SOCKCONN */ + + +#ifdef UNIXCONN + +static +TRANS(SocketUNIXCreateListener) (ciptr, port) + +XtransConnInfo ciptr; +char *port; + +{ + struct sockaddr_un sockname; + int namelen; + int oldUmask; + int status; + + PRMSG (2, "SocketUNIXCreateListener(%s)\n", + port ? port : "NULL", 0, 0); + + /* Make sure the directory is created */ + + oldUmask = umask (0); + +#ifdef UNIX_DIR + if (!mkdir (UNIX_DIR, 01777)) + chmod (UNIX_DIR, 01777); +#endif + + sockname.sun_family = AF_UNIX; + + if (port && *port) { + if (*port == '/') { /* a full pathname */ + sprintf (sockname.sun_path, "%s", port); + } else { + sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port); + } + } else { + sprintf (sockname.sun_path, "%s%d", UNIX_PATH, getpid()); + } + +#if defined(BSD44SOCKETS) && !defined(Lynx) + sockname.sun_len = strlen(sockname.sun_path); + namelen = SUN_LEN(&sockname); +#else + namelen = strlen(sockname.sun_path) + sizeof(sockname.sun_family); +#endif + + unlink (sockname.sun_path); + + if ((status = TRANS(SocketCreateListener) (ciptr, + (struct sockaddr *) &sockname, namelen)) < 0) + { + PRMSG (1, + "SocketUNIXCreateListener: ...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 *) xalloc (namelen)) == NULL) + { + PRMSG (1, + "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, "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) || defined(sco) || !defined(S_IFSOCK) + S_IFIFO)) +#else + S_IFSOCK)) +#endif + { + int oldUmask = umask (0); + +#ifdef UNIX_DIR + if (!mkdir (UNIX_DIR, 01777)) + chmod (UNIX_DIR, 01777); +#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, BACKLOG) < 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, "SocketINETAccept(%x,%d)\n", ciptr, ciptr->fd, 0); + + if ((newciptr = (XtransConnInfo) xcalloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "SocketINETAccept: malloc failed\n", 0, 0, 0); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + + if ((newciptr->fd = accept (ciptr->fd, + (struct sockaddr *) &sockname, &namelen)) < 0) + { + PRMSG (1, "SocketINETAccept: accept() failed\n", 0, 0, 0); + xfree (newciptr); + *status = TRANS_ACCEPT_FAILED; + return NULL; + } + +#ifdef TCP_NODELAY + { + /* + * turn off TCP coalescence for INET sockets + */ + + int tmp = 1; + setsockopt (newciptr->fd, IPPROTO_TCP, TCP_NODELAY, + (char *) &tmp, sizeof (int)); + } +#endif + + /* + * Get this address again because the transport may give a more + * specific address now that a connection is established. + */ + + if (TRANS(SocketINETGetAddr) (newciptr) < 0) + { + PRMSG (1, + "SocketINETAccept: ...SocketINETGetAddr() failed:\n", + 0, 0, 0); + close (newciptr->fd); + xfree (newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + if (TRANS(SocketINETGetPeerAddr) (newciptr) < 0) + { + PRMSG (1, + "SocketINETAccept: ...SocketINETGetPeerAddr() failed:\n", + 0, 0, 0); + close (newciptr->fd); + if (newciptr->addr) xfree (newciptr->addr); + xfree (newciptr); + *status = TRANS_ACCEPT_MISC_ERROR; + return NULL; + } + + *status = 0; + + return newciptr; +} + +#endif /* TCPCONN */ + + +#ifdef UNIXCONN +static XtransConnInfo +TRANS(SocketUNIXAccept) (ciptr, status) + +XtransConnInfo ciptr; +int *status; + +{ + XtransConnInfo newciptr; + struct sockaddr_un sockname; +#if defined(SVR4) || defined(SCO325) + size_t namelen = sizeof sockname; +#else + int namelen = sizeof sockname; +#endif + + PRMSG (2, "SocketUNIXAccept(%x,%d)\n", ciptr, ciptr->fd, 0); + + if ((newciptr = (XtransConnInfo) xcalloc ( + 1, sizeof(struct _XtransConnInfo))) == NULL) + { + PRMSG (1, "SocketUNIXAccept: malloc() failed\n", 0, 0, 0); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + + if ((newciptr->fd = accept (ciptr->fd, + (struct sockaddr *) &sockname, &namelen)) < 0) + { + PRMSG (1, "SocketUNIXAccept: accept() failed\n", 0, 0, 0); + xfree (newciptr); + *status = TRANS_ACCEPT_FAILED; + return NULL; + } + + /* + * Get the socket name and the peer name from the listener socket, + * since this is unix domain. + */ + + if ((newciptr->addr = (char *) xalloc (ciptr->addrlen)) == NULL) + { + PRMSG (1, + "SocketUNIXAccept: Can't allocate space for the addr\n", + 0, 0, 0); + close (newciptr->fd); + xfree (newciptr); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + + + newciptr->addrlen = ciptr->addrlen; + memcpy (newciptr->addr, ciptr->addr, newciptr->addrlen); + + if ((newciptr->peeraddr = (char *) xalloc (ciptr->addrlen)) == NULL) + { + PRMSG (1, + "SocketUNIXAccept: Can't allocate space for the addr\n", + 0, 0, 0); + close (newciptr->fd); + if (newciptr->addr) xfree (newciptr->addr); + xfree (newciptr); + *status = TRANS_ACCEPT_BAD_MALLOC; + return NULL; + } + + newciptr->peeraddrlen = ciptr->addrlen; + memcpy (newciptr->peeraddr, ciptr->addr, newciptr->addrlen); + + newciptr->family = AF_UNIX; + + *status = 0; + + return newciptr; +} + +#endif /* UNIXCONN */ + +#endif /* TRANS_SERVER */ + + +#ifdef TRANS_CLIENT + +#ifdef TCPCONN +static int +TRANS(SocketINETConnect) (ciptr, host, port) + +XtransConnInfo ciptr; +char *host; +char *port; + +{ + struct sockaddr_in sockname; +#if defined(SVR4) || defined(SCO325) + size_t namelen = sizeof sockname; +#else + int namelen = sizeof sockname; +#endif + _Xgethostbynameparams hparams; + _Xgetservbynameparams sparams; + struct hostent *hostp; + struct servent *servp; + +#define PORTBUFSIZE 64 /* what is a real size for this? */ + char portbuf[PORTBUFSIZE]; + + int ret; + short tmpport; + unsigned long tmpaddr; + char hostnamebuf[256]; /* tmp space */ + + PRMSG (2,"SocketINETConnect(%d,%s,%s)\n", ciptr->fd, host, port); + + if (!host) + { + hostnamebuf[0] = '\0'; + (void) TRANS(GetHostname) (hostnamebuf, sizeof hostnamebuf); + host = hostnamebuf; + } + +#ifdef X11_t + /* + * X has a well known port, that is transport dependent. It is easier + * to handle it here, than try and come up with a transport independent + * representation that can be passed in and resolved the usual way. + * + * The port that is passed here is really a string containing the idisplay + * from ConnectDisplay(). + */ + + if (is_numeric (port)) + { + tmpport = (short) atoi (port); + + sprintf (portbuf, "%d", X_TCP_PORT + tmpport); + } + else +#endif + strncpy (portbuf, port, PORTBUFSIZE); + + /* + * 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,"SocketINETConnect: inet_addr(%s) = %x\n", + host, tmpaddr, 0); + + if (tmpaddr == -1) + { + if ((hostp = _XGethostbyname(host,hparams)) == NULL) + { + PRMSG (1,"SocketINETConnect: Can't get address for %s\n", + host, 0, 0); + ESET(EINVAL); + return TRANS_CONNECT_FAILED; + } + if (hostp->h_addrtype != AF_INET) /* is IP host? */ + { + PRMSG (1,"SocketINETConnect: not INET host%s\n", + host, 0, 0); + ESET(EPROTOTYPE); + return TRANS_CONNECT_FAILED; + } + +#if defined(CRAY) && defined(OLDTCP) + /* Only Cray UNICOS3 and UNICOS4 will define this */ + { + long t; + memcpy ((char *)&t, (char *) hostp->h_addr, sizeof (t)); + sockname.sin_addr = t; + } +#else + memcpy ((char *) &sockname.sin_addr, (char *) hostp->h_addr, + sizeof (sockname.sin_addr)); +#endif /* CRAY and OLDTCP */ + + } +else + { +#if defined(CRAY) && defined(OLDTCP) + /* Only Cray UNICOS3 and UNICOS4 will define this */ + sockname.sin_addr = tmpaddr; +#else + sockname.sin_addr.s_addr = tmpaddr; +#endif /* CRAY and OLDTCP */ + } + + /* + * fill in sin_port + */ + + /* Check for number in the port string */ + + if (!is_numeric (portbuf)) + { + if ((servp = _XGetservbyname (portbuf,"tcp",sparams)) == NULL) + { + PRMSG (1,"SocketINETConnect: Can't get service for %s\n", + portbuf, 0, 0); + return TRANS_CONNECT_FAILED; + } + sockname.sin_port = servp->s_port; + } + else + { + tmpport = (short) atoi (portbuf); + sockname.sin_port = htons (tmpport); + } + + PRMSG (4,"SocketINETConnect: sockname.sin_port = %d\n", + ntohs(sockname.sin_port), 0, 0); + + /* + * Do the connect() + */ + + if (connect (ciptr->fd, (struct sockaddr *) &sockname, namelen) < 0) + { +#ifdef WIN32 + int olderrno = WSAGetLastError(); +#else + int olderrno = errno; +#endif + + PRMSG (1,"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, + "SocketINETConnect: ...SocketINETGetAddr() failed:\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + if (TRANS(SocketINETGetPeerAddr) (ciptr) < 0) + { + PRMSG (1, + "SocketINETConnect: ...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,"SocketUNIXConnect(%d,%s,%s)\n", ciptr->fd, host, port); + + /* + * Make sure 'host' is really local. If not, we return failure. + * The reason we make this check is because a process may advertise + * a "local" network ID for which it can accept connections, but if + * a process on a remote machine tries to connect to this network ID, + * we know for sure it will fail. + */ + + if (strcmp (host, "unix") != 0 && !UnixHostReallyLocal (host)) + { + PRMSG (1, + "SocketUNIXConnect: Cannot connect to non-local host %s\n", + host, 0, 0); + return TRANS_CONNECT_FAILED; + } + + + /* + * Check the port. + */ + + if (!port || !*port) + { + PRMSG (1,"SocketUNIXConnect: Missing port specification\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + /* + * Build the socket name. + */ + + sockname.sun_family = AF_UNIX; + + if (*port == '/') { /* a full pathname */ + sprintf (sockname.sun_path, "%s", port); + } else { + sprintf (sockname.sun_path, "%s%s", UNIX_PATH, port); + } + +#if defined(BSD44SOCKETS) && !defined(Lynx) + sockname.sun_len = strlen (sockname.sun_path); + namelen = SUN_LEN (&sockname); +#else + namelen = strlen (sockname.sun_path) + sizeof (sockname.sun_family); +#endif + + +#if defined(hpux) && defined(X11_t) + /* + * This is gross, but it was in Xlib + */ + old_sockname.sun_family = AF_UNIX; + if (*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,"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 *) xalloc(namelen)) == NULL || + (ciptr->peeraddr = (char *) xalloc(namelen)) == NULL) + { + PRMSG (1, + "SocketUNIXCreateListener: Can't allocate space for the addr\n", + 0, 0, 0); + return TRANS_CONNECT_FAILED; + } + + ciptr->family = AF_UNIX; + ciptr->addrlen = namelen; + ciptr->peeraddrlen = namelen; + memcpy (ciptr->addr, &sockname, ciptr->addrlen); + memcpy (ciptr->peeraddr, &sockname, ciptr->peeraddrlen); + + return 0; +} + +#endif /* UNIXCONN */ + +#endif /* TRANS_CLIENT */ + + +static int +TRANS(SocketBytesReadable) (ciptr, pend) + +XtransConnInfo ciptr; +BytesReadable_t *pend; +{ + PRMSG (2,"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(_SEQUENT_) + return ioctl (ciptr->fd, I_NREAD, (char *) pend); +#else +#if defined(__EMX__) + return ioctl (ciptr->fd, FIONREAD, (char*) pend, sizeof(int)); +#else + return ioctl (ciptr->fd, FIONREAD, (char *) pend); +#endif /* __EMX__ */ +#endif /* i386 && SYSV && !SCO || _SEQUENT_ */ +#endif /* WIN32 */ +} + + +static int +TRANS(SocketRead) (ciptr, buf, size) + +XtransConnInfo ciptr; +char *buf; +int size; + +{ + PRMSG (2,"SocketRead(%d,%x,%d)\n", ciptr->fd, buf, size); + +#if defined(WIN32) || defined(__EMX__) + 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,"SocketWrite(%d,%x,%d)\n", ciptr->fd, buf, size); + +#if defined(WIN32) || defined(__EMX__) + 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,"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,"SocketWritev(%d,%x,%d)\n", ciptr->fd, buf, size); + + return WRITEV (ciptr, buf, size); +} + + +static int +TRANS(SocketDisconnect) (ciptr) + +XtransConnInfo ciptr; + +{ + PRMSG (2,"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,"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,"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,"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 */