Minix1.5/amoeba/util/rsh.c

Compare this file to the similar file:
Show the results in this format:

/*	rsh [-ei] machine command
 *
 *	-b:	run remote process in background
 *	-e:	separate error output
 *	-i:	send input
 */

#include <stdio.h>
#include <signal.h>
#include "amoeba.h"
#include "sherver.h"

char *prog, *mach, buf[BUFFERSIZE];

usage(){
	fprintf(stderr, "Usage: %s [-bei] machine command ...\n", prog);
	exit(1);
}

panic(s)
char *s;
{
	fprintf(stderr, "%s: %s\n", prog, s);
	exit(1);
}

char *collect(buf, vec, sep)
char *buf, **vec, sep;
{
	register char *p;

	while ((p = *vec++) != 0) {
		while (*p != 0) {
			*buf++ = *p++;
			if (buf == &buf[BUFFERSIZE])
				panic("environment too large\n");
		}
		*buf++ = *vec == 0 ? 0 : sep;
	}
	return(buf);
}

char *setupbuf(argv, flags)
char **argv;
int *flags;
{
	register char *p;
	extern char **environ, *getenv();

	if (*argv == 0) {
		if ((p = getenv("SHELL")) == 0)
			p = "/bin/sh";
		if (strlen(p) > BUFFERSIZE - 10) /* 10 > strlen("exec  -i") */
			panic("pathname of shell too large");
		sprintf(buf, "exec %s -i", p);
		p = &buf[strlen(buf) + 1];
		*flags |= IFLG;
	}
	else
		p = collect(buf, argv, ' ');
	return collect(p, environ, 0);
}

execute(hdr, p, flags)
header *hdr;
char *p;
{
	register unshort cnt;

	timeout(50);
	strncpy(&hdr->h_port, mach, PORTSIZE);
	hdr->h_command = EXEC_COMMAND;
	hdr->h_size = p - buf;
	hdr->h_extra = flags;
	cnt = trans(hdr, buf, p - buf, hdr, buf, BUFFERSIZE);
	if ((short) cnt < 0) {
		fprintf(stderr, "%s: %s not available\n", prog, mach);
		return(0);
	}
	if (hdr->h_status != COMM_DONE) {
		if (cnt == 0)
			fprintf(stderr, "can't execute command\n");
		else
			fprintf(stderr, "%.*s\n", cnt, buf);
		return(0);
	}
	return(1);
}

alrm(){
	fprintf(stderr, "rsh: getreq timed out\n");
	exit(1);
}

commandloop(hdr)
header *hdr;
{
	register unshort cnt;

	for (;;) {
		alarm(12*60*60);
		cnt = getreq(hdr, buf, BUFFERSIZE);
		alarm(0);
		if ((short) cnt < 0) {
			fprintf(stderr, "getreq failed\n");
			return(-1);
		}
		switch (hdr->h_command) {
		case READ_FD:
			if (hdr->h_extra < NFD)
				cnt = read(hdr->h_extra, buf, hdr->h_size);
			else
				fprintf(stderr, "read: bad fd\n");
			hdr->h_size = (unshort) cnt;
			putrep(hdr, buf, cnt < 0 ? 0 : cnt);
			if (cnt == 0)
				return(0);
			break;
		case WRITE_FD:
			if (hdr->h_extra < NFD)
				if (cnt == 0)
					close(hdr->h_extra);
				else
					write(hdr->h_extra, buf, cnt);
			else
				fprintf(stderr, "write: bad fd\n");
			putrep(hdr, NILBUF, 0);
			break;
		case EXIT_STATUS:
			if (cnt != 0) {
				write(2, "Remote message: ", 16);
				write(2, buf, cnt);
				write(2, "\n", 1);
			}
			putrep(hdr, NILBUF, 0);
			return(hdr->h_extra >> 8);
			break;
		default:
			fprintf(stderr, "unknown command\n");
			putrep(hdr, NILBUF, 0);
		}
	}
}

setupin(hdr)
header *hdr;
{
	register pid;

	uniqport(&hdr->h_priv.prv_random);
	if ((pid = fork()) < 0) {
		perror(prog);
		exit(-1);
	}
	if (pid == 0) {
		hdr->h_port = hdr->h_priv.prv_random;
		_exit(commandloop(hdr));   /* get read commands from sherver */
	}
	return(pid);
}

main(argc, argv)
char **argv;
{
	char *p;
	header hdr;
	register pid, status;
	int flags;

#ifdef sun
	put_user_name_in_env();
#endif
	prog = *argv++;
	if (argc == 1)
		usage();
	signal(SIGALRM, alrm);
	while (*argv != 0 && **argv == '-') {
		while (*++*argv)
			switch (**argv) {
			case 'b':	flags |= BFLG;		break;
			case 'e':	flags |= EFLG;		break;
			case 'i':	flags |= IFLG;		break;
			default:	usage();
			}
		argv++;
	}
	if ((mach = *argv++) == 0)
		usage();
	chkperm(mach);
	p = setupbuf(argv, &flags);	/* get command and environment */
	if (flags & IFLG)		/* set up input process */
		pid = setupin(&hdr);
	if (!execute(&hdr, p, flags)) {	/* send command to sherver */
		if (flags & IFLG)
			kill(pid, SIGKILL);
		exit(1);
	}
	if (!(flags & BFLG))		/* get commands from sherver */
		status = commandloop(&hdr);
	if (flags & IFLG) {		/* wait for input process */
		close(0); close(1); close(2);
		while (wait((int *) 0) != pid)
			;
	}
	exit(status);
}

chkperm(svport)
char *svport;
{
	static char chkfil[] = "/etc/XXXXXXXXXXXXXX";
	extern char *strchr();

	sprintf(strchr(chkfil, 'X'), "rsh:%.14s", svport);
	if (chkprot(chkfil, "/etc/rsh:default", geteuid(), getegid()) == 0)
		panic("permission denied");
}

char *strchr(s, c)
register char *s;
{
	while (*s) {
		if (*s == c)
			return s;
		s++;
	}
	return 0;
}

#ifdef sun
#include <pwd.h>

put_user_name_in_env()
{
	extern struct passwd *getpwuid();
	register struct passwd *pw;
	static char buf[512];
	char host[10];

	gethostname(host, sizeof host);
	pw = getpwuid(getuid());
	sprintf(buf, "UserName=%s@%s", pw ? pw->pw_name : "???", host);
	putenv(buf);
}
#endif sun