add -DCRYPT to get -x processing
[unix-history] / usr / src / bin / rcp / rcp.c
index c67efef..893129d 100644 (file)
@@ -1,28 +1,18 @@
 /*
 /*
- * Copyright (c) 1983 The Regents of the University of California.
+ * Copyright (c) 1983, 1990 The Regents of the University of California.
  * All rights reserved.
  *
  * 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[] =
  */
 
 #ifndef lint
 char copyright[] =
-"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
  All rights reserved.\n";
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)rcp.c      5.20 (Berkeley) %G%";
+static char sccsid[] = "@(#)rcp.c      5.30 (Berkeley) %G%";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -36,30 +26,43 @@ static char sccsid[] = "@(#)rcp.c   5.20 (Berkeley) %G%";
 #include <sys/dir.h>
 #include <sys/signal.h>
 #include <netinet/in.h>
 #include <sys/dir.h>
 #include <sys/signal.h>
 #include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 #include <pwd.h>
 #include <netdb.h>
 #include <errno.h>
 #include <pwd.h>
 #include <netdb.h>
 #include <errno.h>
-#include <strings.h>
+#include <string.h>
 #include <stdio.h>
 #include <ctype.h>
 #include "pathnames.h"
 
 #ifdef KERBEROS
 #include <stdio.h>
 #include <ctype.h>
 #include "pathnames.h"
 
 #ifdef KERBEROS
-#include <kerberos/krb.h>
-
-char krb_realm[REALM_SZ];
-int use_kerberos = 1, encrypt = 0;
-CREDENTIALS cred;
-Key_schedule schedule;
+#include <kerberosIV/des.h>
+#include <kerberosIV/krb.h>
+char   dst_realm_buf[REALM_SZ];
+char   *dest_realm = NULL;
+int    use_kerberos = 1;
+CREDENTIALS    cred;
+Key_schedule   schedule;
+extern char    *krb_realmofhost();
+#ifdef CRYPT
+int    encrypt = 0;
+#define        OPTIONS "dfkprtx"
+#else
+#define        OPTIONS "dfkprt"
+#endif
+#else
+#define        OPTIONS "dfprt"
 #endif
 
 extern int errno;
 #endif
 
 extern int errno;
-extern char *sys_errlist[];
 struct passwd *pwd;
 struct passwd *pwd;
