xref: /original-bsd/usr.bin/rsh/rsh.c (revision ec7df300)
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