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

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 int svr4plus = 0;
static char clonedev[MAX_AUTO_BUF_LEN];

static int OpenAndBind();
static int Read();

/* Routines for handling TLI streams */

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

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

        if(NameServer < 0 &&
		 (NameServer = OpenLocalServer(NAME_SERVER_NODE)) < 0)
	{
                        return(-1);
	}

	dispno = display;

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

/* pcc */
	if(first)	{
		Network._nnets = X_TLI_STREAM;
		first = 0;
	}
	type = Network._nnets++;

	if((Network._net[type] = malloc(n)) == NULL){
             		PRMSG( "malloc failed\n",0,0);
			return(-2);
			}

	memcpy(Network._net[type], stype, n);

	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 = OpenAndBind(machine.nodename, atoi(display), MAXCONNECTIONS, Network._net[type], type);
	
	if( fd < 0){
		PRMSG("Cannot OpenAndBind %s", machine.nodename,0);
		free(Network._net[type]);
		return(-2);
		}


	_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);
			return(-1);
	    }
	    if((tmp->CurrentCall = (struct t_call *) t_alloc(fd,T_CALL,T_ALL)) == NULL)
            {
			PRMSG( "t_alloc failed\n",0,0);
			return(-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);
}
_XsCallTliServer(host, idisplay, nettype)
    char *host;
    int	idisplay;
    char *nettype;
{
	int	fd, i, t;
	PFV	savef;
	int	netlen, type;
	char	*retptr, *ptr;
	char	first = 1;
	char	netbuffer[MAX_AUTO_BUF_LEN];
	static	char	firstime = 1;

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

        if(NameServer<0 && (NameServer = OpenLocalServer(NAME_SERVER_NODE)) < 0)
	{
			return(-1);
	}

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

	savef = signal (SIGALRM, dummy);

/* 
 * Give up after MAX_TRIES tries or for CONNECT_TIME seconds or an error
 * occurred which comes first.
*/

	retptr = NULL;

#define MAX_TRIES	3
#define CONNECT_TIME    10

	alarm (CONNECT_TIME);

	if(svr4plus)
	{
		int	naddrs, n, j;

		if(GetNetworkInfo (-1, nettype, ConvertNameToTliCall,
                      addheader(host, strlen(host)), &retptr, &naddrs) <= 0)
		{
                	fprintf(stderr, "Cannot create address for system %s \n", 
			host);
			t = -1;
			goto outofloop;
		}

                call.opt.len = 0;
                call.opt.maxlen = 0;
                call.opt.buf = NULL;

                call.udata.len = 0;
                call.udata.maxlen = 0;
                call.udata.buf = NULL;
#ifdef DEBUG
fprintf(stderr, "We got %d addresses for host %s\n", naddrs, host);
fprintf(stderr, "NETPATH sent to daemon is %s\n", nettype);
#endif
		ptr = retptr;
		for(i=0; i< naddrs; i++)
		{
                        call.addr.len = ((xHostEntry *) ptr)->length;
                        call.addr.maxlen = ((xHostEntry *) ptr)->length;
                        call.addr.buf = (ptr+sizeof(xHostEntry));

			call.addr.buf[call.addr.len] = '\0';
#ifdef DEBUG
			fprintf(stderr, "ADDRESS LENGTH IS %d\n", call.addr.len);
			fprintf(stderr, "Address returned is <%s>\n",call.addr.buf);
#endif
			ptr += (((sizeof(xHostEntry) + call.addr.len+3) >> 2) << 2);

			n =  ((xHostEntry *) ptr)->length;
			if(n > 0)
                                nettype = (ptr+sizeof(xHostEntry));
			else	nettype = NULL;
		
			ptr += (((sizeof(xHostEntry) + n+3) >> 2) << 2);
			n = ((xHostEntry *) ptr)->length;
			sprintf(clonedev, "%s", (ptr+sizeof(xHostEntry)));

			ptr += (((sizeof(xHostEntry) + n+3) >> 2) << 2);
#ifdef DEBUG
            		fprintf(stderr, "Clonedev is %s\n", clonedev);
            		fprintf(stderr, "netid is %s\n", nettype);
#endif
			
			fd = OpenAndBind(NULL, -1, 0, nettype, X_TLI_STREAM);
			if(fd  < 0)
			{
				PRMSG("Openandbind failed\n",0,0);
				continue;	
			}
			t = -1;

	                PRMSG("Connecting to %s ... \n", host, 0);
			if((t = t_connect(fd, &call, NULL)) < 0)
			{
       	          		if(t_errno == TLOOK)
       	                 	{
       	                  		checkNewEvent(fd);
       	                         	t_close(fd);
       	                 	}
       	                 	else
       	                 	{
       	                  		t_error("t_connect failed");
       	                         	t_close(fd);
       	                 	}
			} else break;

		}
	}
	else
	for(i=0; i < MAX_TRIES;i++)
	{
	
		if((fd = OpenAndBind(NULL, -1, 0, nettype, X_TLI_STREAM)) < 0)
		{
				PRMSG("Openandbind failed\n",0,0);
				break;	
		}
	 	if(first)
		{
			first = 0;

	   		if( GetNetworkInfo (-1, nettype, ConvertNameToTliCall,
				 addheader(host, strlen(host)),  &retptr, NULL) <= 0)
			{
				fprintf(stderr,
					"Cannot create address for system %s\n",host);
				t = -1;
				goto outofloop;
	   		}

			ptr = retptr;

	   		call.addr.len = ((xHostEntry *) ptr)->length;
	   		call.addr.maxlen = ((xHostEntry *) ptr)->length;
			call.addr.buf = (ptr+sizeof(xHostEntry));
		
			call.addr.buf[call.addr.len] = '\0';
#ifdef DEBUG
			fprintf(stderr, "ADDRESS LENGTH IS %d\n", call.addr.len);
			fprintf(stderr, "Address returned is <%s>\n",call.addr.buf);
#endif
			ptr += (((sizeof(xHostEntry) + call.addr.len+3) >> 2) << 2);

			call.opt.len = ((xHostEntry *) ptr)->length;
			call.opt.maxlen = ((xHostEntry *) ptr)->length;
			if(call.opt.len > 0)
				call.opt.buf = (ptr+sizeof(xHostEntry));
			else	call.opt.buf = NULL;
		
			ptr += (((sizeof(xHostEntry) + call.opt.len+3) >> 2) << 2);

			call.udata.len = ((xHostEntry *) ptr)->length;
			call.udata.maxlen = ((xHostEntry *) ptr)->length;
			if(call.udata.len > 0){
				call.udata.buf = (ptr+sizeof(xHostEntry));
#ifdef DEBUG
			fprintf(stderr, "ADDRESS LENGTH IS %d\n", call.udata.len);
                        fprintf(stderr, "Address returned is <%s>\n",call.udata.buf);
#endif
			}
			else	call.udata.buf = NULL;
#ifdef DEBUG
			fprintf(stderr, "addrlen %d optlen %d udatalen %d\n",
					call.addr.len,
					call.opt.len,
					call.udata.len);
#endif
		}

		t = -1;

		PRMSG("Connecting to %s ... \n", host, 0);
		if((t = t_connect(fd, &call, NULL)) < 0)
		{
			if(t_errno == TLOOK)
			{
				checkNewEvent(fd);
		        	t_close(fd);
				continue;
			}
			else
			{
				t_error("t_connect failed");
				t_close(fd);
				break;
			}
		} else break;
	}

outofloop:

#undef MAX_TRIES
#undef CONNECT_TIME

	alarm (0);
	signal (SIGALRM, savef);

	close(NameServer);
	NameServer = -1;
	netlen = strlen(nettype);
	if(netlen > 127)
	{
		netlen = 127;
		nettype[netlen] = '\0';
	}
	memcpy(netbuffer, nettype, netlen + 1);
	if(retptr != NULL)
		free(retptr);
	if(t < 0)
	{
		close(fd);
		return(-1);
	}

/*
	if (t_rcvconnect (fd, &call) < 0) {
		if(t_errno == TLOOK)
			checkNewEvent(fd);
		t_close(fd);
		t_error ("t_rcvconnect failed!");
		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);
	}

        if (_XsInputBuffer[fd].DataBuffer == NULL)
            if ((_XsInputBuffer[fd].DataBuffer = (char *) malloc(BUFFERSIZE)) == NULL)
               {
		        errno = ENOMEM;
               		perror("Client can't connect to remote server");
			close(fd);
               		return (-1);
               }
	_XsInputBuffer[fd].LastBytePtr = 0;
	_XsInputBuffer[fd].FirstBytePtr = 0;
	type = -1;
	for(i= X_TLI_STREAM; i< Network._nnets; i++)
	{
		if(strcmp(nettype, Network._net[i]) == 0)
		{
			type = i;
			break;
		}
	}
	if(type < 0)
	{
		Network._net[Network._nnets] = malloc(netlen+1);
		if(Network._net[Network._nnets] == NULL)
		{
		        errno = ENOMEM;
               		perror("Client can't connect to remote server");
			close(fd);
               		return (-1);
               }
	       memcpy(Network._net[Network._nnets], netbuffer, netlen+1);
	       type = Network._nnets++;
	}
	_XsTypeOfStream[fd] = type;
	PRMSG("A Connection has been established to %s ... \n", host,0);
	PRMSG("CallTliServer() returns success\n",0,0);

	return(fd);
}

static int
OpenAndBind(name, port, maxcon, nettype, type)
    char *name;
    int	port, maxcon, type;
    char *nettype;
{
	char	bind_buf[MAX_AUTO_BUF_LEN];
	int	i, fd;
	char	*retptr;
	
	if(!svr4plus)
		sprintf(clonedev, "/dev/%s", nettype);
	if(name != NULL)
		PRMSG("OpenAndBind name %s, clonedev is %s \n",
				 name, clonedev);

	/* point to the virtual circuit */

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

	_XsTypeOfStream[fd] = type;
	/* fill in the request call structure with necessary infomation */

	if(name != NULL)
	{
	   if(GetNetworkInfo (-1, nettype, ConvertNameToTliBind, 
		addheader(name, strlen(name)), &retptr, NULL)<0)
	   {
		PRMSG("Cannot create address for system %s \n", name, 0);
		return(-1);
	   }
	   bind_req.addr.buf = bind_buf;
	   bind_req.addr.len = ((xHostEntry *) retptr)->length;
	   memcpy (bind_buf, retptr+sizeof(xHostEntry), bind_req.addr.len);
	   free(retptr);
	   bind_buf[bind_req.addr.len] = '\0';
#ifdef DEBUG
	   fprintf(stderr, "ADDRESS LENGTH IS %d\n", bind_req.addr.len);
	   fprintf(stderr, "Address returned is <%s>\n", bind_buf);
#endif
	   bind_req.qlen = maxcon;

	/* bind the name to the transport endpoint.  This operation will */
	/* take some time if the name is not already in the local name  */
	/* table or if the name is not a group name   */
#ifdef SHARELIB
#define t_bind (*_libX_t_bind)
#endif
		i = t_bind (fd, &bind_req, NULL) ;
	}
	else 	i = t_bind (fd, NULL, NULL);

	if(i < 0)
	{
		t_error("t_bind failed");
		close(fd);
		return(-1);
	}

#ifdef SHARELIB
#undef t_bind
#endif
	if(name != NULL)
		PRMSG("OpenAndBind(%s, %d) (success)\n", name, maxcon);
	return(fd);
}

