/*
 *	rpcremot.c
 *
 *	Client (Communication site)
 */

#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/signal.h>

#include "mcrpc.h"
#include "rpcfktns.h"
#include "rpcremot.h"
#include "os.h"
#include "mcfktns.h"

char hostname[256];

char	*processtype = "COMMUNICATION";

CLIENT	*cl;
workstationprognum	wspn;

unsigned long	prognum;

void *
rpc_service_stop_client_site(x)
		/* Version der remote Communications */
	void	*x;
{
		/* Vom Deamon abmelden */

	svc_unregister (prognum, V1);

		/* Vom Prozessor-Modul abmelden */
	procmod_unregister_1 (&wspn, cl);

		/* Verbindung loesen */
	clnt_destroy (cl);

	exit (0);
}



main (argc, argv)
	int	argc;
	char	*argv[];
{
	int	s;
	SVCXPRT	*xprt;

	setbuf (stdin, NULL);
	setlinebuf (stdout);
	setlinebuf (stderr);

	if (argc != 6 && argc != 4) {
		printf (stderr, "usage: %s <localname> <communication_id> <processno> <hostname> <prognum>\n", argv [0]);
		printf (stderr, "or\n", argv [0]);
		printf (stderr, "usage: %s <localname> <prognum> <authorization-code>\n", argv [0]);
		exit (1);
	}

	if (argc == 4) {
		/* killing portmap entry */
		prognum_of_initialization_server = atol (argv [2]);

		if (strcmp (argv [3], "wrdlprmpft") == 0) {
			pmap_unset (prognum_of_initialization_server, 1L);
			fprintf (stderr, "Program number '%lu' from portmap deamon at workstation '%s' removed\n",
				prognum_of_initialization_server, argv [1]);
		} else {
			fprintf (stderr, "\t<authorization-code> is invalid!\n");
			fprintf (stderr, "usage: %s <localname> <prognum> <authorization-code>\n", argv [0]);
		}
		exit (0);
	}

			/* Der Puffer wird auf Non-Buffered gesetzt */
	setbuf (IN_FILE, NULL);
	setbuf (OUT_FILE, NULL);

	gethostname (hostname, sizeof (hostname));

	wspn.modula_p_wsname = argv [1];
	wspn.real_wsname = hostname;
	wspn.commid = argv [2];
	wspn.processid = m0_processid = (int) getpid ();
	wspn.processno = m0_processno = atoi (argv [3]);

	s = RPC_ANYSOCK;
	wspn.prognum = prognum = gettransient (IPPROTO_TCP, 1, &s);

	prognum_of_initialization_server = atol (argv [5]);

	cl = clnt_create (argv [4], prognum_of_initialization_server, V1, "tcp");

	if (cl == NULL) {
		printf ("Server not found\n");
		exit (1);
	}

		/* Beim Prozessor-Modul anmelden */
	procmod_register_1 (&wspn, cl);

	
	if ((xprt = svctcp_create (s, 0, 0)) == NULL) {
		fprintf (stderr, "Host '%s': Error in svctcp_create\n", argv [1]);
		pmap_unset (prognum, V1);
		exit (1);
	}
	/* protocol is 0 - gettransient does registering */
	svc_register (xprt, prognum, V1, communication_1, IPPROTO_TCP);

	svc_run ();

	/* will only be reached in case of error */	
	rpc_service_stop_client_site (NULL);
}


extern struct comm_in;
extern struct comm_out;
extern bool_t xdr_comm_in();
extern bool_t xdr_comm_out();
extern struct comm_out *comm_procedure_1();
extern struct comm_in argument;
extern int argument_length;


static void
communication_1(rqstp, transp)
	struct svc_req *rqstp;
	SVCXPRT *transp;
{
	char *result;
	bool_t (*xdr_argument)(), (*xdr_result)();
	char *(*local)();

	switch (rqstp->rq_proc) {
	case NULLPROC:
		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
		return;

	case COMMUNICATION_PROCEDURE:
		xdr_argument = xdr_comm_in;
		xdr_result = xdr_comm_out;
		local = (char *(*)()) comm_procedure_1;
		break;

	case RPC_SERVICE_STOP:
		xdr_argument = xdr_void;
		xdr_result = xdr_void;
		local = (char *(*)()) rpc_service_stop_client_site;
		break;

	default:
		svcerr_noproc(transp);
		return;
	}
	memset ((char *) &argument, 0, argument_length);
	if (!svc_getargs(transp, xdr_argument, &argument)) {
		svcerr_decode(transp);
		return;
	}
	result = (*local)(&argument, rqstp);
	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
		svcerr_systemerr(transp);
	}
	if (!svc_freeargs(transp, xdr_argument, &argument)) {
		(void)fprintf(stderr, "unable to free arguments\n");
		exit(1);
	}
}