-int errs, pflag, port, rem, userid;
-int iamremote, iamrecursive, targetshouldbedirectory;
+u_short        port;
+uid_t  userid;
+int errs, rem;
+int pflag, iamremote, iamrecursive, targetshouldbedirectory;
 
 
-#define        CMDNEEDS        20
+#define        CMDNEEDS        64
 char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
 
 typedef struct _buf {
 char cmd[CMDNEEDS];            /* must hold "rcp -r -p -d\0" */
 
 typedef struct _buf {
@@ -74,60 +77,45 @@ main(argc, argv)
        extern int optind;
        struct servent *sp;
        int ch, fflag, tflag;
        extern int optind;
        struct servent *sp;
        int ch, fflag, tflag;
-       char *targ, *colon();
+       char *targ, *shell, *colon();
        struct passwd *getpwuid();
        int lostconn();
 
        struct passwd *getpwuid();
        int lostconn();
 
-#ifdef KERBEROS
-       sp = getservbyname("kshell", "tcp");
-       if (sp == NULL) {
-               use_kerberos = 0;
-               old_warning("kshell service unknown");
-               sp = getservbyname("kshell", "tcp");
-       }
-#else
-       sp = getservbyname("shell", "tcp");
-#endif
-       if (!sp) {
-               (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
-               exit(1);
-       }
-       port = sp->s_port;
-
-       if (!(pwd = getpwuid(userid = getuid()))) {
-               (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
-               exit(1);
-       }
-
        fflag = tflag = 0;
        fflag = tflag = 0;
-       while ((ch = getopt(argc, argv, "dfkprtx")) != EOF)
+       while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
                switch(ch) {
                switch(ch) {
-               case 'd':
-                       targetshouldbedirectory = 1;
-                       break;
-               case 'f':                       /* "from" */
-                       fflag = 1;
-                       break;
-#ifdef KERBEROS
-               case 'k':
-                       strncpy(krb_realm, ++argv, REALM_SZ);
-                       break;
-#endif
+               /* user-visible flags */
                case 'p':                       /* preserve access/mod times */
                        ++pflag;
                        break;
                case 'r':
                        ++iamrecursive;
                        break;
                case 'p':                       /* preserve access/mod times */
                        ++pflag;
                        break;
                case 'r':
                        ++iamrecursive;
                        break;
-               case 't':                       /* "to" */
-                       tflag = 1;
+#ifdef KERBEROS
+               case 'k':
+                       strncpy(dst_realm_buf, ++argv, REALM_SZ);
+                       dest_realm = dst_realm_buf;
                        break;
                        break;
-#ifdef KERBEROS
+#ifdef CRYPT
                case 'x':
                        encrypt = 1;
                case 'x':
                        encrypt = 1;
-                       des_set_key(cred.session, schedule);
+                       /* des_set_key(cred.session, schedule); */
                        break;
 #endif
                        break;
 #endif
+#endif
+               /* rshd-invoked options (server) */
+               case 'd':
+                       targetshouldbedirectory = 1;
+                       break;
+               case 'f':                       /* "from" */
+                       iamremote = 1;
+                       fflag = 1;
+                       break;
+               case 't':                       /* "to" */
+                       iamremote = 1;
+                       tflag = 1;
+                       break;
+
                case '?':
                default:
                        usage();
                case '?':
                default:
                        usage();
@@ -135,8 +123,37 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
+#ifdef KERBEROS
+#ifdef CRYPT
+       shell = encrypt ? "ekshell" : "kshell";
+#else
+       shell = "kshell";
+#endif
+       sp = getservbyname(shell, "tcp");
+       if (sp == NULL) {
+               char    msgbuf[64];
+               use_kerberos = 0;
+               (void) sprintf(msgbuf, "can't get entry for %s/tcp service",
+                       shell);
+               old_warning(msgbuf);
+               sp = getservbyname("shell", "tcp");
+       }
+#else
+       sp = getservbyname("shell", "tcp");
+#endif
+       if (sp == NULL) {
+               (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
+               exit(1);
+       }
+       port = sp->s_port;
+
+       if (!(pwd = getpwuid(userid = getuid()))) {
+               (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
+               exit(1);
+       }
+
        if (fflag) {
        if (fflag) {
-               iamremote = 1;
+               /* follow "protocol", send data */
                (void)response();
                (void)setuid(userid);
                source(argc, argv);
                (void)response();
                (void)setuid(userid);
                source(argc, argv);
@@ -144,7 +161,7 @@ main(argc, argv)
        }
 
        if (tflag) {
        }
 
        if (tflag) {
-               iamremote = 1;
+               /* receive data */
                (void)setuid(userid);
                sink(argc, argv);
                exit(errs);
                (void)setuid(userid);
                sink(argc, argv);
                exit(errs);
@@ -156,15 +173,26 @@ main(argc, argv)
                targetshouldbedirectory = 1;
 
        rem = -1;
                targetshouldbedirectory = 1;
 
        rem = -1;
+       /* command to be executed on remote system using "rsh" */
+#ifdef KERBEROS
+       (void)sprintf(cmd, "rcp%s%s%s%s", iamrecursive ? " -r" : "",
+#ifdef CRYPT
+           ((encrypt && use_kerberos) ? " -x" : ""),
+#else
+           "",
+#endif
+           pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+#else
        (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
            pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
        (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
            pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
+#endif
 
        (void)signal(SIGPIPE, lostconn);
 
        if (targ = colon(argv[argc - 1]))
 
        (void)signal(SIGPIPE, lostconn);
 
        if (targ = colon(argv[argc - 1]))
-               toremote(targ, argc, argv);
+               toremote(targ, argc, argv);     /* destination is remote host */
        else {
        else {
-               tolocal(argc, argv);
+               tolocal(argc, argv);            /* destination is local host */
                if (targetshouldbedirectory)
                        verifydir(argv[argc - 1]);
        }
                if (targetshouldbedirectory)
                        verifydir(argv[argc - 1]);
        }
@@ -176,7 +204,7 @@ toremote(targ, argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       int i;
+       int i, tos;
        char *bp, *host, *src, *suser, *thost, *tuser;
        char *colon(), *malloc();
 
        char *bp, *host, *src, *suser, *thost, *tuser;
        char *colon(), *malloc();
 
@@ -185,6 +213,7 @@ toremote(targ, argc, argv)
                targ = ".";
 
        if (thost = index(argv[argc - 1], '@')) {
                targ = ".";
 
        if (thost = index(argv[argc - 1], '@')) {
+               /* user@host */
                *thost++ = 0;
                tuser = argv[argc - 1];
                if (*tuser == '\0')
                *thost++ = 0;
                tuser = argv[argc - 1];
                if (*tuser == '\0')
@@ -205,7 +234,7 @@ toremote(targ, argc, argv)
                        host = index(argv[i], '@');
                        if (!(bp = malloc((u_int)(strlen(_PATH_RSH) +
                                    strlen(argv[i]) + strlen(src) +
                        host = index(argv[i], '@');
                        if (!(bp = malloc((u_int)(strlen(_PATH_RSH) +
                                    strlen(argv[i]) + strlen(src) +
-                                   strlen(tuser) + strlen(thost) +
+                                   tuser ? strlen(tuser) : 0 + strlen(thost) +
                                    strlen(targ)) + CMDNEEDS + 20)))
                                        nospace();
                        if (host) {
                                    strlen(targ)) + CMDNEEDS + 20)))
                                        nospace();
                        if (host) {
@@ -236,7 +265,8 @@ toremote(targ, argc, argv)
                                host = thost;
 #ifdef KERBEROS
                                if (use_kerberos)
                                host = thost;
 #ifdef KERBEROS
                                if (use_kerberos)
-                                       kerberos(bp,
+                                       rem = kerberos(&host, bp,
+                                           pwd->pw_name,
                                            tuser ? tuser : pwd->pw_name);
                                else
 #endif
                                            tuser ? tuser : pwd->pw_name);
                                else
 #endif
@@ -245,6 +275,10 @@ toremote(targ, argc, argv)
                                            bp, 0);
                                if (rem < 0)
                                        exit(1);
                                            bp, 0);
                                if (rem < 0)
                                        exit(1);
+                               tos = IPTOS_THROUGHPUT;
+                               if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+                                   (char *)&tos, sizeof(int)) < 0)
+                                       perror("rcp: setsockopt TOS (ignored)");
                                if (response() < 0)
                                        exit(1);
                                (void)free(bp);
                                if (response() < 0)
                                        exit(1);
                                (void)free(bp);
@@ -259,7 +293,7 @@ tolocal(argc, argv)
        int argc;
        char **argv;
 {
        int argc;
        char **argv;
 {
-       int i;
+       int i, tos;
        char *bp, *host, *src, *suser;
        char *colon(), *malloc();
 
        char *bp, *host, *src, *suser;
        char *colon(), *malloc();
 
@@ -295,57 +329,25 @@ tolocal(argc, argv)
                (void)sprintf(bp, "%s -f %s", cmd, src);
 #ifdef KERBEROS
                if (use_kerberos)
                (void)sprintf(bp, "%s -f %s", cmd, src);
 #ifdef KERBEROS
                if (use_kerberos)
-                       kerberos(bp, suser);
+                       rem = kerberos(&host, bp, pwd->pw_name, suser);
                else
 #endif
                        rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
                (void)free(bp);
                if (rem < 0)
                        continue;
                else
 #endif
                        rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
                (void)free(bp);
                if (rem < 0)
                        continue;
-               (void)setreuid(0, userid);
+               (void)seteuid(userid);
+               tos = IPTOS_THROUGHPUT;
+               if (setsockopt(rem, IPPROTO_IP, IP_TOS,
+                   (char *)&tos, sizeof(int)) < 0)
+                       perror("rcp: setsockopt TOS (ignored)");
                sink(1, argv + argc - 1);
                sink(1, argv + argc - 1);
-               (void)setreuid(userid, 0);
+               (void)seteuid(0);
                (void)close(rem);
                rem = -1;
        }
 }
 
                (void)close(rem);
                rem = -1;
        }
 }
 
-#ifdef KERBEROS
-kerberos(bp, user)
-       char *bp, *user;
-{
-       struct servent *sp;
-       char *host;
-
-again: rem = KSUCCESS;
-       if (krb_realm[0] == '\0')
-               rem = krb_get_lrealm(krb_realm, 1);
-       if (rem == KSUCCESS) {
-               if (encrypt)
-                       rem = krcmd_mutual(&host, port, user, bp, 0,
-                           krb_realm, &cred, schedule);
-               else
-                       rem = krcmd(&host, port, user, bp, 0, krb_realm);
-       } else {
-               (void)fprintf(stderr,
-                   "rcp: error getting local realm %s\n", krb_err_txt[rem]);
-               exit(1);
-       }
-       if (rem < 0 && errno == ECONNREFUSED) {
-               use_kerberos = 0;
-               old_warning("remote host doesn't support Kerberos");
-               sp = getservbyname("shell", "tcp");
-               if (sp == NULL) {
-                       (void)fprintf(stderr,
-                           "rcp: unknown service shell/tcp\n");
-                       exit(1);
-               }
-               port = sp->s_port;
-               goto again;
-       }
-}
-#endif /* KERBEROS */
-
 verifydir(cp)
        char *cp;
 {
 verifydir(cp)
        char *cp;
 {
@@ -356,7 +358,7 @@ verifydir(cp)
                        return;
                errno = ENOTDIR;
        }
                        return;
                errno = ENOTDIR;
        }
-       error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
+       error("rcp: %s: %s.\n", cp, strerror(errno));
        exit(1);
 }
 
        exit(1);
 }
 
@@ -396,7 +398,7 @@ susystem(s)
        char *s;
 {
        int status, pid, w;
        char *s;
 {
        int status, pid, w;
-       register int (*istat)(), (*qstat)();
+       register sig_t istat, qstat;
 
        if ((pid = vfork()) == 0) {
                (void)setuid(userid);
 
        if ((pid = vfork()) == 0) {
                (void)setuid(userid);
@@ -429,7 +431,7 @@ source(argc, argv)
        for (x = 0; x < argc; x++) {
                name = argv[x];
                if ((f = open(name, O_RDONLY, 0)) < 0) {
        for (x = 0; x < argc; x++) {
                name = argv[x];
                if ((f = open(name, O_RDONLY, 0)) < 0) {
-                       error("rcp: %s: %s\n", name, sys_errlist[errno]);
+                       error("rcp: %s: %s\n", name, strerror(errno));
                        continue;
                }
                if (fstat(f, &stb) < 0)
                        continue;
                }
                if (fstat(f, &stb) < 0)
@@ -493,7 +495,7 @@ notreg:                     (void)close(f);
                if (readerr == 0)
                        (void)write(rem, "", 1);
                else
                if (readerr == 0)
                        (void)write(rem, "", 1);
                else
-                       error("rcp: %s: %s\n", name, sys_errlist[readerr]);
+                       error("rcp: %s: %s\n", name, strerror(readerr));
                (void)response();
        }
 }
                (void)response();
        }
 }
@@ -507,7 +509,7 @@ rsource(name, statp)
        char *last, *vect[1], path[MAXPATHLEN];
 
        if (!(d = opendir(name))) {
        char *last, *vect[1], path[MAXPATHLEN];
 
        if (!(d = opendir(name))) {
-               error("rcp: %s: %s\n", name, sys_errlist[errno]);
+               error("rcp: %s: %s\n", name, strerror(errno));
                return;
        }
        last = rindex(name, '/');
                return;
        }
        last = rindex(name, '/');
@@ -596,11 +598,12 @@ sink(argc, argv)
        static BUF buffer;
        struct stat stb;
        struct timeval tv[2];
        static BUF buffer;
        struct stat stb;
        struct timeval tv[2];
+       enum { YES, NO, DISPLAYED } wrerr;
        BUF *bp, *allocbuf();
        off_t i, j;
        char ch, *targ, *why;
        int amt, count, exists, first, mask, mode;
        BUF *bp, *allocbuf();
        off_t i, j;
        char ch, *targ, *why;
        int amt, count, exists, first, mask, mode;
-       int ofd, setimes, size, targisdir, wrerr;
+       int ofd, setimes, size, targisdir;
        char *np, *vect[1], buf[BUFSIZ], *malloc();
 
 #define        atime   tv[0]
        char *np, *vect[1], buf[BUFSIZ], *malloc();
 
 #define        atime   tv[0]
@@ -730,12 +733,12 @@ sink(argc, argv)
                                setimes = 0;
                                if (utimes(np, tv) < 0)
                                    error("rcp: can't set times on %s: %s\n",
                                setimes = 0;
                                if (utimes(np, tv) < 0)
                                    error("rcp: can't set times on %s: %s\n",
-                                       np, sys_errlist[errno]);
+                                       np, strerror(errno));
                        }
                        continue;
                }
                if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
                        }
                        continue;
                }
                if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
-bad:                   error("rcp: %s: %s\n", np, sys_errlist[errno]);
+bad:                   error("rcp: %s: %s\n", np, strerror(errno));
                        continue;
                }
                if (exists && pflag)
                        continue;
                }
                if (exists && pflag)
@@ -747,7 +750,7 @@ bad:                        error("rcp: %s: %s\n", np, sys_errlist[errno]);
                }
                cp = bp->buf;
                count = 0;
                }
                cp = bp->buf;
                count = 0;
-               wrerr = 0;
+               wrerr = NO;
                for (i = 0; i < size; i += BUFSIZ) {
                        amt = BUFSIZ;
                        if (i + amt > size)
                for (i = 0; i < size; i += BUFSIZ) {
                        amt = BUFSIZ;
                        if (i + amt > size)
@@ -757,7 +760,7 @@ bad:                        error("rcp: %s: %s\n", np, sys_errlist[errno]);
                                j = read(rem, cp, amt);
                                if (j <= 0) {
                                        error("rcp: %s\n",
                                j = read(rem, cp, amt);
                                if (j <= 0) {
                                        error("rcp: %s\n",
-                                           j ? sys_errlist[errno] :
+                                           j ? strerror(errno) :
                                            "dropped connection");
                                        exit(1);
                                }
                                            "dropped connection");
                                        exit(1);
                                }
@@ -765,31 +768,41 @@ bad:                      error("rcp: %s: %s\n", np, sys_errlist[errno]);
                                cp += j;
                        } while (amt > 0);
                        if (count == bp->cnt) {
                                cp += j;
                        } while (amt > 0);
                        if (count == bp->cnt) {
-                               if (wrerr == 0 &&
+                               if (wrerr == NO &&
                                    write(ofd, bp->buf, count) != count)
                                    write(ofd, bp->buf, count) != count)
-                                       wrerr++;
+                                       wrerr = YES;
                                count = 0;
                                cp = bp->buf;
                        }
                }
                                count = 0;
                                cp = bp->buf;
                        }
                }
-               if (count != 0 && wrerr == 0 &&
+               if (count != 0 && wrerr == NO &&
                    write(ofd, bp->buf, count) != count)
                    write(ofd, bp->buf, count) != count)
-                       wrerr++;
-               if (ftruncate(ofd, size))
+                       wrerr = YES;
+               if (ftruncate(ofd, size)) {
                        error("rcp: can't truncate %s: %s\n", np,
                        error("rcp: can't truncate %s: %s\n", np,
-                           sys_errlist[errno]);
+                           strerror(errno));
+                       wrerr = DISPLAYED;
+               }
                (void)close(ofd);
                (void)response();
                (void)close(ofd);
                (void)response();
-               if (setimes) {
+               if (setimes && wrerr == NO) {
                        setimes = 0;
                        setimes = 0;
-                       if (utimes(np, tv) < 0)
+                       if (utimes(np, tv) < 0) {
                                error("rcp: can't set times on %s: %s\n",
                                error("rcp: can't set times on %s: %s\n",
-                                   np, sys_errlist[errno]);
-               }                                  
-               if (wrerr)
-                       error("rcp: %s: %s\n", np, sys_errlist[errno]);
-               else
+                                   np, strerror(errno));
+                               wrerr = DISPLAYED;
+                       }
+               }
+               switch(wrerr) {
+               case YES:
+                       error("rcp: %s: %s\n", np, strerror(errno));
+                       break;
+               case NO:
                        (void)write(rem, "", 1);
                        (void)write(rem, "", 1);
+                       break;
+               case DISPLAYED:
+                       break;
+               }
        }
 screwup:
        error("rcp: protocol screwup: %s\n", why);
        }
 screwup:
        error("rcp: protocol screwup: %s\n", why);