static char *erazeComment(line)
    char *line;
{
 	char	*ptr = line;

        while(*ptr <= ' ' && *ptr != '\0')
                        ptr++;
/*
 *	If you want to check the version do it here
 *if( strncmp(ptr, "#VERSION", 8) == 0)
 *			return(NULL);
 */
   	if(*ptr == '\0' || *ptr == '#'){
                        return(NULL);
                        }
	line = ptr;
	while(*ptr != '\0' && *ptr != '#')
                        ptr++;
	*ptr = '\0';
	return(line);
}


#define XNETDB "lib/Xconnections"

int _XMakeStreamsConnection (name, idisplay, retries,
			     familyp, serveraddrlenp, serveraddrp)
    char	*name;
    int	idisplay;
    int	retries;
    int	*familyp;		/* return */
    int	*serveraddrlenp;	/* return */
    char **serveraddrp;		/* return */
{
	struct	utsname	 machine;
	register	i;
	FILE	*file;
	char	*line, *ptr,buf[160];
	int	fd, nfound = 0, n;
	static  char	netype[MAX_AUTO_BUF_LEN], nodname[MAX_AUTO_BUF_LEN];
	char *home;
	char	sysname[128] ;
	char	*procname = "Xlib/_XMakeStreamsConnection";



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

        if(uname(&machine) < 0){
		t_error("Cannot get nodename");
		return(-1);
		}

	if(
		name == NULL || 
		strcmp(name, "") == 0 ||
		strcmp(name, "unix") == 0 ||
		strcmp(name, "local") == 0 ||
		strcmp(name, machine.nodename) == 0 
	  )	{
		
	    /*
	     * auth information for local connection set above
	     */

	    fd = ((*_XsStream[X_LOCAL_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(machine.release[0] !=  '3')
	{
		char	*netpath;

		svr4plus = 1;
#ifdef DEBUG
		fprintf(stderr,
"sysname <%s>, nodename <%s>, release <%s>, version <%s>, machine <%s>\n",
			machine.sysname ,
			machine.nodename,
			machine.release,
			machine.version,
			machine.machine);
#endif

		if((netpath = (char *) getenv("NETPATH")) == NULL)
				netpath = "";
		return (*_XsStream[X_TLI_STREAM].CallTheListener)
				(name, idisplay, netpath);
	}

	file = fopen(home = GetXWINHome(XNETDB), "r");
	if(file == NULL){
		fprintf(stderr, "Cannot open %s\n", home);
		return(-1);
		}
	while((line = fgets(buf, 160, file)) != NULL)
	{
               	if((n = strlen(line)) > 1)
                              line[n-1] = '\0';
		if((ptr = erazeComment(line)) == NULL)
			continue;

		n = sscanf(ptr, "%s%s%s", sysname, nodname, netype);
		if(
			n >= 3 &&
			strcmp(name, sysname) == 0
		  ){
			nfound++;
		        fd = (*_XsStream[X_TLI_STREAM].CallTheListener)
						(nodname, idisplay, netype);
			if(fd >= 0)
			{
				fclose(file);
				return(fd);
			}
		   }
		else if(strcmp(sysname, "*") == 0 || strcmp(nodname, "*") == 0) 
		   {
			sprintf(nodname, name);
			fd = (*_XsStream[X_TLI_STREAM].CallTheListener)     
                                                (nodname, idisplay, netype);
			fclose(file);
                        return(fd);
		   }
	}
	fclose(file);
	if(!nfound)
	{
		fprintf(stderr, "There is no entry for %s in %s\n",
					name, home);
	}
	return(-1);
}


#ifdef DEBUG
dump(buf, len)
    char *buf;
    int	len;
{
 	int	i;
	if(buf != NULL)
		for(i=0; i< len; i++)
                        fprintf(stderr, "<%o> ", buf[i]);
	fprintf(stderr, "\n");
	fflush(stderr);
}

#endif


#define	NSECONDS	60

static int	_errflag = 0;

/* ARGSUSED */
static SIGNAL_T OnAlarm(i)
    int i;
{
	_errflag = 1;
}

static int
CallTheNameServer(service, nettype, arg1, arg2, arg3)
    char	*nettype, **arg1, **arg2;
    int	service, *arg3;
{
	int	m, n, ret;
	char   *ptr, *p;
	char	buf[MAX_AUTO_BUF_LEN];

PRMSG("In CallTheNameServer, \n", 0, 0);

	if(NameServer < 0)
		return(-1);
	if(_errflag)
	{
		int	flags;

		if((flags = fcntl(NameServer, F_GETFL)) == -1)
			flags = O_RDWR;
		fcntl (NameServer, F_SETFL, O_NDELAY);
		while(read (NameServer, buf, MAX_AUTO_BUF_LEN) > 0);
		if(errno != EAGAIN && errno != EINTR)
		{
			fprintf(stderr, "errno %d while reading the nameserver\n",
					errno);
			close(NameServer);
			NameServer = -1;
			return(-1);
		}
		fcntl (NameServer, F_SETFL, flags);
		_errflag = 0;	
	}
	
	ret = n = (* (int *) (*arg1)) + 2*sizeof(int);

        ptr = buf;
	m = HEADERSIZE + strlen(nettype)+ 1;
	m = (((m +3) >>2)<<2);

	*(int *) ptr = n+m;
	ptr += sizeof(int);
	*(int *) ptr = m;
	ptr += sizeof(int);
	*(int *) ptr = service;
	ptr += sizeof(int);
	*(int *) ptr = atoi(dispno);
	ptr += sizeof(int);
	*(int *) ptr = strlen(nettype);
	ptr += sizeof(int);
	sprintf(ptr, nettype);

  	p = malloc(m + n);
	if(p == NULL)
		return(-1);
	memcpy(p, buf, m);
	memcpy(p+m, *arg1, n);
	
	signal(SIGALRM, OnAlarm);
	alarm(NSECONDS); 

	if(write(NameServer, p, m+n) != m+n){
		fprintf(stderr, "write error\n");
		ret = -1;
		close(NameServer);
		NameServer = -1;
		}
	else if(Read(NameServer, buf, 2*sizeof(int)) == 0)
	{
		ret = -1;
#ifdef DEBUG
		fprintf(stderr, "Server fails to read header from nameserver\n");
#endif
	}
	else {
		ptr = buf;
		ret = *(int *) buf;
		ptr += sizeof(int);
		if(*(int *) ptr <= 0)
		{
#ifdef DEBUG
			fprintf(stderr, "No Of entries returned <= 0\n");
#endif
			ret = -1;
			goto theend;
		}
		if(arg3 != NULL){
			*arg3 = *(int *) ptr;
#ifdef DEBUG
			fprintf(stderr, "No Of Entries returned {%d}\n", *arg3);
#endif
			}
		ptr = *arg2 = (char *) malloc(ret );
#ifdef DEBUG
		if(ptr == NULL)
			fprintf(stderr, "MALLOC returns NULL\n");
#endif
		if(ptr == NULL)
		{
			errno = ENOMEM;
			ret = -1;
		}
		else {
			if(Read(NameServer, ptr, ret) == 0)
			{
				fprintf(stderr, 
					"Server fails to read %d chars\n", ret);
				free(*arg2);
				ret = -1;
			}
		}
	}
theend:
	alarm(0); 
	free(p);
	return(ret);
}


static int
Read(fd, buf, count)
    int	fd, count;
    char	*buf;
{
	int	n;
	while((n = read(fd, buf, count)) > 0)
	{
		if(n == count)
		{
			return(1);
		}
		buf += n;
		count -= n;
	}
	return(0);
}

static int
OpenVirtualCircuit(lfd)
    int	lfd;
{
	return(OpenAndBind(NULL, -1, 0,
		 	Network._net[_XsTypeOfStream[lfd]], _XsTypeOfStream[lfd]));
}

#endif /* XSTREAMS_COMPILE */
