/* $XConsortium: nameaddr.c,v 1.7 94/04/17 20:22:16 rws Exp $ */
/*	nameaddr.c - included by Xstreams.c			*/
/*	Used for System V Release 4.0 networking code		*/

/*

Copyright (c) 1991  X Consortium

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Except as contained in this notice, the name of the X Consortium shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from the X Consortium.

*/


/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. 
 * Copyright 1988, 1989 AT&T, Inc.
 *
 * Permission to use, copy, modify, and distribute this software and
 * its documentation for any purpose and without fee is hereby
 * granted, provided that the above copyright notice appear in all
 * copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of
 * AT&T or USL not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  AT&T and USL make no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * AT&T AND USL DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
 * NO EVENT SHALL AT&T OR USL BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifdef XSTREAMS_COMPILE /* magic symbol to avoid lint problems */

static void   *handlep = NULL;
static int    family = 0;
static char   tcphalf[4];
static int    *tcpfamilyp = NULL;
static char   **tcpremoteaddrp = NULL;
static int    *tcpremoteaddrlenp = NULL;

static int SetupNetworkStream();
static int BindAndListen();
static int BindAndConnect();
static int addentry();

/* Routines for handling TLI streams */
static int
InitializeNetPath()
{
	if(handlep == NULL && (handlep = setnetpath()) == NULL)
	{
		nc_perror("Cannot set network selection path\n");
		return(-1);
	}
	return(1);

}

_XsSetupTliStream(display, dummy)
    char *display;
    void *dummy;
{
	int	i, n;
	int	fd, type;
	struct	utsname  machine;
	struct listenCall *tmp;
	int	nameserver();
	static int firstime=1;

	PRMSG("Calling SetupTliStream()\n",0,0);

	if(InitializeNetPath() < 0)
		return(-1);

	dispno = display;

	if(uname(&machine) < 0){
		t_error("Cannot get nodename");
		return(-2);
		}
		
	bind_req.addr.buf = req_buf;

/* pcc */
	if (firstime)	{
		Network._nnets = X_TLI_STREAM;
		firstime = 0;
	}

/*	type = Network._nnets;	*/

	bind_ret.addr.buf = ret_buf;
	call.addr.buf	  = call_buf;
	bind_req.addr.maxlen = MAXLEN;
	bind_ret.addr.maxlen = MAXLEN;
	call.addr.maxlen     = MAXLEN;

	fd = SetupNetworkStream(
			machine.nodename, 
			atoi(display), 
			BindAndListen, 
			&type, 
			handlep
			);
	
	if( fd < 0)
	{
         		PRMSG("SetupNetworkStream failed\n",0,0);
                        return(-1);
	}

	_XsTypeOfStream[fd] = type;

/*
 * set up call save list for general network listen service
 */
	for (i = 0; i < LISTEN_QUE_SIZE; ++i) 
	{
	    if((tmp = (struct listenCall *) malloc(sizeof(struct listenCall))) == NULL)
	    {
			PRMSG( "malloc failed\n",0,0);
			exit(1);
	    }
	    if((tmp->CurrentCall = (struct t_call *) t_alloc(fd,T_CALL,T_ALL)) == NULL)
            {
			PRMSG( "t_alloc failed\n",0,0);
			exit(1);
	    }
	    Que(&Network.FreeList[type], tmp, CLEAR);
	}

	if(Network._npeers > 0 && Network._peer == NULL)
	{
		register	i;
		register	char	*ptr;
		int		n;

		n =  (Network._npeers + 1) * 
			(sizeof(int) + sizeof(char *) + (1 + UNAME_LENGTH));

		PRMSG("Allocating %d chars for %d peeers names", 
							n, Network._npeers);

		if((ptr = malloc(n)) == NULL){
			fprintf(stderr,"Cannot malloc space for peers names\n");
			exit(1);
		}

		
		Network._peerlen = (int *) ptr;
		ptr += Network._npeers * sizeof(int);
		Network._peer = (char **) ptr; 
		ptr += Network._npeers * sizeof(char *);
		for(i= 0; i< Network._npeers; i++)
		{
			Network._peerlen[i] = 0;
			Network._peer[i]    = ptr;
#ifdef DEBUG
/*
			fprintf(stderr, "peer[%d] is %u; peerlen[%d] is %u\n",
				i, Network._peer[i], i, &Network._peerlen[i]);
*/
#endif
			ptr += (1 + UNAME_LENGTH);
		}
	}
	PRMSG("SetupTliStream () (success) fd = %d\n", fd,0);
	return(fd);
}

