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