ENV

#include <sys/socket.h>
#include <setjmp.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/errno.h>


/* Added returns of -1 on error, 0 for Okay.   -Kdz */

xx_getserv(host,num,sock,rc)
char *host;
int *num;
int *sock;
int *rc;
{
	struct sockaddr_in sin;
	struct servent *sp;
	struct hostent *hp;
	int s,i=0;

	char server[5];
	int flag=0;

    /* better check NULL, too. -Kdz */
	if ( (num == NULL) || (*num > 40) || (*num < 1) )
	{
		printf("Error in getserv: server number unknown\n");
		*rc = 1;
		return(-1); 
	}

	s = socket(AF_INET,SOCK_STREAM,0);
	setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *) 0,0);
	
	if ( (hp = gethostbyname(host)) == NULL )
	{
		printf("Error in getserv: %s: unknown host\n",host);
		*rc = 2;
		close(s);
		return(-1); 
	}
	else
	    printf("sox.U DEBUG: hp = %x\n",hp);

	sprintf(server,"jak%d",*num);

	if ( (sp = getservbyname(server,"tcp")) == NULL )
	{
		printf("Error in getserv: for %d server %s unknown on %s\n",
			ntohl(xx_my_id.proc_table_indx),server,host);
		*rc = 3;
		close(s);
		return(-1);
	}

	bzero( (char *) &sin, sizeof(sin) );
	bcopy( hp->h_addr, (char *) &sin.sin_addr, hp->h_length );
   	sin.sin_family = hp->h_addrtype;
	sin.sin_port = sp->s_port;

	if (flag = connect( s, (char *) &sin, sizeof(sin)))
	{
		perror("Error in getserv connect");
		*rc = 4;
		close(s);
		return(-1);
	}

	*sock = s;
	*rc = 0;

    return(0);
}


xx_sendserv(sock,proc_id,msg_type,msgtype_len,msg,length,ack)
int sock;
PROC_ID *proc_id;
int msg_type,msgtype_len;
char *msg;
int length,ack;
{
	int n=0;
	struct xx_msg_rec *buff,buff2;
	PROC_ID temp;

	buff = &buff2;
	WHO_AM_I(&temp);

	bcopy(proc_id,&(buff->target),sizeof(PROC_ID));
	bcopy(&temp,&(buff->sender),sizeof(PROC_ID));

	buff->ack = htonl(ack);
	buff->msg_type = htonl(msg_type);

	if ( msg ) {
		n = length ? length : msgtype_len;
		bcopy(msg,buff->data,n);
		}

	buff->length = htonl(n);

	if ( send(sock,buff,
		   sizeof(struct xx_msg_rec)-(MSG_BUFF_SIZE-n),
		   0) == -1 )
	{
		perror("Error in xx_sendserv send");
		return(-1); 
	}
	/*
	printf("Slave: %d just sent msg to %d size %d\n",ntohl(xx_my_id.proc_table_indx),ntohl(proc_id->proc_table_indx),n);
	*/
    return(0);
}


xx_recvserv(sock,bufr,ln,rc)
int sock;
char *bufr;
int *ln;
int *rc;
{
	/* got rid of unneeded temps.	-Kdz */

	if ( (*rc = recv(sock,bufr,*ln,0))  == -1 )
	{
		printf("Error in recvserv for %d\n",ntohl(xx_my_id.proc_table_indx));
		*rc = 2;
		return(-1); 
	}

	return(0);
}