int
_XsCallTliServer(host, idisplay)
    char *host;
    int	idisplay;
{
	int	fd, type;
	int	nameserver ();
	static  char	firsttime = 1;

	PRMSG("Calling CallTliServer()\n",0,0);

	if(firsttime == 1)
	{
		firsttime = 0;
		SetupNetworkInfo();
		Network._nnets = X_TLI_STREAM;
	}
	
	sprintf(_dispno, "%d", idisplay);
	dispno = _dispno;


	if((fd = SetupNetworkStream(
			host, 
			idisplay, 
			BindAndConnect, 
			&type, 
			handlep)) < 0)
	{
			PRMSG("SetupNetworkStream failed\n",0,0);
			return(-1);
	}

	if(ioctl(fd, I_POP, "timod") < 0)
	{
	    PRMSG("failed to pop timod\n",0,0);
	}
	if(ioctl(fd, I_PUSH, "tirdwr") < 0)
	{
         	t_close(fd);
		return(-1);
	}

	PRMSG("A Connection has been established to %s ... \n", host,0);
	_XsTypeOfStream[fd] = type;
        if (_XsInputBuffer[fd].DataBuffer == NULL)
            if ((_XsInputBuffer[fd].DataBuffer = (char *) malloc(BUFFERSIZE)) == NULL)
               {
	       errno = ENOMEM;
               perror("Client can't connect to remote server");
               return (-1);
               }
	_XsInputBuffer[fd].LastBytePtr = 0;
	_XsInputBuffer[fd].FirstBytePtr = 0;
	PRMSG("CallTliServer() returns success\n",0,0);

	return(fd);
}


int _XMakeStreamsConnection (name, idisplay, retries,
			     familyp, serveraddrlenp, serveraddrp)
    char	*name;
    int	idisplay;
    int	retries;
    int	*familyp;		/* return */
    int	*serveraddrlenp;	/* return */
    char **serveraddrp;		/* return */
{
	char	netype[128], sysname[128], nodname[128];
	char	*procname = "Xlib/_XMakeStreamsConnection";
	struct	utsname	 machine;
	int	fd; 
	int	tryother = 0;

	PRMSG("GetConnectionType(%s)\n", name, 0);

        if(uname(&machine) < 0){
		t_error("Cannot get nodename");
		return(-1);
		}
	if(
		(name == NULL && (tryother = 1)) || 
		(strcmp(name, "") == 0 && (tryother = 1)) ||
		strcmp(name, "unix") == 0 ||
		strcmp(name, "local") == 0 ||
		(strcmp(name, machine.nodename) == 0 && (tryother = 1))
	  )
	{
	    fd = ((*_XsStream[X_NAMED_STREAM].CallTheListener)
		  ("unix", idisplay, "local"));

	    if (fd >= 0) {
		*familyp = FamilyLocal;
		*serveraddrlenp = strlen (machine.nodename);
		*serveraddrp = (char *) Xmalloc ((*serveraddrlenp) + 1);
		if (!*serveraddrp) {
		    *serveraddrlenp = 0;
		} else {
		    strcpy (*serveraddrp, machine.nodename);
		}
		return fd;
	    }
	    if (!tryother)
		return fd;
	    if (!name || !*name)
		name = machine.nodename;
	}

	if((handlep = setnetpath()) == NULL)
	{
         	nc_perror("Cannot set network selection path\n");
		return(-1);
	}
	/* For backward compatibility, we have to pass authorization
	   data in global variables.  Ugh. */
	tcpfamilyp = familyp;
	tcpremoteaddrp = serveraddrp;
	tcpremoteaddrlenp = serveraddrlenp;

	fd = (*_XsStream[X_TLI_STREAM].CallTheListener)(name, idisplay);
	return(fd);
}


