2 * Copyright (c) 1983 The Regents of the University of California.
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.
18 #include <afsconfig.h>
19 #include <afs/param.h>
24 #include <unistd.h> /* select() prototype */
25 #include <sys/types.h> /* fd_set on older platforms */
26 #include <sys/time.h> /* struct timeval, select() prototype */
28 # include <sys/select.h> /* fd_set on newer platforms */
30 #include <sys/socket.h>
34 #include <sys/ioctl.h>
37 #include <netinet/in.h>
50 #define MSGSTR(n,s) NLgetamsg(MF_RSH, MS_RSH, n, s)
57 #include <afs/cellconfig.h>
63 extern char **environ;
65 #define RSHNAME "remsh"
68 #endif /* AFS_HPUX_ENV */
82 #define mask(s) (1 << ((s) - 1))
83 #if defined(AFS_AIX32_ENV) && (defined(NLS) || defined(KJI))
87 #include "AFS_component_version_number.c"
92 * We don't really need a definition for AFS_SGI_ENV since SGI's own rsh
93 * does the right thing.
95 * In some older platforms, such as SunOS 4.x, rlogin lives in /usr/ucb.
96 * But for all our currently supported platforms for AFS 3.5, it's in /usr/bin.
99 #define _PATH_RLOGIN "/usr/bsd/rlogin"
101 #define _PATH_RLOGIN "/usr/bin/rlogin"
109 char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
113 fd_set readfrom, ready;
119 int someSignals[100];
123 struct stat stat_buf;
126 #if defined(AFS_AIX32_ENV)
127 struct sigaction ign_act, save_old_act;
132 #if defined(AFS_AIX32_ENV) && (defined(NLS) || defined(KJI))
133 setlocale(LC_ALL, "");
138 * If we're being called as a non-afs version of the program, and if AFS extensions
139 * have been loaded, run the AFS version of the program.
141 check_and_run_afs_vers(argv);
143 memset(&ign_act, 0, sizeof(ign_act));
144 ign_act.sa_handler = SIG_IGN;
146 host = strrchr(argv[0], '/');
153 /* if invoked as something other than remsh or rsh, use the
154 * invocation name as the host name to connect to (clever).
156 if (!strcmp(host, "remsh") || !strcmp(host, "rsh")) {
158 host = *argv++, --argc;
161 clientname = "remsh";
164 if (!strcmp(host, RSHNAME)) {
167 if (*argv[0] != '-') {
168 host = *argv++, --argc;
175 pass_tokens = (int)getenv("KAUTH");
177 pass_tokens = (!strcmp((char *)pass_tokens, "afs"));
181 /* make sure file descriptors 0, 1, and 2 are open */
182 for (fd = 0; fd <= 2; fd++) {
183 if (fstat(fd, &stat_buf) != 0) {
184 if (open("/dev/null", O_RDWR) < 0) {
185 fprintf(stderr, "%s: ", clientname);
191 /* save a copy of original environment in case we exec rlogin */
193 int vecsize = 0, envsize = 0, i = 0;
195 while (vp != (char **)NULL && *vp != (char *)NULL) {
197 envsize += strlen(*vp) + 1;
200 vp = (char **)malloc((vecsize + 1) * sizeof(char *));
201 cp = malloc(envsize);
202 while (i < vecsize) {
204 strcpy(vp[i], environ[i]);
205 while (*cp != (char)NULL)
212 /* clear timers, close open files, and wipe out environment */
213 cleanenv(&environ, "LANG", "LANGOPTS", "NLSPATH", "LOCALDOMAIN",
217 if (argc > 0 && !strcmp(*argv, "-l")) {
220 user = *argv++, argc--;
223 if (argc > 0 && !strcmp(*argv, "-n")) {
228 (void)open("/dev/null", 0);
232 if (argc > 0 && !strcmp(*argv, "-d")) {
238 if (argc > 0 && !strcmp(*argv, "-v")) {
243 if (argc > 0 && !strcmp(*argv, "-V")) {
250 * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
253 * There must be a better way to do this! -jmb
255 if (argc > 0 && !strncmp(*argv, "-L", 2)) {
259 if (argc > 0 && !strncmp(*argv, "-w", 2)) {
263 if (argc > 0 && !strncmp(*argv, "-e", 2)) {
267 if (argc > 0 && !strncmp(*argv, "-8", 2)) {
272 if (argc > 0 && !strncmp(*argv, "-7", 2)) {
280 host = *argv++, --argc;
288 execve(_PATH_RLOGIN, argv0, vp);
290 execv(_PATH_RLOGIN, argv0);
292 perror(_PATH_RLOGIN);
295 pwd = getpwuid(getuid());
297 fprintf(stderr, "who are you?\n");
301 for (ap = argv; *ap; ap++)
302 cc += strlen(*ap) + 1;
303 cp = args = malloc(cc);
304 for (ap = argv; *ap; ap++) {
305 (void)strcpy(cp, *ap);
311 sp = getservbyname("shell", "tcp");
313 fprintf(stderr, "%s: shell/tcp: unknown service\n", RSHNAME);
316 rem = rcmd(&host, sp->s_port, pwd->pw_name,
318 user ? user : pwd->pw_name, args, &rfd2, /* long timeout? */
321 user ? user : pwd->pw_name, args, &rfd2);
326 fprintf(stderr, "%s: can't establish stderr\n", RSHNAME);
329 if (options & SO_DEBUG) {
330 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, (char *)&one, sizeof(one)) <
332 perror("setsockopt (stdin)");
333 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, (char *)&one, sizeof(one))
335 perror("setsockopt (stderr)");
337 (void)setuid(getuid());
339 memset((char *)someSignals, 0, sizeof(someSignals));
342 mask(SIGINT) | mask(SIGQUIT) | mask(SIGTERM) | mask(SIGHUP);
344 someSignals[0] = mask(SIGINT) | mask(SIGQUIT) | mask(SIGTERM);
346 sigBlock = *((sigset_t *) someSignals);
347 sigprocmask(SIG_BLOCK, &sigBlock, &oset);
349 (void)sigaction(SIGINT, &ign_act, &save_old_act);
350 if (save_old_act.sa_handler != SIG_IGN)
351 (void)signal(SIGINT, sendsig);
352 (void)sigaction(SIGQUIT, &ign_act, &save_old_act);
353 if (save_old_act.sa_handler != SIG_IGN)
354 (void)signal(SIGQUIT, sendsig);
355 (void)sigaction(SIGTERM, &ign_act, &save_old_act);
356 if (save_old_act.sa_handler != SIG_IGN)
357 (void)signal(SIGTERM, sendsig);
359 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
360 signal(SIGINT, sendsig);
361 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
362 signal(SIGQUIT, sendsig);
363 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
364 signal(SIGTERM, sendsig);
366 if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
367 signal(SIGHUP, sendsig);
368 /* ignore the death of my child -- banish zombies! */
369 signal(SIGCLD, SIG_IGN);
379 ioctl(rfd2, FIONBIO, &one);
380 ioctl(rem, FIONBIO, &one);
381 if (nflag == 0 && pid == 0) {
388 cc = read(0, buf, sizeof buf);
394 FD_SET(rem, &rembits);
395 if (select(rem + 1, 0, &rembits, 0, 0) < 0) {
396 if (errno != EINTR) {
402 if (!FD_ISSET(rem, &rembits))
404 wc = write(rem, bp, cc);
406 if (errno == EWOULDBLOCK)
416 (void)shutdown(rem, 1);
419 sigprocmask(SIG_SETMASK, &oset, (sigset_t *) 0);
421 FD_SET(rfd2, &readfrom);
422 FD_SET(rem, &readfrom);
426 if (FD_ISSET(rfd2, &readfrom) && maxfd < rfd2)
428 if (FD_ISSET(rem, &readfrom) && maxfd < rem)
433 if (select(maxfd + 1, &ready, 0, 0, 0) < 0) {
434 if (errno != EINTR) {
440 if (FD_ISSET(rfd2, &ready)) {
442 cc = read(rfd2, buf, sizeof buf);
444 if (errno != EWOULDBLOCK)
445 FD_CLR(rfd2, &readfrom);
447 (void)write(2, buf, cc);
449 if (FD_ISSET(rem, &ready)) {
451 cc = read(rem, buf, sizeof buf);
453 if (errno != EWOULDBLOCK)
454 FD_CLR(rem, &readfrom);
456 (void)write(1, buf, cc);
460 (void)kill(pid, SIGKILL);
463 fprintf(stderr, "usage: %s host [ -l login ] [ -n ] command\n", RSHNAME);
472 (void)write(rfd2, &signo, 1);