/* 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