Thread View: comp.bugs.2bsd
1 messages
1 total messages
Started by Steven M. Schultz(Y)
Fri, 26 May 1989 05:50
Security Problem in rcp/rdist (4.3BSD Fix V1.82&3)
Author: Steven M. Schultz(Y)
Date: Fri, 26 May 1989 05:50
Date: Fri, 26 May 1989 05:50
1040 lines
24891 bytes
24891 bytes
This is V1.82 for 2.10.1BSD, the only difference was one
long vs. int change in rcp.c.
>Subject: V1.82 (Rcp/rdist security patch)
>Approved: ucb-fixes@okeeffe.berkeley.edu
>
>Subject: Rcp/rdist security patch
>Index: bin/rcp.c 4.3BSD
>Index: ucb/rdist/server.c 4.3BSD
>
>Description:
> There's a security problem associated with rcp and rdist
> in the 4.3BSD, 4.3BSD-tahoe, and first BSD networking
> distributions.
>Fix:
> Replace your current bin/rcp.c with the attached rcp.c.
> Patch the server.c module in your current rdist with the
> attached patched. Recompile and re-install.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# rcp.c
# pathnames.h
# rdist.diff
# This archive created: Thu May 25 22:43:03 1989
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'rcp.c'
then
echo shar: "will not over-write existing file 'rcp.c'"
else
sed 's/^X//' << \SHAR_EOF > 'rcp.c'
X/*
X * Copyright (c) 1983 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley. The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)rcp.c 5.20 (Berkeley) 5/23/89";
X#endif /* not lint */
X
X/*
X * rcp
X */
X#include <sys/param.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <sys/time.h>
X#include <sys/ioctl.h>
X#include <sys/dir.h>
X#include <sys/signal.h>
X#include <netinet/in.h>
X#include <pwd.h>
X#include <netdb.h>
X#include <errno.h>
X#include <string.h>
X#include <stdio.h>
X#include <ctype.h>
X#include "pathnames.h"
X
X#ifdef KERBEROS
X#include <kerberos/krb.h>
X
Xchar krb_realm[REALM_SZ];
Xint use_kerberos = 1, encrypt = 0;
XCREDENTIALS cred;
XKey_schedule schedule;
X#endif
X
Xextern int errno;
Xextern char *sys_errlist[];
Xstruct passwd *pwd;
Xint errs, pflag, port, rem, userid;
Xint iamremote, iamrecursive, targetshouldbedirectory;
X
X#define CMDNEEDS 20
Xchar cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
X
Xtypedef struct _buf {
X int cnt;
X char *buf;
X} BUF;
X
Xmain(argc, argv)
X int argc;
X char **argv;
X{
X extern int optind;
X struct servent *sp;
X int ch, fflag, tflag;
X char *targ, *colon();
X struct passwd *getpwuid();
X int lostconn();
X
X#ifdef KERBEROS
X sp = getservbyname("kshell", "tcp");
X if (sp == NULL) {
X use_kerberos = 0;
X old_warning("kshell service unknown");
X sp = getservbyname("kshell", "tcp");
X }
X#else
X sp = getservbyname("shell", "tcp");
X#endif
X if (!sp) {
X (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
X exit(1);
X }
X port = sp->s_port;
X
X if (!(pwd = getpwuid(userid = getuid()))) {
X (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
X exit(1);
X }
X
X fflag = tflag = 0;
X while ((ch = getopt(argc, argv, "dfkprtx")) != EOF)
X switch(ch) {
X case 'd':
X targetshouldbedirectory = 1;
X break;
X case 'f': /* "from" */
X fflag = 1;
X break;
X#ifdef KERBEROS
X case 'k':
X strncpy(krb_realm, ++argv, REALM_SZ);
X break;
X#endif
X case 'p': /* preserve access/mod times */
X ++pflag;
X break;
X case 'r':
X ++iamrecursive;
X break;
X case 't': /* "to" */
X tflag = 1;
X break;
X#ifdef KERBEROS
X case 'x':
X encrypt = 1;
X des_set_key(cred.session, schedule);
X break;
X#endif
X case '?':
X default:
X usage();
X }
X argc -= optind;
X argv += optind;
X
X if (fflag) {
X iamremote = 1;
X (void)response();
X (void)setuid(userid);
X source(argc, argv);
X exit(errs);
X }
X
X if (tflag) {
X iamremote = 1;
X (void)setuid(userid);
X sink(argc, argv);
X exit(errs);
X }
X
X if (argc < 2)
X usage();
X if (argc > 2)
X targetshouldbedirectory = 1;
X
X rem = -1;
X (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
X pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
X
X (void)signal(SIGPIPE, lostconn);
X
X if (targ = colon(argv[argc - 1]))
X toremote(targ, argc, argv);
X else {
X tolocal(argc, argv);
X if (targetshouldbedirectory)
X verifydir(argv[argc - 1]);
X }
X exit(errs);
X}
X
Xtoremote(targ, argc, argv)
X char *targ;
X int argc;
X char **argv;
X{
X int i;
X char *bp, *host, *src, *suser, *thost, *tuser;
X char *colon(), *malloc();
X
X *targ++ = 0;
X if (*targ == 0)
X targ = ".";
X
X if (thost = index(argv[argc - 1], '@')) {
X *thost++ = 0;
X tuser = argv[argc - 1];
X if (*tuser == '\0')
X tuser = NULL;
X else if (!okname(tuser))
X exit(1);
X } else {
X thost = argv[argc - 1];
X tuser = NULL;
X }
X
X for (i = 0; i < argc - 1; i++) {
X src = colon(argv[i]);
X if (src) { /* remote to remote */
X *src++ = 0;
X if (*src == 0)
X src = ".";
X host = index(argv[i], '@');
X if (!(bp = malloc((u_int)(strlen(_PATH_RSH) +
X strlen(argv[i]) + strlen(src) +
X strlen(tuser) + strlen(thost) +
X strlen(targ)) + CMDNEEDS + 20)))
X nospace();
X if (host) {
X *host++ = 0;
X suser = argv[i];
X if (*suser == '\0')
X suser = pwd->pw_name;
X else if (!okname(suser))
X continue;
X (void)sprintf(bp,
X "%s %s -l %s -n %s %s '%s%s%s:%s'",
X _PATH_RSH, host, suser, cmd, src,
X tuser ? tuser : "", tuser ? "@" : "",
X thost, targ);
X } else
X (void)sprintf(bp, "%s %s -n %s %s '%s%s%s:%s'",
X _PATH_RSH, argv[i], cmd, src,
X tuser ? tuser : "", tuser ? "@" : "",
X thost, targ);
X (void)susystem(bp);
X (void)free(bp);
X } else { /* local to remote */
X if (rem == -1) {
X if (!(bp = malloc((u_int)strlen(targ) +
X CMDNEEDS + 20)))
X nospace();
X (void)sprintf(bp, "%s -t %s", cmd, targ);
X host = thost;
X#ifdef KERBEROS
X if (use_kerberos)
X kerberos(bp,
X tuser ? tuser : pwd->pw_name);
X else
X#endif
X rem = rcmd(&host, port, pwd->pw_name,
X tuser ? tuser : pwd->pw_name,
X bp, 0);
X if (rem < 0)
X exit(1);
X if (response() < 0)
X exit(1);
X (void)free(bp);
X (void)setuid(userid);
X }
X source(1, argv+i);
X }
X }
X}
X
Xtolocal(argc, argv)
X int argc;
X char **argv;
X{
X int i;
X char *bp, *host, *src, *suser;
X char *colon(), *malloc();
X
X for (i = 0; i < argc - 1; i++) {
X if (!(src = colon(argv[i]))) { /* local to local */
X if (!(bp = malloc((u_int)(strlen(_PATH_CP) +
X strlen(argv[i]) + strlen(argv[argc - 1])) + 20)))
X nospace();
X (void)sprintf(bp, "%s%s%s %s %s", _PATH_CP,
X iamrecursive ? " -r" : "", pflag ? " -p" : "",
X argv[i], argv[argc - 1]);
X (void)susystem(bp);
X (void)free(bp);
X continue;
X }
X *src++ = 0;
X if (*src == 0)
X src = ".";
X host = index(argv[i], '@');
X if (host) {
X *host++ = 0;
X suser = argv[i];
X if (*suser == '\0')
X suser = pwd->pw_name;
X else if (!okname(suser))
X continue;
X } else {
X host = argv[i];
X suser = pwd->pw_name;
X }
X if (!(bp = malloc((u_int)(strlen(src)) + CMDNEEDS + 20)))
X nospace();
X (void)sprintf(bp, "%s -f %s", cmd, src);
X#ifdef KERBEROS
X if (use_kerberos)
X kerberos(bp, suser);
X else
X#endif
X rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
X (void)free(bp);
X if (rem < 0)
X continue;
X (void)setreuid(0, userid);
X sink(1, argv + argc - 1);
X (void)setreuid(userid, 0);
X (void)close(rem);
X rem = -1;
X }
X}
X
X#ifdef KERBEROS
Xkerberos(bp, user)
X char *bp, *user;
X{
X struct servent *sp;
X char *host;
X
Xagain: rem = KSUCCESS;
X if (krb_realm[0] == '\0')
X rem = krb_get_lrealm(krb_realm, 1);
X if (rem == KSUCCESS) {
X if (encrypt)
X rem = krcmd_mutual(&host, port, user, bp, 0,
X krb_realm, &cred, schedule);
X else
X rem = krcmd(&host, port, user, bp, 0, krb_realm);
X } else {
X (void)fprintf(stderr,
X "rcp: error getting local realm %s\n", krb_err_txt[rem]);
X exit(1);
X }
X if (rem < 0 && errno == ECONNREFUSED) {
X use_kerberos = 0;
X old_warning("remote host doesn't support Kerberos");
X sp = getservbyname("shell", "tcp");
X if (sp == NULL) {
X (void)fprintf(stderr,
X "rcp: unknown service shell/tcp\n");
X exit(1);
X }
X port = sp->s_port;
X goto again;
X }
X}
X#endif /* KERBEROS */
X
Xverifydir(cp)
X char *cp;
X{
X struct stat stb;
X
X if (stat(cp, &stb) >= 0) {
X if ((stb.st_mode & S_IFMT) == S_IFDIR)
X return;
X errno = ENOTDIR;
X }
X error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
X exit(1);
X}
X
Xchar *
Xcolon(cp)
X register char *cp;
X{
X for (; *cp; ++cp) {
X if (*cp == ':')
X return(cp);
X if (*cp == '/')
X return(0);
X }
X return(0);
X}
X
Xokname(cp0)
X char *cp0;
X{
X register char *cp = cp0;
X register int c;
X
X do {
X c = *cp;
X if (c & 0200)
X goto bad;
X if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
X goto bad;
X } while (*++cp);
X return(1);
Xbad:
X (void)fprintf(stderr, "rcp: invalid user name %s\n", cp0);
X return(0);
X}
X
Xsusystem(s)
X char *s;
X{
X int status, pid, w;
X register int (*istat)(), (*qstat)();
X
X if ((pid = vfork()) == 0) {
X (void)setuid(userid);
X execl(_PATH_BSHELL, "sh", "-c", s, (char *)0);
X _exit(127);
X }
X istat = signal(SIGINT, SIG_IGN);
X qstat = signal(SIGQUIT, SIG_IGN);
X while ((w = wait(&status)) != pid && w != -1)
X ;
X if (w == -1)
X status = -1;
X (void)signal(SIGINT, istat);
X (void)signal(SIGQUIT, qstat);
X return(status);
X}
X
Xsource(argc, argv)
X int argc;
X char **argv;
X{
X struct stat stb;
X static BUF buffer;
X BUF *bp;
X off_t i;
X int x, readerr, f, amt;
X char *last, *name, buf[BUFSIZ];
X BUF *allocbuf();
X
X for (x = 0; x < argc; x++) {
X name = argv[x];
X if ((f = open(name, O_RDONLY, 0)) < 0) {
X error("rcp: %s: %s\n", name, sys_errlist[errno]);
X continue;
X }
X if (fstat(f, &stb) < 0)
X goto notreg;
X switch (stb.st_mode&S_IFMT) {
X
X case S_IFREG:
X break;
X
X case S_IFDIR:
X if (iamrecursive) {
X (void)close(f);
X rsource(name, &stb);
X continue;
X }
X /* FALLTHROUGH */
X default:
Xnotreg: (void)close(f);
X error("rcp: %s: not a plain file\n", name);
X continue;
X }
X last = rindex(name, '/');
X if (last == 0)
X last = name;
X else
X last++;
X if (pflag) {
X /*
X * Make it compatible with possible future
X * versions expecting microseconds.
X */
X (void)sprintf(buf, "T%ld 0 %ld 0\n", stb.st_mtime,
X stb.st_atime);
X (void)write(rem, buf, strlen(buf));
X if (response() < 0) {
X (void)close(f);
X continue;
X }
X }
X (void)sprintf(buf, "C%04o %ld %s\n", stb.st_mode&07777,
X stb.st_size, last);
X (void)write(rem, buf, strlen(buf));
X if (response() < 0) {
X (void)close(f);
X continue;
X }
X if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) {
X (void)close(f);
X continue;
X }
X readerr = 0;
X for (i = 0; i < stb.st_size; i += bp->cnt) {
X amt = bp->cnt;
X if (i + amt > stb.st_size)
X amt = stb.st_size - i;
X if (readerr == 0 && read(f, bp->buf, amt) != amt)
X readerr = errno;
X (void)write(rem, bp->buf, amt);
X }
X (void)close(f);
X if (readerr == 0)
X (void)write(rem, "", 1);
X else
X error("rcp: %s: %s\n", name, sys_errlist[readerr]);
X (void)response();
X }
X}
X
Xrsource(name, statp)
X char *name;
X struct stat *statp;
X{
X DIR *d;
X struct direct *dp;
X char *last, *vect[1], path[MAXPATHLEN];
X
X if (!(d = opendir(name))) {
X error("rcp: %s: %s\n", name, sys_errlist[errno]);
X return;
X }
X last = rindex(name, '/');
X if (last == 0)
X last = name;
X else
X last++;
X if (pflag) {
X (void)sprintf(path, "T%ld 0 %ld 0\n", statp->st_mtime,
X statp->st_atime);
X (void)write(rem, path, strlen(path));
X if (response() < 0) {
X closedir(d);
X return;
X }
X }
X (void)sprintf(path, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
X (void)write(rem, path, strlen(path));
X if (response() < 0) {
X closedir(d);
X return;
X }
X while (dp = readdir(d)) {
X if (dp->d_ino == 0)
X continue;
X if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
X continue;
X if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
X error("%s/%s: name too long.\n", name, dp->d_name);
X continue;
X }
X (void)sprintf(path, "%s/%s", name, dp->d_name);
X vect[0] = path;
X source(1, vect);
X }
X closedir(d);
X (void)write(rem, "E\n", 2);
X (void)response();
X}
X
Xresponse()
X{
X register char *cp;
X char ch, resp, rbuf[BUFSIZ];
X
X if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
X lostconn();
X
X cp = rbuf;
X switch(resp) {
X case 0: /* ok */
X return(0);
X default:
X *cp++ = resp;
X /* FALLTHROUGH */
X case 1: /* error, followed by err msg */
X case 2: /* fatal error, "" */
X do {
X if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
X lostconn();
X *cp++ = ch;
X } while (cp < &rbuf[BUFSIZ] && ch != '\n');
X
X if (!iamremote)
X (void)write(2, rbuf, cp - rbuf);
X ++errs;
X if (resp == 1)
X return(-1);
X exit(1);
X }
X /*NOTREACHED*/
X}
X
Xlostconn()
X{
X if (!iamremote)
X (void)fprintf(stderr, "rcp: lost connection\n");
X exit(1);
X}
X
Xsink(argc, argv)
X int argc;
X char **argv;
X{
X register char *cp;
X static BUF buffer;
X struct stat stb;
X struct timeval tv[2];
X BUF *bp, *allocbuf();
X off_t i, j;
X char ch, *targ, *why;
X int amt, count, exists, first, mask, mode;
X int ofd, setimes, targisdir, wrerr;
X off_t size;
X char *np, *vect[1], buf[BUFSIZ], *malloc();
X
X#define atime tv[0]
X#define mtime tv[1]
X#define SCREWUP(str) { why = str; goto screwup; }
X
X setimes = targisdir = 0;
X mask = umask(0);
X if (!pflag)
X (void)umask(mask);
X if (argc != 1) {
X error("rcp: ambiguous target\n");
X exit(1);
X }
X targ = *argv;
X if (targetshouldbedirectory)
X verifydir(targ);
X (void)write(rem, "", 1);
X if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
X targisdir = 1;
X for (first = 1;; first = 0) {
X cp = buf;
X if (read(rem, cp, 1) <= 0)
X return;
X if (*cp++ == '\n')
X SCREWUP("unexpected <newline>");
X do {
X if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
X SCREWUP("lost connection");
X *cp++ = ch;
X } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
X *cp = 0;
X
X if (buf[0] == '\01' || buf[0] == '\02') {
X if (iamremote == 0)
X (void)write(2, buf + 1, strlen(buf + 1));
X if (buf[0] == '\02')
X exit(1);
X errs++;
X continue;
X }
X if (buf[0] == 'E') {
X (void)write(rem, "", 1);
X return;
X }
X
X if (ch == '\n')
X *--cp = 0;
X
X#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
X cp = buf;
X if (*cp == 'T') {
X setimes++;
X cp++;
X getnum(mtime.tv_sec);
X if (*cp++ != ' ')
X SCREWUP("mtime.sec not delimited");
X getnum(mtime.tv_usec);
X if (*cp++ != ' ')
X SCREWUP("mtime.usec not delimited");
X getnum(atime.tv_sec);
X if (*cp++ != ' ')
X SCREWUP("atime.sec not delimited");
X getnum(atime.tv_usec);
X if (*cp++ != '\0')
X SCREWUP("atime.usec not delimited");
X (void)write(rem, "", 1);
X continue;
X }
X if (*cp != 'C' && *cp != 'D') {
X /*
X * Check for the case "rcp remote:foo\* local:bar".
X * In this case, the line "No match." can be returned
X * by the shell before the rcp command on the remote is
X * executed so the ^Aerror_message convention isn't
X * followed.
X */
X if (first) {
X error("%s\n", cp);
X exit(1);
X }
X SCREWUP("expected control record");
X }
X mode = 0;
X for (++cp; cp < buf + 5; cp++) {
X if (*cp < '0' || *cp > '7')
X SCREWUP("bad mode");
X mode = (mode << 3) | (*cp - '0');
X }
X if (*cp++ != ' ')
X SCREWUP("mode not delimited");
X size = 0;
X while (isdigit(*cp))
X size = size * 10 + (*cp++ - '0');
X if (*cp++ != ' ')
X SCREWUP("size not delimited");
X if (targisdir) {
X static char *namebuf;
X static int cursize;
X int need;
X
X need = strlen(targ) + strlen(cp) + 250;
X if (need > cursize) {
X if (!(namebuf = malloc((u_int)need)))
X error("out of memory\n");
X }
X (void)sprintf(namebuf, "%s%s%s", targ,
X *targ ? "/" : "", cp);
X np = namebuf;
X }
X else
X np = targ;
X exists = stat(np, &stb) == 0;
X if (buf[0] == 'D') {
X if (exists) {
X if ((stb.st_mode&S_IFMT) != S_IFDIR) {
X errno = ENOTDIR;
X goto bad;
X }
X if (pflag)
X (void)chmod(np, mode);
X } else if (mkdir(np, mode) < 0)
X goto bad;
X vect[0] = np;
X sink(1, vect);
X if (setimes) {
X setimes = 0;
X if (utimes(np, tv) < 0)
X error("rcp: can't set times on %s: %s\n",
X np, sys_errlist[errno]);
X }
X continue;
X }
X if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
Xbad: error("rcp: %s: %s\n", np, sys_errlist[errno]);
X continue;
X }
X if (exists && pflag)
X (void)fchmod(ofd, mode);
X (void)write(rem, "", 1);
X if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == 0) {
X (void)close(ofd);
X continue;
X }
X cp = bp->buf;
X count = 0;
X wrerr = 0;
X for (i = 0; i < size; i += BUFSIZ) {
X amt = BUFSIZ;
X if (i + amt > size)
X amt = size - i;
X count += amt;
X do {
X j = read(rem, cp, amt);
X if (j <= 0) {
X error("rcp: %s\n",
X j ? sys_errlist[errno] :
X "dropped connection");
X exit(1);
X }
X amt -= j;
X cp += j;
X } while (amt > 0);
X if (count == bp->cnt) {
X if (wrerr == 0 &&
X write(ofd, bp->buf, count) != count)
X wrerr++;
X count = 0;
X cp = bp->buf;
X }
X }
X if (count != 0 && wrerr == 0 &&
X write(ofd, bp->buf, count) != count)
X wrerr++;
X if (ftruncate(ofd, size))
X error("rcp: can't truncate %s: %s\n", np,
X sys_errlist[errno]);
X (void)close(ofd);
X (void)response();
X if (setimes) {
X setimes = 0;
X if (utimes(np, tv) < 0)
X error("rcp: can't set times on %s: %s\n",
X np, sys_errlist[errno]);
X }
X if (wrerr)
X error("rcp: %s: %s\n", np, sys_errlist[errno]);
X else
X (void)write(rem, "", 1);
X }
Xscrewup:
X error("rcp: protocol screwup: %s\n", why);
X exit(1);
X}
X
XBUF *
Xallocbuf(bp, fd, blksize)
X BUF *bp;
X int fd, blksize;
X{
X struct stat stb;
X int size;
X char *malloc();
X
X if (fstat(fd, &stb) < 0) {
X error("rcp: fstat: %s\n", sys_errlist[errno]);
X return(0);
X }
X size = roundup(stb.st_blksize, blksize);
X if (size == 0)
X size = blksize;
X if (bp->cnt < size) {
X if (bp->buf != 0)
X free(bp->buf);
X bp->buf = (char *)malloc((u_int)size);
X if (!bp->buf) {
X error("rcp: malloc: out of memory\n");
X return(0);
X }
X }
X bp->cnt = size;
X return(bp);
X}
X
X/* VARARGS1 */
Xerror(fmt, a1, a2, a3)
X char *fmt;
X int a1, a2, a3;
X{
X static FILE *fp;
X
X ++errs;
X if (!fp && !(fp = fdopen(rem, "w")))
X return;
X (void)fprintf(fp, "%c", 0x01);
X (void)fprintf(fp, fmt, a1, a2, a3);
X (void)fflush(fp);
X if (!iamremote)
X (void)fprintf(stderr, fmt, a1, a2, a3);
X}
X
Xnospace()
X{
X (void)fprintf(stderr, "rcp: out of memory.\n");
X exit(1);
X}
X
X#ifdef KERBEROS
Xold_warning(str)
X char *str;
X{
X (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
X}
X#endif
X
Xusage()
X{
X#ifdef KERBEROS
X (void)fprintf(stderr, "%s\n\t%s\n",
X "usage: rcp [-k realm] [-px] f1 f2",
X "or: rcp [-k realm] [-rpx] f1 ... fn directory");
X#else
X (void)fprintf(stderr,
X "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
X#endif
X exit(1);
X}
SHAR_EOF
fi
if test -f 'pathnames.h'
then
echo shar: "will not over-write existing file 'pathnames.h'"
else
sed 's/^X//' << \SHAR_EOF > 'pathnames.h'
X/*
X * Copyright (c) 1989 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley. The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X * @(#)pathnames.h 5.2 (Berkeley) 5/10/89
X */
X
X#define _PATH_BSHELL "/bin/sh"
X#define _PATH_CP "/bin/cp"
X#define _PATH_RSH "/usr/ucb/rsh"
SHAR_EOF
fi
if test -f 'rdist.diff'
then
echo shar: "will not over-write existing file 'rdist.diff'"
else
sed 's/^X//' << \SHAR_EOF > 'rdist.diff'
X*** old_server.c Wed Jun 29 20:19:34 1988
X--- server.c Wed May 24 20:17:51 1989
X***************
X*** 1369,1384 ****
X char *fmt;
X int a1, a2, a3;
X {
X! nerrs++;
X! strcpy(buf, "\1rdist: ");
X! (void) sprintf(buf+8, fmt, a1, a2, a3);
X! if (!iamremote) {
X fflush(stdout);
X! (void) write(2, buf+1, strlen(buf+1));
X! } else
X! (void) write(rem, buf, strlen(buf));
X! if (lfp != NULL)
X! (void) fwrite(buf+1, 1, strlen(buf+1), lfp);
X }
X
X /*VARARGS1*/
X--- 1369,1395 ----
X char *fmt;
X int a1, a2, a3;
X {
X! static FILE *fp;
X!
X! ++nerrs;
X! if (!fp && !(fp = fdopen(rem, "w")))
X! return;
X! if (iamremote) {
X! (void)fprintf(fp, "%crdist: ", 0x01);
X! (void)fprintf(fp, fmt, a1, a2, a3);
X! fflush(fp);
X! }
X! else {
X fflush(stdout);
X! (void)fprintf(stderr, "rdist: ");
X! (void)fprintf(stderr, fmt, a1, a2, a3);
X! fflush(stderr);
X! }
X! if (lfp != NULL) {
X! (void)fprintf(lfp, "rdist: ");
X! (void)fprintf(lfp, fmt, a1, a2, a3);
X! fflush(lfp);
X! }
X }
X
X /*VARARGS1*/
X***************
X*** 1386,1401 ****
X char *fmt;
X int a1, a2, a3;
X {
X! nerrs++;
X! strcpy(buf, "\2rdist: ");
X! (void) sprintf(buf+8, fmt, a1, a2, a3);
X! if (!iamremote) {
X fflush(stdout);
X! (void) write(2, buf+1, strlen(buf+1));
X! } else
X! (void) write(rem, buf, strlen(buf));
X! if (lfp != NULL)
X! (void) fwrite(buf+1, 1, strlen(buf+1), lfp);
X cleanup();
X }
X
X--- 1397,1423 ----
X char *fmt;
X int a1, a2, a3;
X {
X! static FILE *fp;
X!
X! ++nerrs;
X! if (!fp && !(fp = fdopen(rem, "w")))
X! return;
X! if (iamremote) {
X! (void)fprintf(fp, "%crdist: ", 0x02);
X! (void)fprintf(fp, fmt, a1, a2, a3);
X! fflush(fp);
X! }
X! else {
X fflush(stdout);
X! (void)fprintf(stderr, "rdist: ");
X! (void)fprintf(stderr, fmt, a1, a2, a3);
X! fflush(stderr);
X! }
X! if (lfp != NULL) {
X! (void)fprintf(lfp, "rdist: ");
X! (void)fprintf(lfp, fmt, a1, a2, a3);
X! fflush(lfp);
X! }
X cleanup();
X }
X
SHAR_EOF
fi
exit 0
# End of shell archive
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads