Xtrans.c revision 94f982db
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. 65e45ace2bSmrg * For compatibility, 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 78e45ace2bSmrg/* 10 used to be PTS, but that's gone. */ 7973143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX 11 80af928962Smrg/* 12 used to be ISC, but that's gone. */ 81e45ace2bSmrg/* 13 used to be SCO, but that's gone. */ 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 }, 103e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 10473143b9aSmrg { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX }, 10573143b9aSmrg#endif 1063d2ed3e3Smrg#ifdef __sun 10773143b9aSmrg { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX }, 1083d2ed3e3Smrg#endif /* __sun */ 10973143b9aSmrg#endif /* LOCALCONN */ 11073143b9aSmrg}; 11173143b9aSmrg 11273143b9aSmrg#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) 11373143b9aSmrg 11473143b9aSmrg 11573143b9aSmrg#ifdef WIN32 11673143b9aSmrg#define ioctl ioctlsocket 11773143b9aSmrg#endif 11873143b9aSmrg 11973143b9aSmrg 12073143b9aSmrg 12173143b9aSmrg/* 12273143b9aSmrg * These are a few utility function used by the public interface functions. 12373143b9aSmrg */ 12473143b9aSmrg 12573143b9aSmrgvoid 12673143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr) 12773143b9aSmrg 12873143b9aSmrg{ 129fe567363Smrg prmsg (3,"FreeConnInfo(%p)\n", ciptr); 13073143b9aSmrg 13173143b9aSmrg if (ciptr->addr) 132fe567363Smrg free (ciptr->addr); 13373143b9aSmrg 13473143b9aSmrg if (ciptr->peeraddr) 135fe567363Smrg free (ciptr->peeraddr); 13673143b9aSmrg 13773143b9aSmrg if (ciptr->port) 138fe567363Smrg free (ciptr->port); 13973143b9aSmrg 140fe567363Smrg free (ciptr); 14173143b9aSmrg} 14273143b9aSmrg 14373143b9aSmrg 14473143b9aSmrg#define PROTOBUFSIZE 20 14573143b9aSmrg 14673143b9aSmrgstatic Xtransport * 147fe567363SmrgTRANS(SelectTransport) (const char *protocol) 14873143b9aSmrg 14973143b9aSmrg{ 1503d2ed3e3Smrg#ifndef HAVE_STRCASECMP 15173143b9aSmrg char protobuf[PROTOBUFSIZE]; 1523d2ed3e3Smrg#endif 15373143b9aSmrg 154fe567363Smrg prmsg (3,"SelectTransport(%s)\n", protocol); 15573143b9aSmrg 1563d2ed3e3Smrg#ifndef HAVE_STRCASECMP 15773143b9aSmrg /* 15873143b9aSmrg * Force Protocol to be lowercase as a way of doing 15973143b9aSmrg * a case insensitive match. 16073143b9aSmrg */ 16173143b9aSmrg 16273143b9aSmrg strncpy (protobuf, protocol, PROTOBUFSIZE - 1); 16373143b9aSmrg protobuf[PROTOBUFSIZE-1] = '\0'; 16473143b9aSmrg 16594f982dbSmrg for (unsigned int i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) 1668a0d9095Smrg if (isupper ((unsigned char)protobuf[i])) 1678a0d9095Smrg protobuf[i] = tolower ((unsigned char)protobuf[i]); 1683d2ed3e3Smrg#endif 16973143b9aSmrg 17073143b9aSmrg /* Look at all of the configured protocols */ 17173143b9aSmrg 17294f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 17373143b9aSmrg { 1743d2ed3e3Smrg#ifndef HAVE_STRCASECMP 17573143b9aSmrg if (!strcmp (protobuf, Xtransports[i].transport->TransName)) 1763d2ed3e3Smrg#else 1773d2ed3e3Smrg if (!strcasecmp (protocol, Xtransports[i].transport->TransName)) 1783d2ed3e3Smrg#endif 17973143b9aSmrg return Xtransports[i].transport; 18073143b9aSmrg } 18173143b9aSmrg 18273143b9aSmrg return NULL; 18373143b9aSmrg} 18473143b9aSmrg 185e45ace2bSmrgstatic int 1866a3641a6SsnjTRANS(ParseAddress) (const char *address, 1876a3641a6Ssnj char **protocol, char **host, char **port) 18873143b9aSmrg 18973143b9aSmrg{ 19073143b9aSmrg /* 19173143b9aSmrg * For the font library, the address is a string formatted 19273143b9aSmrg * as "protocol/host:port[/catalogue]". Note that the catologue 19373143b9aSmrg * is optional. At this time, the catologue info is ignored, but 19473143b9aSmrg * we have to parse it anyways. 19573143b9aSmrg * 19673143b9aSmrg * Other than fontlib, the address is a string formatted 19773143b9aSmrg * as "protocol/host:port". 19873143b9aSmrg * 19973143b9aSmrg * If the protocol part is missing, then assume TCP. 20073143b9aSmrg * If the protocol part and host part are missing, then assume local. 20173143b9aSmrg * If a "::" is found then assume DNET. 20273143b9aSmrg */ 20373143b9aSmrg 204e45ace2bSmrg char *mybuf, *tmpptr = NULL; 205e45ace2bSmrg const char *_protocol = NULL; 20694f982dbSmrg const char *_host, *_port; 20773143b9aSmrg char hostnamebuf[256]; 20894f982dbSmrg char *_host_buf; 20973143b9aSmrg int _host_len; 21073143b9aSmrg 211fe567363Smrg prmsg (3,"ParseAddress(%s)\n", address); 21273143b9aSmrg 213e45ace2bSmrg /* First, check for AF_UNIX socket paths */ 214e45ace2bSmrg if (address[0] == '/') { 215e45ace2bSmrg _protocol = "local"; 216e45ace2bSmrg _host = ""; 217e45ace2bSmrg _port = address; 218e45ace2bSmrg } else 219e45ace2bSmrg#ifdef HAVE_LAUNCHD 220e45ace2bSmrg /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ 221e45ace2bSmrg if(!strncmp(address,"local//",7)) { 222e45ace2bSmrg _protocol="local"; 223e45ace2bSmrg _host=""; 224e45ace2bSmrg _port=address+6; 225e45ace2bSmrg } else 226e45ace2bSmrg#endif 227e45ace2bSmrg if (!strncmp(address, "unix:", 5)) { 228e45ace2bSmrg _protocol = "local"; 229e45ace2bSmrg _host = ""; 230e45ace2bSmrg _port = address + 5; 231e45ace2bSmrg } 232e45ace2bSmrg if (_protocol) 233e45ace2bSmrg goto done_parsing; 234e45ace2bSmrg 23573143b9aSmrg /* Copy the string so it can be changed */ 23673143b9aSmrg 237fe567363Smrg tmpptr = mybuf = strdup (address); 23873143b9aSmrg 23973143b9aSmrg /* Parse the string to get each component */ 240fe567363Smrg 24173143b9aSmrg /* Get the protocol part */ 24273143b9aSmrg 24373143b9aSmrg _protocol = mybuf; 24473143b9aSmrg 24573143b9aSmrg 24694f982dbSmrg if ((mybuf == NULL) || 24794f982dbSmrg ( ((mybuf = strchr (mybuf, '/')) == NULL) && 24894f982dbSmrg ((mybuf = strrchr (tmpptr, ':')) == NULL) ) ) 24994f982dbSmrg { 25073143b9aSmrg /* address is in a bad format */ 25173143b9aSmrg *protocol = NULL; 25273143b9aSmrg *host = NULL; 25373143b9aSmrg *port = NULL; 254fe567363Smrg free (tmpptr); 25573143b9aSmrg return 0; 25673143b9aSmrg } 25773143b9aSmrg 25873143b9aSmrg if (*mybuf == ':') 25973143b9aSmrg { 26073143b9aSmrg /* 26173143b9aSmrg * If there is a hostname, then assume tcp, otherwise 26273143b9aSmrg * it must be local. 26373143b9aSmrg */ 26473143b9aSmrg if (mybuf == tmpptr) 26573143b9aSmrg { 26673143b9aSmrg /* There is neither a protocol or host specified */ 26773143b9aSmrg _protocol = "local"; 26873143b9aSmrg } 26973143b9aSmrg else 27073143b9aSmrg { 27173143b9aSmrg /* There is a hostname specified */ 27273143b9aSmrg _protocol = "tcp"; 273e45ace2bSmrg mybuf = tmpptr; /* reset to the beginning of the host ptr */ 27473143b9aSmrg } 27573143b9aSmrg } 27673143b9aSmrg else 27773143b9aSmrg { 27873143b9aSmrg /* *mybuf == '/' */ 27973143b9aSmrg 28073143b9aSmrg *mybuf ++= '\0'; /* put a null at the end of the protocol */ 28173143b9aSmrg 28273143b9aSmrg if (strlen(_protocol) == 0) 28373143b9aSmrg { 28473143b9aSmrg /* 28573143b9aSmrg * If there is a hostname, then assume tcp, otherwise 28673143b9aSmrg * it must be local. 28773143b9aSmrg */ 28873143b9aSmrg if (*mybuf != ':') 28973143b9aSmrg _protocol = "tcp"; 29073143b9aSmrg else 29173143b9aSmrg _protocol = "local"; 29273143b9aSmrg } 29373143b9aSmrg } 29473143b9aSmrg 29573143b9aSmrg /* Get the host part */ 29673143b9aSmrg 29794f982dbSmrg _host = _host_buf = mybuf; 29873143b9aSmrg 29973143b9aSmrg if ((mybuf = strrchr (mybuf,':')) == NULL) 30073143b9aSmrg { 30173143b9aSmrg *protocol = NULL; 30273143b9aSmrg *host = NULL; 30373143b9aSmrg *port = NULL; 304fe567363Smrg free (tmpptr); 30573143b9aSmrg return 0; 30673143b9aSmrg } 30773143b9aSmrg 30873143b9aSmrg *mybuf ++= '\0'; 30973143b9aSmrg 31073143b9aSmrg _host_len = strlen(_host); 31173143b9aSmrg if (_host_len == 0) 31273143b9aSmrg { 31373143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 31473143b9aSmrg _host = hostnamebuf; 31573143b9aSmrg } 31673143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 31773143b9aSmrg /* hostname in IPv6 [numeric_addr]:0 form? */ 318fe567363Smrg else if ( (_host_len > 3) && 31973143b9aSmrg ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) 32094f982dbSmrg && (_host_buf[0] == '[') && (_host_buf[_host_len - 1] == ']') ) { 32173143b9aSmrg struct sockaddr_in6 sin6; 32273143b9aSmrg 32394f982dbSmrg _host_buf[_host_len - 1] = '\0'; 32473143b9aSmrg 32573143b9aSmrg /* Verify address is valid IPv6 numeric form */ 32673143b9aSmrg if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { 32773143b9aSmrg /* It is. Use it as such. */ 32873143b9aSmrg _host++; 32973143b9aSmrg _protocol = "inet6"; 33073143b9aSmrg } else { 33173143b9aSmrg /* It's not, restore it just in case some other code can use it. */ 33294f982dbSmrg _host_buf[_host_len - 1] = ']'; 33373143b9aSmrg } 33473143b9aSmrg } 33573143b9aSmrg#endif 33673143b9aSmrg 33773143b9aSmrg 33873143b9aSmrg /* Get the port */ 33973143b9aSmrg 34073143b9aSmrg _port = mybuf; 34173143b9aSmrg 34273143b9aSmrg#if defined(FONT_t) || defined(FS_t) 34373143b9aSmrg /* 34473143b9aSmrg * Is there an optional catalogue list? 34573143b9aSmrg */ 34673143b9aSmrg 34773143b9aSmrg if ((mybuf = strchr (mybuf,'/')) != NULL) 34873143b9aSmrg *mybuf ++= '\0'; 34973143b9aSmrg 35073143b9aSmrg /* 35173143b9aSmrg * The rest, if any, is the (currently unused) catalogue list. 35273143b9aSmrg * 35373143b9aSmrg * _catalogue = mybuf; 35473143b9aSmrg */ 35573143b9aSmrg#endif 35673143b9aSmrg 357e45ace2bSmrgdone_parsing: 35873143b9aSmrg /* 35973143b9aSmrg * Now that we have all of the components, allocate new 36073143b9aSmrg * string space for them. 36173143b9aSmrg */ 36273143b9aSmrg 363fe567363Smrg if ((*protocol = strdup (_protocol)) == NULL) 36473143b9aSmrg { 36573143b9aSmrg /* Malloc failed */ 36673143b9aSmrg *port = NULL; 36773143b9aSmrg *host = NULL; 36873143b9aSmrg *protocol = NULL; 369fe567363Smrg free (tmpptr); 37073143b9aSmrg return 0; 37173143b9aSmrg } 37273143b9aSmrg 373fe567363Smrg if ((*host = strdup (_host)) == NULL) 37473143b9aSmrg { 37573143b9aSmrg /* Malloc failed */ 37673143b9aSmrg *port = NULL; 37773143b9aSmrg *host = NULL; 378fe567363Smrg free (*protocol); 37973143b9aSmrg *protocol = NULL; 380fe567363Smrg free (tmpptr); 38173143b9aSmrg return 0; 382fe567363Smrg } 38373143b9aSmrg 384fe567363Smrg if ((*port = strdup (_port)) == NULL) 38573143b9aSmrg { 38673143b9aSmrg /* Malloc failed */ 38773143b9aSmrg *port = NULL; 388fe567363Smrg free (*host); 38973143b9aSmrg *host = NULL; 390fe567363Smrg free (*protocol); 39173143b9aSmrg *protocol = NULL; 392fe567363Smrg free (tmpptr); 39373143b9aSmrg return 0; 39473143b9aSmrg } 39573143b9aSmrg 396fe567363Smrg free (tmpptr); 39773143b9aSmrg 39873143b9aSmrg return 1; 39973143b9aSmrg} 40073143b9aSmrg 40173143b9aSmrg 40273143b9aSmrg/* 40373143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only 40473143b9aSmrg * funny part about this is the type parameter which is used to decide which 40573143b9aSmrg * type of open to perform. 40673143b9aSmrg */ 40773143b9aSmrg 40873143b9aSmrgstatic XtransConnInfo 4096a3641a6SsnjTRANS(Open) (int type, const char *address) 41073143b9aSmrg 41173143b9aSmrg{ 41273143b9aSmrg char *protocol = NULL, *host = NULL, *port = NULL; 41373143b9aSmrg XtransConnInfo ciptr = NULL; 41473143b9aSmrg Xtransport *thistrans; 41573143b9aSmrg 416fe567363Smrg prmsg (2,"Open(%d,%s)\n", type, address); 41773143b9aSmrg 418fe567363Smrg#if defined(WIN32) && defined(TCPCONN) 41973143b9aSmrg if (TRANS(WSAStartup)()) 42073143b9aSmrg { 421fe567363Smrg prmsg (1,"Open: WSAStartup failed\n"); 42273143b9aSmrg return NULL; 42373143b9aSmrg } 42473143b9aSmrg#endif 42573143b9aSmrg 42673143b9aSmrg /* Parse the Address */ 42773143b9aSmrg 42873143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 42973143b9aSmrg { 430fe567363Smrg prmsg (1,"Open: Unable to Parse address %s\n", address); 43173143b9aSmrg return NULL; 43273143b9aSmrg } 43373143b9aSmrg 43473143b9aSmrg /* Determine the transport type */ 43573143b9aSmrg 43673143b9aSmrg if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) 43773143b9aSmrg { 438fe567363Smrg prmsg (1,"Open: Unable to find transport for %s\n", 439fe567363Smrg protocol); 44073143b9aSmrg 441fe567363Smrg free (protocol); 442fe567363Smrg free (host); 443fe567363Smrg free (port); 44473143b9aSmrg return NULL; 44573143b9aSmrg } 44673143b9aSmrg 44773143b9aSmrg /* Open the transport */ 44873143b9aSmrg 44973143b9aSmrg switch (type) 45073143b9aSmrg { 45173143b9aSmrg case XTRANS_OPEN_COTS_CLIENT: 45273143b9aSmrg#ifdef TRANS_CLIENT 45373143b9aSmrg ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); 45473143b9aSmrg#endif /* TRANS_CLIENT */ 45573143b9aSmrg break; 45673143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 45773143b9aSmrg#ifdef TRANS_SERVER 45873143b9aSmrg ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); 45973143b9aSmrg#endif /* TRANS_SERVER */ 46073143b9aSmrg break; 46173143b9aSmrg default: 462fe567363Smrg prmsg (1,"Open: Unknown Open type %d\n", type); 46373143b9aSmrg } 46473143b9aSmrg 46573143b9aSmrg if (ciptr == NULL) 46673143b9aSmrg { 467fe567363Smrg if (!(thistrans->flags & TRANS_DISABLED)) 46873143b9aSmrg { 469fe567363Smrg prmsg (1,"Open: transport open failed for %s/%s:%s\n", 47073143b9aSmrg protocol, host, port); 47173143b9aSmrg } 472fe567363Smrg free (protocol); 473fe567363Smrg free (host); 474fe567363Smrg free (port); 47573143b9aSmrg return NULL; 47673143b9aSmrg } 47773143b9aSmrg 47873143b9aSmrg ciptr->transptr = thistrans; 47973143b9aSmrg ciptr->port = port; /* We need this for TRANS(Reopen) */ 48073143b9aSmrg 481fe567363Smrg free (protocol); 482fe567363Smrg free (host); 48373143b9aSmrg 48473143b9aSmrg return ciptr; 48573143b9aSmrg} 48673143b9aSmrg 48773143b9aSmrg 48873143b9aSmrg#ifdef TRANS_REOPEN 48973143b9aSmrg 49073143b9aSmrg/* 49173143b9aSmrg * We might want to create an XtransConnInfo object based on a previously 49273143b9aSmrg * opened connection. For example, the font server may clone itself and 49373143b9aSmrg * pass file descriptors to the parent. 49473143b9aSmrg */ 49573143b9aSmrg 49673143b9aSmrgstatic XtransConnInfo 4976a3641a6SsnjTRANS(Reopen) (int type, int trans_id, int fd, const char *port) 49873143b9aSmrg 49973143b9aSmrg{ 50073143b9aSmrg XtransConnInfo ciptr = NULL; 50173143b9aSmrg Xtransport *thistrans = NULL; 50273143b9aSmrg char *save_port; 50373143b9aSmrg 504fe567363Smrg prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); 50573143b9aSmrg 50673143b9aSmrg /* Determine the transport type */ 50773143b9aSmrg 50894f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 50994f982dbSmrg { 51073143b9aSmrg if (Xtransports[i].transport_id == trans_id) 51173143b9aSmrg { 51273143b9aSmrg thistrans = Xtransports[i].transport; 51373143b9aSmrg break; 51473143b9aSmrg } 51594f982dbSmrg } 51673143b9aSmrg 51773143b9aSmrg if (thistrans == NULL) 51873143b9aSmrg { 519fe567363Smrg prmsg (1,"Reopen: Unable to find transport id %d\n", 520fe567363Smrg trans_id); 52173143b9aSmrg 52273143b9aSmrg return NULL; 52373143b9aSmrg } 52473143b9aSmrg 525fe567363Smrg if ((save_port = strdup (port)) == NULL) 52673143b9aSmrg { 527fe567363Smrg prmsg (1,"Reopen: Unable to malloc port string\n"); 52873143b9aSmrg 52973143b9aSmrg return NULL; 53073143b9aSmrg } 53173143b9aSmrg 53273143b9aSmrg /* Get a new XtransConnInfo object */ 53373143b9aSmrg 53473143b9aSmrg switch (type) 53573143b9aSmrg { 53673143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 53773143b9aSmrg ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); 53873143b9aSmrg break; 53973143b9aSmrg default: 540fe567363Smrg prmsg (1,"Reopen: Bad Open type %d\n", type); 54173143b9aSmrg } 54273143b9aSmrg 54373143b9aSmrg if (ciptr == NULL) 54473143b9aSmrg { 545fe567363Smrg prmsg (1,"Reopen: transport open failed\n"); 546fe567363Smrg free (save_port); 54773143b9aSmrg return NULL; 54873143b9aSmrg } 54973143b9aSmrg 55073143b9aSmrg ciptr->transptr = thistrans; 55173143b9aSmrg ciptr->port = save_port; 55273143b9aSmrg 55373143b9aSmrg return ciptr; 55473143b9aSmrg} 55573143b9aSmrg 55673143b9aSmrg#endif /* TRANS_REOPEN */ 55773143b9aSmrg 55873143b9aSmrg 55973143b9aSmrg 56073143b9aSmrg/* 56173143b9aSmrg * These are the public interfaces to this Transport interface. 56273143b9aSmrg * These are the only functions that should have knowledge of the transport 56373143b9aSmrg * table. 56473143b9aSmrg */ 56573143b9aSmrg 56673143b9aSmrg#ifdef TRANS_CLIENT 56773143b9aSmrg 56873143b9aSmrgXtransConnInfo 5696a3641a6SsnjTRANS(OpenCOTSClient) (const char *address) 57073143b9aSmrg 57173143b9aSmrg{ 572fe567363Smrg prmsg (2,"OpenCOTSClient(%s)\n", address); 57373143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); 57473143b9aSmrg} 57573143b9aSmrg 57673143b9aSmrg#endif /* TRANS_CLIENT */ 57773143b9aSmrg 57873143b9aSmrg 57973143b9aSmrg#ifdef TRANS_SERVER 58073143b9aSmrg 58173143b9aSmrgXtransConnInfo 5826a3641a6SsnjTRANS(OpenCOTSServer) (const char *address) 58373143b9aSmrg 58473143b9aSmrg{ 585fe567363Smrg prmsg (2,"OpenCOTSServer(%s)\n", address); 58673143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); 58773143b9aSmrg} 58873143b9aSmrg 58973143b9aSmrg#endif /* TRANS_SERVER */ 59073143b9aSmrg 59173143b9aSmrg 59273143b9aSmrg#ifdef TRANS_REOPEN 59373143b9aSmrg 59473143b9aSmrgXtransConnInfo 5956a3641a6SsnjTRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port) 59673143b9aSmrg 59773143b9aSmrg{ 598fe567363Smrg prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); 59973143b9aSmrg return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); 60073143b9aSmrg} 60173143b9aSmrg 60273143b9aSmrgint 603fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr, 60473143b9aSmrg int *trans_id, int *fd, char **port) 60573143b9aSmrg 60673143b9aSmrg{ 60794f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 60894f982dbSmrg { 60973143b9aSmrg if (Xtransports[i].transport == ciptr->transptr) 61073143b9aSmrg { 61173143b9aSmrg *trans_id = Xtransports[i].transport_id; 61273143b9aSmrg *fd = ciptr->fd; 61373143b9aSmrg 614fe567363Smrg if ((*port = strdup (ciptr->port)) == NULL) 61573143b9aSmrg return 0; 61673143b9aSmrg else 61773143b9aSmrg return 1; 61873143b9aSmrg } 61994f982dbSmrg } 62073143b9aSmrg 62173143b9aSmrg return 0; 62273143b9aSmrg} 62373143b9aSmrg 62473143b9aSmrg#endif /* TRANS_REOPEN */ 62573143b9aSmrg 62673143b9aSmrg 62773143b9aSmrgint 62873143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) 62973143b9aSmrg 63073143b9aSmrg{ 63173143b9aSmrg int fd = ciptr->fd; 63273143b9aSmrg int ret = 0; 63373143b9aSmrg 634fe567363Smrg prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg); 63573143b9aSmrg 63673143b9aSmrg /* 63773143b9aSmrg * For now, all transport type use the same stuff for setting options. 63873143b9aSmrg * As long as this is true, we can put the common code here. Once a more 63973143b9aSmrg * complicated transport such as shared memory or an OSI implementation 64073143b9aSmrg * that uses the session and application libraries is implemented, this 64173143b9aSmrg * code may have to move to a transport dependent function. 64273143b9aSmrg * 64373143b9aSmrg * ret = ciptr->transptr->SetOption (ciptr, option, arg); 64473143b9aSmrg */ 64573143b9aSmrg 64673143b9aSmrg switch (option) 64773143b9aSmrg { 64873143b9aSmrg case TRANS_NONBLOCKING: 64973143b9aSmrg switch (arg) 65073143b9aSmrg { 65173143b9aSmrg case 0: 65273143b9aSmrg /* Set to blocking mode */ 65373143b9aSmrg break; 65473143b9aSmrg case 1: /* Set to non-blocking mode */ 65573143b9aSmrg 656e45ace2bSmrg#if defined(O_NONBLOCK) 65773143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 65873143b9aSmrg if (ret != -1) 65973143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); 66073143b9aSmrg#else 66173143b9aSmrg#ifdef FIOSNBIO 66273143b9aSmrg { 66373143b9aSmrg int arg; 66473143b9aSmrg arg = 1; 66573143b9aSmrg ret = ioctl (fd, FIOSNBIO, &arg); 66673143b9aSmrg } 66773143b9aSmrg#else 668fe567363Smrg#if defined(WIN32) 66973143b9aSmrg { 67073143b9aSmrg#ifdef WIN32 67173143b9aSmrg u_long arg; 67273143b9aSmrg#else 67373143b9aSmrg int arg; 67473143b9aSmrg#endif 67573143b9aSmrg arg = 1; 67673143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail 67773143b9aSmrg * eventually with EWOULDBLOCK */ 67873143b9aSmrg ret = ioctl (fd, FIONBIO, &arg); 67973143b9aSmrg } 68073143b9aSmrg#else 68173143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 68273143b9aSmrg#ifdef FNDELAY 68373143b9aSmrg ret = fcntl (fd, F_SETFL, ret | FNDELAY); 68473143b9aSmrg#else 68573143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NDELAY); 68673143b9aSmrg#endif 68773143b9aSmrg#endif /* AIXV3 || uniosu */ 68873143b9aSmrg#endif /* FIOSNBIO */ 68973143b9aSmrg#endif /* O_NONBLOCK */ 69073143b9aSmrg break; 69173143b9aSmrg default: 69273143b9aSmrg /* Unknown option */ 69373143b9aSmrg break; 69473143b9aSmrg } 69573143b9aSmrg break; 69673143b9aSmrg case TRANS_CLOSEONEXEC: 69773143b9aSmrg#ifdef F_SETFD 69873143b9aSmrg#ifdef FD_CLOEXEC 69973143b9aSmrg ret = fcntl (fd, F_SETFD, FD_CLOEXEC); 70073143b9aSmrg#else 70173143b9aSmrg ret = fcntl (fd, F_SETFD, 1); 70273143b9aSmrg#endif /* FD_CLOEXEC */ 70373143b9aSmrg#endif /* F_SETFD */ 70473143b9aSmrg break; 70573143b9aSmrg } 706fe567363Smrg 70773143b9aSmrg return ret; 70873143b9aSmrg} 70973143b9aSmrg 71073143b9aSmrg#ifdef TRANS_SERVER 71173143b9aSmrg 71273143b9aSmrgint 7136a3641a6SsnjTRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags) 71473143b9aSmrg 71573143b9aSmrg{ 71673143b9aSmrg return ciptr->transptr->CreateListener (ciptr, port, flags); 71773143b9aSmrg} 71873143b9aSmrg 71975ebec6dSmrgint 72075ebec6dSmrgTRANS(Received) (const char * protocol) 72175ebec6dSmrg 72275ebec6dSmrg{ 72375ebec6dSmrg Xtransport *trans; 72475ebec6dSmrg int i = 0, ret = 0; 72575ebec6dSmrg 72675ebec6dSmrg prmsg (5, "Received(%s)\n", protocol); 72775ebec6dSmrg 72875ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 72975ebec6dSmrg { 73075ebec6dSmrg prmsg (1,"Received: unable to find transport: %s\n", 73175ebec6dSmrg protocol); 73275ebec6dSmrg 73375ebec6dSmrg return -1; 73475ebec6dSmrg } 73575ebec6dSmrg if (trans->flags & TRANS_ALIAS) { 73675ebec6dSmrg if (trans->nolisten) 73775ebec6dSmrg while (trans->nolisten[i]) { 73875ebec6dSmrg ret |= TRANS(Received)(trans->nolisten[i]); 73975ebec6dSmrg i++; 74075ebec6dSmrg } 74175ebec6dSmrg } 74275ebec6dSmrg 74375ebec6dSmrg trans->flags |= TRANS_RECEIVED; 74475ebec6dSmrg return ret; 74575ebec6dSmrg} 74675ebec6dSmrg 74773143b9aSmrgint 748fe567363SmrgTRANS(NoListen) (const char * protocol) 749fe567363Smrg 75073143b9aSmrg{ 75173143b9aSmrg Xtransport *trans; 75273143b9aSmrg int i = 0, ret = 0; 753fe567363Smrg 754fe567363Smrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 75573143b9aSmrg { 756fe567363Smrg prmsg (1,"TransNoListen: unable to find transport: %s\n", 757fe567363Smrg protocol); 75873143b9aSmrg 75973143b9aSmrg return -1; 76073143b9aSmrg } 76173143b9aSmrg if (trans->flags & TRANS_ALIAS) { 76273143b9aSmrg if (trans->nolisten) 76373143b9aSmrg while (trans->nolisten[i]) { 76473143b9aSmrg ret |= TRANS(NoListen)(trans->nolisten[i]); 76573143b9aSmrg i++; 76673143b9aSmrg } 76773143b9aSmrg } 76873143b9aSmrg 76973143b9aSmrg trans->flags |= TRANS_NOLISTEN; 77073143b9aSmrg return ret; 77173143b9aSmrg} 77273143b9aSmrg 7736a3641a6Ssnjint 7746a3641a6SsnjTRANS(Listen) (const char * protocol) 7756a3641a6Ssnj{ 7766a3641a6Ssnj Xtransport *trans; 7776a3641a6Ssnj int i = 0, ret = 0; 7786a3641a6Ssnj 7796a3641a6Ssnj if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 7806a3641a6Ssnj { 7816a3641a6Ssnj prmsg (1,"TransListen: unable to find transport: %s\n", 7826a3641a6Ssnj protocol); 7836a3641a6Ssnj 7846a3641a6Ssnj return -1; 7856a3641a6Ssnj } 7866a3641a6Ssnj if (trans->flags & TRANS_ALIAS) { 7876a3641a6Ssnj if (trans->nolisten) 7886a3641a6Ssnj while (trans->nolisten[i]) { 7896a3641a6Ssnj ret |= TRANS(Listen)(trans->nolisten[i]); 7906a3641a6Ssnj i++; 7916a3641a6Ssnj } 7926a3641a6Ssnj } 7936a3641a6Ssnj 7946a3641a6Ssnj trans->flags &= ~TRANS_NOLISTEN; 7956a3641a6Ssnj return ret; 7966a3641a6Ssnj} 7976a3641a6Ssnj 79875ebec6dSmrgint 79975ebec6dSmrgTRANS(IsListening) (const char * protocol) 80075ebec6dSmrg{ 80175ebec6dSmrg Xtransport *trans; 80275ebec6dSmrg 80375ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 80475ebec6dSmrg { 80575ebec6dSmrg prmsg (1,"TransIsListening: unable to find transport: %s\n", 80675ebec6dSmrg protocol); 80775ebec6dSmrg 80875ebec6dSmrg return 0; 80975ebec6dSmrg } 81075ebec6dSmrg 81175ebec6dSmrg return !(trans->flags & TRANS_NOLISTEN); 81275ebec6dSmrg} 81375ebec6dSmrg 81473143b9aSmrgint 81573143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr) 81673143b9aSmrg 81773143b9aSmrg{ 81873143b9aSmrg if (ciptr->transptr->ResetListener) 81973143b9aSmrg return ciptr->transptr->ResetListener (ciptr); 82073143b9aSmrg else 82173143b9aSmrg return TRANS_RESET_NOOP; 82273143b9aSmrg} 82373143b9aSmrg 82473143b9aSmrg 82573143b9aSmrgXtransConnInfo 82673143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status) 82773143b9aSmrg 82873143b9aSmrg{ 82973143b9aSmrg XtransConnInfo newciptr; 83073143b9aSmrg 831fe567363Smrg prmsg (2,"Accept(%d)\n", ciptr->fd); 83273143b9aSmrg 83373143b9aSmrg newciptr = ciptr->transptr->Accept (ciptr, status); 83473143b9aSmrg 83573143b9aSmrg if (newciptr) 83673143b9aSmrg newciptr->transptr = ciptr->transptr; 83773143b9aSmrg 83873143b9aSmrg return newciptr; 83973143b9aSmrg} 84073143b9aSmrg 84173143b9aSmrg#endif /* TRANS_SERVER */ 84273143b9aSmrg 84373143b9aSmrg 84473143b9aSmrg#ifdef TRANS_CLIENT 84573143b9aSmrg 84673143b9aSmrgint 8476a3641a6SsnjTRANS(Connect) (XtransConnInfo ciptr, const char *address) 84873143b9aSmrg 84973143b9aSmrg{ 85073143b9aSmrg char *protocol; 85173143b9aSmrg char *host; 85273143b9aSmrg char *port; 85373143b9aSmrg int ret; 85473143b9aSmrg 855fe567363Smrg prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address); 85673143b9aSmrg 85773143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 85873143b9aSmrg { 859fe567363Smrg prmsg (1,"Connect: Unable to Parse address %s\n", 860fe567363Smrg address); 86173143b9aSmrg return -1; 86273143b9aSmrg } 86373143b9aSmrg 86473143b9aSmrg#ifdef HAVE_LAUNCHD 8658d4c0f7bSmrg if (!host) host=strdup(""); 86673143b9aSmrg#endif 86773143b9aSmrg 86873143b9aSmrg if (!port || !*port) 86973143b9aSmrg { 870fe567363Smrg prmsg (1,"Connect: Missing port specification in %s\n", 871fe567363Smrg address); 872fe567363Smrg if (protocol) free (protocol); 873fe567363Smrg if (host) free (host); 87473143b9aSmrg return -1; 87573143b9aSmrg } 87673143b9aSmrg 87773143b9aSmrg ret = ciptr->transptr->Connect (ciptr, host, port); 87873143b9aSmrg 879fe567363Smrg if (protocol) free (protocol); 880fe567363Smrg if (host) free (host); 881fe567363Smrg if (port) free (port); 882fe567363Smrg 88373143b9aSmrg return ret; 88473143b9aSmrg} 88573143b9aSmrg 88673143b9aSmrg#endif /* TRANS_CLIENT */ 88773143b9aSmrg 88873143b9aSmrg 88973143b9aSmrgint 89073143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 89173143b9aSmrg 89273143b9aSmrg{ 89373143b9aSmrg return ciptr->transptr->BytesReadable (ciptr, pend); 89473143b9aSmrg} 89573143b9aSmrg 89673143b9aSmrgint 89773143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size) 89873143b9aSmrg 89973143b9aSmrg{ 90073143b9aSmrg return ciptr->transptr->Read (ciptr, buf, size); 90173143b9aSmrg} 90273143b9aSmrg 90373143b9aSmrgint 90473143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size) 90573143b9aSmrg 90673143b9aSmrg{ 90773143b9aSmrg return ciptr->transptr->Write (ciptr, buf, size); 90873143b9aSmrg} 90973143b9aSmrg 91073143b9aSmrgint 91173143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) 91273143b9aSmrg 91373143b9aSmrg{ 91473143b9aSmrg return ciptr->transptr->Readv (ciptr, buf, size); 91573143b9aSmrg} 91673143b9aSmrg 91773143b9aSmrgint 91873143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) 91973143b9aSmrg 92073143b9aSmrg{ 92173143b9aSmrg return ciptr->transptr->Writev (ciptr, buf, size); 92273143b9aSmrg} 92373143b9aSmrg 92475ebec6dSmrg#if XTRANS_SEND_FDS 92575ebec6dSmrgint 92675ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) 92775ebec6dSmrg{ 92875ebec6dSmrg return ciptr->transptr->SendFd(ciptr, fd, do_close); 92975ebec6dSmrg} 93075ebec6dSmrg 93175ebec6dSmrgint 93275ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr) 93375ebec6dSmrg{ 93475ebec6dSmrg return ciptr->transptr->RecvFd(ciptr); 93575ebec6dSmrg} 93675ebec6dSmrg#endif 93775ebec6dSmrg 93873143b9aSmrgint 93973143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr) 94073143b9aSmrg 94173143b9aSmrg{ 94273143b9aSmrg return ciptr->transptr->Disconnect (ciptr); 94373143b9aSmrg} 94473143b9aSmrg 94573143b9aSmrgint 94673143b9aSmrgTRANS(Close) (XtransConnInfo ciptr) 94773143b9aSmrg 94873143b9aSmrg{ 94973143b9aSmrg int ret; 95073143b9aSmrg 951fe567363Smrg prmsg (2,"Close(%d)\n", ciptr->fd); 95273143b9aSmrg 95373143b9aSmrg ret = ciptr->transptr->Close (ciptr); 95473143b9aSmrg 95573143b9aSmrg TRANS(FreeConnInfo) (ciptr); 95673143b9aSmrg 95773143b9aSmrg return ret; 95873143b9aSmrg} 95973143b9aSmrg 96073143b9aSmrgint 96173143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr) 96273143b9aSmrg 96373143b9aSmrg{ 96473143b9aSmrg int ret; 96573143b9aSmrg 966fe567363Smrg prmsg (2,"CloseForCloning(%d)\n", ciptr->fd); 96773143b9aSmrg 96873143b9aSmrg ret = ciptr->transptr->CloseForCloning (ciptr); 96973143b9aSmrg 97073143b9aSmrg TRANS(FreeConnInfo) (ciptr); 97173143b9aSmrg 97273143b9aSmrg return ret; 97373143b9aSmrg} 97473143b9aSmrg 97573143b9aSmrgint 97673143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr) 97773143b9aSmrg 97873143b9aSmrg{ 97973143b9aSmrg return (ciptr->family == AF_UNIX); 98073143b9aSmrg} 98173143b9aSmrg 98273143b9aSmrgint 983fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 98473143b9aSmrg Xtransaddr **addrp) 98573143b9aSmrg 98673143b9aSmrg{ 987fe567363Smrg prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd); 98873143b9aSmrg 98973143b9aSmrg *familyp = ciptr->family; 99073143b9aSmrg *addrlenp = ciptr->peeraddrlen; 99173143b9aSmrg 992fe567363Smrg if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL) 99373143b9aSmrg { 994fe567363Smrg prmsg (1,"GetPeerAddr: malloc failed\n"); 99573143b9aSmrg return -1; 99673143b9aSmrg } 99773143b9aSmrg memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); 99873143b9aSmrg 99973143b9aSmrg return 0; 100073143b9aSmrg} 100173143b9aSmrg 100273143b9aSmrg 100373143b9aSmrgint 100473143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr) 100573143b9aSmrg 100673143b9aSmrg{ 100773143b9aSmrg return ciptr->fd; 100873143b9aSmrg} 100973143b9aSmrg 101073143b9aSmrg 101173143b9aSmrg/* 101273143b9aSmrg * These functions are really utility functions, but they require knowledge 101373143b9aSmrg * of the internal data structures, so they have to be part of the Transport 1014e45ace2bSmrg * Independent API. 101573143b9aSmrg */ 101673143b9aSmrg 101773143b9aSmrg#ifdef TRANS_SERVER 101873143b9aSmrg 101973143b9aSmrgstatic int 102073143b9aSmrgcomplete_network_count (void) 102173143b9aSmrg 102273143b9aSmrg{ 102373143b9aSmrg int count = 0; 102473143b9aSmrg int found_local = 0; 102573143b9aSmrg 102673143b9aSmrg /* 102773143b9aSmrg * For a complete network, we only need one LOCALCONN transport to work 102873143b9aSmrg */ 102973143b9aSmrg 103094f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 103173143b9aSmrg { 103273143b9aSmrg if (Xtransports[i].transport->flags & TRANS_ALIAS 103373143b9aSmrg || Xtransports[i].transport->flags & TRANS_NOLISTEN) 103473143b9aSmrg continue; 103573143b9aSmrg 103673143b9aSmrg if (Xtransports[i].transport->flags & TRANS_LOCAL) 103773143b9aSmrg found_local = 1; 103873143b9aSmrg else 103973143b9aSmrg count++; 104073143b9aSmrg } 104173143b9aSmrg 104273143b9aSmrg return (count + found_local); 104373143b9aSmrg} 104473143b9aSmrg 104573143b9aSmrg 104675ebec6dSmrgstatic int 10476a3641a6Ssnjreceive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs, 10486a3641a6Ssnj int* count_ret) 104975ebec6dSmrg 105075ebec6dSmrg{ 105175ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON 105275ebec6dSmrg XtransConnInfo ciptr; 105375ebec6dSmrg int i, systemd_listen_fds; 105475ebec6dSmrg 105575ebec6dSmrg systemd_listen_fds = sd_listen_fds(1); 105675ebec6dSmrg if (systemd_listen_fds < 0) 105775ebec6dSmrg { 105875ebec6dSmrg prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n", 105975ebec6dSmrg strerror(-systemd_listen_fds)); 106075ebec6dSmrg return -1; 106175ebec6dSmrg } 106275ebec6dSmrg 106394f982dbSmrg for (i = 0; i < systemd_listen_fds && *count_ret < (int)NUMTRANS; i++) 106475ebec6dSmrg { 106575ebec6dSmrg struct sockaddr_storage a; 106675ebec6dSmrg int ti; 106775ebec6dSmrg const char* tn; 106875ebec6dSmrg socklen_t al; 106975ebec6dSmrg 107075ebec6dSmrg al = sizeof(a); 107175ebec6dSmrg if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) { 107275ebec6dSmrg prmsg (1, "receive_listening_fds: getsockname error: %s\n", 107375ebec6dSmrg strerror(errno)); 107475ebec6dSmrg return -1; 107575ebec6dSmrg } 107675ebec6dSmrg 107775ebec6dSmrg switch (a.ss_family) 107875ebec6dSmrg { 107975ebec6dSmrg case AF_UNIX: 108075ebec6dSmrg ti = TRANS_SOCKET_UNIX_INDEX; 108175ebec6dSmrg if (*((struct sockaddr_un*)&a)->sun_path == '\0' && 108275ebec6dSmrg al > sizeof(sa_family_t)) 108375ebec6dSmrg tn = "local"; 108475ebec6dSmrg else 108575ebec6dSmrg tn = "unix"; 108675ebec6dSmrg break; 108775ebec6dSmrg case AF_INET: 108875ebec6dSmrg ti = TRANS_SOCKET_INET_INDEX; 108975ebec6dSmrg tn = "inet"; 109075ebec6dSmrg break; 109175ebec6dSmrg#if defined(IPv6) && defined(AF_INET6) 109275ebec6dSmrg case AF_INET6: 109375ebec6dSmrg ti = TRANS_SOCKET_INET6_INDEX; 109475ebec6dSmrg tn = "inet6"; 109575ebec6dSmrg break; 109675ebec6dSmrg#endif /* IPv6 */ 109775ebec6dSmrg default: 109875ebec6dSmrg prmsg (1, "receive_listening_fds:" 109975ebec6dSmrg "Got unknown socket address family\n"); 110075ebec6dSmrg return -1; 110175ebec6dSmrg } 110275ebec6dSmrg 110375ebec6dSmrg ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port); 110475ebec6dSmrg if (!ciptr) 110575ebec6dSmrg { 110675ebec6dSmrg prmsg (1, "receive_listening_fds:" 110775ebec6dSmrg "Got NULL while trying to reopen socket received from systemd.\n"); 110875ebec6dSmrg return -1; 110975ebec6dSmrg } 111075ebec6dSmrg 111175ebec6dSmrg prmsg (5, "receive_listening_fds: received listener for %s, %d\n", 111275ebec6dSmrg tn, ciptr->fd); 111375ebec6dSmrg temp_ciptrs[(*count_ret)++] = ciptr; 111475ebec6dSmrg TRANS(Received)(tn); 111575ebec6dSmrg } 111675ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */ 111775ebec6dSmrg return 0; 111875ebec6dSmrg} 111975ebec6dSmrg 11208d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11218d4c0f7bSmrgextern int xquartz_launchd_fd; 11228d4c0f7bSmrg#endif 112373143b9aSmrg 112473143b9aSmrgint 11256a3641a6SsnjTRANS(MakeAllCOTSServerListeners) (const char *port, int *partial, 11266a3641a6Ssnj int *count_ret, XtransConnInfo **ciptrs_ret) 112773143b9aSmrg 112873143b9aSmrg{ 112973143b9aSmrg char buffer[256]; /* ??? What size ?? */ 113094f982dbSmrg XtransConnInfo ciptr, temp_ciptrs[NUMTRANS] = { NULL }; 113194f982dbSmrg int status, j; 113273143b9aSmrg 113373143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 113473143b9aSmrg int ipv6_succ = 0; 113573143b9aSmrg#endif 1136fe567363Smrg prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n", 1137fe567363Smrg port ? port : "NULL", ciptrs_ret); 113873143b9aSmrg 113973143b9aSmrg *count_ret = 0; 114073143b9aSmrg 11418d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11428d4c0f7bSmrg fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd); 11438d4c0f7bSmrg if(xquartz_launchd_fd != -1) { 11448d4c0f7bSmrg if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, 11458d4c0f7bSmrg xquartz_launchd_fd, getenv("DISPLAY"))))==NULL) 11468d4c0f7bSmrg fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); 1147fe567363Smrg else 11488d4c0f7bSmrg temp_ciptrs[(*count_ret)++] = ciptr; 11498d4c0f7bSmrg } 115073143b9aSmrg#endif 115173143b9aSmrg 115275ebec6dSmrg if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0) 115375ebec6dSmrg return -1; 115475ebec6dSmrg 115594f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 115673143b9aSmrg { 115773143b9aSmrg Xtransport *trans = Xtransports[i].transport; 115873143b9aSmrg unsigned int flags = 0; 115973143b9aSmrg 116075ebec6dSmrg if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN || 116175ebec6dSmrg trans->flags&TRANS_RECEIVED) 116273143b9aSmrg continue; 116373143b9aSmrg 116473143b9aSmrg snprintf(buffer, sizeof(buffer), "%s/:%s", 116573143b9aSmrg trans->TransName, port ? port : ""); 116673143b9aSmrg 1167fe567363Smrg prmsg (5,"MakeAllCOTSServerListeners: opening %s\n", 1168fe567363Smrg buffer); 116973143b9aSmrg 117073143b9aSmrg if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) 117173143b9aSmrg { 117273143b9aSmrg if (trans->flags & TRANS_DISABLED) 117373143b9aSmrg continue; 117473143b9aSmrg 1175fe567363Smrg prmsg (1, 117673143b9aSmrg "MakeAllCOTSServerListeners: failed to open listener for %s\n", 1177fe567363Smrg trans->TransName); 117873143b9aSmrg continue; 117973143b9aSmrg } 118073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 118173143b9aSmrg if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX 118273143b9aSmrg && ipv6_succ)) 118373143b9aSmrg flags |= ADDR_IN_USE_ALLOWED; 118473143b9aSmrg#endif 118573143b9aSmrg 118673143b9aSmrg if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) 118773143b9aSmrg { 1188e45ace2bSmrg if (*partial != 0) 1189e45ace2bSmrg continue; 1190e45ace2bSmrg 119173143b9aSmrg if (status == TRANS_ADDR_IN_USE) 119273143b9aSmrg { 119373143b9aSmrg /* 119473143b9aSmrg * We failed to bind to the specified address because the 119573143b9aSmrg * address is in use. It must be that a server is already 119673143b9aSmrg * running at this address, and this function should fail. 119773143b9aSmrg */ 119873143b9aSmrg 1199fe567363Smrg prmsg (1, 1200fe567363Smrg "MakeAllCOTSServerListeners: server already running\n"); 120173143b9aSmrg 120273143b9aSmrg for (j = 0; j < *count_ret; j++) 120394f982dbSmrg if (temp_ciptrs[j] != NULL) 120494f982dbSmrg TRANS(Close) (temp_ciptrs[j]); 120573143b9aSmrg 120673143b9aSmrg *count_ret = 0; 120773143b9aSmrg *ciptrs_ret = NULL; 120873143b9aSmrg *partial = 0; 120973143b9aSmrg return -1; 121073143b9aSmrg } 121173143b9aSmrg else 121273143b9aSmrg { 1213fe567363Smrg prmsg (1, 121473143b9aSmrg "MakeAllCOTSServerListeners: failed to create listener for %s\n", 1215fe567363Smrg trans->TransName); 121673143b9aSmrg 121773143b9aSmrg continue; 121873143b9aSmrg } 121973143b9aSmrg } 122073143b9aSmrg 122173143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 122273143b9aSmrg if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) 122373143b9aSmrg ipv6_succ = 1; 122473143b9aSmrg#endif 1225fe567363Smrg 1226fe567363Smrg prmsg (5, 122773143b9aSmrg "MakeAllCOTSServerListeners: opened listener for %s, %d\n", 1228fe567363Smrg trans->TransName, ciptr->fd); 122973143b9aSmrg 123073143b9aSmrg temp_ciptrs[*count_ret] = ciptr; 123173143b9aSmrg (*count_ret)++; 123273143b9aSmrg } 123373143b9aSmrg 123473143b9aSmrg *partial = (*count_ret < complete_network_count()); 123573143b9aSmrg 1236fe567363Smrg prmsg (5, 123773143b9aSmrg "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", 123873143b9aSmrg *partial, *count_ret, complete_network_count()); 123973143b9aSmrg 124073143b9aSmrg if (*count_ret > 0) 124173143b9aSmrg { 1242fe567363Smrg if ((*ciptrs_ret = malloc ( 124373143b9aSmrg *count_ret * sizeof (XtransConnInfo))) == NULL) 124473143b9aSmrg { 124573143b9aSmrg return -1; 124673143b9aSmrg } 124773143b9aSmrg 124894f982dbSmrg for (int i = 0; i < *count_ret; i++) 124973143b9aSmrg { 125073143b9aSmrg (*ciptrs_ret)[i] = temp_ciptrs[i]; 125173143b9aSmrg } 125273143b9aSmrg } 125373143b9aSmrg else 125473143b9aSmrg *ciptrs_ret = NULL; 1255fe567363Smrg 125673143b9aSmrg return 0; 125773143b9aSmrg} 125873143b9aSmrg 125973143b9aSmrg#endif /* TRANS_SERVER */ 126073143b9aSmrg 126173143b9aSmrg 126273143b9aSmrg 126373143b9aSmrg/* 126473143b9aSmrg * These routines are not part of the X Transport Interface, but they 126573143b9aSmrg * may be used by it. 126673143b9aSmrg */ 126773143b9aSmrg 126873143b9aSmrg 12693d2ed3e3Smrg#ifdef WIN32 127073143b9aSmrg 127173143b9aSmrg/* 127273143b9aSmrg * emulate readv 127373143b9aSmrg */ 127473143b9aSmrg 127573143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 127673143b9aSmrg 127773143b9aSmrg{ 127873143b9aSmrg int i, len, total; 127973143b9aSmrg char *base; 128073143b9aSmrg 128173143b9aSmrg ESET(0); 128273143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 128373143b9aSmrg len = iov->iov_len; 128473143b9aSmrg base = iov->iov_base; 128573143b9aSmrg while (len > 0) { 128673143b9aSmrg register int nbytes; 128773143b9aSmrg nbytes = TRANS(Read) (ciptr, base, len); 128873143b9aSmrg if (nbytes < 0 && total == 0) return -1; 128973143b9aSmrg if (nbytes <= 0) return total; 129073143b9aSmrg ESET(0); 129173143b9aSmrg len -= nbytes; 129273143b9aSmrg total += nbytes; 129373143b9aSmrg base += nbytes; 129473143b9aSmrg } 129573143b9aSmrg } 129673143b9aSmrg return total; 129773143b9aSmrg} 129873143b9aSmrg 129973143b9aSmrg 130073143b9aSmrg/* 130173143b9aSmrg * emulate writev 130273143b9aSmrg */ 130373143b9aSmrg 130473143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 130573143b9aSmrg 130673143b9aSmrg{ 130773143b9aSmrg int i, len, total; 130873143b9aSmrg char *base; 130973143b9aSmrg 131073143b9aSmrg ESET(0); 131173143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 131273143b9aSmrg len = iov->iov_len; 131373143b9aSmrg base = iov->iov_base; 131473143b9aSmrg while (len > 0) { 131573143b9aSmrg register int nbytes; 131673143b9aSmrg nbytes = TRANS(Write) (ciptr, base, len); 131773143b9aSmrg if (nbytes < 0 && total == 0) return -1; 131873143b9aSmrg if (nbytes <= 0) return total; 131973143b9aSmrg ESET(0); 132073143b9aSmrg len -= nbytes; 132173143b9aSmrg total += nbytes; 132273143b9aSmrg base += nbytes; 132373143b9aSmrg } 132473143b9aSmrg } 132573143b9aSmrg return total; 132673143b9aSmrg} 132773143b9aSmrg 13283d2ed3e3Smrg#endif /* WIN32 */ 132973143b9aSmrg 133073143b9aSmrg 1331e45ace2bSmrg#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__SVR4) 133273143b9aSmrg#ifndef NEED_UTSNAME 133373143b9aSmrg#define NEED_UTSNAME 133473143b9aSmrg#endif 133573143b9aSmrg#include <sys/utsname.h> 133673143b9aSmrg#endif 133773143b9aSmrg 133873143b9aSmrg/* 133973143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing. 134073143b9aSmrg */ 134173143b9aSmrg 134273143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen) 134373143b9aSmrg 134473143b9aSmrg{ 134573143b9aSmrg int len; 134673143b9aSmrg 134773143b9aSmrg#ifdef NEED_UTSNAME 134873143b9aSmrg struct utsname name; 134973143b9aSmrg 135073143b9aSmrg uname (&name); 135173143b9aSmrg len = strlen (name.nodename); 135273143b9aSmrg if (len >= maxlen) len = maxlen - 1; 135394f982dbSmrg memcpy (buf, name.nodename, len); 135473143b9aSmrg buf[len] = '\0'; 135573143b9aSmrg#else 135673143b9aSmrg buf[0] = '\0'; 135773143b9aSmrg (void) gethostname (buf, maxlen); 135873143b9aSmrg buf [maxlen - 1] = '\0'; 135973143b9aSmrg len = strlen(buf); 136073143b9aSmrg#endif /* NEED_UTSNAME */ 136173143b9aSmrg return len; 136273143b9aSmrg} 1363