# 2.11BSD#431 - /usr/src/bin/rcp.c

##### Functions

    allocbuf          X
    colon             X
    error             X
    kerberos          X
    lostconn          X
    main              X
    nospace           X
    okname            X
    old_warning       X
    response          X
    rsource           X
    sink              X
    source            X
    susystem          X
    tolocal           X
    toremote          X
    usage             X
    verifydir         X

##### Variables

    cmd               X
    copyright         X
    errs              X
    iamrecursive      X
    iamremote         X
    krb_realm         X
    pflag             X
    port              X
    pwd               X
    rem               X
    targetshouldbedirectoryX
    use_kerberos      X
    userid            X

##### Macros

    CMDNEEDS          X
    SCREWUP           X
    atime             X
    getnum            X
    mtime             X

##### struct's

    _buf              X

##### typedef's

    BUF               X

       1: /*
       2:  * Copyright (c) 1983 The Regents of the University of California.
       3:  * All rights reserved.
       4:  *
       5:  * Redistribution and use in source and binary forms are permitted
       6:  * provided that the above copyright notice and this paragraph are
       7:  * duplicated in all such forms and that any documentation,
       8:  * advertising materials, and other materials related to such
       9:  * distribution and use acknowledge that the software was developed
      10:  * by the University of California, Berkeley.  The name of the
      11:  * University may not be used to endorse or promote products derived
      12:  * from this software without specific prior written permission.
      13:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
      14:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
      15:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
      16:  */
      17:
      18: #if !defined(lint) && defined(DOSCCS)
      19: char copyright[] =
      20: "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
      21:  All rights reserved.\n";
      22:
      23: static char sccsid[] = "@(#)rcp.c	5.20.1 (2.11BSD) 1996/3/21";
      24: #endif /* not lint */
      25:
      26: /*
      27:  * rcp
      28:  */
      29: #include <sys/param.h>
      30: #include <sys/file.h>
      31: #include <sys/stat.h>
      32: #include <sys/time.h>
      33: #include <sys/ioctl.h>
      34: #include <sys/dir.h>
      35: #include <sys/signal.h>
      36: #include <netinet/in.h>
      37: #include <pwd.h>
      38: #include <netdb.h>
      39: #include <errno.h>
      40: #include <string.h>
      41: #include <stdio.h>
      42: #include <ctype.h>
      43: #include "pathnames.h"
      44:
      45: #ifdef KERBEROS
      46: #include <kerberos/krb.h>
      47:
      48: char krb_realm[REALM_SZ];
      49: int use_kerberos = 1, encrypt = 0;
      50: CREDENTIALS cred;
      51: Key_schedule schedule;
      52: #endif
      53:
      54: extern int errno;
      55: struct passwd *pwd;
      56: int errs, pflag, port, rem, userid;
      57: int iamremote, iamrecursive, targetshouldbedirectory;
      58:
      59: #define CMDNEEDS    20
      60: char cmd[CMDNEEDS];     /* must hold "rcp -r -p -d\0" */
      61:
      62: typedef struct _buf {
      63:     int cnt;
      64:     char    *buf;
      65: } BUF;
      66:
      67: main(argc, argv)
      68:     int argc;
      69:     char **argv;
      70: {
      71:     extern int optind;
      72:     struct servent *sp;
      73:     int ch, fflag, tflag;
      74:     char *targ, *colon();
      75:     struct passwd *getpwuid();
      76:     int lostconn();
      77:
      78: #ifdef KERBEROS
      79:     sp = getservbyname("kshell", "tcp");
      80:     if (sp == NULL) {
      81:         use_kerberos = 0;
      82:         old_warning("kshell service unknown");
      83:         sp = getservbyname("kshell", "tcp");
      84:     }
      85: #else
      86:     sp = getservbyname("shell", "tcp");
      87: #endif
      88:     if (!sp) {
      89:         (void)fprintf(stderr, "rcp: shell/tcp: unknown service\n");
      90:         exit(1);
      91:     }
      92:     port = sp->s_port;
      93:
      94:     if (!(pwd = getpwuid(userid = getuid()))) {
      95:         (void)fprintf(stderr, "rcp: unknown user %d.\n", userid);
      96:         exit(1);
      97:     }
      98:
      99:     fflag = tflag = 0;
     100:     while ((ch = getopt(argc, argv, "dfkprtx")) != EOF)
     101:         switch(ch) {
     102:         case 'd':
     103:             targetshouldbedirectory = 1;
     104:             break;
     105:         case 'f':           /* "from" */
     106:             fflag = 1;
     107:             break;
     108: #ifdef KERBEROS
     109:         case 'k':
     110:             strncpy(krb_realm, ++argv, REALM_SZ);
     111:             break;
     112: #endif
     113:         case 'p':           /* preserve access/mod times */
     114:             ++pflag;
     115:             break;
     116:         case 'r':
     117:             ++iamrecursive;
     118:             break;
     119:         case 't':           /* "to" */
     120:             tflag = 1;
     121:             break;
     122: #ifdef KERBEROS
     123:         case 'x':
     124:             encrypt = 1;
     125:             des_set_key(cred.session, schedule);
     126:             break;
     127: #endif
     128:         case '?':
     129:         default:
     130:             usage();
     131:         }
     132:     argc -= optind;
     133:     argv += optind;
     134:
     135:     if (fflag) {
     136:         iamremote = 1;
     137:         (void)response();
     138:         (void)setuid(userid);
     139:         source(argc, argv);
     140:         exit(errs);
     141:     }
     142:
     143:     if (tflag) {
     144:         iamremote = 1;
     145:         (void)setuid(userid);
     146:         sink(argc, argv);
     147:         exit(errs);
     148:     }
     149:
     150:     if (argc < 2)
     151:         usage();
     152:     if (argc > 2)
     153:         targetshouldbedirectory = 1;
     154:
     155:     rem = -1;
     156:     (void)sprintf(cmd, "rcp%s%s%s", iamrecursive ? " -r" : "",
     157:         pflag ? " -p" : "", targetshouldbedirectory ? " -d" : "");
     158:
     159:     (void)signal(SIGPIPE, lostconn);
     160:
     161:     if (targ = colon(argv[argc - 1]))
     162:         toremote(targ, argc, argv);
     163:     else {
     164:         tolocal(argc, argv);
     165:         if (targetshouldbedirectory)
     166:             verifydir(argv[argc - 1]);
     167:     }
     168:     exit(errs);
     169: }
     170:
     171: toremote(targ, argc, argv)
     172:     char *targ;
     173:     int argc;
     174:     char **argv;
     175: {
     176:     int i;
     177:     char *bp, *host, *src, *suser, *thost, *tuser;
     178:     char *colon(), *malloc();
     179:
     180:     *targ++ = 0;
     181:     if (*targ == 0)
     182:         targ = ".";
     183:
     184:     if (thost = index(argv[argc - 1], '@')) {
     185:         *thost++ = 0;
     186:         tuser = argv[argc - 1];
     187:         if (*tuser == '\0')
     188:             tuser = NULL;
     189:         else if (!okname(tuser))
     190:             exit(1);
     191:     } else {
     192:         thost = argv[argc - 1];
     193:         tuser = NULL;
     194:     }
     195:
     196:     for (i = 0; i < argc - 1; i++) {
     197:         src = colon(argv[i]);
     198:         if (src) {          /* remote to remote */
     199:             *src++ = 0;
     200:             if (*src == 0)
     201:                 src = ".";
     202:             host = index(argv[i], '@');
     203:             if (!(bp = malloc((u_int)(strlen(_PATH_RSH) +
     204:                     strlen(argv[i]) + strlen(src) +
     205:                     strlen(tuser) + strlen(thost) +
     206:                     strlen(targ)) + CMDNEEDS + 20)))
     207:                     nospace();
     208:             if (host) {
     209:                 *host++ = 0;
     210:                 suser = argv[i];
     211:                 if (*suser == '\0')
     212:                     suser = pwd->pw_name;
     213:                 else if (!okname(suser))
     214:                     continue;
     215:                 (void)sprintf(bp,
     216:                     "%s %s -l %s -n %s %s '%s%s%s:%s'",
     217:                     _PATH_RSH, host, suser, cmd, src,
     218:                     tuser ? tuser : "", tuser ? "@" : "",
     219:                     thost, targ);
     220:             } else
     221:                 (void)sprintf(bp, "%s %s -n %s %s '%s%s%s:%s'",
     222:                     _PATH_RSH, argv[i], cmd, src,
     223:                     tuser ? tuser : "", tuser ? "@" : "",
     224:                     thost, targ);
     225:             (void)susystem(bp);
     226:             (void)free(bp);
     227:         } else {            /* local to remote */
     228:             if (rem == -1) {
     229:                 if (!(bp = malloc((u_int)strlen(targ) +
     230:                     CMDNEEDS + 20)))
     231:                     nospace();
     232:                 (void)sprintf(bp, "%s -t %s", cmd, targ);
     233:                 host = thost;
     234: #ifdef KERBEROS
     235:                 if (use_kerberos)
     236:                     kerberos(bp,
     237:                         tuser ? tuser : pwd->pw_name);
     238:                 else
     239: #endif
     240:                     rem = rcmd(&host, port, pwd->pw_name,
     241:                         tuser ? tuser : pwd->pw_name,
     242:                         bp, 0);
     243:                 if (rem < 0)
     244:                     exit(1);
     245:                 if (response() < 0)
     246:                     exit(1);
     247:                 (void)free(bp);
     248:                 (void)setuid(userid);
     249:             }
     250:             source(1, argv+i);
     251:         }
     252:     }
     253: }
     254:
     255: tolocal(argc, argv)
     256:     int argc;
     257:     char **argv;
     258: {
     259:     int i;
     260:     char *bp, *host, *src, *suser;
     261:     char *colon(), *malloc();
     262:
     263:     for (i = 0; i < argc - 1; i++) {
     264:         if (!(src = colon(argv[i]))) {  /* local to local */
     265:             if (!(bp = malloc((u_int)(strlen(_PATH_CP) +
     266:                 strlen(argv[i]) + strlen(argv[argc - 1])) + 20)))
     267:                 nospace();
     268:             (void)sprintf(bp, "%s%s%s %s %s", _PATH_CP,
     269:                 iamrecursive ? " -r" : "", pflag ? " -p" : "",
     270:                 argv[i], argv[argc - 1]);
     271:             (void)susystem(bp);
     272:             (void)free(bp);
     273:             continue;
     274:         }
     275:         *src++ = 0;
     276:         if (*src == 0)
     277:             src = ".";
     278:         host = index(argv[i], '@');
     279:         if (host) {
     280:             *host++ = 0;
     281:             suser = argv[i];
     282:             if (*suser == '\0')
     283:                 suser = pwd->pw_name;
     284:             else if (!okname(suser))
     285:                 continue;
     286:         } else {
     287:             host = argv[i];
     288:             suser = pwd->pw_name;
     289:         }
     290:         if (!(bp = malloc((u_int)(strlen(src)) + CMDNEEDS + 20)))
     291:             nospace();
     292:         (void)sprintf(bp, "%s -f %s", cmd, src);
     293: #ifdef KERBEROS
     294:         if (use_kerberos)
     295:             kerberos(bp, suser);
     296:         else
     297: #endif
     298:             rem = rcmd(&host, port, pwd->pw_name, suser, bp, 0);
     299:         (void)free(bp);
     300:         if (rem < 0)
     301:             continue;
     302:         (void)setreuid(0, userid);
     303:         sink(1, argv + argc - 1);
     304:         (void)setreuid(userid, 0);
     305:         (void)close(rem);
     306:         rem = -1;
     307:     }
     308: }
     309:
     310: #ifdef KERBEROS
     311: kerberos(bp, user)
     312:     char *bp, *user;
     313: {
     314:     struct servent *sp;
     315:     char *host;
     316:
     317: again:  rem = KSUCCESS;
     318:     if (krb_realm[0] == '\0')
     319:         rem = krb_get_lrealm(krb_realm, 1);
     320:     if (rem == KSUCCESS) {
     321:         if (encrypt)
     322:             rem = krcmd_mutual(&host, port, user, bp, 0,
     323:                 krb_realm, &cred, schedule);
     324:         else
     325:             rem = krcmd(&host, port, user, bp, 0, krb_realm);
     326:     } else {
     327:         (void)fprintf(stderr,
     328:             "rcp: error getting local realm %s\n", krb_err_txt[rem]);
     329:         exit(1);
     330:     }
     331:     if (rem < 0 && errno == ECONNREFUSED) {
     332:         use_kerberos = 0;
     333:         old_warning("remote host doesn't support Kerberos");
     334:         sp = getservbyname("shell", "tcp");
     335:         if (sp == NULL) {
     336:             (void)fprintf(stderr,
     337:                 "rcp: unknown service shell/tcp\n");
     338:             exit(1);
     339:         }
     340:         port = sp->s_port;
     341:         goto again;
     342:     }
     343: }
     344: #endif /* KERBEROS */
     345:
     346: verifydir(cp)
     347:     char *cp;
     348: {
     349:     struct stat stb;
     350:
     351:     if (stat(cp, &stb) >= 0) {
     352:         if ((stb.st_mode & S_IFMT) == S_IFDIR)
     353:             return;
     354:         errno = ENOTDIR;
     355:     }
     356:     error("rcp: %s: %s.\n", cp, strerror(errno));
     357:     exit(1);
     358: }
     359:
     360: char *
     361: colon(cp)
     362:     register char *cp;
     363: {
     364:     for (; *cp; ++cp) {
     365:         if (*cp == ':')
     366:             return(cp);
     367:         if (*cp == '/')
     368:             return(0);
     369:     }
     370:     return(0);
     371: }
     372:
     373: okname(cp0)
     374:     char *cp0;
     375: {
     376:     register char *cp = cp0;
     377:     register int c;
     378:
     379:     do {
     380:         c = *cp;
     381:         if (c & 0200)
     382:             goto bad;
     383:         if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
     384:             goto bad;
     385:     } while (*++cp);
     386:     return(1);
     387: bad:
     388:     (void)fprintf(stderr, "rcp: invalid user name %s\n", cp0);
     389:     return(0);
     390: }
     391:
     392: susystem(s)
     393:     char *s;
     394: {
     395:     int status, pid, w;
     396:     register int (*istat)(), (*qstat)();
     397:
     398:     if ((pid = vfork()) == 0) {
     399:         (void)setuid(userid);
     400:         execl(_PATH_BSHELL, "sh", "-c", s, (char *)0);
     401:         _exit(127);
     402:     }
     403:     istat = signal(SIGINT, SIG_IGN);
     404:     qstat = signal(SIGQUIT, SIG_IGN);
     405:     while ((w = wait(&status)) != pid && w != -1)
     406:         ;
     407:     if (w == -1)
     408:         status = -1;
     409:     (void)signal(SIGINT, istat);
     410:     (void)signal(SIGQUIT, qstat);
     411:     return(status);
     412: }
     413:
     414: source(argc, argv)
     415:     int argc;
     416:     char **argv;
     417: {
     418:     struct stat stb;
     419:     static BUF buffer;
     420:     BUF *bp;
     421:     off_t i;
     422:     int x, readerr, f, amt;
     423:     char *last, *name, buf[BUFSIZ];
     424:     BUF *allocbuf();
     425:
     426:     for (x = 0; x < argc; x++) {
     427:         name = argv[x];
     428:         if ((f = open(name, O_RDONLY, 0)) < 0) {
     429:             error("rcp: %s: %s\n", name, strerror(errno));
     430:             continue;
     431:         }
     432:         if (fstat(f, &stb) < 0)
     433:             goto notreg;
     434:         switch (stb.st_mode&S_IFMT) {
     435:
     436:         case S_IFREG:
     437:             break;
     438:
     439:         case S_IFDIR:
     440:             if (iamrecursive) {
     441:                 (void)close(f);
     442:                 rsource(name, &stb);
     443:                 continue;
     444:             }
     445:             /* FALLTHROUGH */
     446:         default:
     447: notreg:         (void)close(f);
     448:             error("rcp: %s: not a plain file\n", name);
     449:             continue;
     450:         }
     451:         last = rindex(name, '/');
     452:         if (last == 0)
     453:             last = name;
     454:         else
     455:             last++;
     456:         if (pflag) {
     457:             /*
     458: 			 * Make it compatible with possible future
     459: 			 * versions expecting microseconds.
     460: 			 */
     461:             (void)sprintf(buf, "T%ld 0 %ld 0\n", stb.st_mtime,
     462:                 stb.st_atime);
     463:             (void)write(rem, buf, strlen(buf));
     464:             if (response() < 0) {
     465:                 (void)close(f);
     466:                 continue;
     467:             }
     468:         }
     469:         (void)sprintf(buf, "C%04o %ld %s\n", stb.st_mode&07777,
     470:             stb.st_size, last);
     471:         (void)write(rem, buf, strlen(buf));
     472:         if (response() < 0) {
     473:             (void)close(f);
     474:             continue;
     475:         }
     476:         if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) {
     477:             (void)close(f);
     478:             continue;
     479:         }
     480:         readerr = 0;
     481:         for (i = 0; i < stb.st_size; i += bp->cnt) {
     482:             amt = bp->cnt;
     483:             if (i + amt > stb.st_size)
     484:                 amt = stb.st_size - i;
     485:             if (readerr == 0 && read(f, bp->buf, amt) != amt)
     486:                 readerr = errno;
     487:             (void)write(rem, bp->buf, amt);
     488:         }
     489:         (void)close(f);
     490:         if (readerr == 0)
     491:             (void)write(rem, "", 1);
     492:         else
     493:             error("rcp: %s: %s\n", name, strerror(readerr));
     494:         (void)response();
     495:     }
     496: }
     497:
     498: rsource(name, statp)
     499:     char *name;
     500:     struct stat *statp;
     501: {
     502:     DIR *d;
     503:     struct direct *dp;
     504:     char *last, *vect[1], path[MAXPATHLEN];
     505:
     506:     if (!(d = opendir(name))) {
     507:         error("rcp: %s: %s\n", name, strerror(errno));
     508:         return;
     509:     }
     510:     last = rindex(name, '/');
     511:     if (last == 0)
     512:         last = name;
     513:     else
     514:         last++;
     515:     if (pflag) {
     516:         (void)sprintf(path, "T%ld 0 %ld 0\n", statp->st_mtime,
     517:             statp->st_atime);
     518:         (void)write(rem, path, strlen(path));
     519:         if (response() < 0) {
     520:             closedir(d);
     521:             return;
     522:         }
     523:     }
     524:     (void)sprintf(path, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
     525:     (void)write(rem, path, strlen(path));
     526:     if (response() < 0) {
     527:         closedir(d);
     528:         return;
     529:     }
     530:     while (dp = readdir(d)) {
     531:         if (dp->d_ino == 0)
     532:             continue;
     533:         if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
     534:             continue;
     535:         if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) {
     536:             error("%s/%s: name too long.\n", name, dp->d_name);
     537:             continue;
     538:         }
     539:         (void)sprintf(path, "%s/%s", name, dp->d_name);
     540:         vect[0] = path;
     541:         source(1, vect);
     542:     }
     543:     closedir(d);
     544:     (void)write(rem, "E\n", 2);
     545:     (void)response();
     546: }
     547:
     548: response()
     549: {
     550:     register char *cp;
     551:     char ch, resp, rbuf[BUFSIZ];
     552:
     553:     if (read(rem, &resp, sizeof(resp)) != sizeof(resp))
     554:         lostconn();
     555:
     556:     cp = rbuf;
     557:     switch(resp) {
     558:     case 0:             /* ok */
     559:         return(0);
     560:     default:
     561:         *cp++ = resp;
     562:         /* FALLTHROUGH */
     563:     case 1:             /* error, followed by err msg */
     564:     case 2:             /* fatal error, "" */
     565:         do {
     566:             if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
     567:                 lostconn();
     568:             *cp++ = ch;
     569:         } while (cp < &rbuf[BUFSIZ] && ch != '\n');
     570:
     571:         if (!iamremote)
     572:             (void)write(2, rbuf, cp - rbuf);
     573:         ++errs;
     574:         if (resp == 1)
     575:             return(-1);
     576:         exit(1);
     577:     }
     578:     /*NOTREACHED*/
     579: }
     580:
     581: lostconn()
     582: {
     583:     if (!iamremote)
     584:         (void)fprintf(stderr, "rcp: lost connection\n");
     585:     exit(1);
     586: }
     587:
     588: sink(argc, argv)
     589:     int argc;
     590:     char **argv;
     591: {
     592:     register char *cp;
     593:     static BUF buffer;
     594:     struct stat stb;
     595:     struct timeval tv[2];
     596:     BUF *bp, *allocbuf();
     597:     off_t i, j;
     598:     char ch, *targ, *why;
     599:     int amt, count, exists, first, mask, mode;
     600:     int ofd, setimes, targisdir, wrerr, cursize = 0;
     601:     off_t size;
     602:     char *np, *vect[1], buf[BUFSIZ], *malloc(), *namebuf = NULL;
     603:
     604: #define atime   tv[0]
     605: #define mtime   tv[1]
     606: #define SCREWUP(str)    { why = str; goto screwup; }
     607:
     608:     setimes = targisdir = 0;
     609:     mask = umask(0);
     610:     if (!pflag)
     611:         (void)umask(mask);
     612:     if (argc != 1) {
     613:         error("rcp: ambiguous target\n");
     614:         exit(1);
     615:     }
     616:     targ = *argv;
     617:     if (targetshouldbedirectory)
     618:         verifydir(targ);
     619:     (void)write(rem, "", 1);
     620:     if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
     621:         targisdir = 1;
     622:     for (first = 1;; first = 0) {
     623:         cp = buf;
     624:         if (read(rem, cp, 1) <= 0) {
     625:             if (namebuf)
     626:                 free(namebuf);
     627:             return;
     628:         }
     629:         if (*cp++ == '\n')
     630:             SCREWUP("unexpected <newline>");
     631:         do {
     632:             if (read(rem, &ch, sizeof(ch)) != sizeof(ch))
     633:                 SCREWUP("lost connection");
     634:             *cp++ = ch;
     635:         } while (cp < &buf[BUFSIZ - 1] && ch != '\n');
     636:         *cp = 0;
     637:
     638:         if (buf[0] == '\01' || buf[0] == '\02') {
     639:             if (iamremote == 0)
     640:                 (void)write(2, buf + 1, strlen(buf + 1));
     641:             if (buf[0] == '\02')
     642:                 exit(1);
     643:             errs++;
     644:             continue;
     645:         }
     646:         if (buf[0] == 'E') {
     647:             (void)write(rem, "", 1);
     648:             if (namebuf)
     649:                 free(namebuf);
     650:             return;
     651:         }
     652:
     653:         if (ch == '\n')
     654:             *--cp = 0;
     655:
     656: #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
     657:         cp = buf;
     658:         if (*cp == 'T') {
     659:             setimes++;
     660:             cp++;
     661:             getnum(mtime.tv_sec);
     662:             if (*cp++ != ' ')
     663:                 SCREWUP("mtime.sec not delimited");
     664:             getnum(mtime.tv_usec);
     665:             if (*cp++ != ' ')
     666:                 SCREWUP("mtime.usec not delimited");
     667:             getnum(atime.tv_sec);
     668:             if (*cp++ != ' ')
     669:                 SCREWUP("atime.sec not delimited");
     670:             getnum(atime.tv_usec);
     671:             if (*cp++ != '\0')
     672:                 SCREWUP("atime.usec not delimited");
     673:             (void)write(rem, "", 1);
     674:             continue;
     675:         }
     676:         if (*cp != 'C' && *cp != 'D') {
     677:             /*
     678: 			 * Check for the case "rcp remote:foo\* local:bar".
     679: 			 * In this case, the line "No match." can be returned
     680: 			 * by the shell before the rcp command on the remote is
     681: 			 * executed so the ^Aerror_message convention isn't
     682: 			 * followed.
     683: 			 */
     684:             if (first) {
     685:                 error("%s\n", cp);
     686:                 exit(1);
     687:             }
     688:             SCREWUP("expected control record");
     689:         }
     690:         mode = 0;
     691:         for (++cp; cp < buf + 5; cp++) {
     692:             if (*cp < '0' || *cp > '7')
     693:                 SCREWUP("bad mode");
     694:             mode = (mode << 3) | (*cp - '0');
     695:         }
     696:         if (*cp++ != ' ')
     697:             SCREWUP("mode not delimited");
     698:         size = 0;
     699:         while (isdigit(*cp))
     700:             size = size * 10 + (*cp++ - '0');
     701:         if (*cp++ != ' ')
     702:             SCREWUP("size not delimited");
     703:         if (targisdir) {
     704:             int need;
     705:
     706:             need = strlen(targ) + strlen(cp) + 250;
     707:             if (need > cursize) {
     708:                 if (namebuf)
     709:                     free(namebuf);
     710:                 if (!(namebuf = malloc((u_int)need)))
     711:                     error("out of memory\n");
     712:                 cursize = need;
     713:             }
     714:             (void)sprintf(namebuf, "%s%s%s", targ,
     715:                 *targ ? "/" : "", cp);
     716:             np = namebuf;
     717:         }
     718:         else
     719:             np = targ;
     720:         exists = stat(np, &stb) == 0;
     721:         if (buf[0] == 'D') {
     722:             if (exists) {
     723:                 if ((stb.st_mode&S_IFMT) != S_IFDIR) {
     724:                     errno = ENOTDIR;
     725:                     goto bad;
     726:                 }
     727:                 if (pflag)
     728:                     (void)chmod(np, mode);
     729:             } else if (mkdir(np, mode) < 0)
     730:                 goto bad;
     731:             vect[0] = np;
     732:             sink(1, vect);
     733:             if (setimes) {
     734:                 setimes = 0;
     735:                 if (utimes(np, tv) < 0)
     736:                     error("rcp: can't set times on %s: %s\n",
     737:                     np, strerror(errno));
     738:             }
     739:             continue;
     740:         }
     741:         if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
     742: bad:            error("rcp: %s: %s\n", np, strerror(errno));
     743:             continue;
     744:         }
     745:         if (exists && pflag)
     746:             (void)fchmod(ofd, mode);
     747:         (void)write(rem, "", 1);
     748:         if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == 0) {
     749:             (void)close(ofd);
     750:             continue;
     751:         }
     752:         cp = bp->buf;
     753:         count = 0;
     754:         wrerr = 0;
     755:         for (i = 0; i < size; i += BUFSIZ) {
     756:             amt = BUFSIZ;
     757:             if (i + amt > size)
     758:                 amt = size - i;
     759:             count += amt;
     760:             do {
     761:                 j = read(rem, cp, amt);
     762:                 if (j <= 0) {
     763:                     error("rcp: %s\n",
     764:                         j ? strerror(errno) :
     765:                         "dropped connection");
     766:                     exit(1);
     767:                 }
     768:                 amt -= j;
     769:                 cp += j;
     770:             } while (amt > 0);
     771:             if (count == bp->cnt) {
     772:                 if (wrerr == 0 &&
     773:                     write(ofd, bp->buf, count) != count)
     774:                     wrerr++;
     775:                 count = 0;
     776:                 cp = bp->buf;
     777:             }
     778:         }
     779:         if (count != 0 && wrerr == 0 &&
     780:             write(ofd, bp->buf, count) != count)
     781:             wrerr++;
     782:         if (ftruncate(ofd, size))
     783:             error("rcp: can't truncate %s: %s\n", np,
     784:                 strerror(errno));
     785:         (void)close(ofd);
     786:         (void)response();
     787:         if (setimes) {
     788:             setimes = 0;
     789:             if (utimes(np, tv) < 0)
     790:                 error("rcp: can't set times on %s: %s\n",
     791:                     np, strerror(errno));
     792:         }
     793:         if (wrerr)
     794:             error("rcp: %s: %s\n", np, strerror(errno));
     795:         else
     796:             (void)write(rem, "", 1);
     797:     }
     798: screwup:
     799:     error("rcp: protocol screwup: %s\n", why);
     800:     exit(1);
     801: }
     802:
     803: BUF *
     804: allocbuf(bp, fd, blksize)
     805:     BUF *bp;
     806:     int fd, blksize;
     807: {
     808:     struct stat stb;
     809:     int size;
     810:     char *malloc();
     811:
     812:     if (fstat(fd, &stb) < 0) {
     813:         error("rcp: fstat: %s\n", strerror(errno));
     814:         return(0);
     815:     }
     816:     size = roundup(stb.st_blksize, blksize);
     817:     if (size == 0)
     818:         size = blksize;
     819:     if (bp->cnt < size) {
     820:         if (bp->buf != 0)
     821:             free(bp->buf);
     822:         bp->buf = (char *)malloc((u_int)size);
     823:         if (!bp->buf) {
     824:             error("rcp: malloc: out of memory\n");
     825:             return(0);
     826:         }
     827:     }
     828:     bp->cnt = size;
     829:     return(bp);
     830: }
     831:
     832: /* VARARGS1 */
     833: error(fmt, a1, a2, a3)
     834:     char *fmt;
     835:     int a1, a2, a3;
     836: {
     837:     static FILE *fp;
     838:
     839:     ++errs;
     840:     if (!fp && !(fp = fdopen(rem, "w")))
     841:         return;
     842:     (void)fprintf(fp, "%c", 0x01);
     843:     (void)fprintf(fp, fmt, a1, a2, a3);
     844:     (void)fflush(fp);
     845:     if (!iamremote)
     846:         (void)fprintf(stderr, fmt, a1, a2, a3);
     847: }
     848:
     849: nospace()
     850: {
     851:     (void)fprintf(stderr, "rcp: out of memory.\n");
     852:     exit(1);
     853: }
     854:
     855: #ifdef KERBEROS
     856: old_warning(str)
     857:     char *str;
     858: {
     859:     (void)fprintf(stderr, "rcp: warning: %s, using standard rcp\n", str);
     860: }
     861: #endif
     862:
     863: usage()
     864: {
     865: #ifdef KERBEROS
     866:     (void)fprintf(stderr, "%s\n\t%s\n",
     867:         "usage: rcp [-k realm] [-px] f1 f2",
     868:         "or: rcp [-k realm] [-rpx] f1 ... fn directory");
     869: #else
     870:     (void)fprintf(stderr,
     871:         "usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn directory\n");
     872: #endif
     873:     exit(1);
     874: }