static int
SetupNetworkStream(host, dispno, action, typtr, handlep)
    char *host;
    int	dispno;
    int	(*action)();
    int	*typtr;
    void *handlep;
{
	int	i;
	char	service[MAX_AUTO_BUF_LEN];
	int	fd, type;
	struct nd_hostserv  nd_hostserv; 
	struct netconfig   *netconfigp = NULL;
	struct nd_addrlist *nd_addrlistp = NULL;
	struct netbuf	   *netbufp = NULL;
 

#ifdef DEBUG
fprintf(stderr, "Calling SetupNetworkStream(%s, %d)\n", host, dispno);
#endif

        sprintf(service , "xserver%d", dispno);
	nd_hostserv.h_host = host;
	nd_hostserv.h_serv = service;
#ifdef DEBUG
fprintf(stderr, "Trying to get the binding address for service %s on %s\n", 
					service, host);
#endif
	while((netconfigp = getnetpath(handlep)) != NULL)
	{
#ifdef DEBUG
	  fprintf(stderr, "Trying to bind using %s\n", netconfigp->nc_device);
#endif
	  if(netdir_getbyname(netconfigp, &nd_hostserv, &nd_addrlistp) == 0)
	  {

#ifdef DEBUG
	  fprintf(stderr, "There are %d ways\n", nd_addrlistp->n_cnt);
#endif
            netbufp = nd_addrlistp->n_addrs;
            for(i=0; i< nd_addrlistp->n_cnt; i++)
            {
		
#ifdef DEBUG
		fprintf(stderr, "Address: len %d maxlen %d \n", 
			netbufp->len, netbufp->maxlen);
#endif
		if( strcmp(netconfigp->nc_netid, "starlan") == 0 )
		{
			register char *from, *to;
			int	i, len;

			from = to = netbufp->buf;
			len = 0;
			for(i=0; i< netbufp->len; i++, from++)
				if(*from != '.')
				{
					*to++ = *from;	
					len++;
				}
			*to = '\0';
			netbufp->len = len;
		}
		
#ifdef DEBUG
		fprintf(stderr, "Address: maxlen %d buf ", netbufp->maxlen);
		dumpBytes(netbufp->len, netbufp->buf);
#endif
		if((fd = (*action)(netconfigp->nc_device, netbufp)) < 0)
		{
			netbufp++;
			continue;
		}
		if(
                   strcmp(netconfigp->nc_protofmly, "inet") == 0 &&
                   strcmp(netconfigp->nc_proto    , "tcp") == 0
          	  )
		{
			memcpy(tcphalf, netbufp->buf, 4);
			if (tcpfamilyp != NULL) {
			    *tcpfamilyp = FamilyInternet;
			    *tcpremoteaddrlenp = 4;
			    *tcpremoteaddrp = Xmalloc(*tcpremoteaddrlenp);
			    /* This is a kludge.  What is the right way to get
			       this info out? */
			    memcpy(*tcpremoteaddrp, netbufp->buf+4,
				   *tcpremoteaddrlenp);
#ifdef DEBUG
			    fprintf(stderr, "tcp remote addr = %0x\n",
				    *(long *)*tcpremoteaddrp);
#endif
			}
		}
		type = 0;
		for(i=X_TLI_STREAM; i< Network._nnets; i++)
		 if(strcmp(Network._net[i]->nc_netid, netconfigp->nc_netid) == 0)
		 {
			type = i;
			break;
		 }
		if(type == 0)
		{
			Network._net[Network._nnets] = netconfigp;
			type = Network._nnets++;
		}
		*typtr = type;
	  	/* free(netconfigp) the right way */
		(void) netdir_free((char *)nd_addrlistp, ND_ADDRLIST);

		return(fd);
            }
	    /* free(nd_addrlistp) the right way */
	    (void) netdir_free((char *)nd_addrlistp, ND_ADDRLIST);
	  }
#ifdef DEBUG
	  else netdir_perror("netdir_getbyname() failed");
#endif
	}
	return(-1);
}


static int
BindAndListen(clonedev, netbufp)
    char	*clonedev;
    struct   netbuf *netbufp;
{
	int	fd;
	struct  t_bind bindbuf;


	bindbuf.addr.buf = netbufp->buf;
        bindbuf.addr.len = netbufp->len;
        bindbuf.addr.maxlen = netbufp->maxlen;

			
	if ((fd = t_open(clonedev,  O_RDWR, NULL)) < 0)
	{
		fprintf(stderr, "Cannot open %s\n", clonedev);
		return(-1);
	}
#ifdef DEBUG
	fprintf(stderr, "opening device %s\n", clonedev);
#endif

