X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4915309067602ac28585d822b98c9d4c42a01bf6..a9f6bdc7e061375b05c9c24e06295c3613bbc9e7:/usr/src/usr.bin/rsh/rsh.c diff --git a/usr/src/usr.bin/rsh/rsh.c b/usr/src/usr.bin/rsh/rsh.c index 51249b66f3..6e2c26d152 100644 --- a/usr/src/usr.bin/rsh/rsh.c +++ b/usr/src/usr.bin/rsh/rsh.c @@ -1,371 +1,406 @@ -/* - * Copyright (c) 1983 The Regents of the University of California. - * All rights reserved. +/*- + * Copyright (c) 1983, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * %sccs.include.redist.c% */ #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1983 The Regents of the University of California.\n\ - All rights reserved.\n"; +static char copyright[] = +"@(#) Copyright (c) 1983, 1990, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)rsh.c 5.12 (Berkeley) %G%"; +static char sccsid[] = "@(#)rsh.c 8.3 (Berkeley) %G%"; #endif /* not lint */ +/* + * $Source: mit/rsh/RCS/rsh.c,v $ + * $Header: mit/rsh/RCS/rsh.c,v 5.1 89/07/31 19:28:59 kfall Exp Locker: kfall $ + */ + #include +#include #include #include #include #include +#include -#include +#include #include -#include #include -#include +#include +#include +#include +#include +#include +#include + #include "pathnames.h" -#ifdef KERBEROS -#include -char krb_realm[REALM_SZ]; -int use_kerberos = 1, encrypt = 0; -CREDENTIALS cred; -Key_schedule schedule; -#endif /* KERBEROS */ +#ifdef KERBEROS +#include +#include + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm; +extern char *krb_realmofhost(); +#endif /* * rsh - remote shell */ -/* VARARGS */ -int error(); -char *index(), *rindex(), *malloc(), *getpass(), *strcpy(); - -struct passwd *getpwuid(); - -int errno; -int options; int rfd2; -int nflag; -int sendsig(); -#define mask(s) (1 << ((s) - 1)) +char *copyargs __P((char **)); +void sendsig __P((int)); +void talk __P((int, long, pid_t, int)); +void usage __P((void)); +void warning __P(()); -main(argc, argv0) +int +main(argc, argv) int argc; - char **argv0; + char **argv; { - int rem, pid; - char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0; - register int cc; - int asrsh = 0; - struct passwd *pwd; - int readfrom, ready; - int one = 1; + struct passwd *pw; struct servent *sp; - int omask; + long omask; + int argoff, asrsh, ch, dflag, nflag, one, rem; + pid_t pid; + uid_t uid; + char *args, *host, *p, *user; + + argoff = asrsh = dflag = nflag = 0; + one = 1; + host = user = NULL; - host = rindex(argv[0], '/'); - if (host) - host++; + /* if called as something other than "rsh", use it as the host name */ + if (p = strrchr(argv[0], '/')) + ++p; + else + p = argv[0]; + if (strcmp(p, "rsh")) + host = p; else - host = argv[0]; - argv++, --argc; - if (!strcmp(host, "rsh")) { - host = *argv++, --argc; asrsh = 1; - } -another: - if (argc > 0 && !strcmp(*argv, "-l")) { - argv++, argc--; - if (argc > 0) - user = *argv++, argc--; - goto another; - } - if (argc > 0 && !strcmp(*argv, "-n")) { - argv++, argc--; - nflag++; - goto another; - } - if (argc > 0 && !strcmp(*argv, "-d")) { - argv++, argc--; - options |= SO_DEBUG; - goto another; - } - /* - * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin - * to work - * - * There must be a better way to do this! -jmb - */ - if (argc > 0 && !strncmp(*argv, "-L", 2)) { - argv++, argc--; - goto another; - } - if (argc > 0 && !strncmp(*argv, "-w", 2)) { - argv++, argc--; - goto another; - } - if (argc > 0 && !strncmp(*argv, "-e", 2)) { - argv++, argc--; - goto another; - } - if (argc > 0 && !strncmp(*argv, "-8", 2)) { - argv++, argc--; - goto another; - } -#ifdef KERBEROS - if(argc > 0 && !strncmp(*argv, "-x", 2)) { - encrypt = 1; - des_set_key(cred.session, schedule); - argv++, argc--; - goto another; + /* handle "rsh host flags" */ + if (!host && argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; } - if(argc > 0 && !strcmp(*argv, "-k")) { - argv++, argc--; - if(argc <= 0 || (**argv == '-')) { - fprintf(stderr, "-k option requires an argument\n"); - exit(1); - } - strncpy(krb_realm, *argv, REALM_SZ); - argv++, argc--; - goto another; - } +#ifdef KERBEROS +#define OPTIONS "8KLdek:l:nw" +#else +#define OPTIONS "8KLdel:nw" +#endif + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case 'K': +#ifdef KERBEROS + use_kerberos = 0; +#endif + break; + case 'L': /* -8Lew are ignored to allow rlogin aliases */ + case 'e': + case 'w': + case '8': + break; + case 'd': + dflag = 1; + break; + case 'l': + user = optarg; + break; +#ifdef KERBEROS + case 'k': + dest_realm = dst_realm_buf; + strncpy(dest_realm, optarg, REALM_SZ); + break; +#endif + case 'n': + nflag = 1; + break; +#ifdef KERBEROS #endif + case '?': + default: + usage(); + } + optind += argoff; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = argv[optind++])) + usage(); - if (host == 0) - goto usage; - if (argv[0] == 0) { + /* if no further arguments, must have been called as rlogin. */ + if (!argv[optind]) { if (asrsh) - *argv0 = "rlogin"; - execv(_PATH_RLOGIN, argv0); - perror(_PATH_RLOGIN); - exit(1); + *argv = "rlogin"; + execv(_PATH_RLOGIN, argv); + err(1, "can't exec %s", _PATH_RLOGIN); } - pwd = getpwuid(getuid()); - if (pwd == 0) { - fprintf(stderr, "who are you?\n"); - exit(1); - } - cc = 0; - for (ap = argv; *ap; ap++) - cc += strlen(*ap) + 1; - cp = args = malloc(cc); - for (ap = argv; *ap; ap++) { - (void) strcpy(cp, *ap); - while (*cp) - cp++; - if (ap[1]) - *cp++ = ' '; - } -#ifdef KERBEROS - sp = getservbyname("kshell", "tcp"); - if (sp == NULL) { - use_kerberos = 0; - old_warning("kshell service unknown"); - sp = getservbyname("shell", "tcp"); - } -#else - sp = getservbyname("shell", "tcp"); + + argc -= optind; + argv += optind; + + if (!(pw = getpwuid(uid = getuid()))) + errx(1, "unknown user id"); + if (!user) + user = pw->pw_name; + +#ifdef KERBEROS #endif - if (sp == 0) { - fprintf(stderr, "rsh: shell/tcp: unknown service\n"); - exit(1); + args = copyargs(argv); + + sp = NULL; +#ifdef KERBEROS + if (use_kerberos) { + sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp"); + if (sp == NULL) { + use_kerberos = 0; + warning("can't get entry for %s/tcp service", + doencrypt ? "ekshell" : "kshell"); + } } +#endif + if (sp == NULL) + sp = getservbyname("shell", "tcp"); + if (sp == NULL) + errx(1, "shell/tcp: unknown service"); -#ifdef KERBEROS +#ifdef KERBEROS try_connect: - if(use_kerberos) { + if (use_kerberos) { + struct hostent *hp; + + /* fully qualify hostname (needed for krb_realmofhost) */ + hp = gethostbyname(host); + if (hp != NULL && !(host = strdup(hp->h_name))) + err(1, NULL); + rem = KSUCCESS; - if(krb_realm[0] == '\0') { - rem = krb_get_lrealm(krb_realm, 1); - } + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); - if(rem == KSUCCESS) { - if(encrypt) { - rem = krcmd_mutual( - &host, sp->s_port, - user ? user : pwd->pw_name, - args, - &rfd2, - krb_realm, - &cred, schedule); - } else { - rem = krcmd( - &host, - sp->s_port, - user ? user : pwd->pw_name, - args, - &rfd2, - krb_realm - ); - } - } else { - fprintf(stderr, - "%s: error getting local realm\n", - argv0[0]); - exit(1); - } - if((rem < 0) && errno == ECONNREFUSED) { + rem = krcmd(&host, sp->s_port, user, args, &rfd2, + dest_realm); + if (rem < 0) { use_kerberos = 0; sp = getservbyname("shell", "tcp"); - if(sp == NULL) { - fprintf(stderr, "unknown service shell/tcp\n"); - exit(1); - } - old_warning("remote host doesn't support Kerberos"); + if (sp == NULL) + errx(1, "shell/tcp: unknown service"); + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); goto try_connect; } } else { - if(encrypt) { - fprintf(stderr,"The -x flag requires Kerberos authentication\n"); - exit(1); - } - rem = rcmd(&host, sp->s_port, pwd->pw_name, - user ? user : pwd->pw_name, args, &rfd2); + if (doencrypt) + errx(1, "the -x flag requires Kerberos authentication"); + rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); } - #else - - rem = rcmd(&host, sp->s_port, pwd->pw_name, - user ? user : pwd->pw_name, args, &rfd2); + rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); #endif - if (rem < 0) - exit(1); + if (rem < 0) + exit(1); - if (rfd2 < 0) { - fprintf(stderr, "rsh: can't establish stderr\n"); - exit(2); + if (rfd2 < 0) + errx(1, "can't establish stderr"); + if (dflag) { + if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, + sizeof(one)) < 0) + warn("setsockopt"); + if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, + sizeof(one)) < 0) + warn("setsockopt"); } - if (options & SO_DEBUG) { - if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0) - perror("setsockopt (stdin)"); - if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, sizeof (one)) < 0) - perror("setsockopt (stderr)"); - } - (void) setuid(getuid()); - omask = sigblock(mask(SIGINT)|mask(SIGQUIT)|mask(SIGTERM)); + + (void)setuid(uid); + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)); if (signal(SIGINT, SIG_IGN) != SIG_IGN) - signal(SIGINT, sendsig); + (void)signal(SIGINT, sendsig); if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) - signal(SIGQUIT, sendsig); + (void)signal(SIGQUIT, sendsig); if (signal(SIGTERM, SIG_IGN) != SIG_IGN) - signal(SIGTERM, sendsig); - if (nflag == 0) { + (void)signal(SIGTERM, sendsig); + + if (!nflag) { pid = fork(); - if (pid < 0) { - perror("fork"); - exit(1); - } + if (pid < 0) + err(1, "fork"); } - ioctl(rfd2, FIONBIO, &one); - ioctl(rem, FIONBIO, &one); - if (nflag == 0 && pid == 0) { - char *bp; int rembits, wc; - (void) close(rfd2); - reread: - errno = 0; - cc = read(0, buf, sizeof buf); - if (cc <= 0) + +#ifdef KERBEROS +#endif + { + (void)ioctl(rfd2, FIONBIO, &one); + (void)ioctl(rem, FIONBIO, &one); + } + + talk(nflag, omask, pid, rem); + + if (!nflag) + (void)kill(pid, SIGKILL); + exit(0); +} + +void +talk(nflag, omask, pid, rem) + int nflag; + long omask; + pid_t pid; + int rem; +{ + int cc, wc; + fd_set readfrom, ready, rembits; + char *bp, buf[BUFSIZ]; + + if (!nflag && pid == 0) { + (void)close(rfd2); + +reread: errno = 0; + if ((cc = read(0, buf, sizeof buf)) <= 0) goto done; bp = buf; - rewrite: - rembits = 1<