Xtrans.c revision 3d2ed3e3
173143b9aSmrg/* 273143b9aSmrg 373143b9aSmrgCopyright 1993, 1994, 1998 The Open Group 473143b9aSmrg 573143b9aSmrgPermission to use, copy, modify, distribute, and sell this software and its 673143b9aSmrgdocumentation for any purpose is hereby granted without fee, provided that 773143b9aSmrgthe above copyright notice appear in all copies and that both that 873143b9aSmrgcopyright notice and this permission notice appear in supporting 973143b9aSmrgdocumentation. 1073143b9aSmrg 1173143b9aSmrgThe above copyright notice and this permission notice shall be included 1273143b9aSmrgin all copies or substantial portions of the Software. 1373143b9aSmrg 1473143b9aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1573143b9aSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1673143b9aSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1773143b9aSmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 1873143b9aSmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1973143b9aSmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2073143b9aSmrgOTHER DEALINGS IN THE SOFTWARE. 2173143b9aSmrg 2273143b9aSmrgExcept as contained in this notice, the name of The Open Group shall 2373143b9aSmrgnot be used in advertising or otherwise to promote the sale, use or 2473143b9aSmrgother dealings in this Software without prior written authorization 2573143b9aSmrgfrom The Open Group. 2673143b9aSmrg 2773143b9aSmrg * Copyright 1993, 1994 NCR Corporation - Dayton, Ohio, USA 2873143b9aSmrg * 2973143b9aSmrg * All Rights Reserved 3073143b9aSmrg * 3173143b9aSmrg * Permission to use, copy, modify, and distribute this software and its 3273143b9aSmrg * documentation for any purpose and without fee is hereby granted, provided 3373143b9aSmrg * that the above copyright notice appear in all copies and that both that 3473143b9aSmrg * copyright notice and this permission notice appear in supporting 3573143b9aSmrg * documentation, and that the name NCR not be used in advertising 3673143b9aSmrg * or publicity pertaining to distribution of the software without specific, 3773143b9aSmrg * written prior permission. NCR makes no representations about the 3873143b9aSmrg * suitability of this software for any purpose. It is provided "as is" 3973143b9aSmrg * without express or implied warranty. 4073143b9aSmrg * 4173143b9aSmrg * NCR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 4273143b9aSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 4373143b9aSmrg * NO EVENT SHALL NCR BE LIABLE FOR ANY SPECIAL, INDIRECT OR 4473143b9aSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 4573143b9aSmrg * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 4673143b9aSmrg * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 4773143b9aSmrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 4873143b9aSmrg */ 4973143b9aSmrg 5073143b9aSmrg#include <ctype.h> 518a0d9095Smrg#include <stdlib.h> 5275ebec6dSmrg#include <string.h> 538a0d9095Smrg#ifdef HAVE_SYSTEMD_DAEMON 5475ebec6dSmrg#include <systemd/sd-daemon.h> 5575ebec6dSmrg#endif 5673143b9aSmrg 5773143b9aSmrg/* 5873143b9aSmrg * The transport table contains a definition for every transport (protocol) 5973143b9aSmrg * family. All operations that can be made on the transport go through this 6073143b9aSmrg * table. 6173143b9aSmrg * 6273143b9aSmrg * Each transport is assigned a unique transport id. 6373143b9aSmrg * 6473143b9aSmrg * New transports can be added by adding an entry in this table. 6573143b9aSmrg * For compatiblity, the transport ids should never be renumbered. 6673143b9aSmrg * Always add to the end of the list. 6773143b9aSmrg */ 6873143b9aSmrg 6973143b9aSmrg#define TRANS_TLI_INET_INDEX 1 7073143b9aSmrg#define TRANS_TLI_TCP_INDEX 2 7173143b9aSmrg#define TRANS_TLI_TLI_INDEX 3 7273143b9aSmrg#define TRANS_SOCKET_UNIX_INDEX 4 7373143b9aSmrg#define TRANS_SOCKET_LOCAL_INDEX 5 7473143b9aSmrg#define TRANS_SOCKET_INET_INDEX 6 7573143b9aSmrg#define TRANS_SOCKET_TCP_INDEX 7 7673143b9aSmrg#define TRANS_DNET_INDEX 8 7773143b9aSmrg#define TRANS_LOCAL_LOCAL_INDEX 9 7873143b9aSmrg#define TRANS_LOCAL_PTS_INDEX 10 7973143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX 11 80af928962Smrg/* 12 used to be ISC, but that's gone. */ 8173143b9aSmrg#define TRANS_LOCAL_SCO_INDEX 13 8273143b9aSmrg#define TRANS_SOCKET_INET6_INDEX 14 8373143b9aSmrg#define TRANS_LOCAL_PIPE_INDEX 15 8473143b9aSmrg 8573143b9aSmrg 8673143b9aSmrgstatic 8773143b9aSmrgXtransport_table Xtransports[] = { 8873143b9aSmrg#if defined(TCPCONN) 8973143b9aSmrg { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, 9073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 9173143b9aSmrg { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, 9273143b9aSmrg#endif /* IPv6 */ 9373143b9aSmrg { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, 9473143b9aSmrg#endif /* TCPCONN */ 9573143b9aSmrg#if defined(UNIXCONN) 9673143b9aSmrg#if !defined(LOCALCONN) 9773143b9aSmrg { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX }, 9873143b9aSmrg#endif /* !LOCALCONN */ 9973143b9aSmrg { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, 10073143b9aSmrg#endif /* UNIXCONN */ 10173143b9aSmrg#if defined(LOCALCONN) 10273143b9aSmrg { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, 1033d2ed3e3Smrg#ifndef __sun 10473143b9aSmrg { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX }, 1053d2ed3e3Smrg#endif /* __sun */ 106e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 10773143b9aSmrg { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX }, 10873143b9aSmrg#endif 1093d2ed3e3Smrg#ifdef __sun 11073143b9aSmrg { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX }, 1113d2ed3e3Smrg#endif /* __sun */ 112af928962Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 113af928962Smrg { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX }, 114af928962Smrg#endif /* __SCO__ || __UNIXWARE__ */ 11573143b9aSmrg#endif /* LOCALCONN */ 11673143b9aSmrg}; 11773143b9aSmrg 11873143b9aSmrg#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) 11973143b9aSmrg 12073143b9aSmrg 12173143b9aSmrg#ifdef WIN32 12273143b9aSmrg#define ioctl ioctlsocket 12373143b9aSmrg#endif 12473143b9aSmrg 12573143b9aSmrg 12673143b9aSmrg 12773143b9aSmrg/* 12873143b9aSmrg * These are a few utility function used by the public interface functions. 12973143b9aSmrg */ 13073143b9aSmrg 13173143b9aSmrgvoid 13273143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr) 13373143b9aSmrg 13473143b9aSmrg{ 135fe567363Smrg prmsg (3,"FreeConnInfo(%p)\n", ciptr); 13673143b9aSmrg 13773143b9aSmrg if (ciptr->addr) 138fe567363Smrg free (ciptr->addr); 13973143b9aSmrg 14073143b9aSmrg if (ciptr->peeraddr) 141fe567363Smrg free (ciptr->peeraddr); 14273143b9aSmrg 14373143b9aSmrg if (ciptr->port) 144fe567363Smrg free (ciptr->port); 14573143b9aSmrg 146fe567363Smrg free (ciptr); 14773143b9aSmrg} 14873143b9aSmrg 14973143b9aSmrg 15073143b9aSmrg#define PROTOBUFSIZE 20 15173143b9aSmrg 15273143b9aSmrgstatic Xtransport * 153fe567363SmrgTRANS(SelectTransport) (const char *protocol) 15473143b9aSmrg 15573143b9aSmrg{ 1563d2ed3e3Smrg#ifndef HAVE_STRCASECMP 15773143b9aSmrg char protobuf[PROTOBUFSIZE]; 1583d2ed3e3Smrg#endif 15973143b9aSmrg int i; 16073143b9aSmrg 161fe567363Smrg prmsg (3,"SelectTransport(%s)\n", protocol); 16273143b9aSmrg 1633d2ed3e3Smrg#ifndef HAVE_STRCASECMP 16473143b9aSmrg /* 16573143b9aSmrg * Force Protocol to be lowercase as a way of doing 16673143b9aSmrg * a case insensitive match. 16773143b9aSmrg */ 16873143b9aSmrg 16973143b9aSmrg strncpy (protobuf, protocol, PROTOBUFSIZE - 1); 17073143b9aSmrg protobuf[PROTOBUFSIZE-1] = '\0'; 17173143b9aSmrg 17273143b9aSmrg for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) 1738a0d9095Smrg if (isupper ((unsigned char)protobuf[i])) 1748a0d9095Smrg protobuf[i] = tolower ((unsigned char)protobuf[i]); 1753d2ed3e3Smrg#endif 17673143b9aSmrg 17773143b9aSmrg /* Look at all of the configured protocols */ 17873143b9aSmrg 17973143b9aSmrg for (i = 0; i < NUMTRANS; i++) 18073143b9aSmrg { 1813d2ed3e3Smrg#ifndef HAVE_STRCASECMP 18273143b9aSmrg if (!strcmp (protobuf, Xtransports[i].transport->TransName)) 1833d2ed3e3Smrg#else 1843d2ed3e3Smrg if (!strcasecmp (protocol, Xtransports[i].transport->TransName)) 1853d2ed3e3Smrg#endif 18673143b9aSmrg return Xtransports[i].transport; 18773143b9aSmrg } 18873143b9aSmrg 18973143b9aSmrg return NULL; 19073143b9aSmrg} 19173143b9aSmrg 19273143b9aSmrg#ifndef TEST_t 19373143b9aSmrgstatic 19473143b9aSmrg#endif /* TEST_t */ 19573143b9aSmrgint 1966a3641a6SsnjTRANS(ParseAddress) (const char *address, 1976a3641a6Ssnj char **protocol, char **host, char **port) 19873143b9aSmrg 19973143b9aSmrg{ 20073143b9aSmrg /* 20173143b9aSmrg * For the font library, the address is a string formatted 20273143b9aSmrg * as "protocol/host:port[/catalogue]". Note that the catologue 20373143b9aSmrg * is optional. At this time, the catologue info is ignored, but 20473143b9aSmrg * we have to parse it anyways. 20573143b9aSmrg * 20673143b9aSmrg * Other than fontlib, the address is a string formatted 20773143b9aSmrg * as "protocol/host:port". 20873143b9aSmrg * 20973143b9aSmrg * If the protocol part is missing, then assume TCP. 21073143b9aSmrg * If the protocol part and host part are missing, then assume local. 21173143b9aSmrg * If a "::" is found then assume DNET. 21273143b9aSmrg */ 21373143b9aSmrg 21473143b9aSmrg char *mybuf, *tmpptr; 215fe567363Smrg const char *_protocol; 216fe567363Smrg char *_host, *_port; 21773143b9aSmrg char hostnamebuf[256]; 21873143b9aSmrg int _host_len; 21973143b9aSmrg 220fe567363Smrg prmsg (3,"ParseAddress(%s)\n", address); 22173143b9aSmrg 22273143b9aSmrg /* Copy the string so it can be changed */ 22373143b9aSmrg 224fe567363Smrg tmpptr = mybuf = strdup (address); 22573143b9aSmrg 22673143b9aSmrg /* Parse the string to get each component */ 227fe567363Smrg 22873143b9aSmrg /* Get the protocol part */ 22973143b9aSmrg 23073143b9aSmrg _protocol = mybuf; 23173143b9aSmrg 23273143b9aSmrg 23373143b9aSmrg if ( ((mybuf = strchr (mybuf,'/')) == NULL) && 23473143b9aSmrg ((mybuf = strrchr (tmpptr,':')) == NULL) ) 23573143b9aSmrg { 23673143b9aSmrg /* address is in a bad format */ 23773143b9aSmrg *protocol = NULL; 23873143b9aSmrg *host = NULL; 23973143b9aSmrg *port = NULL; 240fe567363Smrg free (tmpptr); 24173143b9aSmrg return 0; 24273143b9aSmrg } 24373143b9aSmrg 24473143b9aSmrg if (*mybuf == ':') 24573143b9aSmrg { 24673143b9aSmrg /* 24773143b9aSmrg * If there is a hostname, then assume tcp, otherwise 24873143b9aSmrg * it must be local. 24973143b9aSmrg */ 25073143b9aSmrg if (mybuf == tmpptr) 25173143b9aSmrg { 25273143b9aSmrg /* There is neither a protocol or host specified */ 25373143b9aSmrg _protocol = "local"; 25473143b9aSmrg } 25573143b9aSmrg else 25673143b9aSmrg { 25773143b9aSmrg /* There is a hostname specified */ 25873143b9aSmrg _protocol = "tcp"; 25973143b9aSmrg mybuf = tmpptr; /* reset to the begining of the host ptr */ 26073143b9aSmrg } 26173143b9aSmrg } 26273143b9aSmrg else 26373143b9aSmrg { 26473143b9aSmrg /* *mybuf == '/' */ 26573143b9aSmrg 26673143b9aSmrg *mybuf ++= '\0'; /* put a null at the end of the protocol */ 26773143b9aSmrg 26873143b9aSmrg if (strlen(_protocol) == 0) 26973143b9aSmrg { 27073143b9aSmrg /* 27173143b9aSmrg * If there is a hostname, then assume tcp, otherwise 27273143b9aSmrg * it must be local. 27373143b9aSmrg */ 27473143b9aSmrg if (*mybuf != ':') 27573143b9aSmrg _protocol = "tcp"; 27673143b9aSmrg else 27773143b9aSmrg _protocol = "local"; 27873143b9aSmrg } 27973143b9aSmrg } 28073143b9aSmrg 28173143b9aSmrg /* Get the host part */ 28273143b9aSmrg 28373143b9aSmrg _host = mybuf; 28473143b9aSmrg 28573143b9aSmrg if ((mybuf = strrchr (mybuf,':')) == NULL) 28673143b9aSmrg { 28773143b9aSmrg *protocol = NULL; 28873143b9aSmrg *host = NULL; 28973143b9aSmrg *port = NULL; 290fe567363Smrg free (tmpptr); 29173143b9aSmrg return 0; 29273143b9aSmrg } 29373143b9aSmrg 29473143b9aSmrg *mybuf ++= '\0'; 29573143b9aSmrg 29673143b9aSmrg _host_len = strlen(_host); 29773143b9aSmrg if (_host_len == 0) 29873143b9aSmrg { 29973143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 30073143b9aSmrg _host = hostnamebuf; 30173143b9aSmrg } 30273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 30373143b9aSmrg /* hostname in IPv6 [numeric_addr]:0 form? */ 304fe567363Smrg else if ( (_host_len > 3) && 30573143b9aSmrg ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) 306fe567363Smrg && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { 30773143b9aSmrg struct sockaddr_in6 sin6; 30873143b9aSmrg 30973143b9aSmrg *(_host + _host_len - 1) = '\0'; 31073143b9aSmrg 31173143b9aSmrg /* Verify address is valid IPv6 numeric form */ 31273143b9aSmrg if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { 31373143b9aSmrg /* It is. Use it as such. */ 31473143b9aSmrg _host++; 31573143b9aSmrg _protocol = "inet6"; 31673143b9aSmrg } else { 31773143b9aSmrg /* It's not, restore it just in case some other code can use it. */ 31873143b9aSmrg *(_host + _host_len - 1) = ']'; 31973143b9aSmrg } 32073143b9aSmrg } 32173143b9aSmrg#endif 32273143b9aSmrg 32373143b9aSmrg 32473143b9aSmrg /* Get the port */ 32573143b9aSmrg 32673143b9aSmrg _port = mybuf; 32773143b9aSmrg 32873143b9aSmrg#if defined(FONT_t) || defined(FS_t) 32973143b9aSmrg /* 33073143b9aSmrg * Is there an optional catalogue list? 33173143b9aSmrg */ 33273143b9aSmrg 33373143b9aSmrg if ((mybuf = strchr (mybuf,'/')) != NULL) 33473143b9aSmrg *mybuf ++= '\0'; 33573143b9aSmrg 33673143b9aSmrg /* 33773143b9aSmrg * The rest, if any, is the (currently unused) catalogue list. 33873143b9aSmrg * 33973143b9aSmrg * _catalogue = mybuf; 34073143b9aSmrg */ 34173143b9aSmrg#endif 34273143b9aSmrg 34373143b9aSmrg#ifdef HAVE_LAUNCHD 34473143b9aSmrg /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ 34573143b9aSmrg if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) { 34673143b9aSmrg _protocol="local"; 34773143b9aSmrg _host=""; 34873143b9aSmrg _port=address+6; 34973143b9aSmrg } 35073143b9aSmrg#endif 35173143b9aSmrg 35273143b9aSmrg /* 35373143b9aSmrg * Now that we have all of the components, allocate new 35473143b9aSmrg * string space for them. 35573143b9aSmrg */ 35673143b9aSmrg 357fe567363Smrg if ((*protocol = strdup (_protocol)) == NULL) 35873143b9aSmrg { 35973143b9aSmrg /* Malloc failed */ 36073143b9aSmrg *port = NULL; 36173143b9aSmrg *host = NULL; 36273143b9aSmrg *protocol = NULL; 363fe567363Smrg free (tmpptr); 36473143b9aSmrg return 0; 36573143b9aSmrg } 36673143b9aSmrg 367fe567363Smrg if ((*host = strdup (_host)) == NULL) 36873143b9aSmrg { 36973143b9aSmrg /* Malloc failed */ 37073143b9aSmrg *port = NULL; 37173143b9aSmrg *host = NULL; 372fe567363Smrg free (*protocol); 37373143b9aSmrg *protocol = NULL; 374fe567363Smrg free (tmpptr); 37573143b9aSmrg return 0; 376fe567363Smrg } 37773143b9aSmrg 378fe567363Smrg if ((*port = strdup (_port)) == NULL) 37973143b9aSmrg { 38073143b9aSmrg /* Malloc failed */ 38173143b9aSmrg *port = NULL; 382fe567363Smrg free (*host); 38373143b9aSmrg *host = NULL; 384fe567363Smrg free (*protocol); 38573143b9aSmrg *protocol = NULL; 386fe567363Smrg free (tmpptr); 38773143b9aSmrg return 0; 38873143b9aSmrg } 38973143b9aSmrg 390fe567363Smrg free (tmpptr); 39173143b9aSmrg 39273143b9aSmrg return 1; 39373143b9aSmrg} 39473143b9aSmrg 39573143b9aSmrg 39673143b9aSmrg/* 39773143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only 39873143b9aSmrg * funny part about this is the type parameter which is used to decide which 39973143b9aSmrg * type of open to perform. 40073143b9aSmrg */ 40173143b9aSmrg 40273143b9aSmrgstatic XtransConnInfo 4036a3641a6SsnjTRANS(Open) (int type, const char *address) 40473143b9aSmrg 40573143b9aSmrg{ 40673143b9aSmrg char *protocol = NULL, *host = NULL, *port = NULL; 40773143b9aSmrg XtransConnInfo ciptr = NULL; 40873143b9aSmrg Xtransport *thistrans; 40973143b9aSmrg 410fe567363Smrg prmsg (2,"Open(%d,%s)\n", type, address); 41173143b9aSmrg 412fe567363Smrg#if defined(WIN32) && defined(TCPCONN) 41373143b9aSmrg if (TRANS(WSAStartup)()) 41473143b9aSmrg { 415fe567363Smrg prmsg (1,"Open: WSAStartup failed\n"); 41673143b9aSmrg return NULL; 41773143b9aSmrg } 41873143b9aSmrg#endif 41973143b9aSmrg 42073143b9aSmrg /* Parse the Address */ 42173143b9aSmrg 42273143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 42373143b9aSmrg { 424fe567363Smrg prmsg (1,"Open: Unable to Parse address %s\n", address); 42573143b9aSmrg return NULL; 42673143b9aSmrg } 42773143b9aSmrg 42873143b9aSmrg /* Determine the transport type */ 42973143b9aSmrg 43073143b9aSmrg if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) 43173143b9aSmrg { 432fe567363Smrg prmsg (1,"Open: Unable to find transport for %s\n", 433fe567363Smrg protocol); 43473143b9aSmrg 435fe567363Smrg free (protocol); 436fe567363Smrg free (host); 437fe567363Smrg free (port); 43873143b9aSmrg return NULL; 43973143b9aSmrg } 44073143b9aSmrg 44173143b9aSmrg /* Open the transport */ 44273143b9aSmrg 44373143b9aSmrg switch (type) 44473143b9aSmrg { 44573143b9aSmrg case XTRANS_OPEN_COTS_CLIENT: 44673143b9aSmrg#ifdef TRANS_CLIENT 44773143b9aSmrg ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); 44873143b9aSmrg#endif /* TRANS_CLIENT */ 44973143b9aSmrg break; 45073143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 45173143b9aSmrg#ifdef TRANS_SERVER 45273143b9aSmrg ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); 45373143b9aSmrg#endif /* TRANS_SERVER */ 45473143b9aSmrg break; 45573143b9aSmrg default: 456fe567363Smrg prmsg (1,"Open: Unknown Open type %d\n", type); 45773143b9aSmrg } 45873143b9aSmrg 45973143b9aSmrg if (ciptr == NULL) 46073143b9aSmrg { 461fe567363Smrg if (!(thistrans->flags & TRANS_DISABLED)) 46273143b9aSmrg { 463fe567363Smrg prmsg (1,"Open: transport open failed for %s/%s:%s\n", 46473143b9aSmrg protocol, host, port); 46573143b9aSmrg } 466fe567363Smrg free (protocol); 467fe567363Smrg free (host); 468fe567363Smrg free (port); 46973143b9aSmrg return NULL; 47073143b9aSmrg } 47173143b9aSmrg 47273143b9aSmrg ciptr->transptr = thistrans; 47373143b9aSmrg ciptr->port = port; /* We need this for TRANS(Reopen) */ 47473143b9aSmrg 475fe567363Smrg free (protocol); 476fe567363Smrg free (host); 47773143b9aSmrg 47873143b9aSmrg return ciptr; 47973143b9aSmrg} 48073143b9aSmrg 48173143b9aSmrg 48273143b9aSmrg#ifdef TRANS_REOPEN 48373143b9aSmrg 48473143b9aSmrg/* 48573143b9aSmrg * We might want to create an XtransConnInfo object based on a previously 48673143b9aSmrg * opened connection. For example, the font server may clone itself and 48773143b9aSmrg * pass file descriptors to the parent. 48873143b9aSmrg */ 48973143b9aSmrg 49073143b9aSmrgstatic XtransConnInfo 4916a3641a6SsnjTRANS(Reopen) (int type, int trans_id, int fd, const char *port) 49273143b9aSmrg 49373143b9aSmrg{ 49473143b9aSmrg XtransConnInfo ciptr = NULL; 49573143b9aSmrg Xtransport *thistrans = NULL; 49673143b9aSmrg char *save_port; 49773143b9aSmrg int i; 49873143b9aSmrg 499fe567363Smrg prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); 50073143b9aSmrg 50173143b9aSmrg /* Determine the transport type */ 50273143b9aSmrg 50373143b9aSmrg for (i = 0; i < NUMTRANS; i++) 50473143b9aSmrg if (Xtransports[i].transport_id == trans_id) 50573143b9aSmrg { 50673143b9aSmrg thistrans = Xtransports[i].transport; 50773143b9aSmrg break; 50873143b9aSmrg } 50973143b9aSmrg 51073143b9aSmrg if (thistrans == NULL) 51173143b9aSmrg { 512fe567363Smrg prmsg (1,"Reopen: Unable to find transport id %d\n", 513fe567363Smrg trans_id); 51473143b9aSmrg 51573143b9aSmrg return NULL; 51673143b9aSmrg } 51773143b9aSmrg 518fe567363Smrg if ((save_port = strdup (port)) == NULL) 51973143b9aSmrg { 520fe567363Smrg prmsg (1,"Reopen: Unable to malloc port string\n"); 52173143b9aSmrg 52273143b9aSmrg return NULL; 52373143b9aSmrg } 52473143b9aSmrg 52573143b9aSmrg /* Get a new XtransConnInfo object */ 52673143b9aSmrg 52773143b9aSmrg switch (type) 52873143b9aSmrg { 52973143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 53073143b9aSmrg ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); 53173143b9aSmrg break; 53273143b9aSmrg default: 533fe567363Smrg prmsg (1,"Reopen: Bad Open type %d\n", type); 53473143b9aSmrg } 53573143b9aSmrg 53673143b9aSmrg if (ciptr == NULL) 53773143b9aSmrg { 538fe567363Smrg prmsg (1,"Reopen: transport open failed\n"); 539fe567363Smrg free (save_port); 54073143b9aSmrg return NULL; 54173143b9aSmrg } 54273143b9aSmrg 54373143b9aSmrg ciptr->transptr = thistrans; 54473143b9aSmrg ciptr->port = save_port; 54573143b9aSmrg 54673143b9aSmrg return ciptr; 54773143b9aSmrg} 54873143b9aSmrg 54973143b9aSmrg#endif /* TRANS_REOPEN */ 55073143b9aSmrg 55173143b9aSmrg 55273143b9aSmrg 55373143b9aSmrg/* 55473143b9aSmrg * These are the public interfaces to this Transport interface. 55573143b9aSmrg * These are the only functions that should have knowledge of the transport 55673143b9aSmrg * table. 55773143b9aSmrg */ 55873143b9aSmrg 55973143b9aSmrg#ifdef TRANS_CLIENT 56073143b9aSmrg 56173143b9aSmrgXtransConnInfo 5626a3641a6SsnjTRANS(OpenCOTSClient) (const char *address) 56373143b9aSmrg 56473143b9aSmrg{ 565fe567363Smrg prmsg (2,"OpenCOTSClient(%s)\n", address); 56673143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); 56773143b9aSmrg} 56873143b9aSmrg 56973143b9aSmrg#endif /* TRANS_CLIENT */ 57073143b9aSmrg 57173143b9aSmrg 57273143b9aSmrg#ifdef TRANS_SERVER 57373143b9aSmrg 57473143b9aSmrgXtransConnInfo 5756a3641a6SsnjTRANS(OpenCOTSServer) (const char *address) 57673143b9aSmrg 57773143b9aSmrg{ 578fe567363Smrg prmsg (2,"OpenCOTSServer(%s)\n", address); 57973143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); 58073143b9aSmrg} 58173143b9aSmrg 58273143b9aSmrg#endif /* TRANS_SERVER */ 58373143b9aSmrg 58473143b9aSmrg 58573143b9aSmrg#ifdef TRANS_REOPEN 58673143b9aSmrg 58773143b9aSmrgXtransConnInfo 5886a3641a6SsnjTRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port) 58973143b9aSmrg 59073143b9aSmrg{ 591fe567363Smrg prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); 59273143b9aSmrg return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); 59373143b9aSmrg} 59473143b9aSmrg 59573143b9aSmrgint 596fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr, 59773143b9aSmrg int *trans_id, int *fd, char **port) 59873143b9aSmrg 59973143b9aSmrg{ 60073143b9aSmrg int i; 60173143b9aSmrg 60273143b9aSmrg for (i = 0; i < NUMTRANS; i++) 60373143b9aSmrg if (Xtransports[i].transport == ciptr->transptr) 60473143b9aSmrg { 60573143b9aSmrg *trans_id = Xtransports[i].transport_id; 60673143b9aSmrg *fd = ciptr->fd; 60773143b9aSmrg 608fe567363Smrg if ((*port = strdup (ciptr->port)) == NULL) 60973143b9aSmrg return 0; 61073143b9aSmrg else 61173143b9aSmrg return 1; 61273143b9aSmrg } 61373143b9aSmrg 61473143b9aSmrg return 0; 61573143b9aSmrg} 61673143b9aSmrg 61773143b9aSmrg#endif /* TRANS_REOPEN */ 61873143b9aSmrg 61973143b9aSmrg 62073143b9aSmrgint 62173143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) 62273143b9aSmrg 62373143b9aSmrg{ 62473143b9aSmrg int fd = ciptr->fd; 62573143b9aSmrg int ret = 0; 62673143b9aSmrg 627fe567363Smrg prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg); 62873143b9aSmrg 62973143b9aSmrg /* 63073143b9aSmrg * For now, all transport type use the same stuff for setting options. 63173143b9aSmrg * As long as this is true, we can put the common code here. Once a more 63273143b9aSmrg * complicated transport such as shared memory or an OSI implementation 63373143b9aSmrg * that uses the session and application libraries is implemented, this 63473143b9aSmrg * code may have to move to a transport dependent function. 63573143b9aSmrg * 63673143b9aSmrg * ret = ciptr->transptr->SetOption (ciptr, option, arg); 63773143b9aSmrg */ 63873143b9aSmrg 63973143b9aSmrg switch (option) 64073143b9aSmrg { 64173143b9aSmrg case TRANS_NONBLOCKING: 64273143b9aSmrg switch (arg) 64373143b9aSmrg { 64473143b9aSmrg case 0: 64573143b9aSmrg /* Set to blocking mode */ 64673143b9aSmrg break; 64773143b9aSmrg case 1: /* Set to non-blocking mode */ 64873143b9aSmrg 649fe567363Smrg#if defined(O_NONBLOCK) && !defined(SCO325) 65073143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 65173143b9aSmrg if (ret != -1) 65273143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); 65373143b9aSmrg#else 65473143b9aSmrg#ifdef FIOSNBIO 65573143b9aSmrg { 65673143b9aSmrg int arg; 65773143b9aSmrg arg = 1; 65873143b9aSmrg ret = ioctl (fd, FIOSNBIO, &arg); 65973143b9aSmrg } 66073143b9aSmrg#else 661fe567363Smrg#if defined(WIN32) 66273143b9aSmrg { 66373143b9aSmrg#ifdef WIN32 66473143b9aSmrg u_long arg; 66573143b9aSmrg#else 66673143b9aSmrg int arg; 66773143b9aSmrg#endif 66873143b9aSmrg arg = 1; 66973143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail 67073143b9aSmrg * eventually with EWOULDBLOCK */ 67173143b9aSmrg ret = ioctl (fd, FIONBIO, &arg); 67273143b9aSmrg } 67373143b9aSmrg#else 67473143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 67573143b9aSmrg#ifdef FNDELAY 67673143b9aSmrg ret = fcntl (fd, F_SETFL, ret | FNDELAY); 67773143b9aSmrg#else 67873143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NDELAY); 67973143b9aSmrg#endif 68073143b9aSmrg#endif /* AIXV3 || uniosu */ 68173143b9aSmrg#endif /* FIOSNBIO */ 68273143b9aSmrg#endif /* O_NONBLOCK */ 68373143b9aSmrg break; 68473143b9aSmrg default: 68573143b9aSmrg /* Unknown option */ 68673143b9aSmrg break; 68773143b9aSmrg } 68873143b9aSmrg break; 68973143b9aSmrg case TRANS_CLOSEONEXEC: 69073143b9aSmrg#ifdef F_SETFD 69173143b9aSmrg#ifdef FD_CLOEXEC 69273143b9aSmrg ret = fcntl (fd, F_SETFD, FD_CLOEXEC); 69373143b9aSmrg#else 69473143b9aSmrg ret = fcntl (fd, F_SETFD, 1); 69573143b9aSmrg#endif /* FD_CLOEXEC */ 69673143b9aSmrg#endif /* F_SETFD */ 69773143b9aSmrg break; 69873143b9aSmrg } 699fe567363Smrg 70073143b9aSmrg return ret; 70173143b9aSmrg} 70273143b9aSmrg 70373143b9aSmrg#ifdef TRANS_SERVER 70473143b9aSmrg 70573143b9aSmrgint 7066a3641a6SsnjTRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags) 70773143b9aSmrg 70873143b9aSmrg{ 70973143b9aSmrg return ciptr->transptr->CreateListener (ciptr, port, flags); 71073143b9aSmrg} 71173143b9aSmrg 71275ebec6dSmrgint 71375ebec6dSmrgTRANS(Received) (const char * protocol) 71475ebec6dSmrg 71575ebec6dSmrg{ 71675ebec6dSmrg Xtransport *trans; 71775ebec6dSmrg int i = 0, ret = 0; 71875ebec6dSmrg 71975ebec6dSmrg prmsg (5, "Received(%s)\n", protocol); 72075ebec6dSmrg 72175ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 72275ebec6dSmrg { 72375ebec6dSmrg prmsg (1,"Received: unable to find transport: %s\n", 72475ebec6dSmrg protocol); 72575ebec6dSmrg 72675ebec6dSmrg return -1; 72775ebec6dSmrg } 72875ebec6dSmrg if (trans->flags & TRANS_ALIAS) { 72975ebec6dSmrg if (trans->nolisten) 73075ebec6dSmrg while (trans->nolisten[i]) { 73175ebec6dSmrg ret |= TRANS(Received)(trans->nolisten[i]); 73275ebec6dSmrg i++; 73375ebec6dSmrg } 73475ebec6dSmrg } 73575ebec6dSmrg 73675ebec6dSmrg trans->flags |= TRANS_RECEIVED; 73775ebec6dSmrg return ret; 73875ebec6dSmrg} 73975ebec6dSmrg 74073143b9aSmrgint 741fe567363SmrgTRANS(NoListen) (const char * protocol) 742fe567363Smrg 74373143b9aSmrg{ 74473143b9aSmrg Xtransport *trans; 74573143b9aSmrg int i = 0, ret = 0; 746fe567363Smrg 747fe567363Smrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 74873143b9aSmrg { 749fe567363Smrg prmsg (1,"TransNoListen: unable to find transport: %s\n", 750fe567363Smrg protocol); 75173143b9aSmrg 75273143b9aSmrg return -1; 75373143b9aSmrg } 75473143b9aSmrg if (trans->flags & TRANS_ALIAS) { 75573143b9aSmrg if (trans->nolisten) 75673143b9aSmrg while (trans->nolisten[i]) { 75773143b9aSmrg ret |= TRANS(NoListen)(trans->nolisten[i]); 75873143b9aSmrg i++; 75973143b9aSmrg } 76073143b9aSmrg } 76173143b9aSmrg 76273143b9aSmrg trans->flags |= TRANS_NOLISTEN; 76373143b9aSmrg return ret; 76473143b9aSmrg} 76573143b9aSmrg 7666a3641a6Ssnjint 7676a3641a6SsnjTRANS(Listen) (const char * protocol) 7686a3641a6Ssnj{ 7696a3641a6Ssnj Xtransport *trans; 7706a3641a6Ssnj int i = 0, ret = 0; 7716a3641a6Ssnj 7726a3641a6Ssnj if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 7736a3641a6Ssnj { 7746a3641a6Ssnj prmsg (1,"TransListen: unable to find transport: %s\n", 7756a3641a6Ssnj protocol); 7766a3641a6Ssnj 7776a3641a6Ssnj return -1; 7786a3641a6Ssnj } 7796a3641a6Ssnj if (trans->flags & TRANS_ALIAS) { 7806a3641a6Ssnj if (trans->nolisten) 7816a3641a6Ssnj while (trans->nolisten[i]) { 7826a3641a6Ssnj ret |= TRANS(Listen)(trans->nolisten[i]); 7836a3641a6Ssnj i++; 7846a3641a6Ssnj } 7856a3641a6Ssnj } 7866a3641a6Ssnj 7876a3641a6Ssnj trans->flags &= ~TRANS_NOLISTEN; 7886a3641a6Ssnj return ret; 7896a3641a6Ssnj} 7906a3641a6Ssnj 79175ebec6dSmrgint 79275ebec6dSmrgTRANS(IsListening) (const char * protocol) 79375ebec6dSmrg{ 79475ebec6dSmrg Xtransport *trans; 79575ebec6dSmrg 79675ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 79775ebec6dSmrg { 79875ebec6dSmrg prmsg (1,"TransIsListening: unable to find transport: %s\n", 79975ebec6dSmrg protocol); 80075ebec6dSmrg 80175ebec6dSmrg return 0; 80275ebec6dSmrg } 80375ebec6dSmrg 80475ebec6dSmrg return !(trans->flags & TRANS_NOLISTEN); 80575ebec6dSmrg} 80675ebec6dSmrg 80773143b9aSmrgint 80873143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr) 80973143b9aSmrg 81073143b9aSmrg{ 81173143b9aSmrg if (ciptr->transptr->ResetListener) 81273143b9aSmrg return ciptr->transptr->ResetListener (ciptr); 81373143b9aSmrg else 81473143b9aSmrg return TRANS_RESET_NOOP; 81573143b9aSmrg} 81673143b9aSmrg 81773143b9aSmrg 81873143b9aSmrgXtransConnInfo 81973143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status) 82073143b9aSmrg 82173143b9aSmrg{ 82273143b9aSmrg XtransConnInfo newciptr; 82373143b9aSmrg 824fe567363Smrg prmsg (2,"Accept(%d)\n", ciptr->fd); 82573143b9aSmrg 82673143b9aSmrg newciptr = ciptr->transptr->Accept (ciptr, status); 82773143b9aSmrg 82873143b9aSmrg if (newciptr) 82973143b9aSmrg newciptr->transptr = ciptr->transptr; 83073143b9aSmrg 83173143b9aSmrg return newciptr; 83273143b9aSmrg} 83373143b9aSmrg 83473143b9aSmrg#endif /* TRANS_SERVER */ 83573143b9aSmrg 83673143b9aSmrg 83773143b9aSmrg#ifdef TRANS_CLIENT 83873143b9aSmrg 83973143b9aSmrgint 8406a3641a6SsnjTRANS(Connect) (XtransConnInfo ciptr, const char *address) 84173143b9aSmrg 84273143b9aSmrg{ 84373143b9aSmrg char *protocol; 84473143b9aSmrg char *host; 84573143b9aSmrg char *port; 84673143b9aSmrg int ret; 84773143b9aSmrg 848fe567363Smrg prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address); 84973143b9aSmrg 85073143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 85173143b9aSmrg { 852fe567363Smrg prmsg (1,"Connect: Unable to Parse address %s\n", 853fe567363Smrg address); 85473143b9aSmrg return -1; 85573143b9aSmrg } 85673143b9aSmrg 85773143b9aSmrg#ifdef HAVE_LAUNCHD 8588d4c0f7bSmrg if (!host) host=strdup(""); 85973143b9aSmrg#endif 86073143b9aSmrg 86173143b9aSmrg if (!port || !*port) 86273143b9aSmrg { 863fe567363Smrg prmsg (1,"Connect: Missing port specification in %s\n", 864fe567363Smrg address); 865fe567363Smrg if (protocol) free (protocol); 866fe567363Smrg if (host) free (host); 86773143b9aSmrg return -1; 86873143b9aSmrg } 86973143b9aSmrg 87073143b9aSmrg ret = ciptr->transptr->Connect (ciptr, host, port); 87173143b9aSmrg 872fe567363Smrg if (protocol) free (protocol); 873fe567363Smrg if (host) free (host); 874fe567363Smrg if (port) free (port); 875fe567363Smrg 87673143b9aSmrg return ret; 87773143b9aSmrg} 87873143b9aSmrg 87973143b9aSmrg#endif /* TRANS_CLIENT */ 88073143b9aSmrg 88173143b9aSmrg 88273143b9aSmrgint 88373143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 88473143b9aSmrg 88573143b9aSmrg{ 88673143b9aSmrg return ciptr->transptr->BytesReadable (ciptr, pend); 88773143b9aSmrg} 88873143b9aSmrg 88973143b9aSmrgint 89073143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size) 89173143b9aSmrg 89273143b9aSmrg{ 89373143b9aSmrg return ciptr->transptr->Read (ciptr, buf, size); 89473143b9aSmrg} 89573143b9aSmrg 89673143b9aSmrgint 89773143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size) 89873143b9aSmrg 89973143b9aSmrg{ 90073143b9aSmrg return ciptr->transptr->Write (ciptr, buf, size); 90173143b9aSmrg} 90273143b9aSmrg 90373143b9aSmrgint 90473143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) 90573143b9aSmrg 90673143b9aSmrg{ 90773143b9aSmrg return ciptr->transptr->Readv (ciptr, buf, size); 90873143b9aSmrg} 90973143b9aSmrg 91073143b9aSmrgint 91173143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) 91273143b9aSmrg 91373143b9aSmrg{ 91473143b9aSmrg return ciptr->transptr->Writev (ciptr, buf, size); 91573143b9aSmrg} 91673143b9aSmrg 91775ebec6dSmrg#if XTRANS_SEND_FDS 91875ebec6dSmrgint 91975ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) 92075ebec6dSmrg{ 92175ebec6dSmrg return ciptr->transptr->SendFd(ciptr, fd, do_close); 92275ebec6dSmrg} 92375ebec6dSmrg 92475ebec6dSmrgint 92575ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr) 92675ebec6dSmrg{ 92775ebec6dSmrg return ciptr->transptr->RecvFd(ciptr); 92875ebec6dSmrg} 92975ebec6dSmrg#endif 93075ebec6dSmrg 93173143b9aSmrgint 93273143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr) 93373143b9aSmrg 93473143b9aSmrg{ 93573143b9aSmrg return ciptr->transptr->Disconnect (ciptr); 93673143b9aSmrg} 93773143b9aSmrg 93873143b9aSmrgint 93973143b9aSmrgTRANS(Close) (XtransConnInfo ciptr) 94073143b9aSmrg 94173143b9aSmrg{ 94273143b9aSmrg int ret; 94373143b9aSmrg 944fe567363Smrg prmsg (2,"Close(%d)\n", ciptr->fd); 94573143b9aSmrg 94673143b9aSmrg ret = ciptr->transptr->Close (ciptr); 94773143b9aSmrg 94873143b9aSmrg TRANS(FreeConnInfo) (ciptr); 94973143b9aSmrg 95073143b9aSmrg return ret; 95173143b9aSmrg} 95273143b9aSmrg 95373143b9aSmrgint 95473143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr) 95573143b9aSmrg 95673143b9aSmrg{ 95773143b9aSmrg int ret; 95873143b9aSmrg 959fe567363Smrg prmsg (2,"CloseForCloning(%d)\n", ciptr->fd); 96073143b9aSmrg 96173143b9aSmrg ret = ciptr->transptr->CloseForCloning (ciptr); 96273143b9aSmrg 96373143b9aSmrg TRANS(FreeConnInfo) (ciptr); 96473143b9aSmrg 96573143b9aSmrg return ret; 96673143b9aSmrg} 96773143b9aSmrg 96873143b9aSmrgint 96973143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr) 97073143b9aSmrg 97173143b9aSmrg{ 97273143b9aSmrg return (ciptr->family == AF_UNIX); 97373143b9aSmrg} 97473143b9aSmrg 97573143b9aSmrgint 976fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 97773143b9aSmrg Xtransaddr **addrp) 97873143b9aSmrg 97973143b9aSmrg{ 980fe567363Smrg prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd); 98173143b9aSmrg 98273143b9aSmrg *familyp = ciptr->family; 98373143b9aSmrg *addrlenp = ciptr->peeraddrlen; 98473143b9aSmrg 985fe567363Smrg if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL) 98673143b9aSmrg { 987fe567363Smrg prmsg (1,"GetPeerAddr: malloc failed\n"); 98873143b9aSmrg return -1; 98973143b9aSmrg } 99073143b9aSmrg memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); 99173143b9aSmrg 99273143b9aSmrg return 0; 99373143b9aSmrg} 99473143b9aSmrg 99573143b9aSmrg 99673143b9aSmrgint 99773143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr) 99873143b9aSmrg 99973143b9aSmrg{ 100073143b9aSmrg return ciptr->fd; 100173143b9aSmrg} 100273143b9aSmrg 100373143b9aSmrg 100473143b9aSmrg/* 100573143b9aSmrg * These functions are really utility functions, but they require knowledge 100673143b9aSmrg * of the internal data structures, so they have to be part of the Transport 100773143b9aSmrg * Independant API. 100873143b9aSmrg */ 100973143b9aSmrg 101073143b9aSmrg#ifdef TRANS_SERVER 101173143b9aSmrg 101273143b9aSmrgstatic int 101373143b9aSmrgcomplete_network_count (void) 101473143b9aSmrg 101573143b9aSmrg{ 101673143b9aSmrg int count = 0; 101773143b9aSmrg int found_local = 0; 101873143b9aSmrg int i; 101973143b9aSmrg 102073143b9aSmrg /* 102173143b9aSmrg * For a complete network, we only need one LOCALCONN transport to work 102273143b9aSmrg */ 102373143b9aSmrg 102473143b9aSmrg for (i = 0; i < NUMTRANS; i++) 102573143b9aSmrg { 102673143b9aSmrg if (Xtransports[i].transport->flags & TRANS_ALIAS 102773143b9aSmrg || Xtransports[i].transport->flags & TRANS_NOLISTEN) 102873143b9aSmrg continue; 102973143b9aSmrg 103073143b9aSmrg if (Xtransports[i].transport->flags & TRANS_LOCAL) 103173143b9aSmrg found_local = 1; 103273143b9aSmrg else 103373143b9aSmrg count++; 103473143b9aSmrg } 103573143b9aSmrg 103673143b9aSmrg return (count + found_local); 103773143b9aSmrg} 103873143b9aSmrg 103973143b9aSmrg 104075ebec6dSmrgstatic int 10416a3641a6Ssnjreceive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs, 10426a3641a6Ssnj int* count_ret) 104375ebec6dSmrg 104475ebec6dSmrg{ 104575ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON 104675ebec6dSmrg XtransConnInfo ciptr; 104775ebec6dSmrg int i, systemd_listen_fds; 104875ebec6dSmrg 104975ebec6dSmrg systemd_listen_fds = sd_listen_fds(1); 105075ebec6dSmrg if (systemd_listen_fds < 0) 105175ebec6dSmrg { 105275ebec6dSmrg prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n", 105375ebec6dSmrg strerror(-systemd_listen_fds)); 105475ebec6dSmrg return -1; 105575ebec6dSmrg } 105675ebec6dSmrg 105775ebec6dSmrg for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++) 105875ebec6dSmrg { 105975ebec6dSmrg struct sockaddr_storage a; 106075ebec6dSmrg int ti; 106175ebec6dSmrg const char* tn; 106275ebec6dSmrg socklen_t al; 106375ebec6dSmrg 106475ebec6dSmrg al = sizeof(a); 106575ebec6dSmrg if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) { 106675ebec6dSmrg prmsg (1, "receive_listening_fds: getsockname error: %s\n", 106775ebec6dSmrg strerror(errno)); 106875ebec6dSmrg return -1; 106975ebec6dSmrg } 107075ebec6dSmrg 107175ebec6dSmrg switch (a.ss_family) 107275ebec6dSmrg { 107375ebec6dSmrg case AF_UNIX: 107475ebec6dSmrg ti = TRANS_SOCKET_UNIX_INDEX; 107575ebec6dSmrg if (*((struct sockaddr_un*)&a)->sun_path == '\0' && 107675ebec6dSmrg al > sizeof(sa_family_t)) 107775ebec6dSmrg tn = "local"; 107875ebec6dSmrg else 107975ebec6dSmrg tn = "unix"; 108075ebec6dSmrg break; 108175ebec6dSmrg case AF_INET: 108275ebec6dSmrg ti = TRANS_SOCKET_INET_INDEX; 108375ebec6dSmrg tn = "inet"; 108475ebec6dSmrg break; 108575ebec6dSmrg#if defined(IPv6) && defined(AF_INET6) 108675ebec6dSmrg case AF_INET6: 108775ebec6dSmrg ti = TRANS_SOCKET_INET6_INDEX; 108875ebec6dSmrg tn = "inet6"; 108975ebec6dSmrg break; 109075ebec6dSmrg#endif /* IPv6 */ 109175ebec6dSmrg default: 109275ebec6dSmrg prmsg (1, "receive_listening_fds:" 109375ebec6dSmrg "Got unknown socket address family\n"); 109475ebec6dSmrg return -1; 109575ebec6dSmrg } 109675ebec6dSmrg 109775ebec6dSmrg ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port); 109875ebec6dSmrg if (!ciptr) 109975ebec6dSmrg { 110075ebec6dSmrg prmsg (1, "receive_listening_fds:" 110175ebec6dSmrg "Got NULL while trying to reopen socket received from systemd.\n"); 110275ebec6dSmrg return -1; 110375ebec6dSmrg } 110475ebec6dSmrg 110575ebec6dSmrg prmsg (5, "receive_listening_fds: received listener for %s, %d\n", 110675ebec6dSmrg tn, ciptr->fd); 110775ebec6dSmrg temp_ciptrs[(*count_ret)++] = ciptr; 110875ebec6dSmrg TRANS(Received)(tn); 110975ebec6dSmrg } 111075ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */ 111175ebec6dSmrg return 0; 111275ebec6dSmrg} 111375ebec6dSmrg 11148d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11158d4c0f7bSmrgextern int xquartz_launchd_fd; 11168d4c0f7bSmrg#endif 111773143b9aSmrg 111873143b9aSmrgint 11196a3641a6SsnjTRANS(MakeAllCOTSServerListeners) (const char *port, int *partial, 11206a3641a6Ssnj int *count_ret, XtransConnInfo **ciptrs_ret) 112173143b9aSmrg 112273143b9aSmrg{ 112373143b9aSmrg char buffer[256]; /* ??? What size ?? */ 112473143b9aSmrg XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; 112573143b9aSmrg int status, i, j; 112673143b9aSmrg 112773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 112873143b9aSmrg int ipv6_succ = 0; 112973143b9aSmrg#endif 1130fe567363Smrg prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n", 1131fe567363Smrg port ? port : "NULL", ciptrs_ret); 113273143b9aSmrg 113373143b9aSmrg *count_ret = 0; 113473143b9aSmrg 11358d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11368d4c0f7bSmrg fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd); 11378d4c0f7bSmrg if(xquartz_launchd_fd != -1) { 11388d4c0f7bSmrg if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, 11398d4c0f7bSmrg xquartz_launchd_fd, getenv("DISPLAY"))))==NULL) 11408d4c0f7bSmrg fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); 1141fe567363Smrg else 11428d4c0f7bSmrg temp_ciptrs[(*count_ret)++] = ciptr; 11438d4c0f7bSmrg } 114473143b9aSmrg#endif 114573143b9aSmrg 114675ebec6dSmrg if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0) 114775ebec6dSmrg return -1; 114875ebec6dSmrg 114973143b9aSmrg for (i = 0; i < NUMTRANS; i++) 115073143b9aSmrg { 115173143b9aSmrg Xtransport *trans = Xtransports[i].transport; 115273143b9aSmrg unsigned int flags = 0; 115373143b9aSmrg 115475ebec6dSmrg if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN || 115575ebec6dSmrg trans->flags&TRANS_RECEIVED) 115673143b9aSmrg continue; 115773143b9aSmrg 115873143b9aSmrg snprintf(buffer, sizeof(buffer), "%s/:%s", 115973143b9aSmrg trans->TransName, port ? port : ""); 116073143b9aSmrg 1161fe567363Smrg prmsg (5,"MakeAllCOTSServerListeners: opening %s\n", 1162fe567363Smrg buffer); 116373143b9aSmrg 116473143b9aSmrg if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) 116573143b9aSmrg { 116673143b9aSmrg if (trans->flags & TRANS_DISABLED) 116773143b9aSmrg continue; 116873143b9aSmrg 1169fe567363Smrg prmsg (1, 117073143b9aSmrg "MakeAllCOTSServerListeners: failed to open listener for %s\n", 1171fe567363Smrg trans->TransName); 117273143b9aSmrg continue; 117373143b9aSmrg } 117473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 117573143b9aSmrg if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX 117673143b9aSmrg && ipv6_succ)) 117773143b9aSmrg flags |= ADDR_IN_USE_ALLOWED; 117873143b9aSmrg#endif 117973143b9aSmrg 118073143b9aSmrg if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) 118173143b9aSmrg { 118273143b9aSmrg if (status == TRANS_ADDR_IN_USE) 118373143b9aSmrg { 118473143b9aSmrg /* 118573143b9aSmrg * We failed to bind to the specified address because the 118673143b9aSmrg * address is in use. It must be that a server is already 118773143b9aSmrg * running at this address, and this function should fail. 118873143b9aSmrg */ 118973143b9aSmrg 1190fe567363Smrg prmsg (1, 1191fe567363Smrg "MakeAllCOTSServerListeners: server already running\n"); 119273143b9aSmrg 119373143b9aSmrg for (j = 0; j < *count_ret; j++) 119473143b9aSmrg TRANS(Close) (temp_ciptrs[j]); 119573143b9aSmrg 119673143b9aSmrg *count_ret = 0; 119773143b9aSmrg *ciptrs_ret = NULL; 119873143b9aSmrg *partial = 0; 119973143b9aSmrg return -1; 120073143b9aSmrg } 120173143b9aSmrg else 120273143b9aSmrg { 1203fe567363Smrg prmsg (1, 120473143b9aSmrg "MakeAllCOTSServerListeners: failed to create listener for %s\n", 1205fe567363Smrg trans->TransName); 120673143b9aSmrg 120773143b9aSmrg continue; 120873143b9aSmrg } 120973143b9aSmrg } 121073143b9aSmrg 121173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 121273143b9aSmrg if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) 121373143b9aSmrg ipv6_succ = 1; 121473143b9aSmrg#endif 1215fe567363Smrg 1216fe567363Smrg prmsg (5, 121773143b9aSmrg "MakeAllCOTSServerListeners: opened listener for %s, %d\n", 1218fe567363Smrg trans->TransName, ciptr->fd); 121973143b9aSmrg 122073143b9aSmrg temp_ciptrs[*count_ret] = ciptr; 122173143b9aSmrg (*count_ret)++; 122273143b9aSmrg } 122373143b9aSmrg 122473143b9aSmrg *partial = (*count_ret < complete_network_count()); 122573143b9aSmrg 1226fe567363Smrg prmsg (5, 122773143b9aSmrg "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", 122873143b9aSmrg *partial, *count_ret, complete_network_count()); 122973143b9aSmrg 123073143b9aSmrg if (*count_ret > 0) 123173143b9aSmrg { 1232fe567363Smrg if ((*ciptrs_ret = malloc ( 123373143b9aSmrg *count_ret * sizeof (XtransConnInfo))) == NULL) 123473143b9aSmrg { 123573143b9aSmrg return -1; 123673143b9aSmrg } 123773143b9aSmrg 123873143b9aSmrg for (i = 0; i < *count_ret; i++) 123973143b9aSmrg { 124073143b9aSmrg (*ciptrs_ret)[i] = temp_ciptrs[i]; 124173143b9aSmrg } 124273143b9aSmrg } 124373143b9aSmrg else 124473143b9aSmrg *ciptrs_ret = NULL; 1245fe567363Smrg 124673143b9aSmrg return 0; 124773143b9aSmrg} 124873143b9aSmrg 124973143b9aSmrg#endif /* TRANS_SERVER */ 125073143b9aSmrg 125173143b9aSmrg 125273143b9aSmrg 125373143b9aSmrg/* 125473143b9aSmrg * These routines are not part of the X Transport Interface, but they 125573143b9aSmrg * may be used by it. 125673143b9aSmrg */ 125773143b9aSmrg 125873143b9aSmrg 12593d2ed3e3Smrg#ifdef WIN32 126073143b9aSmrg 126173143b9aSmrg/* 126273143b9aSmrg * emulate readv 126373143b9aSmrg */ 126473143b9aSmrg 126573143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 126673143b9aSmrg 126773143b9aSmrg{ 126873143b9aSmrg int i, len, total; 126973143b9aSmrg char *base; 127073143b9aSmrg 127173143b9aSmrg ESET(0); 127273143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 127373143b9aSmrg len = iov->iov_len; 127473143b9aSmrg base = iov->iov_base; 127573143b9aSmrg while (len > 0) { 127673143b9aSmrg register int nbytes; 127773143b9aSmrg nbytes = TRANS(Read) (ciptr, base, len); 127873143b9aSmrg if (nbytes < 0 && total == 0) return -1; 127973143b9aSmrg if (nbytes <= 0) return total; 128073143b9aSmrg ESET(0); 128173143b9aSmrg len -= nbytes; 128273143b9aSmrg total += nbytes; 128373143b9aSmrg base += nbytes; 128473143b9aSmrg } 128573143b9aSmrg } 128673143b9aSmrg return total; 128773143b9aSmrg} 128873143b9aSmrg 128973143b9aSmrg 129073143b9aSmrg/* 129173143b9aSmrg * emulate writev 129273143b9aSmrg */ 129373143b9aSmrg 129473143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 129573143b9aSmrg 129673143b9aSmrg{ 129773143b9aSmrg int i, len, total; 129873143b9aSmrg char *base; 129973143b9aSmrg 130073143b9aSmrg ESET(0); 130173143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 130273143b9aSmrg len = iov->iov_len; 130373143b9aSmrg base = iov->iov_base; 130473143b9aSmrg while (len > 0) { 130573143b9aSmrg register int nbytes; 130673143b9aSmrg nbytes = TRANS(Write) (ciptr, base, len); 130773143b9aSmrg if (nbytes < 0 && total == 0) return -1; 130873143b9aSmrg if (nbytes <= 0) return total; 130973143b9aSmrg ESET(0); 131073143b9aSmrg len -= nbytes; 131173143b9aSmrg total += nbytes; 131273143b9aSmrg base += nbytes; 131373143b9aSmrg } 131473143b9aSmrg } 131573143b9aSmrg return total; 131673143b9aSmrg} 131773143b9aSmrg 13183d2ed3e3Smrg#endif /* WIN32 */ 131973143b9aSmrg 132073143b9aSmrg 1321e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__) 132273143b9aSmrg#ifndef NEED_UTSNAME 132373143b9aSmrg#define NEED_UTSNAME 132473143b9aSmrg#endif 132573143b9aSmrg#include <sys/utsname.h> 132673143b9aSmrg#endif 132773143b9aSmrg 132873143b9aSmrg/* 132973143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing. 133073143b9aSmrg */ 133173143b9aSmrg 133273143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen) 133373143b9aSmrg 133473143b9aSmrg{ 133573143b9aSmrg int len; 133673143b9aSmrg 133773143b9aSmrg#ifdef NEED_UTSNAME 133873143b9aSmrg struct utsname name; 133973143b9aSmrg 134073143b9aSmrg uname (&name); 134173143b9aSmrg len = strlen (name.nodename); 134273143b9aSmrg if (len >= maxlen) len = maxlen - 1; 134373143b9aSmrg strncpy (buf, name.nodename, len); 134473143b9aSmrg buf[len] = '\0'; 134573143b9aSmrg#else 134673143b9aSmrg buf[0] = '\0'; 134773143b9aSmrg (void) gethostname (buf, maxlen); 134873143b9aSmrg buf [maxlen - 1] = '\0'; 134973143b9aSmrg len = strlen(buf); 135073143b9aSmrg#endif /* NEED_UTSNAME */ 135173143b9aSmrg return len; 135273143b9aSmrg} 1353