/*
- * Copyright (c) 1983 The Regents of the University of California.
+ * Copyright (c) 1983, 1990 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\
+"@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\
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 */
/*
#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 <strings.h>
+#include <string.h>
#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;
-extern char *sys_errlist[];
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 {
extern int optind;
struct servent *sp;
int ch, fflag, tflag;
- char *targ, *colon();
+ char *targ, *shell, *colon();
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;
- while ((ch = getopt(argc, argv, "dfkprtx")) != EOF)
+ while ((ch = getopt(argc, argv, OPTIONS)) != EOF)
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 't': /* "to" */
- tflag = 1;
+#ifdef KERBEROS
+ case 'k':
+ strncpy(dst_realm_buf, ++argv, REALM_SZ);
+ dest_realm = dst_realm_buf;
break;
-#ifdef KERBEROS
+#ifdef CRYPT
case 'x':
encrypt = 1;
- des_set_key(cred.session, schedule);
+ /* des_set_key(cred.session, schedule); */
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();
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) {
- iamremote = 1;
+ /* follow "protocol", send data */
(void)response();
(void)setuid(userid);
source(argc, argv);
}
if (tflag) {
- iamremote = 1;
+ /* receive data */
(void)setuid(userid);
sink(argc, argv);
exit(errs);
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" : "");
+#endif
(void)signal(SIGPIPE, lostconn);
if (targ = colon(argv[argc - 1]))
- toremote(targ, argc, argv);
+ toremote(targ, argc, argv); /* destination is remote host */
else {
- tolocal(argc, argv);
+ tolocal(argc, argv); /* destination is local host */
if (targetshouldbedirectory)
verifydir(argv[argc - 1]);
}
int argc;
char **argv;
{
- int i;
+ int i, tos;
char *bp, *host, *src, *suser, *thost, *tuser;
char *colon(), *malloc();
targ = ".";
if (thost = index(argv[argc - 1], '@')) {
+ /* user@host */
*thost++ = 0;
tuser = argv[argc - 1];
if (*tuser == '\0')
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) {
host = thost;
#ifdef KERBEROS
if (use_kerberos)
- kerberos(bp,
+ rem = kerberos(&host, bp,
+ pwd->pw_name,
tuser ? tuser : pwd->pw_name);
else
#endif
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);
int argc;
char **argv;
{
- int i;
+ int i, tos;
char *bp, *host, *src, *suser;
char *colon(), *malloc();
(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;
- (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);
- (void)setreuid(userid, 0);
+ (void)seteuid(0);
(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;
{
return;
errno = ENOTDIR;
}
- error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
+ error("rcp: %s: %s.\n", cp, strerror(errno));
exit(1);
}
char *s;
{
int status, pid, w;
- register int (*istat)(), (*qstat)();
+ register sig_t istat, qstat;
if ((pid = vfork()) == 0) {
(void)setuid(userid);
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)
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();
}
}
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, '/');
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;
- int ofd, setimes, size, targisdir, wrerr;
+ int ofd, setimes, size, targisdir;
char *np, *vect[1], buf[BUFSIZ], *malloc();
#define atime tv[0]
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) {
-bad: error("rcp: %s: %s\n", np, sys_errlist[errno]);
+bad: error("rcp: %s: %s\n", np, strerror(errno));
continue;
}
if (exists && pflag)
}
cp = bp->buf;
count = 0;
- wrerr = 0;
+ wrerr = NO;
for (i = 0; i < size; i += BUFSIZ) {
amt = BUFSIZ;
if (i + amt > size)
j = read(rem, cp, amt);
if (j <= 0) {
error("rcp: %s\n",
- j ? sys_errlist[errno] :
+ j ? strerror(errno) :
"dropped connection");
exit(1);
}
cp += j;
} while (amt > 0);
if (count == bp->cnt) {
- if (wrerr == 0 &&
+ if (wrerr == NO &&
write(ofd, bp->buf, count) != count)
- wrerr++;
+ wrerr = YES;
count = 0;
cp = bp->buf;
}
}
- if (count != 0 && wrerr == 0 &&
+ if (count != 0 && wrerr == NO &&
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,
- sys_errlist[errno]);
+ strerror(errno));
+ wrerr = DISPLAYED;
+ }
(void)close(ofd);
(void)response();
- if (setimes) {
+ if (setimes && wrerr == NO) {
setimes = 0;
- if (utimes(np, tv) < 0)
+ if (utimes(np, tv) < 0) {
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);
+ break;
+ case DISPLAYED:
+ break;
+ }
}
screwup:
error("rcp: protocol screwup: %s\n", why);
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);
exit(1);
}
-#ifdef KERBEROS
-old_warning(str)
- char *str;
-{
- (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
-}
-#endif
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");
+#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);
}
+
+#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 */