246 lines
4.5 KiB
C
246 lines
4.5 KiB
C
/* 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
|