source: trunk/minix/commands/simple/rsh.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 11.4 KB
Line 
1/*-
2 * Copyright (c) 1983, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
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.
20 *
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.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)rsh.c 5.24 (Berkeley) 7/1/91";
42#endif /* not lint */
43
44/*
45 * $Source: /cvsup/minix/src/commands/simple/rsh.c,v $
46 * $Header: /cvsup/minix/src/commands/simple/rsh.c,v 1.2 2005/06/17 13:42:53 beng Exp $
47 */
48
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>
59
60#include <net/netlib.h>
61#include <net/gen/netdb.h>
62void main _ARGS(( int argc, char *argv[] ));
63void usage _ARGS(( void ));
64char *copyargs _ARGS(( char **argv ));
65void sendsig _ARGS(( int signo ));
66void talk _ARGS(( int nflag, long omask, int pid, int rem ));
67
68#define _PATH_RLOGIN1 "/bin/rlogin"
69#define _PATH_RLOGIN2 "/usr/bin/rlogin"
70
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>
77
78#include <netinet/in.h>
79#include <netdb.h>
80
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
88
89#ifdef KERBEROS
90#include <kerberosIV/des.h>
91#include <kerberosIV/krb.h>
92
93CREDENTIALS cred;
94Key_schedule schedule;
95int use_kerberos = 1, doencrypt;
96char dst_realm_buf[REALM_SZ], *dest_realm;
97extern char *krb_realmofhost();
98#endif
99
100/*
101 * rsh - remote shell
102 */
103extern int errno;
104int rfd2;
105
106void
107main(argc, argv)
108 int argc;
109 char **argv;
110{
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
123
124 argoff = asrsh = dflag = nflag = 0;
125 one = 1;
126 host = user = NULL;
127
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;
137
138 /* handle "rsh host flags" */
139 if (!host && argc > 2 && argv[1][0] != '-') {
140 host = argv[1];
141 argoff = 1;
142 }
143
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();
191 }
192 optind += argoff;
193
194 /* if haven't gotten a host yet, do so */
195 if (!host && !(host = argv[optind++]))
196 usage();
197
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);
206 }
207
208 argc -= optind;
209 argv += optind;
210
211 if (!(pw = getpwuid(uid = getuid()))) {
212 (void)fprintf(stderr, "rsh: unknown user id.\n");
213 exit(1);
214 }
215 if (!user)
216 user = pw->pw_name;
217
218#ifdef KERBEROS
219#ifdef CRYPT
220 /* -x turns off -n */
221 if (doencrypt)
222 nflag = 0;
223#endif
224#endif
225
226 args = copyargs(argv);
227
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");
236 }
237 }
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);
244 }
245
246#ifdef KERBEROS
247try_connect:
248 if (use_kerberos) {
249 rem = KSUCCESS;
250 errno = 0;
251 if (dest_realm == NULL)
252 dest_realm = krb_realmofhost(host);
253
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);
269 }
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;
275 }
276 } else {
277 if (doencrypt) {
278 (void)fprintf(stderr,
279 "rsh: the -x flag requires Kerberos authentication.\n");
280 exit(1);
281 }
282 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
283 }
284#else
285 rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2);
286#endif
287
288 if (rem < 0)
289 exit(1);
290
291 if (rfd2 < 0) {
292 (void)fprintf(stderr, "rsh: can't establish stderr.\n");
293 exit(1);
294 }
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));
305 }
306#endif
307
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);
318
319 if (!nflag) {
320 pid = fork();
321 if (pid < 0) {
322 (void)fprintf(stderr,
323 "rsh: fork: %s.\n", strerror(errno));
324 exit(1);
325 }
326 }
327
328#ifdef KERBEROS
329#ifdef CRYPT
330 if (!doencrypt)
331#endif
332#endif
333 {
334#if _MINIX
335 ;
336#else
337 (void)ioctl(rfd2, FIONBIO, &one);
338 (void)ioctl(rem, FIONBIO, &one);
339#endif
340 }
341
342 talk(nflag, omask, pid, rem);
343
344 if (!nflag && pid)
345 {
346#if DEBUG
347 printf("killing %d with %d\n", pid, SIGKILL);
348#endif
349 (void)kill(pid, SIGKILL);
350 }
351 exit(0);
352}
353
354void
355talk(nflag, omask, pid, rem)
356 int nflag, pid;
357 long omask;
358 register int rem;
359{
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
367
368 if (!nflag && pid == 0) {
369 (void)close(rfd2);
370
371reread: errno = 0;
372 if ((cc = read(0, buf, sizeof buf)) <= 0)
373 goto done;
374 bp = buf;
375
376rewrite:
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);
384 }
385 goto rewrite;
386 }
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;
404 }
405 bp += wc;
406 cc -= wc;
407 if (cc == 0)
408 goto reread;
409 goto rewrite;
410done:
411#if _MINIX
412 ioctl(rem, NWIOTCPSHUTDOWN, NULL);
413#else
414 (void)shutdown(rem, 1);
415#endif
416 exit(0);
417 }
418
419#if _MINIX
420 pid1= fork();
421 if (pid1 == -1)
422 {
423 (void)fprintf(stderr, "rsh: fork: %s.\n", strerror(errno));
424 exit(1);
425 }
426 close (pid1 ? rfd2 : rem);
427 for(;;)
428 {
429 errno = 0;
430 cc = read(pid1 ? rem : rfd2, buf, sizeof buf);
431 if (cc <= 0)
432 {
433 if (pid1)
434 {
435#if DEBUG
436 printf("killing %d with %d\n", pid1, SIGKILL);
437#endif
438 kill(pid1, SIGKILL);
439 return;
440 }
441 exit(0);
442 }
443 (void)write(pid1 ? 1 : 2, buf, cc);
444 }
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);
455 }
456 continue;
457 }
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);
473 }
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);
489 }
490 } while (readfrom);
491#endif
492}
493
494void
495sendsig(signo)
496 char signo;
497{
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);
506}
507
508#ifdef KERBEROS
509/* VARARGS */
510warning(va_alist)
511va_dcl
512{
513 va_list ap;
514 char *fmt;
515
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");
522}
523#endif
524
525char *
526copyargs(argv)
527 char **argv;
528{
529 register int cc;
530 register char **ap, *p;
531 char *args;
532#if !_MINIX
533 char *malloc();
534#endif
535
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);
542 }
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++ = ' ';
548 }
549 return(args);
550}
551
552void
553usage()
554{
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);
567}
Note: See TracBrowser for help on using the repository browser.