xx_makeserv(soc_id)
int soc_id;
{
	int rc,ln,f,flag,unix_id;
	int soc2,port;
	int pid;
	struct sockaddr_in from;
	struct sockaddr_in sin;
	struct servent *sp;
	struct xx_msg_rec buf;
	char server[5];
	extern int errno;

	bzero( (char *) &sin, sizeof(sin) );

	if ((f = socket(AF_INET,SOCK_STREAM,0)) == -1) {
		printf("Error in makeserv: socket() error %d\n",errno);
		exit(errno);
	}

	if (setsockopt(f,SOL_SOCKET,SO_REUSEADDR,(char *) 0,0) == -1) {
		printf("Error in makeserv: setsocketopt() error %d\n",errno);
		exit(errno);
	}

	flag = 1;

	/* Locate an available port */

	for (port = 2;( (port < 39) && flag );port++) {

		sprintf(server,"jak%d",port);

		sp = getservbyname(server,"tcp");
		if ( sp == NULL )
		{
			printf("Error in makeserv: server unknown\n");
			close(f);
			exit(errno); 
		}

		sin.sin_port = sp->s_port;
		 
		flag = bind( f, (char *) &sin, sizeof(sin) );


		if ((flag != 0) && (errno != EADDRINUSE)) 
		{ 
			perror("Makeserv: error in bind errno = %d\n",errno);
			close(f);
			exit(); 
		}

		if ( port > 39 )
		{
			printf("Error in makeserv: no ports available\n");
			exit(); 
		}

	}


		if ( listen(f,5) != 0 )
		{
			close(f);
			printf ("Makeserv: error in listen %d\n",errno);
			exit();
		}

		/* Send port info to master */
		ln = sizeof(struct xx_msg_rec) - MSG_BUFF_SIZE;
		buf.msg_type = htonl(--port);

		send(soc_id,(char *) &buf,ln,rc);
		/* put port info in parent's proc table entry */
		xx_cmem->active_processes[ntohl(xx_my_id.proc_table_indx)]->port= port;

		/*  loop */
		for (;;) {
			ln = sizeof(from);
			soc2 = accept( f, &from, &ln );
			while ( soc2 < 0 )
			{
				if ( errno == 4) {
					soc2 = accept( f, &from, &ln );
					}
				else {
					close(f);
					printf ("Ser: error in accept %d\n",errno);
					exit();
				}
			}
			/* creat listener */
			if ( (unix_id = fork()) ==0 ) {
				close(f);
				xx_listener(soc2);
				}
			*(xx_pt_upid++) = unix_id;
			close(soc2);
			}
}


xx_listener(soc_id)
int soc_id;
{
	struct xx_msg_rec *buf_pt;
	struct xx_msg_rec buf;
	struct xx_process *p1;
	struct xx_msg *xx_m1;

	char rest[MSG_BUFF_SIZE];

	int target_indx;
	int msg_length;
	int bytes;
	int more;
	int ln;

	buf_pt = &buf;

	for (;;) 
	{
		bytes = 0;

		ln = sizeof(struct xx_msg_rec) - (MSG_BUFF_SIZE*sizeof(char));

		while ( bytes < ln )
		{
			more = recv(soc_id,rest,ln-bytes,0);

			if ( more == -1 )
			{
				perror("Error in xx_listener header recv");
				return; 
			}

			bcopy(rest,((char *) buf_pt)+bytes,more);

			bytes += more;
		}
		
		msg_length = htonl(buf_pt->length);

		bytes = 0;

		while ( bytes < msg_length ) 
		{
			more = recv(soc_id,rest,msg_length-bytes,0);

			if ( more == -1 )
			{
				perror("Error in xx_listener message recv");
				return; 
			}

			bcopy(rest,buf_pt->data+bytes,more);

			bytes += more;
		}

		/* Now stuff message into queue */
		xx_msgbuf(&xx_m1,msg_length);
		xx_m1->sender = buf_pt->sender;
		xx_m1->link = 0;
		xx_m1->type = ntohl(buf_pt->msg_type);
		xx_m1->ack = ntohl(buf_pt->ack);
		target_indx = ntohl(buf_pt->target.proc_table_indx);
		p1 = xx_cmem->active_processes[target_indx];
		if (p1 == 0) 
		{
			printf ("Listener: no entry for id = %d \n",
				ntohl(buf_pt->target.proc_table_indx));
			exit();
		}
		xx_msgcpy(buf_pt->data,msg_length,&p1,xx_m1);
	}
}


xx_connect(proc_id)
	PROC_ID *proc_id;

	{
		int n,so,i,rc;
		struct xx_process *p1;

		n = ntohl(proc_id->port);
		xx_getserv(proc_id->host,&n,&so,&rc);
		p1 = (struct xx_process *) G_MALLOC(sizeof(struct xx_process));
		xx_cmem->active_processes[ntohl(proc_id->proc_table_indx)] = p1;
		p1->socket_id = so;
		p1->port = ntohl(proc_id->port);
		MONINIT(p1->msg_q_monitor,1)
		p1->first_msg = p1->last_msg = 0;
		/* for (i=0;i<64;i++) p1->host[i] = proc_id->host[i]; */
		bcopy(proc_id->host,p1->host,64);
	}
	