@@ -806,7 +819,7 @@ allocbuf(bp, fd, blksize)
        char *malloc();
 
        if (fstat(fd, &stb) < 0) {
        char *malloc();
 
        if (fstat(fd, &stb) < 0) {
-               error("rcp: fstat: %s\n", sys_errlist[errno]);
+               error("rcp: fstat: %s\n", strerror(errno));
                return(0);
        }
        size = roundup(stb.st_blksize, blksize);
                return(0);
        }
        size = roundup(stb.st_blksize, blksize);
@@ -848,23 +861,88 @@ nospace()
        exit(1);
 }
 
        exit(1);
 }
 
-#ifdef KERBEROS
-old_warning(str)
-       char *str;
-{
-       (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
-}
-#endif
 
 usage()
 {
 #ifdef KERBEROS
 
 usage()
 {
 #ifdef KERBEROS
+#ifdef CRYPT
        (void)fprintf(stderr, "%s\n\t%s\n",
            "usage: rcp [-k realm] [-px] f1 f2",
            "or: rcp [-k realm] [-rpx] f1 ... fn directory");
        (void)fprintf(stderr, "%s\n\t%s\n",
            "usage: rcp [-k realm] [-px] f1 f2",
            "or: rcp [-k realm] [-rpx] f1 ... fn directory");
+#else
+       (void)fprintf(stderr, "%s\n\t%s\n",
+           "usage: rcp [-k realm] [-p] f1 f2",
+           "or: rcp [-k realm] [-rp] f1 ... fn directory");
+#endif
 #else
        (void)fprintf(stderr,
            "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
 #endif
        exit(1);
 }
 #else
        (void)fprintf(stderr,
            "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
 #endif
        exit(1);
 }
+
+#ifdef KERBEROS
+old_warning(str)
+       char *str;
+{
+       (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
+}
+
+int
+kerberos(host, bp, locuser, user)
+
+       char **host, *bp, *locuser, *user;
+{
+       struct servent *sp;
+
+again:
+       if (use_kerberos) {
+               rem = KSUCCESS;
+               errno = 0;
+               if (dest_realm == NULL)
+                       dest_realm = krb_realmofhost(*host);
+
+#ifdef CRYPT
+               if (encrypt)
+                       rem = krcmd_mutual(
+                               host, port,
+                               user, bp, 0,
+                               dest_realm,
+                               &cred, schedule);
+               else
+#endif
+                       rem = krcmd(
+                               host, port,
+                               user, bp, 0, dest_realm);
+
+               if (rem < 0) {
+                       use_kerberos = 0;
+                       sp = getservbyname("shell", "tcp");
+                       if (sp == NULL) {
+                               (void)fprintf(stderr,
+                                   "rcp: unknown service shell/tcp\n");
+                               exit(1);
+                       }
+                       if (errno == ECONNREFUSED)
+                               old_warning(
+                                   "remote host doesn't support Kerberos");
+
+                       if (errno == ENOENT)
+                               old_warning(
+                                   "Can't provide Kerberos auth data");
+                       port = sp->s_port;
+                       goto again;
+               }
+       } else {
+#ifdef CRYPT
+               if (encrypt) {
+                       fprintf(stderr,
+                           "The -x option requires Kerberos authentication\n");
+                       exit(1);
+               }
+#endif
+               rem = rcmd(host, sp->s_port, locuser, user, bp, 0);
+       }
+       return(rem);
+}
+#endif /* KERBEROS */