4.3BSD beta release manual page
[unix-history] / usr / src / usr.bin / rsh / rsh.c
CommitLineData
4a31bc6f 1#ifndef lint
3c1108f1 2static char sccsid[] = "@(#)rsh.c 4.12 85/04/24";
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 76 /*
3c1108f1 77 * Ignore the -w, -e and -8 flags to allow aliases with rlogin
0f09f657
CL
78 * to work
79 */
3c1108f1
JB
80 if (argc > 0 && !strncmp(*argv, "-w", 2)) {
81 argv++, argc--;
82 goto another;
83 }
4659bf8e 84 if (argc > 0 && !strncmp(*argv, "-e", 2)) {
0f09f657
CL
85 argv++, argc--;
86 goto another;
87 }
63556828
JL
88 if (argc > 0 && !strncmp(*argv, "-8", 2)) {
89 argv++, argc--;
90 goto another;
91 }
4a31bc6f
BJ
92 if (host == 0)
93 goto usage;
94 if (argv[0] == 0) {
95 if (asrsh)
96 *argv0 = "rlogin";
97 execv("/usr/ucb/rlogin", argv0);
98 perror("/usr/ucb/rlogin");
99 exit(1);
100 }
101 pwd = getpwuid(getuid());
102 if (pwd == 0) {
103 fprintf(stderr, "who are you?\n");
104 exit(1);
105 }
106 cc = 0;
107 for (ap = argv; *ap; ap++)
108 cc += strlen(*ap) + 1;
109 cp = args = malloc(cc);
110 for (ap = argv; *ap; ap++) {
111 (void) strcpy(cp, *ap);
112 while (*cp)
113 cp++;
114 if (ap[1])
115 *cp++ = ' ';
116 }
e1e93bd3
SL
117 sp = getservbyname("shell", "tcp");
118 if (sp == 0) {
119 fprintf(stderr, "rsh: shell/tcp: unknown service\n");
120 exit(1);
121 }
122 rem = rcmd(&host, sp->s_port, pwd->pw_name,
4a31bc6f
BJ
123 user ? user : pwd->pw_name, args, &rfd2);
124 if (rem < 0)
125 exit(1);
30b254da
SL
126 if (rfd2 < 0) {
127 fprintf(stderr, "rsh: can't establish stderr\n");
128 exit(2);
129 }
130 if (options & SO_DEBUG) {
0975b26d 131 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
30b254da 132 perror("setsockopt (stdin)");
0975b26d 133 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0)
30b254da
SL
134 perror("setsockopt (stderr)");
135 }
4a31bc6f 136 (void) setuid(getuid());
4ca10280
SL
137 omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM));
138 signal(SIGINT, sendsig);
139 signal(SIGQUIT, sendsig);
140 signal(SIGTERM, sendsig);
4a31bc6f
BJ
141 pid = fork();
142 if (pid < 0) {
143 perror("fork");
144 exit(1);
145 }
146 ioctl(rfd2, FIONBIO, &one);
147 ioctl(rem, FIONBIO, &one);
148 if (pid == 0) {
149 char *bp; int rembits, wc;
150 (void) close(rfd2);
151 reread:
420d8a52 152 errno = 0;
4a31bc6f
BJ
153 cc = read(0, buf, sizeof buf);
154 if (cc <= 0)
155 goto done;
156 bp = buf;
157 rewrite:
158 rembits = 1<<rem;
e7d6d17a
SL
159 if (select(16, 0, &rembits, 0, 0) < 0) {
160 if (errno != EINTR) {
161 perror("select");
162 exit(1);
163 }
164 goto rewrite;
165 }
4a31bc6f
BJ
166 if ((rembits & (1<<rem)) == 0)
167 goto rewrite;
168 wc = write(rem, bp, cc);
169 if (wc < 0) {
170 if (errno == EWOULDBLOCK)
171 goto rewrite;
172 goto done;
173 }
174 cc -= wc; bp += wc;
175 if (cc == 0)
176 goto reread;
177 goto rewrite;
178 done:
420d8a52 179 (void) shutdown(rem, 1);
4a31bc6f
BJ
180 exit(0);
181 }
4ca10280 182 sigsetmask(omask);
4a31bc6f
BJ
183 readfrom = (1<<rfd2) | (1<<rem);
184 do {
185 ready = readfrom;
e7d6d17a
SL
186 if (select(16, &ready, 0, 0, 0) < 0) {
187 if (errno != EINTR) {
188 perror("select");
189 exit(1);
190 }
191 continue;
192 }
4a31bc6f
BJ
193 if (ready & (1<<rfd2)) {
194 errno = 0;
195 cc = read(rfd2, buf, sizeof buf);
196 if (cc <= 0) {
197 if (errno != EWOULDBLOCK)
198 readfrom &= ~(1<<rfd2);
199 } else
200 (void) write(2, buf, cc);
201 }
202 if (ready & (1<<rem)) {
203 errno = 0;
204 cc = read(rem, buf, sizeof buf);
205 if (cc <= 0) {
206 if (errno != EWOULDBLOCK)
207 readfrom &= ~(1<<rem);
208 } else
209 (void) write(1, buf, cc);
210 }
211 } while (readfrom);
212 (void) kill(pid, SIGKILL);
213 exit(0);
214usage:
215 fprintf(stderr,
216 "usage: rsh host [ -l login ] [ -p passwd ] command\n");
217 exit(1);
218}
219
4a31bc6f 220sendsig(signo)
8842c908 221 char signo;
4a31bc6f
BJ
222{
223
8842c908 224 (void) write(rfd2, &signo, 1);
4a31bc6f 225}