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.3 (Berkeley) 06/06/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) (1 << ((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 int readfrom, ready; 56 int one = 1; 57 struct servent *sp; 58 int 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 signal(SIGINT, sendsig); 157 signal(SIGQUIT, sendsig); 158 signal(SIGTERM, sendsig); 159 pid = fork(); 160 if (pid < 0) { 161 perror("fork"); 162 exit(1); 163 } 164 ioctl(rfd2, FIONBIO, &one); 165 ioctl(rem, FIONBIO, &one); 166 if (pid == 0) { 167 char *bp; int rembits, wc; 168 (void) close(rfd2); 169 reread: 170 errno = 0; 171 cc = read(0, buf, sizeof buf); 172 if (cc <= 0) 173 goto done; 174 bp = buf; 175 rewrite: 176 rembits = 1<<rem; 177 if (select(16, 0, &rembits, 0, 0) < 0) { 178 if (errno != EINTR) { 179 perror("select"); 180 exit(1); 181 } 182 goto rewrite; 183 } 184 if ((rembits & (1<<rem)) == 0) 185 goto rewrite; 186 wc = write(rem, bp, cc); 187 if (wc < 0) { 188 if (errno == EWOULDBLOCK) 189 goto rewrite; 190 goto done; 191 } 192 cc -= wc; bp += wc; 193 if (cc == 0) 194 goto reread; 195 goto rewrite; 196 done: 197 (void) shutdown(rem, 1); 198 exit(0); 199 } 200 sigsetmask(omask); 201 readfrom = (1<<rfd2) | (1<<rem); 202 do { 203 ready = readfrom; 204 if (select(16, &ready, 0, 0, 0) < 0) { 205 if (errno != EINTR) { 206 perror("select"); 207 exit(1); 208 } 209 continue; 210 } 211 if (ready & (1<<rfd2)) { 212 errno = 0; 213 cc = read(rfd2, buf, sizeof buf); 214 if (cc <= 0) { 215 if (errno != EWOULDBLOCK) 216 readfrom &= ~(1<<rfd2); 217 } else 218 (void) write(2, buf, cc); 219 } 220 if (ready & (1<<rem)) { 221 errno = 0; 222 cc = read(rem, buf, sizeof buf); 223 if (cc <= 0) { 224 if (errno != EWOULDBLOCK) 225 readfrom &= ~(1<<rem); 226 } else 227 (void) write(1, buf, cc); 228 } 229 } while (readfrom); 230 (void) kill(pid, SIGKILL); 231 exit(0); 232 usage: 233 fprintf(stderr, 234 "usage: rsh host [ -l login ] [ -n ] command\n"); 235 exit(1); 236 } 237 238 sendsig(signo) 239 char signo; 240 { 241 242 (void) write(rfd2, &signo, 1); 243 } 244