mkfs, mkproto: minor improvements
[minix.git] / commands / rsh / rsh.c
blob8e906e03bd0f1643ac50a09801fe9b759a89b242
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 static char sccsid[] = "@(#)rsh.c 5.24 (Berkeley) 7/1/91";
42 #endif /* not lint */
45 * $Source$
46 * $Header$
49 #if _MINIX
50 #include <sys/types.h>
51 #include <sys/ioctl.h>
52 #include <errno.h>
53 #include <pwd.h>
54 #include <signal.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <unistd.h>
60 #include <net/netlib.h>
61 #include <net/gen/netdb.h>
62 int main( int argc, char *argv[] );
63 void usage( void );
64 char *copyargs( char **argv );
65 void sendsig( int signo );
66 void talk( int nflag, long omask, int pid, int rem );
68 #define _PATH_RLOGIN1 "/bin/rlogin"
69 #define _PATH_RLOGIN2 "/usr/bin/rlogin"
71 #else
72 #include <sys/types.h>
73 #include <sys/signal.h>
74 #include <sys/socket.h>
75 #include <sys/ioctl.h>
76 #include <sys/file.h>
78 #include <netinet/in.h>
79 #include <netdb.h>
81 #include <pwd.h>
82 #include <stdio.h>
83 #include <errno.h>
84 #include <string.h>
85 #include <varargs.h>
86 #include "pathnames.h"
87 #endif
89 #ifdef KERBEROS
90 #include <kerberosIV/des.h>
91 #include <kerberosIV/krb.h>
93 CREDENTIALS cred;
94 Key_schedule schedule;
95 int use_kerberos = 1, doencrypt;
96 char dst_realm_buf[REALM_SZ], *dest_realm;
97 extern char *krb_realmofhost();
98 #endif
101 * rsh - remote shell
103 extern int errno;
104 int rfd2;
107 main(argc, argv)
108 int argc;
109 char **argv;
111 extern char *optarg;
112 extern int optind;
113 struct passwd *pw;
114 struct servent *sp;
115 long omask;
116 int argoff, asrsh, ch, dflag, nflag, one, pid, rem, uid;
117 register char *p;
118 char *args, *host, *user;
119 #if !_MINIX
120 char *copyargs();
121 void sendsig();
122 #endif
124 argoff = asrsh = dflag = nflag = 0;
125 one = 1;
126 host = user = NULL;
128 /* if called as something other than "rsh", use it as the host name */
129 if (p = rindex(argv[0], '/'))
130 ++p;
131 else
132 p = argv[0];
133 if (strcmp(p, "rsh"))
134 host = p;
135 else
136 asrsh = 1;
138 /* handle "rsh host flags" */
139 if (!host && argc > 2 && argv[1][0] != '-') {
140 host = argv[1];
141 argoff = 1;
144 #ifdef KERBEROS
145 #ifdef CRYPT
146 #define OPTIONS "8KLdek:l:nwx"
147 #else
148 #define OPTIONS "8KLdek:l:nw"
149 #endif
150 #else
151 #define OPTIONS "8KLdel:nw"
152 #endif
153 while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF)
154 switch(ch) {
155 case 'K':
156 #ifdef KERBEROS
157 use_kerberos = 0;
158 #endif
159 break;
160 case 'L': /* -8Lew are ignored to allow rlogin aliases */
161 case 'e':
162 case 'w':
163 case '8':
164 break;
165 case 'd':
166 dflag = 1;
167 break;
168 case 'l':
169 user = optarg;
170 break;
171 #ifdef KERBEROS
172 case 'k':
173 dest_realm = dst_realm_buf;
174 strncpy(dest_realm, optarg, REALM_SZ);
175 break;
176 #endif
177 case 'n':
178 nflag = 1;
179 break;
180 #ifdef KERBEROS
181 #ifdef CRYPT
182 case 'x':
183 doencrypt = 1;
184 des_set_key(cred.session, schedule);
185 break;
186 #endif
187 #endif
188 case '?':
189 default:
190 usage();
192 optind += argoff;
194 /* if haven't gotten a host yet, do so */
195 if (!host && !(host = argv[optind++]))
196 usage();
198 /* if no further arguments, must have been called as rlogin. */
199 if (!argv[optind]) {
200 if (asrsh)
201 *argv = "rlogin";
202 execv(_PATH_RLOGIN1, argv);
203 execv(_PATH_RLOGIN2, argv);
204 (void)fprintf(stderr, "rsh: can't exec rlogin\n");
205 exit(1);
208 argc -= optind;
209 argv += optind;
211 if (!(pw = getpwuid(uid = getuid()))) {
212 (void)fprintf(stderr, "rsh: unknown user id.\n");
213 exit(1);
215 if (!user)
216 user = pw->pw_name;
218 #ifdef KERBEROS
219 #ifdef CRYPT
220 /* -x turns off -n */
221 if (doencrypt)
222 nflag = 0;
223 #endif
224 #endif
226 args = copyargs(argv);
228 sp = NULL;
229 #ifdef KERBEROS
230 if (use_kerberos) {
231 sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp");
232 if (sp == NULL) {
233 use_kerberos = 0;
234 warning("can't get entry for %s/tcp service",
235 doencrypt ? "ekshell" : "kshell");
238 #endif
239 if (sp == NULL)
240 sp = getservbyname("shell", "tcp");
241 if (sp == NULL) {
242 (void)fprintf(stderr, "rsh: shell/tcp: unknown service.\n");
243 exit(1);
246 #ifdef KERBEROS
247 try_connect:
248 if (use_kerberos) {
249 rem = KSUCCESS;
250 errno = 0;
251 if (dest_realm == NULL)
252 dest_realm = krb_realmofhost(host);
254 #ifdef CRYPT
255 if (doencrypt)
256 rem = krcmd_mutual(&host, sp->s_port, user, args,
257 &rfd2, dest_realm, &cred, schedule);
258 else
259 #endif
260 rem = krcmd(&host, sp->s_port, user, args, &rfd2,
261 dest_realm);
262 if (rem < 0) {
263 use_kerberos = 0;
264 sp = getservbyname("shell", "tcp");
265 if (sp == NULL) {
266 (void)fprintf(stderr,
267 "rsh: unknown service shell/tcp.\n");
268 exit(1);
270 if (errno == ECONNREFUSED)
271 warning("remote host doesn't support Kerberos");
272 if (errno == ENOENT)
273 warning("can't provide Kerberos auth data");
274 goto try_connect;
276 } else {
277 if (doencrypt) {
278 (void)fprintf(stderr,
279 "rsh: the -x flag requires Kerberos authentication.\n");
280 exit(1);
282 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
284 #else
285 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
286 #endif
288 if (rem < 0)
289 exit(1);
291 if (rfd2 < 0) {
292 (void)fprintf(stderr, "rsh: can't establish stderr.\n");
293 exit(1);
295 #if !_MINIX
296 if (dflag) {
297 if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one,
298 sizeof(one)) < 0)
299 (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
300 strerror(errno));
301 if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one,
302 sizeof(one)) < 0)
303 (void)fprintf(stderr, "rsh: setsockopt: %s.\n",
304 strerror(errno));
306 #endif
308 (void)setuid(uid);
309 #if !_MINIX
310 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
311 #endif
312 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
313 (void)signal(SIGINT, sendsig);
314 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
315 (void)signal(SIGQUIT, sendsig);
316 if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
317 (void)signal(SIGTERM, sendsig);
319 if (!nflag) {
320 pid = fork();
321 if (pid < 0) {
322 (void)fprintf(stderr,
323 "rsh: fork: %s.\n", strerror(errno));
324 exit(1);
328 #ifdef KERBEROS
329 #ifdef CRYPT
330 if (!doencrypt)
331 #endif
332 #endif
334 #if _MINIX
336 #else
337 (void)ioctl(rfd2, FIONBIO, &one);
338 (void)ioctl(rem, FIONBIO, &one);
339 #endif
342 talk(nflag, omask, pid, rem);
344 if (!nflag && pid)
346 #if DEBUG
347 printf("killing %d with %d\n", pid, SIGKILL);
348 #endif
349 (void)kill(pid, SIGKILL);
351 exit(0);
354 void
355 talk(nflag, omask, pid, rem)
356 int nflag, pid;
357 long omask;
358 register int rem;
360 register int cc, wc;
361 register char *bp;
362 int readfrom, ready, rembits;
363 char buf[BUFSIZ];
364 #if _MINIX
365 int pid1;
366 #endif
368 if (!nflag && pid == 0) {
369 (void)close(rfd2);
371 reread: errno = 0;
372 if ((cc = read(0, buf, sizeof buf)) <= 0)
373 goto done;
374 bp = buf;
376 rewrite:
377 #if !_MINIX
378 rembits = 1 << rem;
379 if (select(16, 0, &rembits, 0, 0) < 0) {
380 if (errno != EINTR) {
381 (void)fprintf(stderr,
382 "rsh: select: %s.\n", strerror(errno));
383 exit(1);
385 goto rewrite;
387 if ((rembits & (1 << rem)) == 0)
388 goto rewrite;
389 #endif
390 #ifdef KERBEROS
391 #ifdef CRYPT
392 if (doencrypt)
393 wc = des_write(rem, bp, cc);
394 else
395 #endif
396 #endif
397 wc = write(rem, bp, cc);
398 if (wc < 0) {
399 #if !_MINIX
400 if (errno == EWOULDBLOCK)
401 goto rewrite;
402 #endif
403 goto done;
405 bp += wc;
406 cc -= wc;
407 if (cc == 0)
408 goto reread;
409 goto rewrite;
410 done:
411 #if _MINIX
412 ioctl(rem, NWIOTCPSHUTDOWN, NULL);
413 #else
414 (void)shutdown(rem, 1);
415 #endif
416 exit(0);
419 #if _MINIX
420 pid1= fork();
421 if (pid1 == -1)
423 (void)fprintf(stderr, "rsh: fork: %s.\n", strerror(errno));
424 exit(1);
426 close (pid1 ? rfd2 : rem);
427 for(;;)
429 errno = 0;
430 cc = read(pid1 ? rem : rfd2, buf, sizeof buf);
431 if (cc <= 0)
433 if (pid1)
435 #if DEBUG
436 printf("killing %d with %d\n", pid1, SIGKILL);
437 #endif
438 kill(pid1, SIGKILL);
439 return;
441 exit(0);
443 (void)write(pid1 ? 1 : 2, buf, cc);
445 #else
446 (void)sigsetmask(omask);
447 readfrom = (1 << rfd2) | (1 << rem);
448 do {
449 ready = readfrom;
450 if (select(16, &ready, 0, 0, 0) < 0) {
451 if (errno != EINTR) {
452 (void)fprintf(stderr,
453 "rsh: select: %s.\n", strerror(errno));
454 exit(1);
456 continue;
458 if (ready & (1 << rfd2)) {
459 errno = 0;
460 #ifdef KERBEROS
461 #ifdef CRYPT
462 if (doencrypt)
463 cc = des_read(rfd2, buf, sizeof buf);
464 else
465 #endif
466 #endif
467 cc = read(rfd2, buf, sizeof buf);
468 if (cc <= 0) {
469 if (errno != EWOULDBLOCK)
470 readfrom &= ~(1 << rfd2);
471 } else
472 (void)write(2, buf, cc);
474 if (ready & (1 << rem)) {
475 errno = 0;
476 #ifdef KERBEROS
477 #ifdef CRYPT
478 if (doencrypt)
479 cc = des_read(rem, buf, sizeof buf);
480 else
481 #endif
482 #endif
483 cc = read(rem, buf, sizeof buf);
484 if (cc <= 0) {
485 if (errno != EWOULDBLOCK)
486 readfrom &= ~(1 << rem);
487 } else
488 (void)write(1, buf, cc);
490 } while (readfrom);
491 #endif
494 void
495 sendsig(signo)
496 char signo;
498 #ifdef KERBEROS
499 #ifdef CRYPT
500 if (doencrypt)
501 (void)des_write(rfd2, &signo, 1);
502 else
503 #endif
504 #endif
505 (void)write(rfd2, &signo, 1);
508 #ifdef KERBEROS
509 /* VARARGS */
510 warning(va_alist)
511 va_dcl
513 va_list ap;
514 char *fmt;
516 (void)fprintf(stderr, "rsh: warning, using standard rsh: ");
517 va_start(ap);
518 fmt = va_arg(ap, char *);
519 vfprintf(stderr, fmt, ap);
520 va_end(ap);
521 (void)fprintf(stderr, ".\n");
523 #endif
525 char *
526 copyargs(argv)
527 char **argv;
529 register int cc;
530 register char **ap, *p;
531 char *args;
532 #if !_MINIX
533 char *malloc();
534 #endif
536 cc = 0;
537 for (ap = argv; *ap; ++ap)
538 cc += strlen(*ap) + 1;
539 if (!(args = malloc((u_int)cc))) {
540 (void)fprintf(stderr, "rsh: %s.\n", strerror(ENOMEM));
541 exit(1);
543 for (p = args, ap = argv; *ap; ++ap) {
544 (void)strcpy(p, *ap);
545 for (p = strcpy(p, *ap); *p; ++p);
546 if (ap[1])
547 *p++ = ' ';
549 return(args);
552 void
553 usage()
555 (void)fprintf(stderr,
556 "usage: rsh [-nd%s]%s[-l login] host [command]\n",
557 #ifdef KERBEROS
558 #ifdef CRYPT
559 "x", " [-k realm] ");
560 #else
561 "", " [-k realm] ");
562 #endif
563 #else
564 "", " ");
565 #endif
566 exit(1);