add opendir alias
[minix.git] / commands / rsh / rsh.c
blob377eb8fc27e6dbc090323a2a0ec204ca8fae98c6
1 /*-
2 * Copyright (c) 1983, 1990 The Regents of the University of California.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #ifndef lint
35 char copyright[] =
36 "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
37 All rights reserved.\n";
38 #endif /* not lint */
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)rsh.c 5.24 (Berkeley) 7/1/91";
43 #endif
44 #endif /* not lint */
47 * $Source$
48 * $Header$
51 #if _MINIX
52 #include <sys/types.h>
53 #include <sys/ioctl.h>
54 #include <errno.h>
55 #include <pwd.h>
56 #include <signal.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <unistd.h>
62 #include <net/netlib.h>
63 #include <net/gen/netdb.h>
64 int main( int argc, char *argv[] );
65 void usage( void );
66 char *copyargs( char **argv );
67 void sendsig( int signo );
68 void talk( int nflag, long omask, int pid, int rem );
70 #define _PATH_RLOGIN1 "/bin/rlogin"
71 #define _PATH_RLOGIN2 "/usr/bin/rlogin"
73 #else
74 #include <sys/types.h>
75 #include <sys/signal.h>
76 #include <sys/socket.h>
77 #include <sys/ioctl.h>
78 #include <sys/file.h>
80 #include <netinet/in.h>
81 #include <netdb.h>
83 #include <pwd.h>
84 #include <stdio.h>
85 #include <errno.h>
86 #include <string.h>
87 #include <varargs.h>
88 #include "pathnames.h"
89 #endif
91 #ifdef KERBEROS
92 #include <kerberosIV/des.h>
93 #include <kerberosIV/krb.h>
95 CREDENTIALS cred;
96 Key_schedule schedule;
97 int use_kerberos = 1, doencrypt;
98 char dst_realm_buf[REALM_SZ], *dest_realm;
99 extern char *krb_realmofhost();
100 #endif
103 * rsh - remote shell
105 extern int errno;
106 int rfd2;
109 main(argc, argv)
110 int argc;
111 char **argv;
113 extern char *optarg;
114 extern int optind;
115 struct passwd *pw;
116 struct servent *sp;
117 long omask;
118 int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
119 register char *p;
120 char *args, *host, *user;
121 #if !_MINIX
122 char *copyargs();
123 void sendsig();
124 #endif
126 argoff = asrsh = dflag = nflag = 0;
127 one = 1;
128 host = user = NULL;
130 /* if called as something other than "rsh", use it as the host name */
131 if ((p = rindex(argv[0], '/')))
132 ++p;
133 else
134 p = argv[0];
135 if (strcmp(p, "rsh"))
136 host = p;
137 else
138 asrsh = 1;
140 /* handle "rsh host flags" */
141 if (!host && argc > 2 && argv[1][0] != '-') {
142 host = argv[1];
143 argoff = 1;
146 #ifdef KERBEROS
147 #ifdef CRYPT
148 #define OPTIONS "8KLdek:l:nwx"
149 #else
150 #define OPTIONS "8KLdek:l:nw"
151 #endif
152 #else
153 #define OPTIONS "8KLdel:nw"
154 #endif
155 while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
156 switch(ch) {
157 case 'K':
158 #ifdef KERBEROS
159 use_kerberos = 0;
160 #endif
161 break;
162 case 'L': /* -8Lew are ignored to allow rlogin aliases */
163 case 'e':
164 case 'w':
165 case '8':
166 break;
167 case 'd':
168 dflag = 1;
169 break;
170 case 'l':
171 user = optarg;
172 break;
173 #ifdef KERBEROS
174 case 'k':
175 dest_realm = dst_realm_buf;
176 strncpy(dest_realm, optarg, REALM_SZ);
177 break;
178 #endif
179 case 'n':
180 nflag = 1;
181 break;
182 #ifdef KERBEROS
183 #ifdef CRYPT
184 case 'x':
185 doencrypt = 1;
186 des_set_key(cred.session, schedule);
187 break;
188 #endif
189 #endif
190 case '?':
191 default:
192 usage();
194 optind += argoff;
196 /* if haven't gotten a host yet, do so */
197 if (!host && !(host = argv[optind++]))
198 usage();
200 /* if no further arguments, must have been called as rlogin. */
201 if (!argv[optind]) {
202 if (asrsh)
203 *argv = "rlogin";
204 execv(_PATH_RLOGIN1, argv);
205 execv(_PATH_RLOGIN2, argv);
206 (void)fprintf(stderr, "rsh: can't exec rlogin\n");
207 exit(1);
210 argc -= optind;
211 argv += optind;
213 if (!(pw = getpwuid(uid = getuid()))) {
214 (void)fprintf(stderr, "rsh: unknown user id.\n");
215 exit(1);
217 if (!user)
218 user = pw->pw_name;
220 #ifdef KERBEROS
221 #ifdef CRYPT
222 /* -x turns off -n */
223 if (doencrypt)
224 nflag = 0;
225 #endif
226 #endif
228 args = copyargs(argv);
230 sp = NULL;
231 #ifdef KERBEROS
232 if (use_kerberos) {
233 sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
234 if (sp == NULL) {
235 use_kerberos = 0;
236 warning("can't get entry for %s/tcp service",
237 doencrypt ? "ekshell" : "kshell");
240 #endif
241 if (sp == NULL)
242 sp = getservbyname("shell", "tcp");
243 if (sp == NULL) {
244 (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
245 exit(1);
248 #ifdef KERBEROS
249 try_connect:
250 if (use_kerberos) {
251 rem = KSUCCESS;
252 errno = 0;
253 if (dest_realm == NULL)
254 dest_realm = krb_realmofhost(host);
256 #ifdef CRYPT
257 if (doencrypt)
258 rem = krcmd_mutual(&host, sp->s_port, user, args,
259 &rfd2, dest_realm, &cred, schedule);
260 else
261 #endif
262 rem = krcmd(&host, sp->s_port, user, args, &rfd2,
263 dest_realm);
264 if (rem < 0) {
265 use_kerberos = 0;
266 sp = getservbyname("shell", "tcp");
267 if (sp == NULL) {
268 (void)fprintf(stderr,
269 "rsh: unknown service shell/tcp.\n");
270 exit(1);
272 if (errno == ECONNREFUSED)
273 warning("remote host doesn't support Kerberos");
274 if (errno == ENOENT)
275 warning("can't provide Kerberos auth data");
276 goto try_connect;
278 } else {
279 if (doencrypt) {
280 (void)fprintf(stderr,
281 "rsh: the -x flag requires Kerberos authentication.\n");
282 exit(1);
284 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
286 #else
287 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
288 #endif
290 if (rem < 0)
291 exit(1);
293 if (rfd2 < 0) {
294 (void)fprintf(stderr, "rsh: can't establish stderr.\n");
295 exit(1);
297 #if !_MINIX
298 if (dflag) {
299 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
300 sizeof(one)) < 0)
301 (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
302 strerror(errno));
303 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
304 sizeof(one)) < 0)
305 (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
306 strerror(errno));
308 #endif
310 (void)setuid(uid);
311 #if !_MINIX
312 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
313 #endif
314 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
315 (void)signal(SIGINT, sendsig);
316 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
317 (void)signal(SIGQUIT, sendsig);
318 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
319 (void)signal(SIGTERM, sendsig);
321 if (!nflag) {
322 pid = fork();
323 if (pid < 0) {
324 (void)fprintf(stderr,
325 "rsh: fork: %s.\n", strerror(errno));
326 exit(1);
330 #ifdef KERBEROS
331 #ifdef CRYPT
332 if (!doencrypt)
333 #endif
334 #endif
336 #if _MINIX
338 #else
339 (void)ioctl(rfd2, FIONBIO, &one);
340 (void)ioctl(rem, FIONBIO, &one);
341 #endif
344 talk(nflag, omask, pid, rem);
346 if (!nflag && pid)
348 #if DEBUG
349 printf("killing %d with %d\n", pid, SIGKILL);
350 #endif
351 (void)kill(pid, SIGKILL);
353 exit(0);
356 void
357 talk(nflag, omask, pid, rem)
358 int nflag, pid;
359 long omask;
360 register int rem;
362 register int cc, wc;
363 register char *bp;
364 #if !_MINIX
365 int readfrom, ready, rembits;
366 #endif
367 char buf[BUFSIZ];
368 #if _MINIX
369 int pid1;
370 #endif
372 if (!nflag && pid == 0) {
373 (void)close(rfd2);
375 reread: errno = 0;
376 if ((cc = read(0, buf, sizeof buf)) <= 0)
377 goto done;
378 bp = buf;
380 rewrite:
381 #if !_MINIX
382 rembits = 1 << rem;
383 if (select(16, 0, &rembits, 0, 0) < 0) {
384 if (errno != EINTR) {
385 (void)fprintf(stderr,
386 "rsh: select: %s.\n", strerror(errno));
387 exit(1);
389 goto rewrite;
391 if ((rembits & (1 << rem)) == 0)
392 goto rewrite;
393 #endif
394 #ifdef KERBEROS
395 #ifdef CRYPT
396 if (doencrypt)
397 wc = des_write(rem, bp, cc);
398 else
399 #endif
400 #endif
401 wc = write(rem, bp, cc);
402 if (wc < 0) {
403 #if !_MINIX
404 if (errno == EWOULDBLOCK)
405 goto rewrite;
406 #endif
407 goto done;
409 bp += wc;
410 cc -= wc;
411 if (cc == 0)
412 goto reread;
413 goto rewrite;
414 done:
415 #if _MINIX
416 ioctl(rem, NWIOTCPSHUTDOWN, NULL);
417 #else
418 (void)shutdown(rem, 1);
419 #endif
420 exit(0);
423 #if _MINIX
424 pid1= fork();
425 if (pid1 == -1)
427 (void)fprintf(stderr, "rsh: fork: %s.\n", strerror(errno));
428 exit(1);
430 close (pid1 ? rfd2 : rem);
431 for(;;)
433 errno = 0;
434 cc = read(pid1 ? rem : rfd2, buf, sizeof buf);
435 if (cc <= 0)
437 if (pid1)
439 #if DEBUG
440 printf("killing %d with %d\n", pid1, SIGKILL);
441 #endif
442 kill(pid1, SIGKILL);
443 return;
445 exit(0);
447 (void)write(pid1 ? 1 : 2, buf, cc);
449 #else
450 (void)sigsetmask(omask);
451 readfrom = (1 << rfd2) | (1 << rem);
452 do {
453 ready = readfrom;
454 if (select(16, &ready, 0, 0, 0) < 0) {
455 if (errno != EINTR) {
456 (void)fprintf(stderr,
457 "rsh: select: %s.\n", strerror(errno));
458 exit(1);
460 continue;
462 if (ready & (1 << rfd2)) {
463 errno = 0;
464 #ifdef KERBEROS
465 #ifdef CRYPT
466 if (doencrypt)
467 cc = des_read(rfd2, buf, sizeof buf);
468 else
469 #endif
470 #endif
471 cc = read(rfd2, buf, sizeof buf);
472 if (cc <= 0) {
473 if (errno != EWOULDBLOCK)
474 readfrom &= ~(1 << rfd2);
475 } else
476 (void)write(2, buf, cc);
478 if (ready & (1 << rem)) {
479 errno = 0;
480 #ifdef KERBEROS
481 #ifdef CRYPT
482 if (doencrypt)
483 cc = des_read(rem, buf, sizeof buf);
484 else
485 #endif
486 #endif
487 cc = read(rem, buf, sizeof buf);
488 if (cc <= 0) {
489 if (errno != EWOULDBLOCK)
490 readfrom &= ~(1 << rem);
491 } else
492 (void)write(1, buf, cc);
494 } while (readfrom);
495 #endif
498 void
499 sendsig(signo)
500 char signo;
502 #ifdef KERBEROS
503 #ifdef CRYPT
504 if (doencrypt)
505 (void)des_write(rfd2, &signo, 1);
506 else
507 #endif
508 #endif
509 (void)write(rfd2, &signo, 1);
512 #ifdef KERBEROS
513 /* VARARGS */
514 warning(va_alist)
515 va_dcl
517 va_list ap;
518 char *fmt;
520 (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
521 va_start(ap);
522 fmt = va_arg(ap, char *);
523 vfprintf(stderr, fmt, ap);
524 va_end(ap);
525 (void)fprintf(stderr, ".\n");
527 #endif
529 char *
530 copyargs(argv)
531 char **argv;
533 register int cc;
534 register char **ap, *p;
535 char *args;
536 #if !_MINIX
537 char *malloc();
538 #endif
540 cc = 0;
541 for (ap = argv; *ap; ++ap)
542 cc += strlen(*ap) + 1;
543 if (!(args = malloc((u_int)cc))) {
544 (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
545 exit(1);
547 for (p = args, ap = argv; *ap; ++ap) {
548 (void)strcpy(p, *ap);
549 for (p = strcpy(p, *ap); *p; ++p);
550 if (ap[1])
551 *p++ = ' ';
553 return(args);
556 void
557 usage()
559 (void)fprintf(stderr,
560 "usage: rsh [-nd%s]%s[-l login] host [command]\n",
561 #ifdef KERBEROS
562 #ifdef CRYPT
563 "x", " [-k realm] ");
564 #else
565 "", " [-k realm] ");
566 #endif
567 #else
568 "", " ");
569 #endif
570 exit(1);