1: /* 2: * Copyright (c) 1983 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: char copyright[] = 9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: #endif not lint 12: 13: #ifndef lint 14: static char sccsid[] = "@(#)rsh.c 5.4 (Berkeley) 8/28/85"; 15: #endif not lint 16: 17: #include <sys/types.h> 18: #include <sys/socket.h> 19: #include <sys/ioctl.h> 20: #include <sys/file.h> 21: 22: #include <netinet/in.h> 23: 24: #include <stdio.h> 25: #include <errno.h> 26: #include <signal.h> 27: #include <pwd.h> 28: #include <netdb.h> 29: 30: /* 31: * rsh - remote shell 32: */ 33: /* VARARGS */ 34: int error(); 35: char *index(), *rindex(), *malloc(), *getpass(), *sprintf(), *strcpy(); 36: 37: struct passwd *getpwuid(); 38: 39: int errno; 40: int options; 41: int rfd2; 42: int sendsig(); 43: 44: #define mask(s) (1L << ((s) - 1)) 45: 46: main(argc, argv0) 47: int argc; 48: char **argv0; 49: { 50: int rem, pid; 51: char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0; 52: register int cc; 53: int asrsh = 0; 54: struct passwd *pwd; 55: long readfrom, ready; 56: long one = 1; 57: struct servent *sp; 58: long omask; 59: 60: host = rindex(argv[0], '/'); 61: if (host) 62: host++; 63: else 64: host = argv[0]; 65: argv++, --argc; 66: if (!strcmp(host, "rsh")) { 67: host = *argv++, --argc; 68: asrsh = 1; 69: } 70: another: 71: if (argc > 0 && !strcmp(*argv, "-l")) { 72: argv++, argc--; 73: if (argc > 0) 74: user = *argv++, argc--; 75: goto another; 76: } 77: if (argc > 0 && !strcmp(*argv, "-n")) { 78: argv++, argc--; 79: (void) close(0); 80: (void) open("/dev/null", 0); 81: goto another; 82: } 83: if (argc > 0 && !strcmp(*argv, "-d")) { 84: argv++, argc--; 85: options |= SO_DEBUG; 86: goto another; 87: } 88: /* 89: * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin 90: * to work 91: * 92: * There must be a better way to do this! -jmb 93: */ 94: if (argc > 0 && !strncmp(*argv, "-L", 2)) { 95: argv++, argc--; 96: goto another; 97: } 98: if (argc > 0 && !strncmp(*argv, "-w", 2)) { 99: argv++, argc--; 100: goto another; 101: } 102: if (argc > 0 && !strncmp(*argv, "-e", 2)) { 103: argv++, argc--; 104: goto another; 105: } 106: if (argc > 0 && !strncmp(*argv, "-8", 2)) { 107: argv++, argc--; 108: goto another; 109: } 110: if (host == 0) 111: goto usage; 112: if (argv[0] == 0) { 113: if (asrsh) 114: *argv0 = "rlogin"; 115: execv("/usr/ucb/rlogin", argv0); 116: perror("/usr/ucb/rlogin"); 117: exit(1); 118: } 119: pwd = getpwuid(getuid()); 120: if (pwd == 0) { 121: fprintf(stderr, "who are you?\n"); 122: exit(1); 123: } 124: cc = 0; 125: for (ap = argv; *ap; ap++) 126: cc += strlen(*ap) + 1; 127: cp = args = malloc(cc); 128: for (ap = argv; *ap; ap++) { 129: (void) strcpy(cp, *ap); 130: while (*cp) 131: cp++; 132: if (ap[1]) 133: *cp++ = ' '; 134: } 135: sp = getservbyname("shell", "tcp"); 136: if (sp == 0) { 137: fprintf(stderr, "rsh: shell/tcp: unknown service\n"); 138: exit(1); 139: } 140: rem = rcmd(&host, sp->s_port, pwd->pw_name, 141: user ? user : pwd->pw_name, args, &rfd2); 142: if (rem < 0) 143: exit(1); 144: if (rfd2 < 0) { 145: fprintf(stderr, "rsh: can't establish stderr\n"); 146: exit(2); 147: } 148: if (options & SO_DEBUG) { 149: if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0) 150: perror("setsockopt (stdin)"); 151: if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0) 152: perror("setsockopt (stderr)"); 153: } 154: (void) setuid(getuid()); 155: omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM)); 156: if (signal(SIGINT, SIG_IGN) != SIG_IGN) 157: signal(SIGINT, sendsig); 158: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) 159: signal(SIGQUIT, sendsig); 160: if (signal(SIGTERM, SIG_IGN) != SIG_IGN) 161: signal(SIGTERM, sendsig); 162: pid = fork(); 163: if (pid < 0) { 164: perror("fork"); 165: exit(1); 166: } 167: ioctl(rfd2, FIONBIO, &one); 168: ioctl(rem, FIONBIO, &one); 169: if (pid == 0) { 170: char *bp; long rembits; int wc; 171: (void) close(rfd2); 172: reread: 173: errno = 0; 174: cc = read(0, buf, sizeof buf); 175: if (cc <= 0) 176: goto done; 177: bp = buf; 178: rewrite: 179: rembits = 1L<<rem; 180: if (select(16, 0, &rembits, 0, 0) < 0) { 181: if (errno != EINTR) { 182: perror("select"); 183: exit(1); 184: } 185: goto rewrite; 186: } 187: if ((rembits & (1L<<rem)) == 0) 188: goto rewrite; 189: wc = write(rem, bp, cc); 190: if (wc < 0) { 191: if (errno == EWOULDBLOCK) 192: goto rewrite; 193: goto done; 194: } 195: cc -= wc; bp += wc; 196: if (cc == 0) 197: goto reread; 198: goto rewrite; 199: done: 200: (void) shutdown(rem, 1); 201: exit(0); 202: } 203: sigsetmask(omask); 204: readfrom = (1L<<rfd2) | (1L<<rem); 205: do { 206: ready = readfrom; 207: if (select(16, &ready, 0, 0, 0) < 0) { 208: if (errno != EINTR) { 209: perror("select"); 210: exit(1); 211: } 212: continue; 213: } 214: if (ready & (1L<<rfd2)) { 215: errno = 0; 216: cc = read(rfd2, buf, sizeof buf); 217: if (cc <= 0) { 218: if (errno != EWOULDBLOCK) 219: readfrom &= ~(1L<<rfd2); 220: } else 221: (void) write(2, buf, cc); 222: } 223: if (ready & (1L<<rem)) { 224: errno = 0; 225: cc = read(rem, buf, sizeof buf); 226: if (cc <= 0) { 227: if (errno != EWOULDBLOCK) 228: readfrom &= ~(1L<<rem); 229: } else 230: (void) write(1, buf, cc); 231: } 232: } while (readfrom); 233: (void) kill(pid, SIGKILL); 234: exit(0); 235: usage: 236: fprintf(stderr, 237: "usage: rsh host [ -l login ] [ -n ] command\n"); 238: exit(1); 239: } 240: 241: sendsig(signo) 242: char signo; 243: { 244: 245: (void) write(rfd2, &signo, 1); 246: }