	bindbuf.qlen = 8;
	if(t_bind (fd, &bindbuf, NULL) < 0)
	{
		t_error("t_bind failed");
		close(fd);
		return(-1);
	}
	return(fd);
}

static int
BindAndConnect(clonedev, netbufp)
    char	*clonedev;
    struct   netbuf *netbufp;
{
	int	fd;
	struct  t_call callbuf;

	callbuf.addr.buf = netbufp->buf;
	callbuf.addr.len = netbufp->len;
	callbuf.addr.maxlen = netbufp->maxlen;
			
	callbuf.opt.buf = NULL;
	callbuf.opt.len = 0;
	callbuf.opt.maxlen = 0;
			
	callbuf.udata.buf = NULL;
	callbuf.udata.len = 0;
	callbuf.udata.maxlen = 0;

	if ((fd = t_open(clonedev,  O_RDWR, NULL)) < 0)
	{
		fprintf(stderr, "Cannot open %s\n", clonedev);
		return(-1);
	}
	
#ifdef DEBUG
	fprintf(stderr, "Connecting to <%s> through device %s\n", 
					callbuf.addr.buf, clonedev);
#endif
	if(t_bind(fd, NULL, NULL) < 0)	
	{
		t_error("t_bind failed");
		t_close(fd);
		return(-1);
	}
	if(t_connect(fd, &callbuf, NULL) < 0)	
	{
		t_error("t_connect failed");
		checkNewEvent(fd);
		t_close(fd);
		return(-1);
	}
	return(fd);
}



/*extern	char	*calloc(), *realloc();*/
extern  char    *program;
static int	network;
static int	nextentry;

static char *makePacket();
static char *staticalloc();
static char    *TheEnd;
static char    *inbuf;
static int     inlen;
static int     nhosts;
static int	nHosts;
static int     flags = 0;
static struct netconfig   *netconfigp = NULL; 

static int
CallTheNameServer(service, nettype, arg1, arg2, arg3)
    int service;
    struct netconfig   *nettype;
    char    **arg1, **arg2;
    int     *arg3;
{
	int	n,m, len;
	char	*ptr, *net;
	int	*iptr;

	flags = service;
	netconfigp = nettype;
	ptr = *arg1;

	iptr = (int *) ptr;
	inlen = iptr[0];

#ifdef DEBUG
fprintf(stderr,"inlen = %d\n", inlen);
#endif
	ptr += sizeof(int);
	nhosts = iptr[1];
#ifdef DEBUG
fprintf(stderr,"nhosts = %d\n", nhosts);
#endif

	inbuf = ptr + sizeof(int);
	TheEnd = &inbuf[inlen];
#ifdef DEBUG
	write(2, inbuf, inlen);
#endif
        nextentry = ((xHostEntry *) inbuf)->length;
        *arg2 = (char *) makePacket(&len);
	if(arg3 != NULL)
		*arg3 = nHosts;

#ifdef DEBUG
fprintf(stderr, "CallTheNameserver return %d\n", len);
#endif
	return(len);
}



static int	bufsize = 512;

static char	*getnextentry();

static struct nd_addrlist *
GetHostServiceByName(host, dispno)
    char *host;
    int	dispno;
{
    struct nd_hostserv  nd_hostserv;
    struct nd_addrlist *nd_addrlistp = NULL;
    struct netbuf	   *netbufp = NULL;
    char	service[MAX_AUTO_BUF_LEN];
    
    sprintf(service , "xserver%d", dispno);
    nd_hostserv.h_host = host;
    nd_hostserv.h_serv = service;
    
    if(netdir_getbyname(netconfigp, &nd_hostserv, &nd_addrlistp) == 0)
	return(nd_addrlistp);
    else	return(NULL); 
}

