#ifndef lint
static char sccsid[] = "%W% (UKC) %G%";
#endif  lint
/*
 * rexinit - the first stage of a remote execution.
 * There is one link to this program for each of the available remotely
 * executing programs.
 * It is called under the name of the service it is to connect to.
 * Establish connection to the remote machine and exec the rpc server this end.
 */

#include <stdio.h>

#include <sys/time.h>		/* needed by resource.h */
#include <sys/resource.h>	/* for propagating CPU time limit */

#include <sys/tsbsp.h>
#include <libtsb.h>
#include "trans.h"
#include "config.h"

char *strcpy();
char *strcat();
char *rindex();
char *getenv();

char **environ;

extern char rexversion[];	/* version number string */

char rpcsrv[]	= RPCSRV;

static int tsfd;

main(argc,argv)
char **argv;
{
	register short envc;
	char *argptr;
	char called[256];
	char strtsfd[3];
	char *rexhost;
	struct rlimit rlimit;
	char *theirversion;
	tscmd_t *reply;		/* response to CONNECT */

	if ( (tsfd = gettsb()) < 0 ) {
		fputs("rexinit: No free tsb ports.\n", stderr);
		exit(-1);
	}
	/* Construct the path to the server we want */
	/* Strip argv[0] down to name */
	if (argptr = rindex(argv[0],'/')) argv[0] = argptr + 1;

	rexhost = getenv("REXHOST");
	if (rexhost == NULL) rexhost = REXHOST;
	(void) strcpy(called,rexhost);
	(void) strcat(called,"/srv/");

	/*(void) strcat(called,argv[0]); /* the remote version of ourselves */
					 /* Bodge for now  - rexboot looks at */
	(void) strcat(called,"rexboot"); /* the argv0 we send it */

	reply = tsconnect(tsfd, called, "", "", "");
	switch (reply->ts_command) {
	case TS_ACCEPT:
		break;

	case TS_DISCONNECT:
		/* Decode reason */
		switch (reply->ts_par[0][0]) {
		case TE_BROKEN:		/* Host down */

	/*
	 * Receive back version number string, which should match ours.
	 * It is done in this direction so that the failure report happens
	 * on the initiating machine.
	 *
	 * Tell recvstring to malloc us enough space.
	 */
	(void) recvstring(tsfd, &theirversion, -1);
	if (strcmp(theirversion, rexversion) != 0) {
		fprintf(stderr, "rexinit: Local and remote software version strings differ.\n");
		fprintf(stderr, "Their version = %s\nOur   version = %s\n",
			theirversion, rexversion);
		/* The other end can just die horribly */
		exit(1);
	}
	free(theirversion);

	/*
	 *	Send argv and envp structures
	 */
	sendvstruct(tsfd, (short) argc, argv);
	for (envc=0; environ[envc]; envc++);	/* Work out envc */
	sendvstruct(tsfd, envc, environ);

	/*
	 * Send CPU time limit for remote troff under batch.
	 * (*not* datasize as troff needs lots when running incore)
	 */
	if (getrlimit(RLIMIT_CPU, &rlimit) != 0) {
		perror("rexinit: getrlimit failed");
		exit(1);
	}
	sendint(tsfd, rlimit.rlim_cur);
	sendint(tsfd, rlimit.rlim_max);

	/* Need to flush TS buffers before exec */
	rpcflush(tsfd);

	/*
	 *	rpcsrv needs to know which fd is the tsb connection;
	 *	passed as a string argument
	 */
	(void) sprintf(strtsfd,"%d",tsfd);
	execl(rpcsrv,rpcsrv,strtsfd,0);
	fprintf(stderr,"%s: could not exec %s\n", argv[0], rpcsrv);
	exit(1);
}