#### Defined functions

allocbuf defined in line 803; used 4 times

- in line 424, 476, 596, 748

colon defined in line 360; used 6 times

- in line 74, 161, 178, 197, 261-264(2)

error defined in line 833; used 18 times

- in line 356, 429, 448, 493, 507, 536, 613, 685, 711, 736, 742, 763, 783, 790-799(3), 813, 824

kerberos defined in line 311; used 2 times

- in line 236, 295

lostconn defined in line 581; used 4 times

- in line 76, 159, 554, 567

main defined in line 67; never used
nospace defined in line 849; used 4 times

- in line 207, 231, 267, 291

okname defined in line 373; used 3 times

- in line 189, 213, 284

old_warning defined in line 856; used 2 times

- in line 82, 333

response defined in line 548; used 9 times

- in line 137, 245, 464, 472, 494, 519, 526, 545, 786

rsource defined in line 498; used 1 times

- in line 442

sink defined in line 588; used 3 times

- in line 146, 303, 732

source defined in line 414; used 3 times

- in line 139, 250, 541

susystem defined in line 392; used 2 times

- in line 225, 271

tolocal defined in line 255; used 1 times

- in line 164

toremote defined in line 171; used 1 times

- in line 162

usage defined in line 863; used 2 times

- in line 130, 151