static int
ConvertName(pktptr, n, entry, len)
    char **pktptr, *entry;
    int	n, len;
{
    struct hostent *hp;
    unsigned long	address;
    int	port;
    char    *ptr;
    int	rndlen;
    struct nd_addrlist *nd_addrlistp = NULL;
    struct netbuf   *netbufp;
    char   *addr;
#ifdef DEBUG
    fprintf(stderr, "in ConvertName %s\n", entry);
#endif
    if((nd_addrlistp = GetHostServiceByName(entry, atoi(dispno))) == NULL)
	return(n);
    netbufp = nd_addrlistp->n_addrs;       /* the netbufs */
    /*
      xhost needs only the last four bytes of the address
      over TCP/IP. 
      */
    if(	
       strcmp(netconfigp->nc_protofmly, "inet") == 0 && 
       strcmp(netconfigp->nc_proto    , "tcp") == 0
       ){
	addr = &netbufp->buf[4];
	len = 4;
	family = 1;
    }
    else
    {
	family = 0;
	addr = netbufp->buf;
	len = netbufp->len;
    }
    rndlen = ((sizeof(xHostEntry) + len + 3) >> 2) << 2;
    
    if((*pktptr = staticalloc(*pktptr, n+rndlen)) == NULL)
    {
	(void) netdir_free((char *)nd_addrlistp, ND_ADDRLIST);
	return(-1);
    }
    
    ptr = &(*pktptr)[n];
    ((xHostEntry *)ptr)->family = family;
    ((xHostEntry *)ptr)->length = len;
    ptr += sizeof(xHostEntry);
    
    memcpy(ptr, addr, len);
    netdir_free((char *)nd_addrlistp, ND_ADDRLIST);
    
#ifdef DEBUG
    ptr[len] = '\0';
    fprintf(stderr, "creating address for host %s address<%d>\n", entry, ptr);
#endif
    
    return(n+rndlen);
}

static struct nd_hostservlist *
GetHostServiceByAddr(addr, len)
    char *addr;
    int	len;
{
    struct nd_hostservlist *nd_hostservlist;
    struct netbuf	   netbuf;
    
    netbuf.buf = addr;
    netbuf.len = len;
    netbuf.maxlen = len;
    
    if(netdir_getbyaddr(netconfigp, &nd_hostservlist, &netbuf) == 0)
	return(nd_hostservlist);
    else	return(NULL);
}


static int
ConvertCallToName(pktptr, n, entry, len)
    char **pktptr, *entry;
    int	n, len;
{
    int	l, rl;
    char	*ptr;
    struct nd_hostservlist *nd_hostservlist;
    
    if((nd_hostservlist = GetHostServiceByAddr(entry, len)) == NULL)
	return(n);
    
    l = strlen(nd_hostservlist->h_hostservs->h_host);
    
    rl = ((sizeof(xHostEntry) + l + 3) >> 2) << 2;
    
    if((*pktptr = staticalloc(*pktptr, n+rl)) == NULL)
    {
	(void) netdir_free((char *)nd_hostservlist, ND_HOSTSERVLIST);
	return(-1);
    }
    
    ptr = &(*pktptr)[n];
    ((xHostEntry *)ptr)->family = 0;
    ((xHostEntry *)ptr)->length = l;
    
    ptr += sizeof(xHostEntry);
    
    sprintf(ptr, nd_hostservlist->h_hostservs->h_host);
    (void) netdir_free((char *)nd_hostservlist, ND_HOSTSERVLIST);
    
#ifdef DEBUG
    fprintf(stderr, "getting the name for host %s\n", ptr);
#endif
    
    return(rl+n);
}

static int
ConvertAddress(pktptr, n, entry, len)
    char **pktptr, *entry;
    int	n, len;
{
    register i;
    char	*ptr;
    int     l, rl; 
    struct nd_hostservlist *nd_hostservlist;
    char	*name;
    char	tcpaddr[8], *addr;
    char	addrbuf[MAX_AUTO_BUF_LEN];
    
#ifdef DEBUG
    entry[len] = '\0';
    fprintf(stderr, "Converting address %s in %s format\n",
	    entry, netconfigp->nc_netid);
#endif
    if(
       strcmp(netconfigp->nc_protofmly, "inet") == 0 &&
       strcmp(netconfigp->nc_proto    , "tcp") == 0
       ){
	addr = tcpaddr;
	memcpy(tcpaddr, tcphalf, 4);
	memcpy(&tcpaddr[4], entry, 4);
	len = 8;
#ifdef DEBUG
	fprintf(stderr, "port %d, family %d\n",
		*(short *) &tcpaddr[2], *(short *) tcpaddr);
#endif
    }
    else
    {
	addr = entry;
    }
    
    if((nd_hostservlist = GetHostServiceByAddr(addr, len)) == NULL)
    {
	int	i;
	
	for(i=0; i< len; i++)
	    if(entry[i] < ' ' || entry[i] > 0177)
		break;
	if(i < len)
	{
	    sprintf(addrbuf, "%d", *(int *) entry);
	    name = addrbuf;
	    len = strlen(name);
	}
	else	name = entry;
	entry[len] = '\0';
	l = len + 1;
    }
    else
    {
	name = nd_hostservlist->h_hostservs->h_host;
	l = strlen(name) +1;
    }
    rl = ((sizeof(xHostEntry) + l + 3) >> 2) << 2;
    
    if((*pktptr = staticalloc(*pktptr, n+rl)) == NULL)
    {
	if(nd_hostservlist != NULL)
	    (void) netdir_free((char *)nd_hostservlist, ND_HOSTSERVLIST);
	return(-1);
    }
    
    ptr = &(*pktptr)[n];
    ((xHostEntry *)ptr)->family = 0;
    ((xHostEntry *)ptr)->length = l;
    ptr += sizeof(xHostEntry);
    
    memcpy(ptr, name, l);	
    if(nd_hostservlist != NULL)
	(void) netdir_free((char *)nd_hostservlist, ND_HOSTSERVLIST);
    
#ifdef DEBUG
    fprintf(stderr, "getting the name for host %s\n", name);
#endif
    
    return(n+rl);
}

