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 85ac57ed83Smrg#if defined(IPv6) && !defined(AF_INET6) 86ac57ed83Smrg#error "Cannot build IPv6 support without AF_INET6" 87ac57ed83Smrg#endif 8873143b9aSmrg 8973143b9aSmrgstatic 9073143b9aSmrgXtransport_table Xtransports[] = { 9173143b9aSmrg#if defined(TCPCONN) 9273143b9aSmrg { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, 93ac57ed83Smrg#if defined(IPv6) 9473143b9aSmrg { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, 9573143b9aSmrg#endif /* IPv6 */ 9673143b9aSmrg { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, 9773143b9aSmrg#endif /* TCPCONN */ 9873143b9aSmrg#if defined(UNIXCONN) 9973143b9aSmrg#if !defined(LOCALCONN) 10073143b9aSmrg { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX }, 10173143b9aSmrg#endif /* !LOCALCONN */ 10273143b9aSmrg { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, 10373143b9aSmrg#endif /* UNIXCONN */ 10473143b9aSmrg#if defined(LOCALCONN) 10573143b9aSmrg { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, 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 */ 11273143b9aSmrg#endif /* LOCALCONN */ 11373143b9aSmrg}; 11473143b9aSmrg 11573143b9aSmrg#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) 11673143b9aSmrg 11773143b9aSmrg 11873143b9aSmrg#ifdef WIN32 11973143b9aSmrg#define ioctl ioctlsocket 12073143b9aSmrg#endif 12173143b9aSmrg 12273143b9aSmrg 12373143b9aSmrg 12473143b9aSmrg/* 12573143b9aSmrg * These are a few utility function used by the public interface functions. 12673143b9aSmrg */ 12773143b9aSmrg 12873143b9aSmrgvoid 12973143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr) 13073143b9aSmrg 13173143b9aSmrg{ 132ac57ed83Smrg prmsg (3,"FreeConnInfo(%p)\n", (void *) ciptr); 13373143b9aSmrg 13473143b9aSmrg if (ciptr->addr) 135fe567363Smrg free (ciptr->addr); 13673143b9aSmrg 13773143b9aSmrg if (ciptr->peeraddr) 138fe567363Smrg free (ciptr->peeraddr); 13973143b9aSmrg 14073143b9aSmrg if (ciptr->port) 141fe567363Smrg free (ciptr->port); 14273143b9aSmrg 143fe567363Smrg free (ciptr); 14473143b9aSmrg} 14573143b9aSmrg 14673143b9aSmrg 14773143b9aSmrg#define PROTOBUFSIZE 20 14873143b9aSmrg 14973143b9aSmrgstatic Xtransport * 150fe567363SmrgTRANS(SelectTransport) (const char *protocol) 15173143b9aSmrg 15273143b9aSmrg{ 1533d2ed3e3Smrg#ifndef HAVE_STRCASECMP 15473143b9aSmrg char protobuf[PROTOBUFSIZE]; 1553d2ed3e3Smrg#endif 15673143b9aSmrg 157fe567363Smrg prmsg (3,"SelectTransport(%s)\n", protocol); 15873143b9aSmrg 1593d2ed3e3Smrg#ifndef HAVE_STRCASECMP 16073143b9aSmrg /* 16173143b9aSmrg * Force Protocol to be lowercase as a way of doing 16273143b9aSmrg * a case insensitive match. 16373143b9aSmrg */ 16473143b9aSmrg 16573143b9aSmrg strncpy (protobuf, protocol, PROTOBUFSIZE - 1); 16673143b9aSmrg protobuf[PROTOBUFSIZE-1] = '\0'; 16773143b9aSmrg 16894f982dbSmrg for (unsigned int i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) 1698a0d9095Smrg if (isupper ((unsigned char)protobuf[i])) 1708a0d9095Smrg protobuf[i] = tolower ((unsigned char)protobuf[i]); 1713d2ed3e3Smrg#endif 17273143b9aSmrg 17373143b9aSmrg /* Look at all of the configured protocols */ 17473143b9aSmrg 17594f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 17673143b9aSmrg { 1773d2ed3e3Smrg#ifndef HAVE_STRCASECMP 17873143b9aSmrg if (!strcmp (protobuf, Xtransports[i].transport->TransName)) 1793d2ed3e3Smrg#else 1803d2ed3e3Smrg if (!strcasecmp (protocol, Xtransports[i].transport->TransName)) 1813d2ed3e3Smrg#endif 18273143b9aSmrg return Xtransports[i].transport; 18373143b9aSmrg } 18473143b9aSmrg 18573143b9aSmrg return NULL; 18673143b9aSmrg} 18773143b9aSmrg 188e45ace2bSmrgstatic int 1896a3641a6SsnjTRANS(ParseAddress) (const char *address, 1906a3641a6Ssnj char **protocol, char **host, char **port) 19173143b9aSmrg 19273143b9aSmrg{ 19373143b9aSmrg /* 19473143b9aSmrg * For the font library, the address is a string formatted 19573143b9aSmrg * as "protocol/host:port[/catalogue]". Note that the catologue 19673143b9aSmrg * is optional. At this time, the catologue info is ignored, but 19773143b9aSmrg * we have to parse it anyways. 19873143b9aSmrg * 19973143b9aSmrg * Other than fontlib, the address is a string formatted 20073143b9aSmrg * as "protocol/host:port". 20173143b9aSmrg * 20273143b9aSmrg * If the protocol part is missing, then assume TCP. 20373143b9aSmrg * If the protocol part and host part are missing, then assume local. 20473143b9aSmrg * If a "::" is found then assume DNET. 20573143b9aSmrg */ 20673143b9aSmrg 207e45ace2bSmrg char *mybuf, *tmpptr = NULL; 208e45ace2bSmrg const char *_protocol = NULL; 20994f982dbSmrg const char *_host, *_port; 21073143b9aSmrg char hostnamebuf[256]; 21194f982dbSmrg char *_host_buf; 21273143b9aSmrg int _host_len; 21373143b9aSmrg 214fe567363Smrg prmsg (3,"ParseAddress(%s)\n", address); 21573143b9aSmrg 216e45ace2bSmrg /* First, check for AF_UNIX socket paths */ 217e45ace2bSmrg if (address[0] == '/') { 218e45ace2bSmrg _protocol = "local"; 219e45ace2bSmrg _host = ""; 220e45ace2bSmrg _port = address; 221e45ace2bSmrg } else 222e45ace2bSmrg#ifdef HAVE_LAUNCHD 223e45ace2bSmrg /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ 224e45ace2bSmrg if(!strncmp(address,"local//",7)) { 225e45ace2bSmrg _protocol="local"; 226e45ace2bSmrg _host=""; 227e45ace2bSmrg _port=address+6; 228e45ace2bSmrg } else 229e45ace2bSmrg#endif 230e45ace2bSmrg if (!strncmp(address, "unix:", 5)) { 231e45ace2bSmrg _protocol = "local"; 232e45ace2bSmrg _host = ""; 233e45ace2bSmrg _port = address + 5; 234e45ace2bSmrg } 235e45ace2bSmrg if (_protocol) 236e45ace2bSmrg goto done_parsing; 237e45ace2bSmrg 23873143b9aSmrg /* Copy the string so it can be changed */ 23973143b9aSmrg 240fe567363Smrg tmpptr = mybuf = strdup (address); 24173143b9aSmrg 24273143b9aSmrg /* Parse the string to get each component */ 243fe567363Smrg 24473143b9aSmrg /* Get the protocol part */ 24573143b9aSmrg 24673143b9aSmrg _protocol = mybuf; 24773143b9aSmrg 24873143b9aSmrg 24994f982dbSmrg if ((mybuf == NULL) || 25094f982dbSmrg ( ((mybuf = strchr (mybuf, '/')) == NULL) && 25194f982dbSmrg ((mybuf = strrchr (tmpptr, ':')) == NULL) ) ) 25294f982dbSmrg { 25373143b9aSmrg /* address is in a bad format */ 25473143b9aSmrg *protocol = NULL; 25573143b9aSmrg *host = NULL; 25673143b9aSmrg *port = NULL; 257fe567363Smrg free (tmpptr); 25873143b9aSmrg return 0; 25973143b9aSmrg } 26073143b9aSmrg 26173143b9aSmrg if (*mybuf == ':') 26273143b9aSmrg { 26373143b9aSmrg /* 26473143b9aSmrg * If there is a hostname, then assume tcp, otherwise 26573143b9aSmrg * it must be local. 26673143b9aSmrg */ 26773143b9aSmrg if (mybuf == tmpptr) 26873143b9aSmrg { 26973143b9aSmrg /* There is neither a protocol or host specified */ 27073143b9aSmrg _protocol = "local"; 27173143b9aSmrg } 27273143b9aSmrg else 27373143b9aSmrg { 27473143b9aSmrg /* There is a hostname specified */ 27573143b9aSmrg _protocol = "tcp"; 276e45ace2bSmrg mybuf = tmpptr; /* reset to the beginning of the host ptr */ 27773143b9aSmrg } 27873143b9aSmrg } 27973143b9aSmrg else 28073143b9aSmrg { 28173143b9aSmrg /* *mybuf == '/' */ 28273143b9aSmrg 28373143b9aSmrg *mybuf ++= '\0'; /* put a null at the end of the protocol */ 28473143b9aSmrg 28573143b9aSmrg if (strlen(_protocol) == 0) 28673143b9aSmrg { 28773143b9aSmrg /* 28873143b9aSmrg * If there is a hostname, then assume tcp, otherwise 28973143b9aSmrg * it must be local. 29073143b9aSmrg */ 29173143b9aSmrg if (*mybuf != ':') 29273143b9aSmrg _protocol = "tcp"; 29373143b9aSmrg else 29473143b9aSmrg _protocol = "local"; 29573143b9aSmrg } 29673143b9aSmrg } 29773143b9aSmrg 29873143b9aSmrg /* Get the host part */ 29973143b9aSmrg 30094f982dbSmrg _host = _host_buf = mybuf; 30173143b9aSmrg 30273143b9aSmrg if ((mybuf = strrchr (mybuf,':')) == NULL) 30373143b9aSmrg { 30473143b9aSmrg *protocol = NULL; 30573143b9aSmrg *host = NULL; 30673143b9aSmrg *port = NULL; 307fe567363Smrg free (tmpptr); 30873143b9aSmrg return 0; 30973143b9aSmrg } 31073143b9aSmrg 31173143b9aSmrg *mybuf ++= '\0'; 31273143b9aSmrg 31373143b9aSmrg _host_len = strlen(_host); 31473143b9aSmrg if (_host_len == 0) 31573143b9aSmrg { 31673143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 31773143b9aSmrg _host = hostnamebuf; 31873143b9aSmrg } 319ac57ed83Smrg#ifdef IPv6 32073143b9aSmrg /* hostname in IPv6 [numeric_addr]:0 form? */ 321fe567363Smrg else if ( (_host_len > 3) && 32273143b9aSmrg ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) 32394f982dbSmrg && (_host_buf[0] == '[') && (_host_buf[_host_len - 1] == ']') ) { 32473143b9aSmrg struct sockaddr_in6 sin6; 32573143b9aSmrg 32694f982dbSmrg _host_buf[_host_len - 1] = '\0'; 32773143b9aSmrg 32873143b9aSmrg /* Verify address is valid IPv6 numeric form */ 32973143b9aSmrg if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { 33073143b9aSmrg /* It is. Use it as such. */ 33173143b9aSmrg _host++; 33273143b9aSmrg _protocol = "inet6"; 33373143b9aSmrg } else { 33473143b9aSmrg /* It's not, restore it just in case some other code can use it. */ 33594f982dbSmrg _host_buf[_host_len - 1] = ']'; 33673143b9aSmrg } 33773143b9aSmrg } 33873143b9aSmrg#endif 33973143b9aSmrg 34073143b9aSmrg 34173143b9aSmrg /* Get the port */ 34273143b9aSmrg 34373143b9aSmrg _port = mybuf; 34473143b9aSmrg 34573143b9aSmrg#if defined(FONT_t) || defined(FS_t) 34673143b9aSmrg /* 34773143b9aSmrg * Is there an optional catalogue list? 34873143b9aSmrg */ 34973143b9aSmrg 35073143b9aSmrg if ((mybuf = strchr (mybuf,'/')) != NULL) 35173143b9aSmrg *mybuf ++= '\0'; 35273143b9aSmrg 35373143b9aSmrg /* 35473143b9aSmrg * The rest, if any, is the (currently unused) catalogue list. 35573143b9aSmrg * 35673143b9aSmrg * _catalogue = mybuf; 35773143b9aSmrg */ 35873143b9aSmrg#endif 35973143b9aSmrg 360e45ace2bSmrgdone_parsing: 36173143b9aSmrg /* 36273143b9aSmrg * Now that we have all of the components, allocate new 36373143b9aSmrg * string space for them. 36473143b9aSmrg */ 36573143b9aSmrg 366fe567363Smrg if ((*protocol = strdup (_protocol)) == NULL) 36773143b9aSmrg { 36873143b9aSmrg /* Malloc failed */ 36973143b9aSmrg *port = NULL; 37073143b9aSmrg *host = NULL; 37173143b9aSmrg *protocol = NULL; 372fe567363Smrg free (tmpptr); 37373143b9aSmrg return 0; 37473143b9aSmrg } 37573143b9aSmrg 376fe567363Smrg if ((*host = strdup (_host)) == NULL) 37773143b9aSmrg { 37873143b9aSmrg /* Malloc failed */ 37973143b9aSmrg *port = NULL; 38073143b9aSmrg *host = NULL; 381fe567363Smrg free (*protocol); 38273143b9aSmrg *protocol = NULL; 383fe567363Smrg free (tmpptr); 38473143b9aSmrg return 0; 385fe567363Smrg } 38673143b9aSmrg 387fe567363Smrg if ((*port = strdup (_port)) == NULL) 38873143b9aSmrg { 38973143b9aSmrg /* Malloc failed */ 39073143b9aSmrg *port = NULL; 391fe567363Smrg free (*host); 39273143b9aSmrg *host = NULL; 393fe567363Smrg free (*protocol); 39473143b9aSmrg *protocol = NULL; 395fe567363Smrg free (tmpptr); 39673143b9aSmrg return 0; 39773143b9aSmrg } 39873143b9aSmrg 399fe567363Smrg free (tmpptr); 40073143b9aSmrg 40173143b9aSmrg return 1; 40273143b9aSmrg} 40373143b9aSmrg 40473143b9aSmrg 40573143b9aSmrg/* 40673143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only 40773143b9aSmrg * funny part about this is the type parameter which is used to decide which 40873143b9aSmrg * type of open to perform. 40973143b9aSmrg */ 41073143b9aSmrg 41173143b9aSmrgstatic XtransConnInfo 4126a3641a6SsnjTRANS(Open) (int type, const char *address) 41373143b9aSmrg 41473143b9aSmrg{ 41573143b9aSmrg char *protocol = NULL, *host = NULL, *port = NULL; 41673143b9aSmrg XtransConnInfo ciptr = NULL; 41773143b9aSmrg Xtransport *thistrans; 41873143b9aSmrg 419fe567363Smrg prmsg (2,"Open(%d,%s)\n", type, address); 42073143b9aSmrg 421fe567363Smrg#if defined(WIN32) && defined(TCPCONN) 42273143b9aSmrg if (TRANS(WSAStartup)()) 42373143b9aSmrg { 424fe567363Smrg prmsg (1,"Open: WSAStartup failed\n"); 42573143b9aSmrg return NULL; 42673143b9aSmrg } 42773143b9aSmrg#endif 42873143b9aSmrg 42973143b9aSmrg /* Parse the Address */ 43073143b9aSmrg 43173143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 43273143b9aSmrg { 433fe567363Smrg prmsg (1,"Open: Unable to Parse address %s\n", address); 43473143b9aSmrg return NULL; 43573143b9aSmrg } 43673143b9aSmrg 43773143b9aSmrg /* Determine the transport type */ 43873143b9aSmrg 43973143b9aSmrg if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) 44073143b9aSmrg { 441fe567363Smrg prmsg (1,"Open: Unable to find transport for %s\n", 442fe567363Smrg protocol); 44373143b9aSmrg 444fe567363Smrg free (protocol); 445fe567363Smrg free (host); 446fe567363Smrg free (port); 44773143b9aSmrg return NULL; 44873143b9aSmrg } 44973143b9aSmrg 45073143b9aSmrg /* Open the transport */ 45173143b9aSmrg 45273143b9aSmrg switch (type) 45373143b9aSmrg { 45473143b9aSmrg case XTRANS_OPEN_COTS_CLIENT: 45573143b9aSmrg#ifdef TRANS_CLIENT 45673143b9aSmrg ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); 45773143b9aSmrg#endif /* TRANS_CLIENT */ 45873143b9aSmrg break; 45973143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 46073143b9aSmrg#ifdef TRANS_SERVER 46173143b9aSmrg ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); 46273143b9aSmrg#endif /* TRANS_SERVER */ 46373143b9aSmrg break; 46473143b9aSmrg default: 465fe567363Smrg prmsg (1,"Open: Unknown Open type %d\n", type); 46673143b9aSmrg } 46773143b9aSmrg 46873143b9aSmrg if (ciptr == NULL) 46973143b9aSmrg { 470fe567363Smrg if (!(thistrans->flags & TRANS_DISABLED)) 47173143b9aSmrg { 472fe567363Smrg prmsg (1,"Open: transport open failed for %s/%s:%s\n", 47373143b9aSmrg protocol, host, port); 47473143b9aSmrg } 475fe567363Smrg free (protocol); 476fe567363Smrg free (host); 477fe567363Smrg free (port); 47873143b9aSmrg return NULL; 47973143b9aSmrg } 48073143b9aSmrg 48173143b9aSmrg ciptr->transptr = thistrans; 48273143b9aSmrg ciptr->port = port; /* We need this for TRANS(Reopen) */ 48373143b9aSmrg 484fe567363Smrg free (protocol); 485fe567363Smrg free (host); 48673143b9aSmrg 48773143b9aSmrg return ciptr; 48873143b9aSmrg} 48973143b9aSmrg 49073143b9aSmrg 49173143b9aSmrg#ifdef TRANS_REOPEN 49273143b9aSmrg 49373143b9aSmrg/* 49473143b9aSmrg * We might want to create an XtransConnInfo object based on a previously 49573143b9aSmrg * opened connection. For example, the font server may clone itself and 49673143b9aSmrg * pass file descriptors to the parent. 49773143b9aSmrg */ 49873143b9aSmrg 49973143b9aSmrgstatic XtransConnInfo 5006a3641a6SsnjTRANS(Reopen) (int type, int trans_id, int fd, const char *port) 50173143b9aSmrg 50273143b9aSmrg{ 50373143b9aSmrg XtransConnInfo ciptr = NULL; 50473143b9aSmrg Xtransport *thistrans = NULL; 50573143b9aSmrg char *save_port; 50673143b9aSmrg 507fe567363Smrg prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); 50873143b9aSmrg 50973143b9aSmrg /* Determine the transport type */ 51073143b9aSmrg 51194f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 51294f982dbSmrg { 51373143b9aSmrg if (Xtransports[i].transport_id == trans_id) 51473143b9aSmrg { 51573143b9aSmrg thistrans = Xtransports[i].transport; 51673143b9aSmrg break; 51773143b9aSmrg } 51894f982dbSmrg } 51973143b9aSmrg 52073143b9aSmrg if (thistrans == NULL) 52173143b9aSmrg { 522fe567363Smrg prmsg (1,"Reopen: Unable to find transport id %d\n", 523fe567363Smrg trans_id); 52473143b9aSmrg 52573143b9aSmrg return NULL; 52673143b9aSmrg } 52773143b9aSmrg 528fe567363Smrg if ((save_port = strdup (port)) == NULL) 52973143b9aSmrg { 530fe567363Smrg prmsg (1,"Reopen: Unable to malloc port string\n"); 53173143b9aSmrg 53273143b9aSmrg return NULL; 53373143b9aSmrg } 53473143b9aSmrg 53573143b9aSmrg /* Get a new XtransConnInfo object */ 53673143b9aSmrg 53773143b9aSmrg switch (type) 53873143b9aSmrg { 53973143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 54073143b9aSmrg ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); 54173143b9aSmrg break; 54273143b9aSmrg default: 543fe567363Smrg prmsg (1,"Reopen: Bad Open type %d\n", type); 54473143b9aSmrg } 54573143b9aSmrg 54673143b9aSmrg if (ciptr == NULL) 54773143b9aSmrg { 548fe567363Smrg prmsg (1,"Reopen: transport open failed\n"); 549fe567363Smrg free (save_port); 55073143b9aSmrg return NULL; 55173143b9aSmrg } 55273143b9aSmrg 55373143b9aSmrg ciptr->transptr = thistrans; 55473143b9aSmrg ciptr->port = save_port; 55573143b9aSmrg 55673143b9aSmrg return ciptr; 55773143b9aSmrg} 55873143b9aSmrg 55973143b9aSmrg#endif /* TRANS_REOPEN */ 56073143b9aSmrg 56173143b9aSmrg 56273143b9aSmrg 56373143b9aSmrg/* 56473143b9aSmrg * These are the public interfaces to this Transport interface. 56573143b9aSmrg * These are the only functions that should have knowledge of the transport 56673143b9aSmrg * table. 56773143b9aSmrg */ 56873143b9aSmrg 56973143b9aSmrg#ifdef TRANS_CLIENT 57073143b9aSmrg 57173143b9aSmrgXtransConnInfo 5726a3641a6SsnjTRANS(OpenCOTSClient) (const char *address) 57373143b9aSmrg 57473143b9aSmrg{ 575fe567363Smrg prmsg (2,"OpenCOTSClient(%s)\n", address); 57673143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); 57773143b9aSmrg} 57873143b9aSmrg 57973143b9aSmrg#endif /* TRANS_CLIENT */ 58073143b9aSmrg 58173143b9aSmrg 58273143b9aSmrg#ifdef TRANS_SERVER 58373143b9aSmrg 58473143b9aSmrgXtransConnInfo 5856a3641a6SsnjTRANS(OpenCOTSServer) (const char *address) 58673143b9aSmrg 58773143b9aSmrg{ 588fe567363Smrg prmsg (2,"OpenCOTSServer(%s)\n", address); 58973143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); 59073143b9aSmrg} 59173143b9aSmrg 59273143b9aSmrg#endif /* TRANS_SERVER */ 59373143b9aSmrg 59473143b9aSmrg 59573143b9aSmrg#ifdef TRANS_REOPEN 59673143b9aSmrg 59773143b9aSmrgXtransConnInfo 5986a3641a6SsnjTRANS(ReopenCOTSServer) (int trans_id, int fd, const char *port) 59973143b9aSmrg 60073143b9aSmrg{ 601fe567363Smrg prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); 60273143b9aSmrg return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); 60373143b9aSmrg} 60473143b9aSmrg 60573143b9aSmrgint 606fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr, 60773143b9aSmrg int *trans_id, int *fd, char **port) 60873143b9aSmrg 60973143b9aSmrg{ 61094f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 61194f982dbSmrg { 61273143b9aSmrg if (Xtransports[i].transport == ciptr->transptr) 61373143b9aSmrg { 61473143b9aSmrg *trans_id = Xtransports[i].transport_id; 61573143b9aSmrg *fd = ciptr->fd; 61673143b9aSmrg 617fe567363Smrg if ((*port = strdup (ciptr->port)) == NULL) 61873143b9aSmrg return 0; 61973143b9aSmrg else 62073143b9aSmrg return 1; 62173143b9aSmrg } 62294f982dbSmrg } 62373143b9aSmrg 62473143b9aSmrg return 0; 62573143b9aSmrg} 62673143b9aSmrg 62773143b9aSmrg#endif /* TRANS_REOPEN */ 62873143b9aSmrg 62973143b9aSmrg 63073143b9aSmrgint 63173143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) 63273143b9aSmrg 63373143b9aSmrg{ 63473143b9aSmrg int fd = ciptr->fd; 63573143b9aSmrg int ret = 0; 63673143b9aSmrg 637fe567363Smrg prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg); 63873143b9aSmrg 63973143b9aSmrg /* 64073143b9aSmrg * For now, all transport type use the same stuff for setting options. 64173143b9aSmrg * As long as this is true, we can put the common code here. Once a more 64273143b9aSmrg * complicated transport such as shared memory or an OSI implementation 64373143b9aSmrg * that uses the session and application libraries is implemented, this 64473143b9aSmrg * code may have to move to a transport dependent function. 64573143b9aSmrg * 64673143b9aSmrg * ret = ciptr->transptr->SetOption (ciptr, option, arg); 64773143b9aSmrg */ 64873143b9aSmrg 64973143b9aSmrg switch (option) 65073143b9aSmrg { 65173143b9aSmrg case TRANS_NONBLOCKING: 65273143b9aSmrg switch (arg) 65373143b9aSmrg { 65473143b9aSmrg case 0: 65573143b9aSmrg /* Set to blocking mode */ 65673143b9aSmrg break; 65773143b9aSmrg case 1: /* Set to non-blocking mode */ 65873143b9aSmrg 659e45ace2bSmrg#if defined(O_NONBLOCK) 66073143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 66173143b9aSmrg if (ret != -1) 66273143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); 66373143b9aSmrg#else 66473143b9aSmrg#ifdef FIOSNBIO 66573143b9aSmrg { 66673143b9aSmrg int arg; 66773143b9aSmrg arg = 1; 66873143b9aSmrg ret = ioctl (fd, FIOSNBIO, &arg); 66973143b9aSmrg } 67073143b9aSmrg#else 671fe567363Smrg#if defined(WIN32) 67273143b9aSmrg { 67373143b9aSmrg#ifdef WIN32 67473143b9aSmrg u_long arg; 67573143b9aSmrg#else 67673143b9aSmrg int arg; 67773143b9aSmrg#endif 67873143b9aSmrg arg = 1; 67973143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail 68073143b9aSmrg * eventually with EWOULDBLOCK */ 68173143b9aSmrg ret = ioctl (fd, FIONBIO, &arg); 68273143b9aSmrg } 68373143b9aSmrg#else 68473143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 68573143b9aSmrg#ifdef FNDELAY 68673143b9aSmrg ret = fcntl (fd, F_SETFL, ret | FNDELAY); 68773143b9aSmrg#else 68873143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NDELAY); 68973143b9aSmrg#endif 69073143b9aSmrg#endif /* AIXV3 || uniosu */ 69173143b9aSmrg#endif /* FIOSNBIO */ 69273143b9aSmrg#endif /* O_NONBLOCK */ 69373143b9aSmrg break; 69473143b9aSmrg default: 69573143b9aSmrg /* Unknown option */ 69673143b9aSmrg break; 69773143b9aSmrg } 69873143b9aSmrg break; 69973143b9aSmrg case TRANS_CLOSEONEXEC: 70073143b9aSmrg#ifdef F_SETFD 70173143b9aSmrg#ifdef FD_CLOEXEC 70273143b9aSmrg ret = fcntl (fd, F_SETFD, FD_CLOEXEC); 70373143b9aSmrg#else 70473143b9aSmrg ret = fcntl (fd, F_SETFD, 1); 70573143b9aSmrg#endif /* FD_CLOEXEC */ 70673143b9aSmrg#endif /* F_SETFD */ 70773143b9aSmrg break; 70873143b9aSmrg } 709fe567363Smrg 71073143b9aSmrg return ret; 71173143b9aSmrg} 71273143b9aSmrg 71373143b9aSmrg#ifdef TRANS_SERVER 71473143b9aSmrg 71573143b9aSmrgint 7166a3641a6SsnjTRANS(CreateListener) (XtransConnInfo ciptr, const char *port, unsigned int flags) 71773143b9aSmrg 71873143b9aSmrg{ 71973143b9aSmrg return ciptr->transptr->CreateListener (ciptr, port, flags); 72073143b9aSmrg} 72173143b9aSmrg 72275ebec6dSmrgint 72375ebec6dSmrgTRANS(Received) (const char * protocol) 72475ebec6dSmrg 72575ebec6dSmrg{ 72675ebec6dSmrg Xtransport *trans; 72775ebec6dSmrg int i = 0, ret = 0; 72875ebec6dSmrg 72975ebec6dSmrg prmsg (5, "Received(%s)\n", protocol); 73075ebec6dSmrg 73175ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 73275ebec6dSmrg { 73375ebec6dSmrg prmsg (1,"Received: unable to find transport: %s\n", 73475ebec6dSmrg protocol); 73575ebec6dSmrg 73675ebec6dSmrg return -1; 73775ebec6dSmrg } 73875ebec6dSmrg if (trans->flags & TRANS_ALIAS) { 73975ebec6dSmrg if (trans->nolisten) 74075ebec6dSmrg while (trans->nolisten[i]) { 74175ebec6dSmrg ret |= TRANS(Received)(trans->nolisten[i]); 74275ebec6dSmrg i++; 74375ebec6dSmrg } 74475ebec6dSmrg } 74575ebec6dSmrg 74675ebec6dSmrg trans->flags |= TRANS_RECEIVED; 74775ebec6dSmrg return ret; 74875ebec6dSmrg} 74975ebec6dSmrg 75073143b9aSmrgint 751fe567363SmrgTRANS(NoListen) (const char * protocol) 752fe567363Smrg 75373143b9aSmrg{ 75473143b9aSmrg Xtransport *trans; 75573143b9aSmrg int i = 0, ret = 0; 756fe567363Smrg 757fe567363Smrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 75873143b9aSmrg { 759fe567363Smrg prmsg (1,"TransNoListen: unable to find transport: %s\n", 760fe567363Smrg protocol); 76173143b9aSmrg 76273143b9aSmrg return -1; 76373143b9aSmrg } 76473143b9aSmrg if (trans->flags & TRANS_ALIAS) { 76573143b9aSmrg if (trans->nolisten) 76673143b9aSmrg while (trans->nolisten[i]) { 76773143b9aSmrg ret |= TRANS(NoListen)(trans->nolisten[i]); 76873143b9aSmrg i++; 76973143b9aSmrg } 77073143b9aSmrg } 77173143b9aSmrg 77273143b9aSmrg trans->flags |= TRANS_NOLISTEN; 77373143b9aSmrg return ret; 77473143b9aSmrg} 77573143b9aSmrg 7766a3641a6Ssnjint 7776a3641a6SsnjTRANS(Listen) (const char * protocol) 7786a3641a6Ssnj{ 7796a3641a6Ssnj Xtransport *trans; 7806a3641a6Ssnj int i = 0, ret = 0; 7816a3641a6Ssnj 7826a3641a6Ssnj if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 7836a3641a6Ssnj { 7846a3641a6Ssnj prmsg (1,"TransListen: unable to find transport: %s\n", 7856a3641a6Ssnj protocol); 7866a3641a6Ssnj 7876a3641a6Ssnj return -1; 7886a3641a6Ssnj } 7896a3641a6Ssnj if (trans->flags & TRANS_ALIAS) { 7906a3641a6Ssnj if (trans->nolisten) 7916a3641a6Ssnj while (trans->nolisten[i]) { 7926a3641a6Ssnj ret |= TRANS(Listen)(trans->nolisten[i]); 7936a3641a6Ssnj i++; 7946a3641a6Ssnj } 7956a3641a6Ssnj } 7966a3641a6Ssnj 7976a3641a6Ssnj trans->flags &= ~TRANS_NOLISTEN; 7986a3641a6Ssnj return ret; 7996a3641a6Ssnj} 8006a3641a6Ssnj 80175ebec6dSmrgint 80275ebec6dSmrgTRANS(IsListening) (const char * protocol) 80375ebec6dSmrg{ 80475ebec6dSmrg Xtransport *trans; 80575ebec6dSmrg 80675ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 80775ebec6dSmrg { 80875ebec6dSmrg prmsg (1,"TransIsListening: unable to find transport: %s\n", 80975ebec6dSmrg protocol); 81075ebec6dSmrg 81175ebec6dSmrg return 0; 81275ebec6dSmrg } 81375ebec6dSmrg 81475ebec6dSmrg return !(trans->flags & TRANS_NOLISTEN); 81575ebec6dSmrg} 81675ebec6dSmrg 81773143b9aSmrgint 81873143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr) 81973143b9aSmrg 82073143b9aSmrg{ 82173143b9aSmrg if (ciptr->transptr->ResetListener) 82273143b9aSmrg return ciptr->transptr->ResetListener (ciptr); 82373143b9aSmrg else 82473143b9aSmrg return TRANS_RESET_NOOP; 82573143b9aSmrg} 82673143b9aSmrg 82773143b9aSmrg 82873143b9aSmrgXtransConnInfo 82973143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status) 83073143b9aSmrg 83173143b9aSmrg{ 83273143b9aSmrg XtransConnInfo newciptr; 83373143b9aSmrg 834fe567363Smrg prmsg (2,"Accept(%d)\n", ciptr->fd); 83573143b9aSmrg 83673143b9aSmrg newciptr = ciptr->transptr->Accept (ciptr, status); 83773143b9aSmrg 83873143b9aSmrg if (newciptr) 83973143b9aSmrg newciptr->transptr = ciptr->transptr; 84073143b9aSmrg 84173143b9aSmrg return newciptr; 84273143b9aSmrg} 84373143b9aSmrg 84473143b9aSmrg#endif /* TRANS_SERVER */ 84573143b9aSmrg 84673143b9aSmrg 84773143b9aSmrg#ifdef TRANS_CLIENT 84873143b9aSmrg 84973143b9aSmrgint 8506a3641a6SsnjTRANS(Connect) (XtransConnInfo ciptr, const char *address) 85173143b9aSmrg 85273143b9aSmrg{ 85373143b9aSmrg char *protocol; 85473143b9aSmrg char *host; 85573143b9aSmrg char *port; 85673143b9aSmrg int ret; 85773143b9aSmrg 858fe567363Smrg prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address); 85973143b9aSmrg 86073143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 86173143b9aSmrg { 862fe567363Smrg prmsg (1,"Connect: Unable to Parse address %s\n", 863fe567363Smrg address); 86473143b9aSmrg return -1; 86573143b9aSmrg } 86673143b9aSmrg 86773143b9aSmrg#ifdef HAVE_LAUNCHD 8688d4c0f7bSmrg if (!host) host=strdup(""); 86973143b9aSmrg#endif 87073143b9aSmrg 87173143b9aSmrg if (!port || !*port) 87273143b9aSmrg { 873fe567363Smrg prmsg (1,"Connect: Missing port specification in %s\n", 874fe567363Smrg address); 875fe567363Smrg if (protocol) free (protocol); 876fe567363Smrg if (host) free (host); 87773143b9aSmrg return -1; 87873143b9aSmrg } 87973143b9aSmrg 88073143b9aSmrg ret = ciptr->transptr->Connect (ciptr, host, port); 88173143b9aSmrg 882fe567363Smrg if (protocol) free (protocol); 883fe567363Smrg if (host) free (host); 884fe567363Smrg if (port) free (port); 885fe567363Smrg 88673143b9aSmrg return ret; 88773143b9aSmrg} 88873143b9aSmrg 88973143b9aSmrg#endif /* TRANS_CLIENT */ 89073143b9aSmrg 89173143b9aSmrg 89273143b9aSmrgint 89373143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 89473143b9aSmrg 89573143b9aSmrg{ 89673143b9aSmrg return ciptr->transptr->BytesReadable (ciptr, pend); 89773143b9aSmrg} 89873143b9aSmrg 89973143b9aSmrgint 90073143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size) 90173143b9aSmrg 90273143b9aSmrg{ 90373143b9aSmrg return ciptr->transptr->Read (ciptr, buf, size); 90473143b9aSmrg} 90573143b9aSmrg 90673143b9aSmrgint 907ac57ed83SmrgTRANS(Write) (XtransConnInfo ciptr, const char *buf, int size) 90873143b9aSmrg 90973143b9aSmrg{ 91073143b9aSmrg return ciptr->transptr->Write (ciptr, buf, size); 91173143b9aSmrg} 91273143b9aSmrg 91373143b9aSmrgint 91473143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) 91573143b9aSmrg 91673143b9aSmrg{ 91773143b9aSmrg return ciptr->transptr->Readv (ciptr, buf, size); 91873143b9aSmrg} 91973143b9aSmrg 92073143b9aSmrgint 92173143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) 92273143b9aSmrg 92373143b9aSmrg{ 92473143b9aSmrg return ciptr->transptr->Writev (ciptr, buf, size); 92573143b9aSmrg} 92673143b9aSmrg 92775ebec6dSmrg#if XTRANS_SEND_FDS 92875ebec6dSmrgint 92975ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) 93075ebec6dSmrg{ 93175ebec6dSmrg return ciptr->transptr->SendFd(ciptr, fd, do_close); 93275ebec6dSmrg} 93375ebec6dSmrg 93475ebec6dSmrgint 93575ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr) 93675ebec6dSmrg{ 93775ebec6dSmrg return ciptr->transptr->RecvFd(ciptr); 93875ebec6dSmrg} 93975ebec6dSmrg#endif 94075ebec6dSmrg 94173143b9aSmrgint 94273143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr) 94373143b9aSmrg 94473143b9aSmrg{ 94573143b9aSmrg return ciptr->transptr->Disconnect (ciptr); 94673143b9aSmrg} 94773143b9aSmrg 94873143b9aSmrgint 94973143b9aSmrgTRANS(Close) (XtransConnInfo ciptr) 95073143b9aSmrg 95173143b9aSmrg{ 95273143b9aSmrg int ret; 95373143b9aSmrg 954fe567363Smrg prmsg (2,"Close(%d)\n", ciptr->fd); 95573143b9aSmrg 95673143b9aSmrg ret = ciptr->transptr->Close (ciptr); 95773143b9aSmrg 95873143b9aSmrg TRANS(FreeConnInfo) (ciptr); 95973143b9aSmrg 96073143b9aSmrg return ret; 96173143b9aSmrg} 96273143b9aSmrg 96373143b9aSmrgint 96473143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr) 96573143b9aSmrg 96673143b9aSmrg{ 96773143b9aSmrg int ret; 96873143b9aSmrg 969fe567363Smrg prmsg (2,"CloseForCloning(%d)\n", ciptr->fd); 97073143b9aSmrg 97173143b9aSmrg ret = ciptr->transptr->CloseForCloning (ciptr); 97273143b9aSmrg 97373143b9aSmrg TRANS(FreeConnInfo) (ciptr); 97473143b9aSmrg 97573143b9aSmrg return ret; 97673143b9aSmrg} 97773143b9aSmrg 97873143b9aSmrgint 97973143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr) 98073143b9aSmrg 98173143b9aSmrg{ 98273143b9aSmrg return (ciptr->family == AF_UNIX); 98373143b9aSmrg} 98473143b9aSmrg 98573143b9aSmrgint 986fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 98773143b9aSmrg Xtransaddr **addrp) 98873143b9aSmrg 98973143b9aSmrg{ 990fe567363Smrg prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd); 99173143b9aSmrg 99273143b9aSmrg *familyp = ciptr->family; 99373143b9aSmrg *addrlenp = ciptr->peeraddrlen; 99473143b9aSmrg 995fe567363Smrg if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL) 99673143b9aSmrg { 997fe567363Smrg prmsg (1,"GetPeerAddr: malloc failed\n"); 99873143b9aSmrg return -1; 99973143b9aSmrg } 100073143b9aSmrg memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); 100173143b9aSmrg 100273143b9aSmrg return 0; 100373143b9aSmrg} 100473143b9aSmrg 100573143b9aSmrg 100673143b9aSmrgint 100773143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr) 100873143b9aSmrg 100973143b9aSmrg{ 101073143b9aSmrg return ciptr->fd; 101173143b9aSmrg} 101273143b9aSmrg 101373143b9aSmrg 101473143b9aSmrg/* 101573143b9aSmrg * These functions are really utility functions, but they require knowledge 101673143b9aSmrg * of the internal data structures, so they have to be part of the Transport 1017e45ace2bSmrg * Independent API. 101873143b9aSmrg */ 101973143b9aSmrg 102073143b9aSmrg#ifdef TRANS_SERVER 102173143b9aSmrg 102273143b9aSmrgstatic int 102373143b9aSmrgcomplete_network_count (void) 102473143b9aSmrg 102573143b9aSmrg{ 102673143b9aSmrg int count = 0; 102773143b9aSmrg int found_local = 0; 102873143b9aSmrg 102973143b9aSmrg /* 103073143b9aSmrg * For a complete network, we only need one LOCALCONN transport to work 103173143b9aSmrg */ 103273143b9aSmrg 103394f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 103473143b9aSmrg { 103573143b9aSmrg if (Xtransports[i].transport->flags & TRANS_ALIAS 103673143b9aSmrg || Xtransports[i].transport->flags & TRANS_NOLISTEN) 103773143b9aSmrg continue; 103873143b9aSmrg 103973143b9aSmrg if (Xtransports[i].transport->flags & TRANS_LOCAL) 104073143b9aSmrg found_local = 1; 104173143b9aSmrg else 104273143b9aSmrg count++; 104373143b9aSmrg } 104473143b9aSmrg 104573143b9aSmrg return (count + found_local); 104673143b9aSmrg} 104773143b9aSmrg 104873143b9aSmrg 104975ebec6dSmrgstatic int 10506a3641a6Ssnjreceive_listening_fds(const char* port, XtransConnInfo* temp_ciptrs, 10516a3641a6Ssnj int* count_ret) 105275ebec6dSmrg 105375ebec6dSmrg{ 105475ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON 105575ebec6dSmrg XtransConnInfo ciptr; 105675ebec6dSmrg int i, systemd_listen_fds; 105775ebec6dSmrg 105875ebec6dSmrg systemd_listen_fds = sd_listen_fds(1); 105975ebec6dSmrg if (systemd_listen_fds < 0) 106075ebec6dSmrg { 106175ebec6dSmrg prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n", 106275ebec6dSmrg strerror(-systemd_listen_fds)); 106375ebec6dSmrg return -1; 106475ebec6dSmrg } 106575ebec6dSmrg 106694f982dbSmrg for (i = 0; i < systemd_listen_fds && *count_ret < (int)NUMTRANS; i++) 106775ebec6dSmrg { 106875ebec6dSmrg struct sockaddr_storage a; 106975ebec6dSmrg int ti; 107075ebec6dSmrg const char* tn; 107175ebec6dSmrg socklen_t al; 107275ebec6dSmrg 107375ebec6dSmrg al = sizeof(a); 107475ebec6dSmrg if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) { 107575ebec6dSmrg prmsg (1, "receive_listening_fds: getsockname error: %s\n", 107675ebec6dSmrg strerror(errno)); 107775ebec6dSmrg return -1; 107875ebec6dSmrg } 107975ebec6dSmrg 108075ebec6dSmrg switch (a.ss_family) 108175ebec6dSmrg { 108275ebec6dSmrg case AF_UNIX: 108375ebec6dSmrg ti = TRANS_SOCKET_UNIX_INDEX; 108475ebec6dSmrg if (*((struct sockaddr_un*)&a)->sun_path == '\0' && 108575ebec6dSmrg al > sizeof(sa_family_t)) 108675ebec6dSmrg tn = "local"; 108775ebec6dSmrg else 108875ebec6dSmrg tn = "unix"; 108975ebec6dSmrg break; 109075ebec6dSmrg case AF_INET: 109175ebec6dSmrg ti = TRANS_SOCKET_INET_INDEX; 109275ebec6dSmrg tn = "inet"; 109375ebec6dSmrg break; 1094ac57ed83Smrg#ifdef IPv6 109575ebec6dSmrg case AF_INET6: 109675ebec6dSmrg ti = TRANS_SOCKET_INET6_INDEX; 109775ebec6dSmrg tn = "inet6"; 109875ebec6dSmrg break; 109975ebec6dSmrg#endif /* IPv6 */ 110075ebec6dSmrg default: 110175ebec6dSmrg prmsg (1, "receive_listening_fds:" 110275ebec6dSmrg "Got unknown socket address family\n"); 110375ebec6dSmrg return -1; 110475ebec6dSmrg } 110575ebec6dSmrg 110675ebec6dSmrg ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port); 110775ebec6dSmrg if (!ciptr) 110875ebec6dSmrg { 110975ebec6dSmrg prmsg (1, "receive_listening_fds:" 111075ebec6dSmrg "Got NULL while trying to reopen socket received from systemd.\n"); 111175ebec6dSmrg return -1; 111275ebec6dSmrg } 111375ebec6dSmrg 111475ebec6dSmrg prmsg (5, "receive_listening_fds: received listener for %s, %d\n", 111575ebec6dSmrg tn, ciptr->fd); 111675ebec6dSmrg temp_ciptrs[(*count_ret)++] = ciptr; 111775ebec6dSmrg TRANS(Received)(tn); 111875ebec6dSmrg } 111975ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */ 112075ebec6dSmrg return 0; 112175ebec6dSmrg} 112275ebec6dSmrg 11238d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11248d4c0f7bSmrgextern int xquartz_launchd_fd; 11258d4c0f7bSmrg#endif 112673143b9aSmrg 112773143b9aSmrgint 11286a3641a6SsnjTRANS(MakeAllCOTSServerListeners) (const char *port, int *partial, 11296a3641a6Ssnj int *count_ret, XtransConnInfo **ciptrs_ret) 113073143b9aSmrg 113173143b9aSmrg{ 113273143b9aSmrg char buffer[256]; /* ??? What size ?? */ 113394f982dbSmrg XtransConnInfo ciptr, temp_ciptrs[NUMTRANS] = { NULL }; 113494f982dbSmrg int status, j; 113573143b9aSmrg 1136ac57ed83Smrg#ifdef IPv6 113773143b9aSmrg int ipv6_succ = 0; 113873143b9aSmrg#endif 1139fe567363Smrg prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n", 1140ac57ed83Smrg port ? port : "NULL", (void *) ciptrs_ret); 114173143b9aSmrg 114273143b9aSmrg *count_ret = 0; 114373143b9aSmrg 11448d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11458d4c0f7bSmrg fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd); 11468d4c0f7bSmrg if(xquartz_launchd_fd != -1) { 11478d4c0f7bSmrg if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, 11488d4c0f7bSmrg xquartz_launchd_fd, getenv("DISPLAY"))))==NULL) 11498d4c0f7bSmrg fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); 1150fe567363Smrg else 11518d4c0f7bSmrg temp_ciptrs[(*count_ret)++] = ciptr; 11528d4c0f7bSmrg } 115373143b9aSmrg#endif 115473143b9aSmrg 115575ebec6dSmrg if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0) 115675ebec6dSmrg return -1; 115775ebec6dSmrg 115894f982dbSmrg for (unsigned int i = 0; i < NUMTRANS; i++) 115973143b9aSmrg { 116073143b9aSmrg Xtransport *trans = Xtransports[i].transport; 116173143b9aSmrg unsigned int flags = 0; 116273143b9aSmrg 116375ebec6dSmrg if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN || 116475ebec6dSmrg trans->flags&TRANS_RECEIVED) 116573143b9aSmrg continue; 116673143b9aSmrg 116773143b9aSmrg snprintf(buffer, sizeof(buffer), "%s/:%s", 116873143b9aSmrg trans->TransName, port ? port : ""); 116973143b9aSmrg 1170fe567363Smrg prmsg (5,"MakeAllCOTSServerListeners: opening %s\n", 1171fe567363Smrg buffer); 117273143b9aSmrg 117373143b9aSmrg if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) 117473143b9aSmrg { 117573143b9aSmrg if (trans->flags & TRANS_DISABLED) 117673143b9aSmrg continue; 117773143b9aSmrg 1178fe567363Smrg prmsg (1, 117973143b9aSmrg "MakeAllCOTSServerListeners: failed to open listener for %s\n", 1180fe567363Smrg trans->TransName); 118173143b9aSmrg continue; 118273143b9aSmrg } 1183ac57ed83Smrg#ifdef IPv6 118473143b9aSmrg if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX 118573143b9aSmrg && ipv6_succ)) 118673143b9aSmrg flags |= ADDR_IN_USE_ALLOWED; 118773143b9aSmrg#endif 118873143b9aSmrg 118973143b9aSmrg if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) 119073143b9aSmrg { 1191e45ace2bSmrg if (*partial != 0) 1192e45ace2bSmrg continue; 1193e45ace2bSmrg 119473143b9aSmrg if (status == TRANS_ADDR_IN_USE) 119573143b9aSmrg { 119673143b9aSmrg /* 119773143b9aSmrg * We failed to bind to the specified address because the 119873143b9aSmrg * address is in use. It must be that a server is already 119973143b9aSmrg * running at this address, and this function should fail. 120073143b9aSmrg */ 120173143b9aSmrg 1202fe567363Smrg prmsg (1, 1203fe567363Smrg "MakeAllCOTSServerListeners: server already running\n"); 120473143b9aSmrg 120573143b9aSmrg for (j = 0; j < *count_ret; j++) 120694f982dbSmrg if (temp_ciptrs[j] != NULL) 120794f982dbSmrg TRANS(Close) (temp_ciptrs[j]); 120873143b9aSmrg 120973143b9aSmrg *count_ret = 0; 121073143b9aSmrg *ciptrs_ret = NULL; 121173143b9aSmrg *partial = 0; 121273143b9aSmrg return -1; 121373143b9aSmrg } 121473143b9aSmrg else 121573143b9aSmrg { 1216fe567363Smrg prmsg (1, 121773143b9aSmrg "MakeAllCOTSServerListeners: failed to create listener for %s\n", 1218fe567363Smrg trans->TransName); 121973143b9aSmrg 122073143b9aSmrg continue; 122173143b9aSmrg } 122273143b9aSmrg } 122373143b9aSmrg 1224ac57ed83Smrg#ifdef IPv6 122573143b9aSmrg if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) 122673143b9aSmrg ipv6_succ = 1; 122773143b9aSmrg#endif 1228fe567363Smrg 1229fe567363Smrg prmsg (5, 123073143b9aSmrg "MakeAllCOTSServerListeners: opened listener for %s, %d\n", 1231fe567363Smrg trans->TransName, ciptr->fd); 123273143b9aSmrg 123373143b9aSmrg temp_ciptrs[*count_ret] = ciptr; 123473143b9aSmrg (*count_ret)++; 123573143b9aSmrg } 123673143b9aSmrg 123773143b9aSmrg *partial = (*count_ret < complete_network_count()); 123873143b9aSmrg 1239fe567363Smrg prmsg (5, 124073143b9aSmrg "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", 124173143b9aSmrg *partial, *count_ret, complete_network_count()); 124273143b9aSmrg 124373143b9aSmrg if (*count_ret > 0) 124473143b9aSmrg { 1245fe567363Smrg if ((*ciptrs_ret = malloc ( 124673143b9aSmrg *count_ret * sizeof (XtransConnInfo))) == NULL) 124773143b9aSmrg { 124873143b9aSmrg return -1; 124973143b9aSmrg } 125073143b9aSmrg 125194f982dbSmrg for (int i = 0; i < *count_ret; i++) 125273143b9aSmrg { 125373143b9aSmrg (*ciptrs_ret)[i] = temp_ciptrs[i]; 125473143b9aSmrg } 125573143b9aSmrg } 125673143b9aSmrg else 125773143b9aSmrg *ciptrs_ret = NULL; 1258fe567363Smrg 125973143b9aSmrg return 0; 126073143b9aSmrg} 126173143b9aSmrg 126273143b9aSmrg#endif /* TRANS_SERVER */ 126373143b9aSmrg 126473143b9aSmrg 126573143b9aSmrg 126673143b9aSmrg/* 126773143b9aSmrg * These routines are not part of the X Transport Interface, but they 126873143b9aSmrg * may be used by it. 126973143b9aSmrg */ 127073143b9aSmrg 127173143b9aSmrg 12723d2ed3e3Smrg#ifdef WIN32 127373143b9aSmrg 127473143b9aSmrg/* 127573143b9aSmrg * emulate readv 127673143b9aSmrg */ 127773143b9aSmrg 127873143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 127973143b9aSmrg 128073143b9aSmrg{ 128173143b9aSmrg int i, len, total; 128273143b9aSmrg char *base; 128373143b9aSmrg 128473143b9aSmrg ESET(0); 128573143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 128673143b9aSmrg len = iov->iov_len; 128773143b9aSmrg base = iov->iov_base; 128873143b9aSmrg while (len > 0) { 128973143b9aSmrg register int nbytes; 129073143b9aSmrg nbytes = TRANS(Read) (ciptr, base, len); 129173143b9aSmrg if (nbytes < 0 && total == 0) return -1; 129273143b9aSmrg if (nbytes <= 0) return total; 129373143b9aSmrg ESET(0); 129473143b9aSmrg len -= nbytes; 129573143b9aSmrg total += nbytes; 129673143b9aSmrg base += nbytes; 129773143b9aSmrg } 129873143b9aSmrg } 129973143b9aSmrg return total; 130073143b9aSmrg} 130173143b9aSmrg 130273143b9aSmrg 130373143b9aSmrg/* 130473143b9aSmrg * emulate writev 130573143b9aSmrg */ 130673143b9aSmrg 130773143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 130873143b9aSmrg 130973143b9aSmrg{ 131073143b9aSmrg int i, len, total; 131173143b9aSmrg char *base; 131273143b9aSmrg 131373143b9aSmrg ESET(0); 131473143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 131573143b9aSmrg len = iov->iov_len; 131673143b9aSmrg base = iov->iov_base; 131773143b9aSmrg while (len > 0) { 131873143b9aSmrg register int nbytes; 131973143b9aSmrg nbytes = TRANS(Write) (ciptr, base, len); 132073143b9aSmrg if (nbytes < 0 && total == 0) return -1; 132173143b9aSmrg if (nbytes <= 0) return total; 132273143b9aSmrg ESET(0); 132373143b9aSmrg len -= nbytes; 132473143b9aSmrg total += nbytes; 132573143b9aSmrg base += nbytes; 132673143b9aSmrg } 132773143b9aSmrg } 132873143b9aSmrg return total; 132973143b9aSmrg} 133073143b9aSmrg 13313d2ed3e3Smrg#endif /* WIN32 */ 133273143b9aSmrg 133373143b9aSmrg 1334e45ace2bSmrg#if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__SVR4) 133573143b9aSmrg#ifndef NEED_UTSNAME 133673143b9aSmrg#define NEED_UTSNAME 133773143b9aSmrg#endif 133873143b9aSmrg#include <sys/utsname.h> 133973143b9aSmrg#endif 134073143b9aSmrg 134173143b9aSmrg/* 134273143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing. 134373143b9aSmrg */ 134473143b9aSmrg 134573143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen) 134673143b9aSmrg 134773143b9aSmrg{ 134873143b9aSmrg int len; 134973143b9aSmrg 135073143b9aSmrg#ifdef NEED_UTSNAME 135173143b9aSmrg struct utsname name; 135273143b9aSmrg 135373143b9aSmrg uname (&name); 135473143b9aSmrg len = strlen (name.nodename); 135573143b9aSmrg if (len >= maxlen) len = maxlen - 1; 135694f982dbSmrg memcpy (buf, name.nodename, len); 135773143b9aSmrg buf[len] = '\0'; 135873143b9aSmrg#else 135973143b9aSmrg buf[0] = '\0'; 136073143b9aSmrg (void) gethostname (buf, maxlen); 136173143b9aSmrg buf [maxlen - 1] = '\0'; 136273143b9aSmrg len = strlen(buf); 136373143b9aSmrg#endif /* NEED_UTSNAME */ 136473143b9aSmrg return len; 136573143b9aSmrg} 1366