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