BSD 4_2 release
[unix-history] / usr / src / ucb / rsh.c
CommitLineData
4a31bc6f 1#ifndef lint
4ca10280 2static char sccsid[] = "@(#)rsh.c 4.8 83/06/10";
4a31bc6f
BJ
3#endif
4
4a31bc6f
BJ
5#include <sys/types.h>
6#include <sys/socket.h>
e7d6d17a 7#include <sys/ioctl.h>
4a31bc6f 8#include <sys/file.h>
e7d6d17a
SL
9
10#include <netinet/in.h>
11
12#include <stdio.h>
4a31bc6f
BJ
13#include <errno.h>
14#include <signal.h>
4a31bc6f 15#include <pwd.h>
e1e93bd3 16#include <netdb.h>
4a31bc6f
BJ
17
18/*
19 * rsh - remote shell
20 */
21/* VARARGS */
22int error();
23char *index(), *rindex(), *malloc(), *getpass(), *sprintf(), *strcpy();
24
25struct passwd *getpwuid();
26
27int errno;
28int options;
29int rfd2;
30int sendsig();
31
4ca10280
SL
32#define mask(s) (1 << ((s) - 1))
33
4a31bc6f
BJ
34main(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;
e1e93bd3 45 struct servent *sp;
4ca10280 46 int omask;
4a31bc6f
BJ
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 }
58another:
4659bf8e 59 if (argc > 0 && !strcmp(*argv, "-l")) {
4a31bc6f
BJ
60 argv++, argc--;
61 if (argc > 0)
62 user = *argv++, argc--;
63 goto another;
64 }
4659bf8e 65 if (argc > 0 && !strcmp(*argv, "-n")) {
4a31bc6f
BJ
66 argv++, argc--;
67 (void) close(0);
68 (void) open("/dev/null", 0);
69 goto another;
70 }
4659bf8e 71 if (argc > 0 && !strcmp(*argv, "-d")) {
4a31bc6f
BJ
72 argv++, argc--;
73 options |= SO_DEBUG;
74 goto another;
75 }
0f09f657
CL
76 /*
77 * Ignore the -e flag to allow aliases with rlogin
78 * to work
79 */
4659bf8e 80 if (argc > 0 && !strncmp(*argv, "-e", 2)) {
0f09f657
CL
81 argv++, argc--;
82 goto another;
83 }
4a31bc6f
BJ
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 }
e1e93bd3
SL
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,
4a31bc6f
BJ
115 user ? user : pwd->pw_name, args, &rfd2);
116 if (rem < 0)
117 exit(1);
30b254da
SL
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, 0, 0) < 0)
124 perror("setsockopt (stdin)");
125 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
126 perror("setsockopt (stderr)");
127 }
4a31bc6f 128 (void) setuid(getuid());
4ca10280
SL
129 omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
130 signal(SIGINT, sendsig);
131 signal(SIGQUIT, sendsig);
132 signal(SIGTERM, sendsig);
4a31bc6f
BJ
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:
420d8a52 144 errno = 0;
4a31bc6f
BJ
145 cc = read(0, buf, sizeof buf);
146 if (cc <= 0)
147 goto done;
148 bp = buf;
149 rewrite:
150 rembits = 1<<rem;
e7d6d17a
SL
151 if (select(16, 0, &rembits, 0, 0) < 0) {
152 if (errno != EINTR) {
153 perror("select");
154 exit(1);
155 }
156 goto rewrite;
157 }
4a31bc6f
BJ
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:
420d8a52 171 (void) shutdown(rem, 1);
4a31bc6f
BJ
172 exit(0);
173 }
4ca10280 174 sigsetmask(omask);
4a31bc6f
BJ
175 readfrom = (1<<rfd2) | (1<<rem);
176 do {
177 ready = readfrom;
e7d6d17a
SL
178 if (select(16, &ready, 0, 0, 0) < 0) {
179 if (errno != EINTR) {
180 perror("select");
181 exit(1);
182 }
183 continue;
184 }
4a31bc6f
BJ
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);
206usage:
207 fprintf(stderr,
208 "usage: rsh host [ -l login ] [ -p passwd ] command\n");
209 exit(1);
210}
211
4a31bc6f
BJ
212sendsig(signo)
213 int signo;
214{
215
216 (void) write(rfd2, (char *)&signo, 1);
217}