Xtrans.c revision 75ebec6d
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> 5175ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON 5275ebec6dSmrg#include <string.h> 5375ebec6dSmrg#include <systemd/sd-daemon.h> 5475ebec6dSmrg#endif 5573143b9aSmrg 5673143b9aSmrg/* 5773143b9aSmrg * The transport table contains a definition for every transport (protocol) 5873143b9aSmrg * family. All operations that can be made on the transport go through this 5973143b9aSmrg * table. 6073143b9aSmrg * 6173143b9aSmrg * Each transport is assigned a unique transport id. 6273143b9aSmrg * 6373143b9aSmrg * New transports can be added by adding an entry in this table. 6473143b9aSmrg * For compatiblity, the transport ids should never be renumbered. 6573143b9aSmrg * Always add to the end of the list. 6673143b9aSmrg */ 6773143b9aSmrg 6873143b9aSmrg#define TRANS_TLI_INET_INDEX 1 6973143b9aSmrg#define TRANS_TLI_TCP_INDEX 2 7073143b9aSmrg#define TRANS_TLI_TLI_INDEX 3 7173143b9aSmrg#define TRANS_SOCKET_UNIX_INDEX 4 7273143b9aSmrg#define TRANS_SOCKET_LOCAL_INDEX 5 7373143b9aSmrg#define TRANS_SOCKET_INET_INDEX 6 7473143b9aSmrg#define TRANS_SOCKET_TCP_INDEX 7 7573143b9aSmrg#define TRANS_DNET_INDEX 8 7673143b9aSmrg#define TRANS_LOCAL_LOCAL_INDEX 9 7773143b9aSmrg#define TRANS_LOCAL_PTS_INDEX 10 7873143b9aSmrg#define TRANS_LOCAL_NAMED_INDEX 11 79af928962Smrg/* 12 used to be ISC, but that's gone. */ 8073143b9aSmrg#define TRANS_LOCAL_SCO_INDEX 13 8173143b9aSmrg#define TRANS_SOCKET_INET6_INDEX 14 8273143b9aSmrg#define TRANS_LOCAL_PIPE_INDEX 15 8373143b9aSmrg 8473143b9aSmrg 8573143b9aSmrgstatic 8673143b9aSmrgXtransport_table Xtransports[] = { 8773143b9aSmrg#if defined(TCPCONN) 8873143b9aSmrg { &TRANS(SocketTCPFuncs), TRANS_SOCKET_TCP_INDEX }, 8973143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 9073143b9aSmrg { &TRANS(SocketINET6Funcs), TRANS_SOCKET_INET6_INDEX }, 9173143b9aSmrg#endif /* IPv6 */ 9273143b9aSmrg { &TRANS(SocketINETFuncs), TRANS_SOCKET_INET_INDEX }, 9373143b9aSmrg#endif /* TCPCONN */ 9473143b9aSmrg#if defined(UNIXCONN) 9573143b9aSmrg#if !defined(LOCALCONN) 9673143b9aSmrg { &TRANS(SocketLocalFuncs), TRANS_SOCKET_LOCAL_INDEX }, 9773143b9aSmrg#endif /* !LOCALCONN */ 9873143b9aSmrg { &TRANS(SocketUNIXFuncs), TRANS_SOCKET_UNIX_INDEX }, 9973143b9aSmrg#endif /* UNIXCONN */ 10073143b9aSmrg#if defined(LOCALCONN) 10173143b9aSmrg { &TRANS(LocalFuncs), TRANS_LOCAL_LOCAL_INDEX }, 10273143b9aSmrg#ifndef sun 10373143b9aSmrg { &TRANS(PTSFuncs), TRANS_LOCAL_PTS_INDEX }, 10473143b9aSmrg#endif /* sun */ 105e8a71cdfSmrg#if defined(SVR4) || defined(__SVR4) 10673143b9aSmrg { &TRANS(NAMEDFuncs), TRANS_LOCAL_NAMED_INDEX }, 10773143b9aSmrg#endif 10873143b9aSmrg#ifdef sun 10973143b9aSmrg { &TRANS(PIPEFuncs), TRANS_LOCAL_PIPE_INDEX }, 11073143b9aSmrg#endif /* sun */ 111af928962Smrg#if defined(__SCO__) || defined(__UNIXWARE__) 112af928962Smrg { &TRANS(SCOFuncs), TRANS_LOCAL_SCO_INDEX }, 113af928962Smrg#endif /* __SCO__ || __UNIXWARE__ */ 11473143b9aSmrg#endif /* LOCALCONN */ 11573143b9aSmrg}; 11673143b9aSmrg 11773143b9aSmrg#define NUMTRANS (sizeof(Xtransports)/sizeof(Xtransport_table)) 11873143b9aSmrg 11973143b9aSmrg 12073143b9aSmrg#ifdef WIN32 12173143b9aSmrg#define ioctl ioctlsocket 12273143b9aSmrg#endif 12373143b9aSmrg 12473143b9aSmrg 12573143b9aSmrg 12673143b9aSmrg/* 12773143b9aSmrg * These are a few utility function used by the public interface functions. 12873143b9aSmrg */ 12973143b9aSmrg 13073143b9aSmrgvoid 13173143b9aSmrgTRANS(FreeConnInfo) (XtransConnInfo ciptr) 13273143b9aSmrg 13373143b9aSmrg{ 134fe567363Smrg prmsg (3,"FreeConnInfo(%p)\n", ciptr); 13573143b9aSmrg 13673143b9aSmrg if (ciptr->addr) 137fe567363Smrg free (ciptr->addr); 13873143b9aSmrg 13973143b9aSmrg if (ciptr->peeraddr) 140fe567363Smrg free (ciptr->peeraddr); 14173143b9aSmrg 14273143b9aSmrg if (ciptr->port) 143fe567363Smrg free (ciptr->port); 14473143b9aSmrg 145fe567363Smrg free (ciptr); 14673143b9aSmrg} 14773143b9aSmrg 14873143b9aSmrg 14973143b9aSmrg#define PROTOBUFSIZE 20 15073143b9aSmrg 15173143b9aSmrgstatic Xtransport * 152fe567363SmrgTRANS(SelectTransport) (const char *protocol) 15373143b9aSmrg 15473143b9aSmrg{ 15573143b9aSmrg char protobuf[PROTOBUFSIZE]; 15673143b9aSmrg int i; 15773143b9aSmrg 158fe567363Smrg prmsg (3,"SelectTransport(%s)\n", protocol); 15973143b9aSmrg 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 16873143b9aSmrg for (i = 0; i < PROTOBUFSIZE && protobuf[i] != '\0'; i++) 16973143b9aSmrg if (isupper (protobuf[i])) 17073143b9aSmrg protobuf[i] = tolower (protobuf[i]); 17173143b9aSmrg 17273143b9aSmrg /* Look at all of the configured protocols */ 17373143b9aSmrg 17473143b9aSmrg for (i = 0; i < NUMTRANS; i++) 17573143b9aSmrg { 17673143b9aSmrg if (!strcmp (protobuf, Xtransports[i].transport->TransName)) 17773143b9aSmrg return Xtransports[i].transport; 17873143b9aSmrg } 17973143b9aSmrg 18073143b9aSmrg return NULL; 18173143b9aSmrg} 18273143b9aSmrg 18373143b9aSmrg#ifndef TEST_t 18473143b9aSmrgstatic 18573143b9aSmrg#endif /* TEST_t */ 18673143b9aSmrgint 18773143b9aSmrgTRANS(ParseAddress) (char *address, 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 20473143b9aSmrg char *mybuf, *tmpptr; 205fe567363Smrg const char *_protocol; 206fe567363Smrg char *_host, *_port; 20773143b9aSmrg char hostnamebuf[256]; 20873143b9aSmrg int _host_len; 20973143b9aSmrg 210fe567363Smrg prmsg (3,"ParseAddress(%s)\n", address); 21173143b9aSmrg 21273143b9aSmrg /* Copy the string so it can be changed */ 21373143b9aSmrg 214fe567363Smrg tmpptr = mybuf = strdup (address); 21573143b9aSmrg 21673143b9aSmrg /* Parse the string to get each component */ 217fe567363Smrg 21873143b9aSmrg /* Get the protocol part */ 21973143b9aSmrg 22073143b9aSmrg _protocol = mybuf; 22173143b9aSmrg 22273143b9aSmrg 22373143b9aSmrg if ( ((mybuf = strchr (mybuf,'/')) == NULL) && 22473143b9aSmrg ((mybuf = strrchr (tmpptr,':')) == NULL) ) 22573143b9aSmrg { 22673143b9aSmrg /* address is in a bad format */ 22773143b9aSmrg *protocol = NULL; 22873143b9aSmrg *host = NULL; 22973143b9aSmrg *port = NULL; 230fe567363Smrg free (tmpptr); 23173143b9aSmrg return 0; 23273143b9aSmrg } 23373143b9aSmrg 23473143b9aSmrg if (*mybuf == ':') 23573143b9aSmrg { 23673143b9aSmrg /* 23773143b9aSmrg * If there is a hostname, then assume tcp, otherwise 23873143b9aSmrg * it must be local. 23973143b9aSmrg */ 24073143b9aSmrg if (mybuf == tmpptr) 24173143b9aSmrg { 24273143b9aSmrg /* There is neither a protocol or host specified */ 24373143b9aSmrg _protocol = "local"; 24473143b9aSmrg } 24573143b9aSmrg else 24673143b9aSmrg { 24773143b9aSmrg /* There is a hostname specified */ 24873143b9aSmrg _protocol = "tcp"; 24973143b9aSmrg mybuf = tmpptr; /* reset to the begining of the host ptr */ 25073143b9aSmrg } 25173143b9aSmrg } 25273143b9aSmrg else 25373143b9aSmrg { 25473143b9aSmrg /* *mybuf == '/' */ 25573143b9aSmrg 25673143b9aSmrg *mybuf ++= '\0'; /* put a null at the end of the protocol */ 25773143b9aSmrg 25873143b9aSmrg if (strlen(_protocol) == 0) 25973143b9aSmrg { 26073143b9aSmrg /* 26173143b9aSmrg * If there is a hostname, then assume tcp, otherwise 26273143b9aSmrg * it must be local. 26373143b9aSmrg */ 26473143b9aSmrg if (*mybuf != ':') 26573143b9aSmrg _protocol = "tcp"; 26673143b9aSmrg else 26773143b9aSmrg _protocol = "local"; 26873143b9aSmrg } 26973143b9aSmrg } 27073143b9aSmrg 27173143b9aSmrg /* Get the host part */ 27273143b9aSmrg 27373143b9aSmrg _host = mybuf; 27473143b9aSmrg 27573143b9aSmrg if ((mybuf = strrchr (mybuf,':')) == NULL) 27673143b9aSmrg { 27773143b9aSmrg *protocol = NULL; 27873143b9aSmrg *host = NULL; 27973143b9aSmrg *port = NULL; 280fe567363Smrg free (tmpptr); 28173143b9aSmrg return 0; 28273143b9aSmrg } 28373143b9aSmrg 28473143b9aSmrg *mybuf ++= '\0'; 28573143b9aSmrg 28673143b9aSmrg _host_len = strlen(_host); 28773143b9aSmrg if (_host_len == 0) 28873143b9aSmrg { 28973143b9aSmrg TRANS(GetHostname) (hostnamebuf, sizeof (hostnamebuf)); 29073143b9aSmrg _host = hostnamebuf; 29173143b9aSmrg } 29273143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 29373143b9aSmrg /* hostname in IPv6 [numeric_addr]:0 form? */ 294fe567363Smrg else if ( (_host_len > 3) && 29573143b9aSmrg ((strcmp(_protocol, "tcp") == 0) || (strcmp(_protocol, "inet6") == 0)) 296fe567363Smrg && (*_host == '[') && (*(_host + _host_len - 1) == ']') ) { 29773143b9aSmrg struct sockaddr_in6 sin6; 29873143b9aSmrg 29973143b9aSmrg *(_host + _host_len - 1) = '\0'; 30073143b9aSmrg 30173143b9aSmrg /* Verify address is valid IPv6 numeric form */ 30273143b9aSmrg if (inet_pton(AF_INET6, _host + 1, &sin6) == 1) { 30373143b9aSmrg /* It is. Use it as such. */ 30473143b9aSmrg _host++; 30573143b9aSmrg _protocol = "inet6"; 30673143b9aSmrg } else { 30773143b9aSmrg /* It's not, restore it just in case some other code can use it. */ 30873143b9aSmrg *(_host + _host_len - 1) = ']'; 30973143b9aSmrg } 31073143b9aSmrg } 31173143b9aSmrg#endif 31273143b9aSmrg 31373143b9aSmrg 31473143b9aSmrg /* Get the port */ 31573143b9aSmrg 31673143b9aSmrg _port = mybuf; 31773143b9aSmrg 31873143b9aSmrg#if defined(FONT_t) || defined(FS_t) 31973143b9aSmrg /* 32073143b9aSmrg * Is there an optional catalogue list? 32173143b9aSmrg */ 32273143b9aSmrg 32373143b9aSmrg if ((mybuf = strchr (mybuf,'/')) != NULL) 32473143b9aSmrg *mybuf ++= '\0'; 32573143b9aSmrg 32673143b9aSmrg /* 32773143b9aSmrg * The rest, if any, is the (currently unused) catalogue list. 32873143b9aSmrg * 32973143b9aSmrg * _catalogue = mybuf; 33073143b9aSmrg */ 33173143b9aSmrg#endif 33273143b9aSmrg 33373143b9aSmrg#ifdef HAVE_LAUNCHD 33473143b9aSmrg /* launchd sockets will look like 'local//tmp/launch-XgkNns/:0' */ 33573143b9aSmrg if(address != NULL && strlen(address)>8 && (!strncmp(address,"local//",7))) { 33673143b9aSmrg _protocol="local"; 33773143b9aSmrg _host=""; 33873143b9aSmrg _port=address+6; 33973143b9aSmrg } 34073143b9aSmrg#endif 34173143b9aSmrg 34273143b9aSmrg /* 34373143b9aSmrg * Now that we have all of the components, allocate new 34473143b9aSmrg * string space for them. 34573143b9aSmrg */ 34673143b9aSmrg 347fe567363Smrg if ((*protocol = strdup (_protocol)) == NULL) 34873143b9aSmrg { 34973143b9aSmrg /* Malloc failed */ 35073143b9aSmrg *port = NULL; 35173143b9aSmrg *host = NULL; 35273143b9aSmrg *protocol = NULL; 353fe567363Smrg free (tmpptr); 35473143b9aSmrg return 0; 35573143b9aSmrg } 35673143b9aSmrg 357fe567363Smrg if ((*host = strdup (_host)) == NULL) 35873143b9aSmrg { 35973143b9aSmrg /* Malloc failed */ 36073143b9aSmrg *port = NULL; 36173143b9aSmrg *host = NULL; 362fe567363Smrg free (*protocol); 36373143b9aSmrg *protocol = NULL; 364fe567363Smrg free (tmpptr); 36573143b9aSmrg return 0; 366fe567363Smrg } 36773143b9aSmrg 368fe567363Smrg if ((*port = strdup (_port)) == NULL) 36973143b9aSmrg { 37073143b9aSmrg /* Malloc failed */ 37173143b9aSmrg *port = NULL; 372fe567363Smrg free (*host); 37373143b9aSmrg *host = NULL; 374fe567363Smrg free (*protocol); 37573143b9aSmrg *protocol = NULL; 376fe567363Smrg free (tmpptr); 37773143b9aSmrg return 0; 37873143b9aSmrg } 37973143b9aSmrg 380fe567363Smrg free (tmpptr); 38173143b9aSmrg 38273143b9aSmrg return 1; 38373143b9aSmrg} 38473143b9aSmrg 38573143b9aSmrg 38673143b9aSmrg/* 38773143b9aSmrg * TRANS(Open) does all of the real work opening a connection. The only 38873143b9aSmrg * funny part about this is the type parameter which is used to decide which 38973143b9aSmrg * type of open to perform. 39073143b9aSmrg */ 39173143b9aSmrg 39273143b9aSmrgstatic XtransConnInfo 39373143b9aSmrgTRANS(Open) (int type, char *address) 39473143b9aSmrg 39573143b9aSmrg{ 39673143b9aSmrg char *protocol = NULL, *host = NULL, *port = NULL; 39773143b9aSmrg XtransConnInfo ciptr = NULL; 39873143b9aSmrg Xtransport *thistrans; 39973143b9aSmrg 400fe567363Smrg prmsg (2,"Open(%d,%s)\n", type, address); 40173143b9aSmrg 402fe567363Smrg#if defined(WIN32) && defined(TCPCONN) 40373143b9aSmrg if (TRANS(WSAStartup)()) 40473143b9aSmrg { 405fe567363Smrg prmsg (1,"Open: WSAStartup failed\n"); 40673143b9aSmrg return NULL; 40773143b9aSmrg } 40873143b9aSmrg#endif 40973143b9aSmrg 41073143b9aSmrg /* Parse the Address */ 41173143b9aSmrg 41273143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 41373143b9aSmrg { 414fe567363Smrg prmsg (1,"Open: Unable to Parse address %s\n", address); 41573143b9aSmrg return NULL; 41673143b9aSmrg } 41773143b9aSmrg 41873143b9aSmrg /* Determine the transport type */ 41973143b9aSmrg 42073143b9aSmrg if ((thistrans = TRANS(SelectTransport) (protocol)) == NULL) 42173143b9aSmrg { 422fe567363Smrg prmsg (1,"Open: Unable to find transport for %s\n", 423fe567363Smrg protocol); 42473143b9aSmrg 425fe567363Smrg free (protocol); 426fe567363Smrg free (host); 427fe567363Smrg free (port); 42873143b9aSmrg return NULL; 42973143b9aSmrg } 43073143b9aSmrg 43173143b9aSmrg /* Open the transport */ 43273143b9aSmrg 43373143b9aSmrg switch (type) 43473143b9aSmrg { 43573143b9aSmrg case XTRANS_OPEN_COTS_CLIENT: 43673143b9aSmrg#ifdef TRANS_CLIENT 43773143b9aSmrg ciptr = thistrans->OpenCOTSClient(thistrans, protocol, host, port); 43873143b9aSmrg#endif /* TRANS_CLIENT */ 43973143b9aSmrg break; 44073143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 44173143b9aSmrg#ifdef TRANS_SERVER 44273143b9aSmrg ciptr = thistrans->OpenCOTSServer(thistrans, protocol, host, port); 44373143b9aSmrg#endif /* TRANS_SERVER */ 44473143b9aSmrg break; 44573143b9aSmrg case XTRANS_OPEN_CLTS_CLIENT: 44673143b9aSmrg#ifdef TRANS_CLIENT 44773143b9aSmrg ciptr = thistrans->OpenCLTSClient(thistrans, protocol, host, port); 44873143b9aSmrg#endif /* TRANS_CLIENT */ 44973143b9aSmrg break; 45073143b9aSmrg case XTRANS_OPEN_CLTS_SERVER: 45173143b9aSmrg#ifdef TRANS_SERVER 45273143b9aSmrg ciptr = thistrans->OpenCLTSServer(thistrans, protocol, host, port); 45373143b9aSmrg#endif /* TRANS_SERVER */ 45473143b9aSmrg break; 45573143b9aSmrg default: 456fe567363Smrg prmsg (1,"Open: Unknown Open type %d\n", type); 45773143b9aSmrg } 45873143b9aSmrg 45973143b9aSmrg if (ciptr == NULL) 46073143b9aSmrg { 461fe567363Smrg if (!(thistrans->flags & TRANS_DISABLED)) 46273143b9aSmrg { 463fe567363Smrg prmsg (1,"Open: transport open failed for %s/%s:%s\n", 46473143b9aSmrg protocol, host, port); 46573143b9aSmrg } 466fe567363Smrg free (protocol); 467fe567363Smrg free (host); 468fe567363Smrg free (port); 46973143b9aSmrg return NULL; 47073143b9aSmrg } 47173143b9aSmrg 47273143b9aSmrg ciptr->transptr = thistrans; 47373143b9aSmrg ciptr->port = port; /* We need this for TRANS(Reopen) */ 47473143b9aSmrg 475fe567363Smrg free (protocol); 476fe567363Smrg free (host); 47773143b9aSmrg 47873143b9aSmrg return ciptr; 47973143b9aSmrg} 48073143b9aSmrg 48173143b9aSmrg 48273143b9aSmrg#ifdef TRANS_REOPEN 48373143b9aSmrg 48473143b9aSmrg/* 48573143b9aSmrg * We might want to create an XtransConnInfo object based on a previously 48673143b9aSmrg * opened connection. For example, the font server may clone itself and 48773143b9aSmrg * pass file descriptors to the parent. 48873143b9aSmrg */ 48973143b9aSmrg 49073143b9aSmrgstatic XtransConnInfo 49173143b9aSmrgTRANS(Reopen) (int type, int trans_id, int fd, char *port) 49273143b9aSmrg 49373143b9aSmrg{ 49473143b9aSmrg XtransConnInfo ciptr = NULL; 49573143b9aSmrg Xtransport *thistrans = NULL; 49673143b9aSmrg char *save_port; 49773143b9aSmrg int i; 49873143b9aSmrg 499fe567363Smrg prmsg (2,"Reopen(%d,%d,%s)\n", trans_id, fd, port); 50073143b9aSmrg 50173143b9aSmrg /* Determine the transport type */ 50273143b9aSmrg 50373143b9aSmrg for (i = 0; i < NUMTRANS; i++) 50473143b9aSmrg if (Xtransports[i].transport_id == trans_id) 50573143b9aSmrg { 50673143b9aSmrg thistrans = Xtransports[i].transport; 50773143b9aSmrg break; 50873143b9aSmrg } 50973143b9aSmrg 51073143b9aSmrg if (thistrans == NULL) 51173143b9aSmrg { 512fe567363Smrg prmsg (1,"Reopen: Unable to find transport id %d\n", 513fe567363Smrg trans_id); 51473143b9aSmrg 51573143b9aSmrg return NULL; 51673143b9aSmrg } 51773143b9aSmrg 518fe567363Smrg if ((save_port = strdup (port)) == NULL) 51973143b9aSmrg { 520fe567363Smrg prmsg (1,"Reopen: Unable to malloc port string\n"); 52173143b9aSmrg 52273143b9aSmrg return NULL; 52373143b9aSmrg } 52473143b9aSmrg 52573143b9aSmrg /* Get a new XtransConnInfo object */ 52673143b9aSmrg 52773143b9aSmrg switch (type) 52873143b9aSmrg { 52973143b9aSmrg case XTRANS_OPEN_COTS_SERVER: 53073143b9aSmrg ciptr = thistrans->ReopenCOTSServer(thistrans, fd, port); 53173143b9aSmrg break; 53273143b9aSmrg case XTRANS_OPEN_CLTS_SERVER: 53373143b9aSmrg ciptr = thistrans->ReopenCLTSServer(thistrans, fd, port); 53473143b9aSmrg break; 53573143b9aSmrg default: 536fe567363Smrg prmsg (1,"Reopen: Bad Open type %d\n", type); 53773143b9aSmrg } 53873143b9aSmrg 53973143b9aSmrg if (ciptr == NULL) 54073143b9aSmrg { 541fe567363Smrg prmsg (1,"Reopen: transport open failed\n"); 542fe567363Smrg free (save_port); 54373143b9aSmrg return NULL; 54473143b9aSmrg } 54573143b9aSmrg 54673143b9aSmrg ciptr->transptr = thistrans; 54773143b9aSmrg ciptr->port = save_port; 54873143b9aSmrg 54973143b9aSmrg return ciptr; 55073143b9aSmrg} 55173143b9aSmrg 55273143b9aSmrg#endif /* TRANS_REOPEN */ 55373143b9aSmrg 55473143b9aSmrg 55573143b9aSmrg 55673143b9aSmrg/* 55773143b9aSmrg * These are the public interfaces to this Transport interface. 55873143b9aSmrg * These are the only functions that should have knowledge of the transport 55973143b9aSmrg * table. 56073143b9aSmrg */ 56173143b9aSmrg 56273143b9aSmrg#ifdef TRANS_CLIENT 56373143b9aSmrg 56473143b9aSmrgXtransConnInfo 56573143b9aSmrgTRANS(OpenCOTSClient) (char *address) 56673143b9aSmrg 56773143b9aSmrg{ 568fe567363Smrg prmsg (2,"OpenCOTSClient(%s)\n", address); 56973143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_CLIENT, address); 57073143b9aSmrg} 57173143b9aSmrg 57273143b9aSmrg#endif /* TRANS_CLIENT */ 57373143b9aSmrg 57473143b9aSmrg 57573143b9aSmrg#ifdef TRANS_SERVER 57673143b9aSmrg 57773143b9aSmrgXtransConnInfo 57873143b9aSmrgTRANS(OpenCOTSServer) (char *address) 57973143b9aSmrg 58073143b9aSmrg{ 581fe567363Smrg prmsg (2,"OpenCOTSServer(%s)\n", address); 58273143b9aSmrg return TRANS(Open) (XTRANS_OPEN_COTS_SERVER, address); 58373143b9aSmrg} 58473143b9aSmrg 58573143b9aSmrg#endif /* TRANS_SERVER */ 58673143b9aSmrg 58773143b9aSmrg 58873143b9aSmrg#ifdef TRANS_CLIENT 58973143b9aSmrg 59073143b9aSmrgXtransConnInfo 59173143b9aSmrgTRANS(OpenCLTSClient) (char *address) 59273143b9aSmrg 59373143b9aSmrg{ 594fe567363Smrg prmsg (2,"OpenCLTSClient(%s)\n", address); 59573143b9aSmrg return TRANS(Open) (XTRANS_OPEN_CLTS_CLIENT, address); 59673143b9aSmrg} 59773143b9aSmrg 59873143b9aSmrg#endif /* TRANS_CLIENT */ 59973143b9aSmrg 60073143b9aSmrg 60173143b9aSmrg#ifdef TRANS_SERVER 60273143b9aSmrg 60373143b9aSmrgXtransConnInfo 60473143b9aSmrgTRANS(OpenCLTSServer) (char *address) 60573143b9aSmrg 60673143b9aSmrg{ 607fe567363Smrg prmsg (2,"OpenCLTSServer(%s)\n", address); 60873143b9aSmrg return TRANS(Open) (XTRANS_OPEN_CLTS_SERVER, address); 60973143b9aSmrg} 61073143b9aSmrg 61173143b9aSmrg#endif /* TRANS_SERVER */ 61273143b9aSmrg 61373143b9aSmrg 61473143b9aSmrg#ifdef TRANS_REOPEN 61573143b9aSmrg 61673143b9aSmrgXtransConnInfo 61773143b9aSmrgTRANS(ReopenCOTSServer) (int trans_id, int fd, char *port) 61873143b9aSmrg 61973143b9aSmrg{ 620fe567363Smrg prmsg (2,"ReopenCOTSServer(%d, %d, %s)\n", trans_id, fd, port); 62173143b9aSmrg return TRANS(Reopen) (XTRANS_OPEN_COTS_SERVER, trans_id, fd, port); 62273143b9aSmrg} 62373143b9aSmrg 62473143b9aSmrgXtransConnInfo 62573143b9aSmrgTRANS(ReopenCLTSServer) (int trans_id, int fd, char *port) 62673143b9aSmrg 62773143b9aSmrg{ 628fe567363Smrg prmsg (2,"ReopenCLTSServer(%d, %d, %s)\n", trans_id, fd, port); 62973143b9aSmrg return TRANS(Reopen) (XTRANS_OPEN_CLTS_SERVER, trans_id, fd, port); 63073143b9aSmrg} 63173143b9aSmrg 63273143b9aSmrg 63373143b9aSmrgint 634fe567363SmrgTRANS(GetReopenInfo) (XtransConnInfo ciptr, 63573143b9aSmrg int *trans_id, int *fd, char **port) 63673143b9aSmrg 63773143b9aSmrg{ 63873143b9aSmrg int i; 63973143b9aSmrg 64073143b9aSmrg for (i = 0; i < NUMTRANS; i++) 64173143b9aSmrg if (Xtransports[i].transport == ciptr->transptr) 64273143b9aSmrg { 64373143b9aSmrg *trans_id = Xtransports[i].transport_id; 64473143b9aSmrg *fd = ciptr->fd; 64573143b9aSmrg 646fe567363Smrg if ((*port = strdup (ciptr->port)) == NULL) 64773143b9aSmrg return 0; 64873143b9aSmrg else 64973143b9aSmrg return 1; 65073143b9aSmrg } 65173143b9aSmrg 65273143b9aSmrg return 0; 65373143b9aSmrg} 65473143b9aSmrg 65573143b9aSmrg#endif /* TRANS_REOPEN */ 65673143b9aSmrg 65773143b9aSmrg 65873143b9aSmrgint 65973143b9aSmrgTRANS(SetOption) (XtransConnInfo ciptr, int option, int arg) 66073143b9aSmrg 66173143b9aSmrg{ 66273143b9aSmrg int fd = ciptr->fd; 66373143b9aSmrg int ret = 0; 66473143b9aSmrg 665fe567363Smrg prmsg (2,"SetOption(%d,%d,%d)\n", fd, option, arg); 66673143b9aSmrg 66773143b9aSmrg /* 66873143b9aSmrg * For now, all transport type use the same stuff for setting options. 66973143b9aSmrg * As long as this is true, we can put the common code here. Once a more 67073143b9aSmrg * complicated transport such as shared memory or an OSI implementation 67173143b9aSmrg * that uses the session and application libraries is implemented, this 67273143b9aSmrg * code may have to move to a transport dependent function. 67373143b9aSmrg * 67473143b9aSmrg * ret = ciptr->transptr->SetOption (ciptr, option, arg); 67573143b9aSmrg */ 67673143b9aSmrg 67773143b9aSmrg switch (option) 67873143b9aSmrg { 67973143b9aSmrg case TRANS_NONBLOCKING: 68073143b9aSmrg switch (arg) 68173143b9aSmrg { 68273143b9aSmrg case 0: 68373143b9aSmrg /* Set to blocking mode */ 68473143b9aSmrg break; 68573143b9aSmrg case 1: /* Set to non-blocking mode */ 68673143b9aSmrg 687fe567363Smrg#if defined(O_NONBLOCK) && !defined(SCO325) 68873143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 68973143b9aSmrg if (ret != -1) 69073143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NONBLOCK); 69173143b9aSmrg#else 69273143b9aSmrg#ifdef FIOSNBIO 69373143b9aSmrg { 69473143b9aSmrg int arg; 69573143b9aSmrg arg = 1; 69673143b9aSmrg ret = ioctl (fd, FIOSNBIO, &arg); 69773143b9aSmrg } 69873143b9aSmrg#else 699fe567363Smrg#if defined(WIN32) 70073143b9aSmrg { 70173143b9aSmrg#ifdef WIN32 70273143b9aSmrg u_long arg; 70373143b9aSmrg#else 70473143b9aSmrg int arg; 70573143b9aSmrg#endif 70673143b9aSmrg arg = 1; 70773143b9aSmrg/* IBM TCP/IP understands this option too well: it causes TRANS(Read) to fail 70873143b9aSmrg * eventually with EWOULDBLOCK */ 70973143b9aSmrg ret = ioctl (fd, FIONBIO, &arg); 71073143b9aSmrg } 71173143b9aSmrg#else 71273143b9aSmrg ret = fcntl (fd, F_GETFL, 0); 71373143b9aSmrg#ifdef FNDELAY 71473143b9aSmrg ret = fcntl (fd, F_SETFL, ret | FNDELAY); 71573143b9aSmrg#else 71673143b9aSmrg ret = fcntl (fd, F_SETFL, ret | O_NDELAY); 71773143b9aSmrg#endif 71873143b9aSmrg#endif /* AIXV3 || uniosu */ 71973143b9aSmrg#endif /* FIOSNBIO */ 72073143b9aSmrg#endif /* O_NONBLOCK */ 72173143b9aSmrg break; 72273143b9aSmrg default: 72373143b9aSmrg /* Unknown option */ 72473143b9aSmrg break; 72573143b9aSmrg } 72673143b9aSmrg break; 72773143b9aSmrg case TRANS_CLOSEONEXEC: 72873143b9aSmrg#ifdef F_SETFD 72973143b9aSmrg#ifdef FD_CLOEXEC 73073143b9aSmrg ret = fcntl (fd, F_SETFD, FD_CLOEXEC); 73173143b9aSmrg#else 73273143b9aSmrg ret = fcntl (fd, F_SETFD, 1); 73373143b9aSmrg#endif /* FD_CLOEXEC */ 73473143b9aSmrg#endif /* F_SETFD */ 73573143b9aSmrg break; 73673143b9aSmrg } 737fe567363Smrg 73873143b9aSmrg return ret; 73973143b9aSmrg} 74073143b9aSmrg 74173143b9aSmrg#ifdef TRANS_SERVER 74273143b9aSmrg 74373143b9aSmrgint 74473143b9aSmrgTRANS(CreateListener) (XtransConnInfo ciptr, char *port, unsigned int flags) 74573143b9aSmrg 74673143b9aSmrg{ 74773143b9aSmrg return ciptr->transptr->CreateListener (ciptr, port, flags); 74873143b9aSmrg} 74973143b9aSmrg 75075ebec6dSmrgint 75175ebec6dSmrgTRANS(Received) (const char * protocol) 75275ebec6dSmrg 75375ebec6dSmrg{ 75475ebec6dSmrg Xtransport *trans; 75575ebec6dSmrg int i = 0, ret = 0; 75675ebec6dSmrg 75775ebec6dSmrg prmsg (5, "Received(%s)\n", protocol); 75875ebec6dSmrg 75975ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 76075ebec6dSmrg { 76175ebec6dSmrg prmsg (1,"Received: unable to find transport: %s\n", 76275ebec6dSmrg protocol); 76375ebec6dSmrg 76475ebec6dSmrg return -1; 76575ebec6dSmrg } 76675ebec6dSmrg if (trans->flags & TRANS_ALIAS) { 76775ebec6dSmrg if (trans->nolisten) 76875ebec6dSmrg while (trans->nolisten[i]) { 76975ebec6dSmrg ret |= TRANS(Received)(trans->nolisten[i]); 77075ebec6dSmrg i++; 77175ebec6dSmrg } 77275ebec6dSmrg } 77375ebec6dSmrg 77475ebec6dSmrg trans->flags |= TRANS_RECEIVED; 77575ebec6dSmrg return ret; 77675ebec6dSmrg} 77775ebec6dSmrg 77873143b9aSmrgint 779fe567363SmrgTRANS(NoListen) (const char * protocol) 780fe567363Smrg 78173143b9aSmrg{ 78273143b9aSmrg Xtransport *trans; 78373143b9aSmrg int i = 0, ret = 0; 784fe567363Smrg 785fe567363Smrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 78673143b9aSmrg { 787fe567363Smrg prmsg (1,"TransNoListen: unable to find transport: %s\n", 788fe567363Smrg protocol); 78973143b9aSmrg 79073143b9aSmrg return -1; 79173143b9aSmrg } 79273143b9aSmrg if (trans->flags & TRANS_ALIAS) { 79373143b9aSmrg if (trans->nolisten) 79473143b9aSmrg while (trans->nolisten[i]) { 79573143b9aSmrg ret |= TRANS(NoListen)(trans->nolisten[i]); 79673143b9aSmrg i++; 79773143b9aSmrg } 79873143b9aSmrg } 79973143b9aSmrg 80073143b9aSmrg trans->flags |= TRANS_NOLISTEN; 80173143b9aSmrg return ret; 80273143b9aSmrg} 80373143b9aSmrg 80475ebec6dSmrgint 80575ebec6dSmrgTRANS(IsListening) (const char * protocol) 80675ebec6dSmrg{ 80775ebec6dSmrg Xtransport *trans; 80875ebec6dSmrg 80975ebec6dSmrg if ((trans = TRANS(SelectTransport)(protocol)) == NULL) 81075ebec6dSmrg { 81175ebec6dSmrg prmsg (1,"TransIsListening: unable to find transport: %s\n", 81275ebec6dSmrg protocol); 81375ebec6dSmrg 81475ebec6dSmrg return 0; 81575ebec6dSmrg } 81675ebec6dSmrg 81775ebec6dSmrg return !(trans->flags & TRANS_NOLISTEN); 81875ebec6dSmrg} 81975ebec6dSmrg 82073143b9aSmrgint 82173143b9aSmrgTRANS(ResetListener) (XtransConnInfo ciptr) 82273143b9aSmrg 82373143b9aSmrg{ 82473143b9aSmrg if (ciptr->transptr->ResetListener) 82573143b9aSmrg return ciptr->transptr->ResetListener (ciptr); 82673143b9aSmrg else 82773143b9aSmrg return TRANS_RESET_NOOP; 82873143b9aSmrg} 82973143b9aSmrg 83073143b9aSmrg 83173143b9aSmrgXtransConnInfo 83273143b9aSmrgTRANS(Accept) (XtransConnInfo ciptr, int *status) 83373143b9aSmrg 83473143b9aSmrg{ 83573143b9aSmrg XtransConnInfo newciptr; 83673143b9aSmrg 837fe567363Smrg prmsg (2,"Accept(%d)\n", ciptr->fd); 83873143b9aSmrg 83973143b9aSmrg newciptr = ciptr->transptr->Accept (ciptr, status); 84073143b9aSmrg 84173143b9aSmrg if (newciptr) 84273143b9aSmrg newciptr->transptr = ciptr->transptr; 84373143b9aSmrg 84473143b9aSmrg return newciptr; 84573143b9aSmrg} 84673143b9aSmrg 84773143b9aSmrg#endif /* TRANS_SERVER */ 84873143b9aSmrg 84973143b9aSmrg 85073143b9aSmrg#ifdef TRANS_CLIENT 85173143b9aSmrg 85273143b9aSmrgint 85373143b9aSmrgTRANS(Connect) (XtransConnInfo ciptr, char *address) 85473143b9aSmrg 85573143b9aSmrg{ 85673143b9aSmrg char *protocol; 85773143b9aSmrg char *host; 85873143b9aSmrg char *port; 85973143b9aSmrg int ret; 86073143b9aSmrg 861fe567363Smrg prmsg (2,"Connect(%d,%s)\n", ciptr->fd, address); 86273143b9aSmrg 86373143b9aSmrg if (TRANS(ParseAddress) (address, &protocol, &host, &port) == 0) 86473143b9aSmrg { 865fe567363Smrg prmsg (1,"Connect: Unable to Parse address %s\n", 866fe567363Smrg address); 86773143b9aSmrg return -1; 86873143b9aSmrg } 86973143b9aSmrg 87073143b9aSmrg#ifdef HAVE_LAUNCHD 8718d4c0f7bSmrg if (!host) host=strdup(""); 87273143b9aSmrg#endif 87373143b9aSmrg 87473143b9aSmrg if (!port || !*port) 87573143b9aSmrg { 876fe567363Smrg prmsg (1,"Connect: Missing port specification in %s\n", 877fe567363Smrg address); 878fe567363Smrg if (protocol) free (protocol); 879fe567363Smrg if (host) free (host); 88073143b9aSmrg return -1; 88173143b9aSmrg } 88273143b9aSmrg 88373143b9aSmrg ret = ciptr->transptr->Connect (ciptr, host, port); 88473143b9aSmrg 885fe567363Smrg if (protocol) free (protocol); 886fe567363Smrg if (host) free (host); 887fe567363Smrg if (port) free (port); 888fe567363Smrg 88973143b9aSmrg return ret; 89073143b9aSmrg} 89173143b9aSmrg 89273143b9aSmrg#endif /* TRANS_CLIENT */ 89373143b9aSmrg 89473143b9aSmrg 89573143b9aSmrgint 89673143b9aSmrgTRANS(BytesReadable) (XtransConnInfo ciptr, BytesReadable_t *pend) 89773143b9aSmrg 89873143b9aSmrg{ 89973143b9aSmrg return ciptr->transptr->BytesReadable (ciptr, pend); 90073143b9aSmrg} 90173143b9aSmrg 90273143b9aSmrgint 90373143b9aSmrgTRANS(Read) (XtransConnInfo ciptr, char *buf, int size) 90473143b9aSmrg 90573143b9aSmrg{ 90673143b9aSmrg return ciptr->transptr->Read (ciptr, buf, size); 90773143b9aSmrg} 90873143b9aSmrg 90973143b9aSmrgint 91073143b9aSmrgTRANS(Write) (XtransConnInfo ciptr, char *buf, int size) 91173143b9aSmrg 91273143b9aSmrg{ 91373143b9aSmrg return ciptr->transptr->Write (ciptr, buf, size); 91473143b9aSmrg} 91573143b9aSmrg 91673143b9aSmrgint 91773143b9aSmrgTRANS(Readv) (XtransConnInfo ciptr, struct iovec *buf, int size) 91873143b9aSmrg 91973143b9aSmrg{ 92073143b9aSmrg return ciptr->transptr->Readv (ciptr, buf, size); 92173143b9aSmrg} 92273143b9aSmrg 92373143b9aSmrgint 92473143b9aSmrgTRANS(Writev) (XtransConnInfo ciptr, struct iovec *buf, int size) 92573143b9aSmrg 92673143b9aSmrg{ 92773143b9aSmrg return ciptr->transptr->Writev (ciptr, buf, size); 92873143b9aSmrg} 92973143b9aSmrg 93075ebec6dSmrg#if XTRANS_SEND_FDS 93175ebec6dSmrgint 93275ebec6dSmrgTRANS(SendFd) (XtransConnInfo ciptr, int fd, int do_close) 93375ebec6dSmrg{ 93475ebec6dSmrg return ciptr->transptr->SendFd(ciptr, fd, do_close); 93575ebec6dSmrg} 93675ebec6dSmrg 93775ebec6dSmrgint 93875ebec6dSmrgTRANS(RecvFd) (XtransConnInfo ciptr) 93975ebec6dSmrg{ 94075ebec6dSmrg return ciptr->transptr->RecvFd(ciptr); 94175ebec6dSmrg} 94275ebec6dSmrg#endif 94375ebec6dSmrg 94473143b9aSmrgint 94573143b9aSmrgTRANS(Disconnect) (XtransConnInfo ciptr) 94673143b9aSmrg 94773143b9aSmrg{ 94873143b9aSmrg return ciptr->transptr->Disconnect (ciptr); 94973143b9aSmrg} 95073143b9aSmrg 95173143b9aSmrgint 95273143b9aSmrgTRANS(Close) (XtransConnInfo ciptr) 95373143b9aSmrg 95473143b9aSmrg{ 95573143b9aSmrg int ret; 95673143b9aSmrg 957fe567363Smrg prmsg (2,"Close(%d)\n", ciptr->fd); 95873143b9aSmrg 95973143b9aSmrg ret = ciptr->transptr->Close (ciptr); 96073143b9aSmrg 96173143b9aSmrg TRANS(FreeConnInfo) (ciptr); 96273143b9aSmrg 96373143b9aSmrg return ret; 96473143b9aSmrg} 96573143b9aSmrg 96673143b9aSmrgint 96773143b9aSmrgTRANS(CloseForCloning) (XtransConnInfo ciptr) 96873143b9aSmrg 96973143b9aSmrg{ 97073143b9aSmrg int ret; 97173143b9aSmrg 972fe567363Smrg prmsg (2,"CloseForCloning(%d)\n", ciptr->fd); 97373143b9aSmrg 97473143b9aSmrg ret = ciptr->transptr->CloseForCloning (ciptr); 97573143b9aSmrg 97673143b9aSmrg TRANS(FreeConnInfo) (ciptr); 97773143b9aSmrg 97873143b9aSmrg return ret; 97973143b9aSmrg} 98073143b9aSmrg 98173143b9aSmrgint 98273143b9aSmrgTRANS(IsLocal) (XtransConnInfo ciptr) 98373143b9aSmrg 98473143b9aSmrg{ 98573143b9aSmrg return (ciptr->family == AF_UNIX); 98673143b9aSmrg} 98773143b9aSmrg 98873143b9aSmrg 98973143b9aSmrgint 990fe567363SmrgTRANS(GetMyAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 99173143b9aSmrg Xtransaddr **addrp) 99273143b9aSmrg 99373143b9aSmrg{ 994fe567363Smrg prmsg (2,"GetMyAddr(%d)\n", ciptr->fd); 99573143b9aSmrg 99673143b9aSmrg *familyp = ciptr->family; 99773143b9aSmrg *addrlenp = ciptr->addrlen; 99873143b9aSmrg 999fe567363Smrg if ((*addrp = malloc (ciptr->addrlen)) == NULL) 100073143b9aSmrg { 1001fe567363Smrg prmsg (1,"GetMyAddr: malloc failed\n"); 100273143b9aSmrg return -1; 100373143b9aSmrg } 100473143b9aSmrg memcpy(*addrp, ciptr->addr, ciptr->addrlen); 100573143b9aSmrg 100673143b9aSmrg return 0; 100773143b9aSmrg} 100873143b9aSmrg 100973143b9aSmrgint 1010fe567363SmrgTRANS(GetPeerAddr) (XtransConnInfo ciptr, int *familyp, int *addrlenp, 101173143b9aSmrg Xtransaddr **addrp) 101273143b9aSmrg 101373143b9aSmrg{ 1014fe567363Smrg prmsg (2,"GetPeerAddr(%d)\n", ciptr->fd); 101573143b9aSmrg 101673143b9aSmrg *familyp = ciptr->family; 101773143b9aSmrg *addrlenp = ciptr->peeraddrlen; 101873143b9aSmrg 1019fe567363Smrg if ((*addrp = malloc (ciptr->peeraddrlen)) == NULL) 102073143b9aSmrg { 1021fe567363Smrg prmsg (1,"GetPeerAddr: malloc failed\n"); 102273143b9aSmrg return -1; 102373143b9aSmrg } 102473143b9aSmrg memcpy(*addrp, ciptr->peeraddr, ciptr->peeraddrlen); 102573143b9aSmrg 102673143b9aSmrg return 0; 102773143b9aSmrg} 102873143b9aSmrg 102973143b9aSmrg 103073143b9aSmrgint 103173143b9aSmrgTRANS(GetConnectionNumber) (XtransConnInfo ciptr) 103273143b9aSmrg 103373143b9aSmrg{ 103473143b9aSmrg return ciptr->fd; 103573143b9aSmrg} 103673143b9aSmrg 103773143b9aSmrg 103873143b9aSmrg/* 103973143b9aSmrg * These functions are really utility functions, but they require knowledge 104073143b9aSmrg * of the internal data structures, so they have to be part of the Transport 104173143b9aSmrg * Independant API. 104273143b9aSmrg */ 104373143b9aSmrg 104473143b9aSmrg#ifdef TRANS_SERVER 104573143b9aSmrg 104673143b9aSmrgstatic int 104773143b9aSmrgcomplete_network_count (void) 104873143b9aSmrg 104973143b9aSmrg{ 105073143b9aSmrg int count = 0; 105173143b9aSmrg int found_local = 0; 105273143b9aSmrg int i; 105373143b9aSmrg 105473143b9aSmrg /* 105573143b9aSmrg * For a complete network, we only need one LOCALCONN transport to work 105673143b9aSmrg */ 105773143b9aSmrg 105873143b9aSmrg for (i = 0; i < NUMTRANS; i++) 105973143b9aSmrg { 106073143b9aSmrg if (Xtransports[i].transport->flags & TRANS_ALIAS 106173143b9aSmrg || Xtransports[i].transport->flags & TRANS_NOLISTEN) 106273143b9aSmrg continue; 106373143b9aSmrg 106473143b9aSmrg if (Xtransports[i].transport->flags & TRANS_LOCAL) 106573143b9aSmrg found_local = 1; 106673143b9aSmrg else 106773143b9aSmrg count++; 106873143b9aSmrg } 106973143b9aSmrg 107073143b9aSmrg return (count + found_local); 107173143b9aSmrg} 107273143b9aSmrg 107373143b9aSmrg 107475ebec6dSmrgstatic int 107575ebec6dSmrgreceive_listening_fds(char* port, XtransConnInfo* temp_ciptrs, int* count_ret) 107675ebec6dSmrg 107775ebec6dSmrg{ 107875ebec6dSmrg#ifdef HAVE_SYSTEMD_DAEMON 107975ebec6dSmrg XtransConnInfo ciptr; 108075ebec6dSmrg int i, systemd_listen_fds; 108175ebec6dSmrg 108275ebec6dSmrg systemd_listen_fds = sd_listen_fds(1); 108375ebec6dSmrg if (systemd_listen_fds < 0) 108475ebec6dSmrg { 108575ebec6dSmrg prmsg (1, "receive_listening_fds: sd_listen_fds error: %s\n", 108675ebec6dSmrg strerror(-systemd_listen_fds)); 108775ebec6dSmrg return -1; 108875ebec6dSmrg } 108975ebec6dSmrg 109075ebec6dSmrg for (i = 0; i < systemd_listen_fds && *count_ret < NUMTRANS; i++) 109175ebec6dSmrg { 109275ebec6dSmrg struct sockaddr_storage a; 109375ebec6dSmrg int ti; 109475ebec6dSmrg const char* tn; 109575ebec6dSmrg socklen_t al; 109675ebec6dSmrg 109775ebec6dSmrg al = sizeof(a); 109875ebec6dSmrg if (getsockname(i + SD_LISTEN_FDS_START, (struct sockaddr*)&a, &al) < 0) { 109975ebec6dSmrg prmsg (1, "receive_listening_fds: getsockname error: %s\n", 110075ebec6dSmrg strerror(errno)); 110175ebec6dSmrg return -1; 110275ebec6dSmrg } 110375ebec6dSmrg 110475ebec6dSmrg switch (a.ss_family) 110575ebec6dSmrg { 110675ebec6dSmrg case AF_UNIX: 110775ebec6dSmrg ti = TRANS_SOCKET_UNIX_INDEX; 110875ebec6dSmrg if (*((struct sockaddr_un*)&a)->sun_path == '\0' && 110975ebec6dSmrg al > sizeof(sa_family_t)) 111075ebec6dSmrg tn = "local"; 111175ebec6dSmrg else 111275ebec6dSmrg tn = "unix"; 111375ebec6dSmrg break; 111475ebec6dSmrg case AF_INET: 111575ebec6dSmrg ti = TRANS_SOCKET_INET_INDEX; 111675ebec6dSmrg tn = "inet"; 111775ebec6dSmrg break; 111875ebec6dSmrg#if defined(IPv6) && defined(AF_INET6) 111975ebec6dSmrg case AF_INET6: 112075ebec6dSmrg ti = TRANS_SOCKET_INET6_INDEX; 112175ebec6dSmrg tn = "inet6"; 112275ebec6dSmrg break; 112375ebec6dSmrg#endif /* IPv6 */ 112475ebec6dSmrg default: 112575ebec6dSmrg prmsg (1, "receive_listening_fds:" 112675ebec6dSmrg "Got unknown socket address family\n"); 112775ebec6dSmrg return -1; 112875ebec6dSmrg } 112975ebec6dSmrg 113075ebec6dSmrg ciptr = TRANS(ReopenCOTSServer)(ti, i + SD_LISTEN_FDS_START, port); 113175ebec6dSmrg if (!ciptr) 113275ebec6dSmrg { 113375ebec6dSmrg prmsg (1, "receive_listening_fds:" 113475ebec6dSmrg "Got NULL while trying to reopen socket received from systemd.\n"); 113575ebec6dSmrg return -1; 113675ebec6dSmrg } 113775ebec6dSmrg 113875ebec6dSmrg prmsg (5, "receive_listening_fds: received listener for %s, %d\n", 113975ebec6dSmrg tn, ciptr->fd); 114075ebec6dSmrg temp_ciptrs[(*count_ret)++] = ciptr; 114175ebec6dSmrg TRANS(Received)(tn); 114275ebec6dSmrg } 114375ebec6dSmrg#endif /* HAVE_SYSTEMD_DAEMON */ 114475ebec6dSmrg return 0; 114575ebec6dSmrg} 114675ebec6dSmrg 11478d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11488d4c0f7bSmrgextern int xquartz_launchd_fd; 11498d4c0f7bSmrg#endif 115073143b9aSmrg 115173143b9aSmrgint 1152fe567363SmrgTRANS(MakeAllCOTSServerListeners) (char *port, int *partial, int *count_ret, 115373143b9aSmrg XtransConnInfo **ciptrs_ret) 115473143b9aSmrg 115573143b9aSmrg{ 115673143b9aSmrg char buffer[256]; /* ??? What size ?? */ 115773143b9aSmrg XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; 115873143b9aSmrg int status, i, j; 115973143b9aSmrg 116073143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 116173143b9aSmrg int ipv6_succ = 0; 116273143b9aSmrg#endif 1163fe567363Smrg prmsg (2,"MakeAllCOTSServerListeners(%s,%p)\n", 1164fe567363Smrg port ? port : "NULL", ciptrs_ret); 116573143b9aSmrg 116673143b9aSmrg *count_ret = 0; 116773143b9aSmrg 11688d4c0f7bSmrg#ifdef XQUARTZ_EXPORTS_LAUNCHD_FD 11698d4c0f7bSmrg fprintf(stderr, "Launchd socket fd: %d\n", xquartz_launchd_fd); 11708d4c0f7bSmrg if(xquartz_launchd_fd != -1) { 11718d4c0f7bSmrg if((ciptr = TRANS(ReopenCOTSServer(TRANS_SOCKET_LOCAL_INDEX, 11728d4c0f7bSmrg xquartz_launchd_fd, getenv("DISPLAY"))))==NULL) 11738d4c0f7bSmrg fprintf(stderr,"Got NULL while trying to Reopen launchd port\n"); 1174fe567363Smrg else 11758d4c0f7bSmrg temp_ciptrs[(*count_ret)++] = ciptr; 11768d4c0f7bSmrg } 117773143b9aSmrg#endif 117873143b9aSmrg 117975ebec6dSmrg if (receive_listening_fds(port, temp_ciptrs, count_ret) < 0) 118075ebec6dSmrg return -1; 118175ebec6dSmrg 118273143b9aSmrg for (i = 0; i < NUMTRANS; i++) 118373143b9aSmrg { 118473143b9aSmrg Xtransport *trans = Xtransports[i].transport; 118573143b9aSmrg unsigned int flags = 0; 118673143b9aSmrg 118775ebec6dSmrg if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN || 118875ebec6dSmrg trans->flags&TRANS_RECEIVED) 118973143b9aSmrg continue; 119073143b9aSmrg 119173143b9aSmrg snprintf(buffer, sizeof(buffer), "%s/:%s", 119273143b9aSmrg trans->TransName, port ? port : ""); 119373143b9aSmrg 1194fe567363Smrg prmsg (5,"MakeAllCOTSServerListeners: opening %s\n", 1195fe567363Smrg buffer); 119673143b9aSmrg 119773143b9aSmrg if ((ciptr = TRANS(OpenCOTSServer(buffer))) == NULL) 119873143b9aSmrg { 119973143b9aSmrg if (trans->flags & TRANS_DISABLED) 120073143b9aSmrg continue; 120173143b9aSmrg 1202fe567363Smrg prmsg (1, 120373143b9aSmrg "MakeAllCOTSServerListeners: failed to open listener for %s\n", 1204fe567363Smrg trans->TransName); 120573143b9aSmrg continue; 120673143b9aSmrg } 120773143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 120873143b9aSmrg if ((Xtransports[i].transport_id == TRANS_SOCKET_INET_INDEX 120973143b9aSmrg && ipv6_succ)) 121073143b9aSmrg flags |= ADDR_IN_USE_ALLOWED; 121173143b9aSmrg#endif 121273143b9aSmrg 121373143b9aSmrg if ((status = TRANS(CreateListener (ciptr, port, flags))) < 0) 121473143b9aSmrg { 121573143b9aSmrg if (status == TRANS_ADDR_IN_USE) 121673143b9aSmrg { 121773143b9aSmrg /* 121873143b9aSmrg * We failed to bind to the specified address because the 121973143b9aSmrg * address is in use. It must be that a server is already 122073143b9aSmrg * running at this address, and this function should fail. 122173143b9aSmrg */ 122273143b9aSmrg 1223fe567363Smrg prmsg (1, 1224fe567363Smrg "MakeAllCOTSServerListeners: server already running\n"); 122573143b9aSmrg 122673143b9aSmrg for (j = 0; j < *count_ret; j++) 122773143b9aSmrg TRANS(Close) (temp_ciptrs[j]); 122873143b9aSmrg 122973143b9aSmrg *count_ret = 0; 123073143b9aSmrg *ciptrs_ret = NULL; 123173143b9aSmrg *partial = 0; 123273143b9aSmrg return -1; 123373143b9aSmrg } 123473143b9aSmrg else 123573143b9aSmrg { 1236fe567363Smrg prmsg (1, 123773143b9aSmrg "MakeAllCOTSServerListeners: failed to create listener for %s\n", 1238fe567363Smrg trans->TransName); 123973143b9aSmrg 124073143b9aSmrg continue; 124173143b9aSmrg } 124273143b9aSmrg } 124373143b9aSmrg 124473143b9aSmrg#if defined(IPv6) && defined(AF_INET6) 124573143b9aSmrg if (Xtransports[i].transport_id == TRANS_SOCKET_INET6_INDEX) 124673143b9aSmrg ipv6_succ = 1; 124773143b9aSmrg#endif 1248fe567363Smrg 1249fe567363Smrg prmsg (5, 125073143b9aSmrg "MakeAllCOTSServerListeners: opened listener for %s, %d\n", 1251fe567363Smrg trans->TransName, ciptr->fd); 125273143b9aSmrg 125373143b9aSmrg temp_ciptrs[*count_ret] = ciptr; 125473143b9aSmrg (*count_ret)++; 125573143b9aSmrg } 125673143b9aSmrg 125773143b9aSmrg *partial = (*count_ret < complete_network_count()); 125873143b9aSmrg 1259fe567363Smrg prmsg (5, 126073143b9aSmrg "MakeAllCOTSServerListeners: partial=%d, actual=%d, complete=%d \n", 126173143b9aSmrg *partial, *count_ret, complete_network_count()); 126273143b9aSmrg 126373143b9aSmrg if (*count_ret > 0) 126473143b9aSmrg { 1265fe567363Smrg if ((*ciptrs_ret = malloc ( 126673143b9aSmrg *count_ret * sizeof (XtransConnInfo))) == NULL) 126773143b9aSmrg { 126873143b9aSmrg return -1; 126973143b9aSmrg } 127073143b9aSmrg 127173143b9aSmrg for (i = 0; i < *count_ret; i++) 127273143b9aSmrg { 127373143b9aSmrg (*ciptrs_ret)[i] = temp_ciptrs[i]; 127473143b9aSmrg } 127573143b9aSmrg } 127673143b9aSmrg else 127773143b9aSmrg *ciptrs_ret = NULL; 1278fe567363Smrg 127973143b9aSmrg return 0; 128073143b9aSmrg} 128173143b9aSmrg 128273143b9aSmrgint 1283fe567363SmrgTRANS(MakeAllCLTSServerListeners) (char *port, int *partial, int *count_ret, 128473143b9aSmrg XtransConnInfo **ciptrs_ret) 128573143b9aSmrg 128673143b9aSmrg{ 128773143b9aSmrg char buffer[256]; /* ??? What size ?? */ 128873143b9aSmrg XtransConnInfo ciptr, temp_ciptrs[NUMTRANS]; 128973143b9aSmrg int status, i, j; 129073143b9aSmrg 1291fe567363Smrg prmsg (2,"MakeAllCLTSServerListeners(%s,%p)\n", 1292fe567363Smrg port ? port : "NULL", ciptrs_ret); 129373143b9aSmrg 129473143b9aSmrg *count_ret = 0; 129573143b9aSmrg 129673143b9aSmrg for (i = 0; i < NUMTRANS; i++) 129773143b9aSmrg { 129873143b9aSmrg Xtransport *trans = Xtransports[i].transport; 129973143b9aSmrg 130073143b9aSmrg if (trans->flags&TRANS_ALIAS || trans->flags&TRANS_NOLISTEN) 130173143b9aSmrg continue; 130273143b9aSmrg 130373143b9aSmrg snprintf(buffer, sizeof(buffer), "%s/:%s", 130473143b9aSmrg trans->TransName, port ? port : ""); 130573143b9aSmrg 1306fe567363Smrg prmsg (5,"MakeAllCLTSServerListeners: opening %s\n", 1307fe567363Smrg buffer); 130873143b9aSmrg 130973143b9aSmrg if ((ciptr = TRANS(OpenCLTSServer (buffer))) == NULL) 131073143b9aSmrg { 1311fe567363Smrg prmsg (1, 131273143b9aSmrg "MakeAllCLTSServerListeners: failed to open listener for %s\n", 1313fe567363Smrg trans->TransName); 131473143b9aSmrg continue; 131573143b9aSmrg } 131673143b9aSmrg 131773143b9aSmrg if ((status = TRANS(CreateListener (ciptr, port, 0))) < 0) 131873143b9aSmrg { 131973143b9aSmrg if (status == TRANS_ADDR_IN_USE) 132073143b9aSmrg { 132173143b9aSmrg /* 132273143b9aSmrg * We failed to bind to the specified address because the 132373143b9aSmrg * address is in use. It must be that a server is already 132473143b9aSmrg * running at this address, and this function should fail. 132573143b9aSmrg */ 132673143b9aSmrg 1327fe567363Smrg prmsg (1, 1328fe567363Smrg "MakeAllCLTSServerListeners: server already running\n"); 132973143b9aSmrg 133073143b9aSmrg for (j = 0; j < *count_ret; j++) 133173143b9aSmrg TRANS(Close) (temp_ciptrs[j]); 133273143b9aSmrg 133373143b9aSmrg *count_ret = 0; 133473143b9aSmrg *ciptrs_ret = NULL; 133573143b9aSmrg *partial = 0; 133673143b9aSmrg return -1; 133773143b9aSmrg } 133873143b9aSmrg else 133973143b9aSmrg { 1340fe567363Smrg prmsg (1, 134173143b9aSmrg "MakeAllCLTSServerListeners: failed to create listener for %s\n", 1342fe567363Smrg trans->TransName); 134373143b9aSmrg 134473143b9aSmrg continue; 134573143b9aSmrg } 134673143b9aSmrg } 134773143b9aSmrg 1348fe567363Smrg prmsg (5, 134973143b9aSmrg "MakeAllCLTSServerListeners: opened listener for %s, %d\n", 1350fe567363Smrg trans->TransName, ciptr->fd); 135173143b9aSmrg temp_ciptrs[*count_ret] = ciptr; 135273143b9aSmrg (*count_ret)++; 135373143b9aSmrg } 135473143b9aSmrg 135573143b9aSmrg *partial = (*count_ret < complete_network_count()); 135673143b9aSmrg 1357fe567363Smrg prmsg (5, 135873143b9aSmrg "MakeAllCLTSServerListeners: partial=%d, actual=%d, complete=%d \n", 135973143b9aSmrg *partial, *count_ret, complete_network_count()); 136073143b9aSmrg 136173143b9aSmrg if (*count_ret > 0) 136273143b9aSmrg { 1363fe567363Smrg if ((*ciptrs_ret = malloc ( 136473143b9aSmrg *count_ret * sizeof (XtransConnInfo))) == NULL) 136573143b9aSmrg { 136673143b9aSmrg return -1; 136773143b9aSmrg } 136873143b9aSmrg 136973143b9aSmrg for (i = 0; i < *count_ret; i++) 137073143b9aSmrg { 137173143b9aSmrg (*ciptrs_ret)[i] = temp_ciptrs[i]; 137273143b9aSmrg } 137373143b9aSmrg } 137473143b9aSmrg else 137573143b9aSmrg *ciptrs_ret = NULL; 1376fe567363Smrg 137773143b9aSmrg return 0; 137873143b9aSmrg} 137973143b9aSmrg 138073143b9aSmrg#endif /* TRANS_SERVER */ 138173143b9aSmrg 138273143b9aSmrg 138373143b9aSmrg 138473143b9aSmrg/* 138573143b9aSmrg * These routines are not part of the X Transport Interface, but they 138673143b9aSmrg * may be used by it. 138773143b9aSmrg */ 138873143b9aSmrg 138973143b9aSmrg 1390fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32) 139173143b9aSmrg 139273143b9aSmrg/* 139373143b9aSmrg * emulate readv 139473143b9aSmrg */ 139573143b9aSmrg 139673143b9aSmrgstatic int TRANS(ReadV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 139773143b9aSmrg 139873143b9aSmrg{ 139973143b9aSmrg int i, len, total; 140073143b9aSmrg char *base; 140173143b9aSmrg 140273143b9aSmrg ESET(0); 140373143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 140473143b9aSmrg len = iov->iov_len; 140573143b9aSmrg base = iov->iov_base; 140673143b9aSmrg while (len > 0) { 140773143b9aSmrg register int nbytes; 140873143b9aSmrg nbytes = TRANS(Read) (ciptr, base, len); 140973143b9aSmrg if (nbytes < 0 && total == 0) return -1; 141073143b9aSmrg if (nbytes <= 0) return total; 141173143b9aSmrg ESET(0); 141273143b9aSmrg len -= nbytes; 141373143b9aSmrg total += nbytes; 141473143b9aSmrg base += nbytes; 141573143b9aSmrg } 141673143b9aSmrg } 141773143b9aSmrg return total; 141873143b9aSmrg} 141973143b9aSmrg 142073143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */ 142173143b9aSmrg 1422fe567363Smrg#if defined(SYSV) && defined(__i386__) && !defined(__SCO__) && !defined(sun) || defined(WIN32) 142373143b9aSmrg 142473143b9aSmrg/* 142573143b9aSmrg * emulate writev 142673143b9aSmrg */ 142773143b9aSmrg 142873143b9aSmrgstatic int TRANS(WriteV) (XtransConnInfo ciptr, struct iovec *iov, int iovcnt) 142973143b9aSmrg 143073143b9aSmrg{ 143173143b9aSmrg int i, len, total; 143273143b9aSmrg char *base; 143373143b9aSmrg 143473143b9aSmrg ESET(0); 143573143b9aSmrg for (i = 0, total = 0; i < iovcnt; i++, iov++) { 143673143b9aSmrg len = iov->iov_len; 143773143b9aSmrg base = iov->iov_base; 143873143b9aSmrg while (len > 0) { 143973143b9aSmrg register int nbytes; 144073143b9aSmrg nbytes = TRANS(Write) (ciptr, base, len); 144173143b9aSmrg if (nbytes < 0 && total == 0) return -1; 144273143b9aSmrg if (nbytes <= 0) return total; 144373143b9aSmrg ESET(0); 144473143b9aSmrg len -= nbytes; 144573143b9aSmrg total += nbytes; 144673143b9aSmrg base += nbytes; 144773143b9aSmrg } 144873143b9aSmrg } 144973143b9aSmrg return total; 145073143b9aSmrg} 145173143b9aSmrg 145273143b9aSmrg#endif /* SYSV && __i386__ || WIN32 || __sxg__ */ 145373143b9aSmrg 145473143b9aSmrg 1455e8a71cdfSmrg#if defined(_POSIX_SOURCE) || defined(USG) || defined(SVR4) || defined(__SVR4) || defined(__SCO__) 145673143b9aSmrg#ifndef NEED_UTSNAME 145773143b9aSmrg#define NEED_UTSNAME 145873143b9aSmrg#endif 145973143b9aSmrg#include <sys/utsname.h> 146073143b9aSmrg#endif 146173143b9aSmrg 146273143b9aSmrg/* 146373143b9aSmrg * TRANS(GetHostname) - similar to gethostname but allows special processing. 146473143b9aSmrg */ 146573143b9aSmrg 146673143b9aSmrgint TRANS(GetHostname) (char *buf, int maxlen) 146773143b9aSmrg 146873143b9aSmrg{ 146973143b9aSmrg int len; 147073143b9aSmrg 147173143b9aSmrg#ifdef NEED_UTSNAME 147273143b9aSmrg struct utsname name; 147373143b9aSmrg 147473143b9aSmrg uname (&name); 147573143b9aSmrg len = strlen (name.nodename); 147673143b9aSmrg if (len >= maxlen) len = maxlen - 1; 147773143b9aSmrg strncpy (buf, name.nodename, len); 147873143b9aSmrg buf[len] = '\0'; 147973143b9aSmrg#else 148073143b9aSmrg buf[0] = '\0'; 148173143b9aSmrg (void) gethostname (buf, maxlen); 148273143b9aSmrg buf [maxlen - 1] = '\0'; 148373143b9aSmrg len = strlen(buf); 148473143b9aSmrg#endif /* NEED_UTSNAME */ 148573143b9aSmrg return len; 148673143b9aSmrg} 1487