prettiness police
[unix-history] / usr / src / usr.bin / rsh / rsh.c
CommitLineData
c2ef0242 1/*-
22cfa90c
KB
2 * Copyright (c) 1983, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
63dd6c18 4 *
744998ff 5 * %sccs.include.redist.c%
22e155fc
DF
6 */
7
8#ifndef lint
22cfa90c
KB
9static char copyright[] =
10"@(#) Copyright (c) 1983, 1990, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
63dd6c18 12#endif /* not lint */
22e155fc 13
4a31bc6f 14#ifndef lint
8b0826c1 15static char sccsid[] = "@(#)rsh.c 8.2 (Berkeley) %G%";
63dd6c18 16#endif /* not lint */
4a31bc6f 17
c2ef0242
KB
18/*
19 * $Source: mit/rsh/RCS/rsh.c,v $
20 * $Header: mit/rsh/RCS/rsh.c,v 5.1 89/07/31 19:28:59 kfall Exp Locker: kfall $
21 */
22
4a31bc6f 23#include <sys/types.h>
c2ef0242 24#include <sys/signal.h>
4a31bc6f 25#include <sys/socket.h>
e7d6d17a 26#include <sys/ioctl.h>
4a31bc6f 27#include <sys/file.h>
e7d6d17a
SL
28
29#include <netinet/in.h>
c2ef0242 30#include <netdb.h>
e7d6d17a 31
8b0826c1
JSP
32#include <err.h>
33#include <errno.h>
c2ef0242 34#include <pwd.h>
8b0826c1 35#include <signal.h>
e7d6d17a 36#include <stdio.h>
8b0826c1 37#include <stdlib.h>
38dde0cd 38#include <string.h>
8b0826c1 39#include <unistd.h>
c2ef0242 40#include <varargs.h>
8b0826c1 41
ade4c407 42#include "pathnames.h"
4a31bc6f 43
c2ef0242 44#ifdef KERBEROS
29cf7b1d 45#include <kerberosIV/des.h>
c2ef0242
KB
46#include <kerberosIV/krb.h>
47
48CREDENTIALS cred;
49Key_schedule schedule;
19188d44 50int use_kerberos = 1, doencrypt;
c2ef0242
KB
51char dst_realm_buf[REALM_SZ], *dest_realm;
52extern char *krb_realmofhost();
53#endif
d70fc2d1 54
4a31bc6f
BJ
55/*
56 * rsh - remote shell
57 */
8b0826c1
JSP
58int rfd2;
59
60char *copyargs __P((char **));
61void sendsig __P((int));
62void talk __P((int, long, pid_t, int));
63void usage __P((void));
64void warning __P(());
4ca10280 65
8b0826c1 66int
c2ef0242 67main(argc, argv)
4a31bc6f 68 int argc;
c2ef0242 69 char **argv;
4a31bc6f 70{
c2ef0242 71 struct passwd *pw;
e1e93bd3 72 struct servent *sp;
c2ef0242 73 long omask;
8b0826c1
JSP
74 int argoff, asrsh, ch, dflag, nflag, one, rem;
75 pid_t pid;
76 uid_t uid;
77 char *args, *host, *p, *user;
c2ef0242
KB
78
79 argoff = asrsh = dflag = nflag = 0;
80 one = 1;
81 host = user = NULL;
4a31bc6f 82
c2ef0242 83 /* if called as something other than "rsh", use it as the host name */
8b0826c1 84 if (p = strrchr(argv[0], '/'))
c2ef0242
KB
85 ++p;
86 else
87 p = argv[0];
88 if (strcmp(p, "rsh"))
89 host = p;
4a31bc6f 90 else
4a31bc6f 91 asrsh = 1;
d70fc2d1 92
c2ef0242
KB
93 /* handle "rsh host flags" */
94 if (!host && argc > 2 && argv[1][0] != '-') {
95 host = argv[1];
96 argoff = 1;
d70fc2d1
KF
97 }
98
c2ef0242 99#ifdef KERBEROS
0a8d69ef 100#define OPTIONS "8KLdek:l:nw"
0a8d69ef 101#else
744998ff 102#define OPTIONS "8KLdel:nw"
c2ef0242
KB
103#endif
104 while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
105 switch(ch) {
744998ff
KB
106 case 'K':
107#ifdef KERBEROS
108 use_kerberos = 0;
109#endif
110 break;
c2ef0242
KB
111 case 'L': /* -8Lew are ignored to allow rlogin aliases */
112 case 'e':
113 case 'w':
114 case '8':
115 break;
116 case 'd':
117 dflag = 1;
118 break;
119 case 'l':
120 user = optarg;
121 break;
122#ifdef KERBEROS
123 case 'k':
124 dest_realm = dst_realm_buf;
125 strncpy(dest_realm, optarg, REALM_SZ);
126 break;
744998ff 127#endif
c2ef0242
KB
128 case 'n':
129 nflag = 1;
130 break;
adec4891 131#ifdef KERBEROS
d70fc2d1 132#endif
c2ef0242
KB
133 case '?':
134 default:
135 usage();
136 }
137 optind += argoff;
d70fc2d1 138
c2ef0242
KB
139 /* if haven't gotten a host yet, do so */
140 if (!host && !(host = argv[optind++]))
141 usage();
142
143 /* if no further arguments, must have been called as rlogin. */
144 if (!argv[optind]) {
4a31bc6f 145 if (asrsh)
c2ef0242
KB
146 *argv = "rlogin";
147 execv(_PATH_RLOGIN, argv);
8b0826c1 148 err(1, "can't exec %s", _PATH_RLOGIN);
4a31bc6f 149 }
c2ef0242
KB
150
151 argc -= optind;
152 argv += optind;
153
8b0826c1
JSP
154 if (!(pw = getpwuid(uid = getuid())))
155 errx(1, "unknown user id");
c2ef0242
KB
156 if (!user)
157 user = pw->pw_name;
158
adec4891 159#ifdef KERBEROS
c2ef0242
KB
160#endif
161
162 args = copyargs(argv);
163
744998ff 164 sp = NULL;
3b9d2ca3 165#ifdef KERBEROS
744998ff 166 if (use_kerberos) {
19188d44 167 sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
744998ff
KB
168 if (sp == NULL) {
169 use_kerberos = 0;
170 warning("can't get entry for %s/tcp service",
19188d44 171 doencrypt ? "ekshell" : "kshell");
744998ff 172 }
d70fc2d1 173 }
d70fc2d1 174#endif
744998ff
KB
175 if (sp == NULL)
176 sp = getservbyname("shell", "tcp");
8b0826c1
JSP
177 if (sp == NULL)
178 errx(1, "shell/tcp: unknown service");
d70fc2d1 179
c2ef0242 180#ifdef KERBEROS
d70fc2d1 181try_connect:
c868210b 182 if (use_kerberos) {
8b0826c1
JSP
183 struct hostent *hp;
184
05d73ecb
EA
185 /* fully qualify hostname (needed for krb_realmofhost) */
186 hp = gethostbyname(host);
8b0826c1
JSP
187 if (hp != NULL && !(host = strdup(hp->h_name)))
188 err(1, NULL);
05d73ecb 189
d70fc2d1 190 rem = KSUCCESS;
fb307d7f
KF
191 errno = 0;
192 if (dest_realm == NULL)
193 dest_realm = krb_realmofhost(host);
d70fc2d1 194
c2ef0242
KB
195 rem = krcmd(&host, sp->s_port, user, args, &rfd2,
196 dest_realm);
fb307d7f 197 if (rem < 0) {
d70fc2d1 198 use_kerberos = 0;
0cb7e774 199 sp = getservbyname("shell", "tcp");
8b0826c1
JSP
200 if (sp == NULL)
201 errx(1, "shell/tcp: unknown service");
fb307d7f 202 if (errno == ECONNREFUSED)
c2ef0242 203 warning("remote host doesn't support Kerberos");
fb307d7f 204 if (errno == ENOENT)
c2ef0242 205 warning("can't provide Kerberos auth data");
d70fc2d1
KF
206 goto try_connect;
207 }
d70fc2d1 208 } else {
8b0826c1
JSP
209 if (doencrypt)
210 errx(1, "the -x flag requires Kerberos authentication");
c2ef0242 211 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
d70fc2d1 212 }
d70fc2d1 213#else
c2ef0242 214 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
d70fc2d1
KF
215#endif
216
c2ef0242
KB
217 if (rem < 0)
218 exit(1);
d70fc2d1 219
8b0826c1
JSP
220 if (rfd2 < 0)
221 errx(1, "can't establish stderr");
c2ef0242
KB
222 if (dflag) {
223 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
224 sizeof(one)) < 0)
8b0826c1 225 warn("setsockopt");
c2ef0242
KB
226 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
227 sizeof(one)) < 0)
8b0826c1 228 warn("setsockopt");
30b254da 229 }
c2ef0242 230
d7c0c048 231 (void)setuid(uid);
c2ef0242 232 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
4db732ec 233 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
c2ef0242 234 (void)signal(SIGINT, sendsig);
4db732ec 235 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
c2ef0242 236 (void)signal(SIGQUIT, sendsig);
4db732ec 237 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
c2ef0242
KB
238 (void)signal(SIGTERM, sendsig);
239
240 if (!nflag) {
e1f4a31c 241 pid = fork();
8b0826c1
JSP
242 if (pid < 0)
243 err(1, "fork");
e1f4a31c 244 }
c2ef0242 245
adec4891 246#ifdef KERBEROS
fb307d7f
KF
247#endif
248 {
c2ef0242
KB
249 (void)ioctl(rfd2, FIONBIO, &one);
250 (void)ioctl(rem, FIONBIO, &one);
fb307d7f 251 }
c2ef0242
KB
252
253 talk(nflag, omask, pid, rem);
254
255 if (!nflag)
256 (void)kill(pid, SIGKILL);
257 exit(0);
258}
259
8b0826c1 260void
c2ef0242 261talk(nflag, omask, pid, rem)
8b0826c1 262 int nflag;
c2ef0242 263 long omask;
8b0826c1
JSP
264 pid_t pid;
265 int rem;
c2ef0242 266{
8b0826c1
JSP
267 int cc, wc;
268 fd_set readfrom, ready, rembits;
269 char *bp, buf[BUFSIZ];
c2ef0242
KB
270
271 if (!nflag && pid == 0) {
272 (void)close(rfd2);
273
274reread: errno = 0;
275 if ((cc = read(0, buf, sizeof buf)) <= 0)
4a31bc6f
BJ
276 goto done;
277 bp = buf;
c2ef0242 278
8b0826c1
JSP
279rewrite:
280 FD_ZERO(&rembits);
281 FD_SET(rem, &rembits);
e7d6d17a 282 if (select(16, 0, &rembits, 0, 0) < 0) {
8b0826c1
JSP
283 if (errno != EINTR)
284 err(1, "select");
e7d6d17a
SL
285 goto rewrite;
286 }
8b0826c1 287 if (!FD_ISSET(rem, &rembits))
4a31bc6f 288 goto rewrite;
adec4891 289#ifdef KERBEROS
fb307d7f 290#endif
c2ef0242 291 wc = write(rem, bp, cc);
4a31bc6f
BJ
292 if (wc < 0) {
293 if (errno == EWOULDBLOCK)
294 goto rewrite;
295 goto done;
296 }
c2ef0242
KB
297 bp += wc;
298 cc -= wc;
4a31bc6f
BJ
299 if (cc == 0)
300 goto reread;
301 goto rewrite;
c2ef0242
KB
302done:
303 (void)shutdown(rem, 1);
4a31bc6f
BJ
304 exit(0);
305 }
c2ef0242
KB
306
307 (void)sigsetmask(omask);
8b0826c1
JSP
308 FD_ZERO(&readfrom);
309 FD_SET(rfd2, &readfrom);
310 FD_SET(rem, &readfrom);
4a31bc6f
BJ
311 do {
312 ready = readfrom;
e7d6d17a 313 if (select(16, &ready, 0, 0, 0) < 0) {
8b0826c1
JSP
314 if (errno != EINTR)
315 err(1, "select");
e7d6d17a
SL
316 continue;
317 }
8b0826c1 318 if (FD_ISSET(rfd2, &ready)) {
4a31bc6f 319 errno = 0;
adec4891 320#ifdef KERBEROS
fb307d7f
KF
321#endif
322 cc = read(rfd2, buf, sizeof buf);
4a31bc6f
BJ
323 if (cc <= 0) {
324 if (errno != EWOULDBLOCK)
8b0826c1 325 FD_CLR(rfd2, &readfrom);
4a31bc6f 326 } else
c2ef0242 327 (void)write(2, buf, cc);
4a31bc6f 328 }
8b0826c1 329 if (FD_ISSET(rem, &ready)) {
4a31bc6f 330 errno = 0;
adec4891 331#ifdef KERBEROS
fb307d7f 332#endif
c2ef0242 333 cc = read(rem, buf, sizeof buf);
4a31bc6f
BJ
334 if (cc <= 0) {
335 if (errno != EWOULDBLOCK)
8b0826c1 336 FD_CLR(rem, &readfrom);
4a31bc6f 337 } else
c2ef0242 338 (void)write(1, buf, cc);
4a31bc6f 339 }
8b0826c1 340 } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom));
4a31bc6f
BJ
341}
342
c2ef0242 343void
8b0826c1
JSP
344sendsig(sig)
345 int sig;
4a31bc6f 346{
8b0826c1
JSP
347 char signo;
348
349 signo = sig;
adec4891 350#ifdef KERBEROS
fb307d7f 351#endif
c2ef0242
KB
352 (void)write(rfd2, &signo, 1);
353}
354
355#ifdef KERBEROS
356/* VARARGS */
8b0826c1 357void
c2ef0242
KB
358warning(va_alist)
359va_dcl
360{
361 va_list ap;
362 char *fmt;
363
364 (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
365 va_start(ap);
366 fmt = va_arg(ap, char *);
367 vfprintf(stderr, fmt, ap);
368 va_end(ap);
369 (void)fprintf(stderr, ".\n");
4a31bc6f 370}
c2ef0242 371#endif
d70fc2d1 372
c2ef0242
KB
373char *
374copyargs(argv)
375 char **argv;
d70fc2d1 376{
8b0826c1
JSP
377 int cc;
378 char **ap, *args, *p;
c2ef0242
KB
379
380 cc = 0;
381 for (ap = argv; *ap; ++ap)
382 cc += strlen(*ap) + 1;
8b0826c1
JSP
383 if (!(args = malloc((u_int)cc)))
384 err(1, NULL);
c2ef0242
KB
385 for (p = args, ap = argv; *ap; ++ap) {
386 (void)strcpy(p, *ap);
387 for (p = strcpy(p, *ap); *p; ++p);
388 if (ap[1])
389 *p++ = ' ';
390 }
8b0826c1 391 return (args);
d70fc2d1 392}
c2ef0242 393
8b0826c1 394void
c2ef0242
KB
395usage()
396{
8b0826c1 397
c2ef0242 398 (void)fprintf(stderr,
0a8d69ef 399 "usage: rsh [-nd%s]%s[-l login] host [command]\n",
c2ef0242 400#ifdef KERBEROS
0a8d69ef 401 "", " [-k realm] ");
c2ef0242 402#else
0a8d69ef 403 "", " ");
d70fc2d1 404#endif
c2ef0242
KB
405 exit(1);
406}