verifydir defined in line 346; used 2 times

- in line 166, 618

#### Defined variables

cmd defined in line 60; used 5 times

- in line 156, 217-222(2), 232, 292

copyright defined in line 19; never used
errs defined in line 56; used 6 times

- in line 140, 147, 168, 573, 643, 839

iamrecursive defined in line 57; used 4 times

- in line 117, 156, 269, 440

iamremote defined in line 57; used 6 times

- in line 136, 144, 571, 583, 639, 845

krb_realm defined in line 48; used 5 times

- in line 110, 318-325(4)

pflag defined in line 56; used 8 times

- in line 114, 157, 269, 456, 515, 610, 727, 745

port defined in line 56; used 6 times

- in line 92, 240, 298, 322-325(2), 340

pwd defined in line 55; used 8 times

- in line 94, 212, 237-241(3), 283-288(2), 298

rem defined in line 56; used 33 times

- in line 155, 228, 240-243(2), 298-306(4), 317-331(7), 463, 471, 487-491(2), 518, 525, 544, 553, 566, 619-624(2), 632, 647, 673, 747, 761, 796, 840

sccsid defined in line 23; never used
targetshouldbedirectory defined in line 57; used 5 times

- in line 103, 153-157(2), 165, 617

use_kerberos defined in line 49; used 4 times

- in line 81, 235, 294, 332

userid defined in line 56; used 8 times

- in line 94-95(2), 138, 145, 248, 302-304(2), 399

#### Defined struct's

_buf defined in line 62; never used

#### Defined typedef's

BUF defined in line 65; used 7 times

- in line 803-424(5), 593-596(2)

#### Defined macros

CMDNEEDS defined in line 59; used 4 times

- in line 60, 206, 230, 290

SCREWUP defined in line 606; used 10 times

- in line 630-633(2), 663-672(4), 688-702(4)

atime defined in line 604; used 2 times

- in line 667-670(2)

getnum defined in line 656; used 4 times

- in line 661-670(4)

mtime defined in line 605; used 2 times

- in line 661-664(2)

Last modified: 1996-03-22 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 3235 |