/*
	using Network-Byte Order instead of strings. -Kdz
*/

xx_copy_ntoh(xx_pt1,xx_pt2)
	PROC_ID *xx_pt1;
	struct xx_proc_id *xx_pt2;

	{
	int xx_i;
	xx_pt1->proc_table_indx = ntohl(xx_pt2->proc_table_indx);
	xx_pt1->port = ntohl(xx_pt2->port);
/*	for (xx_i=0;xx_i<64;xx_i++) xx_pt1->host[xx_i] = xx_pt2->host[xx_i];*/
	bcopy(xx_pt2->host,xx_pt1->host,64);
	}

xx_copy_hton(xx_pt1,xx_pt2)
	PROC_ID *xx_pt2;
	struct xx_proc_id *xx_pt1;

	{
	int xx_i;
/*	sprintf(xx_pt1->proc_table_indx,"%d",xx_pt2->proc_table_indx);
	sprintf(xx_pt1->port,"%d",xx_pt2->port); */
	xx_pt2->proc_table_indx = htonl(xx_pt1->proc_table_indx);
	xx_pt2->port = htonl(xx_pt1->port);
	bcopy(xx_pt2->host,xx_pt1->host,64);
	/* for (xx_i=0;xx_i<64;xx_i++) xx_pt1->host[xx_i] = xx_pt2->host[xx_i]; */
	}

xx_cmp_id(xx_pt1,xx_pt2)
	PROC_ID *xx_pt1,*xx_pt2;
	{
	return(xx_pt1->proc_table_indx == xx_pt2->proc_table_indx); 
	}

xx_copy_id(xx_pt1,xx_pt2)
	PROC_ID *xx_pt1,*xx_pt2;

	{
	/*  USE bcopy instead -kdz  */ /*
	int xx_i;
	xx_pt1->proc_table_indx = xx_pt2->proc_table_indx;
	xx_pt1->port = xx_pt2->port;
	for (xx_i=0;xx_i<64;xx_i++) xx_pt1->host[xx_i] = xx_pt2->host[xx_i];
	*/
	bcopy(xx_pt2, xx_pt1, sizeof(PROC_ID) );
	}

xx_cleanup()
{
	int i;
	struct xx_process *p1;
	union wait status;
/*
	printf("Cleanup: for %d \n",ntohl(xx_my_id.proc_table_indx));
*/
	for (i=0;i<MAX_PROCS;i++) {
		p1 = xx_cmem->active_processes[i];
		if (((int)p1>1) && (i != ntohl(xx_my_id.proc_table_indx)) && (i !=0)) {
			if ( p1->upid ) {
				if ( kill(p1->upid,9) == -1 ) {
					printf ("Error %d in cleanup killing process %d\n",
					errno,p1->upid);
				}
				else if (wait(&status) == -1) 
						printf("Cleanup: error in wait for %d \n",ntohl(xx_my_id.proc_table_indx));
			}
		}
	}
}


xx_handler(sig,code,scp)
int sig,code;
struct sigcontext *scp;
	{
	int pid;
	jmp_buf env;
	union wait status;

	scp = (struct sigcontext *) malloc(sizeof(struct sigcontext));
	if ( (pid = wait(&status)) == -1) {
		printf("Ser: handler failed %d\n",errno);
		};
		/*
	printf ("Ser: in handler on signal %d \n",sig);
	printf("Ser: return from wait for %d \n",pid);
	*/
	longjmp(env,pid);
	}

xx_kill_daemon()
{
	union wait status;
	
		if ( kill(xx_daemon,9) == -1 ) {
			printf ("Error %d in cleanup killing process %d\n",
			errno,xx_daemon);
		}
		else if (wait(&status) == -1) 
						printf("Cleanup: error in wait for %d \n",ntohl(xx_my_id.proc_table_indx));
}

xx_kill_grandkids()
{
	int i;
	union wait status;
/*
*/
	xx_pt_upid = xx_upid;
	printf("Cleanup: for %d \n",ntohl(xx_my_id.proc_table_indx));
	while ( *(xx_pt_upid) ) {
		if ( kill(*(xx_pt_upid),9) == -1 ) {
			printf ("Error %d in cleanup killing process %d\n",
			errno,*(xx_pt_upid));
			}
			xx_pt_upid++;
		}
}
