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