static char *
getnextentry(plen)
    int	*plen;
{
    char	*ptr;
    int	n = nextentry;
    
#ifdef DEBUG
    fprintf(stderr,"In getnextentry()\n");
#endif
    if(inbuf >= TheEnd)
    {
#ifdef DEBUG
	fprintf(stderr,"In getnextentry() end of buffer\n");
#endif
	*plen = -1;
	return(NULL);	
    }
    
    *plen = nextentry;
    family = ((xHostEntry *) inbuf)->family;
    ptr = inbuf + sizeof(xHostEntry);
    inbuf += ((sizeof(xHostEntry) + *plen + 3) >> 2) << 2;
    nextentry = ((xHostEntry *) inbuf)->length;
    ptr[*plen] = '\0';
    return(ptr);
}

static char *
makePacket(plen)
    int *plen;
{
    char *pktptr = NULL, *ptr;
    int	len;
    int	n = 0, m;
    
    
#ifdef DEBUG
    fprintf(stderr,"In makePacket()\n");
#endif
    
    for(nHosts = 0; nHosts < nhosts;)
    {
	ptr = getnextentry(&len);
	if(len < 0)
	    break;
	if(len == 0 || ptr == NULL)
	    continue;	
	m = addentry(&pktptr, n, ptr, len);
	if(m > n){
	    nHosts++;
	    n = m;
	}
    }
#ifdef DEBUG
    fprintf(stderr, "packet size is %d\n", n);
#endif
    
    *plen = n;
    
    return(pktptr);
}

static int
addentry(pktptr, n, entry, len)
    char **pktptr, *entry;
    int	n, len;
{
    
#ifdef DEBUG
    fprintf(stderr, "in addEntry %s\n", entry);
#endif
    
    switch(flags)
    {
    case	ConvertNameToNetAddr:
	return(ConvertName(pktptr, n, entry, len));
    case	ConvertNetAddrToName:
	return(ConvertAddress(pktptr, n, entry, len));
    case	ConvertTliCallToName:
	return(ConvertCallToName(pktptr, n, entry, len));
    }
    return(-1);
}

static char *
staticalloc(ptr, size)
    char *ptr;
    int	size;
{
    
	if(ptr == NULL)
	{
		if(bufsize < size)
			bufsize = size;
		ptr = malloc(bufsize);
	}
	if(bufsize < size)
	{
		bufsize = size + 512;
		ptr = realloc(ptr, bufsize);
	}
	return(ptr);
}

static int
OpenVirtualCircuit(lfd)
    int     lfd;
{
	char	*clonedev;
	int	fd;

       	clonedev = Network._net[_XsTypeOfStream[lfd]]->nc_device;

	if ((fd = t_open(clonedev,  O_RDWR, NULL)) < 0)
	{
		fprintf(stderr, "Cannot open %s\n", clonedev);
		return(-1);
	}
	
	if(t_bind(fd, NULL, NULL) < 0)	
	{
		t_error("t_bind failed");
		t_close(fd);
		return(-1);
	}
	return(fd);
}

#endif /* XSTREAMS_COMPILE */
