1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #ifndef lint
   8: char copyright[] =
   9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  10:  All rights reserved.\n";
  11: #endif not lint
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)rcp.c	5.4 (Berkeley) 9/12/85";
  15: #endif not lint
  16: 
  17: /*
  18:  * rcp
  19:  */
  20: #include <sys/param.h>
  21: #include <sys/stat.h>
  22: #include <sys/time.h>
  23: #include <sys/ioctl.h>
  24: 
  25: #include <netinet/in.h>
  26: 
  27: #include <stdio.h>
  28: #include <signal.h>
  29: #include <pwd.h>
  30: #include <ctype.h>
  31: #include <netdb.h>
  32: #include <errno.h>
  33: 
  34: int rem;
  35: char    *colon(), *index(), *rindex(), *malloc(), *strcpy(), *sprintf();
  36: int errs;
  37: int lostconn();
  38: int errno;
  39: char    *sys_errlist[];
  40: int iamremote, targetshouldbedirectory;
  41: int iamrecursive;
  42: int pflag;
  43: struct  passwd *pwd;
  44: struct  passwd *getpwuid();
  45: int userid;
  46: int port;
  47: 
  48: struct buffer {
  49:     int cnt;
  50:     char    *buf;
  51: } *allocbuf();
  52: 
  53: /*VARARGS*/
  54: int error();
  55: 
  56: #define ga()        (void) write(rem, "", 1)
  57: 
  58: main(argc, argv)
  59:     int argc;
  60:     char **argv;
  61: {
  62:     char *targ, *host, *src;
  63:     char *suser, *tuser, *thost;
  64:     int i;
  65:     char buf[BUFSIZ], cmd[16];
  66:     struct servent *sp;
  67: 
  68:     sp = getservbyname("shell", "tcp");
  69:     if (sp == NULL) {
  70:         fprintf(stderr, "rcp: shell/tcp: unknown service\n");
  71:         exit(1);
  72:     }
  73:     port = sp->s_port;
  74:     pwd = getpwuid(userid = getuid());
  75:     if (pwd == 0) {
  76:         fprintf(stderr, "who are you?\n");
  77:         exit(1);
  78:     }
  79: 
  80:     for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
  81:         (*argv)++;
  82:         while (**argv) switch (*(*argv)++) {
  83: 
  84:             case 'r':
  85:             iamrecursive++;
  86:             break;
  87: 
  88:             case 'p':       /* preserve mtimes and atimes */
  89:             pflag++;
  90:             break;
  91: 
  92:             /* The rest of these are not for users. */
  93:             case 'd':
  94:             targetshouldbedirectory = 1;
  95:             break;
  96: 
  97:             case 'f':       /* "from" */
  98:             iamremote = 1;
  99:             (void) response();
 100:             (void) setuid(userid);
 101:             source(--argc, ++argv);
 102:             exit(errs);
 103: 
 104:             case 't':       /* "to" */
 105:             iamremote = 1;
 106:             (void) setuid(userid);
 107:             sink(--argc, ++argv);
 108:             exit(errs);
 109: 
 110:             default:
 111:             fprintf(stderr,
 112:         "Usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n");
 113:             exit(1);
 114:         }
 115:     }
 116:     rem = -1;
 117:     if (argc > 2)
 118:         targetshouldbedirectory = 1;
 119:     (void) sprintf(cmd, "rcp%s%s%s",
 120:         iamrecursive ? " -r" : "", pflag ? " -p" : "",
 121:         targetshouldbedirectory ? " -d" : "");
 122:     (void) signal(SIGPIPE, lostconn);
 123:     targ = colon(argv[argc - 1]);
 124:     if (targ) {             /* ... to remote */
 125:         *targ++ = 0;
 126:         if (*targ == 0)
 127:             targ = ".";
 128:         thost = index(argv[argc - 1], '@');
 129:         if (thost) {
 130:             *thost++ = 0;
 131:             tuser = argv[argc - 1];
 132:             if (*tuser == '\0')
 133:                 tuser = NULL;
 134:             else if (!okname(tuser))
 135:                 exit(1);
 136:         } else {
 137:             thost = argv[argc - 1];
 138:             tuser = NULL;
 139:         }
 140:         for (i = 0; i < argc - 1; i++) {
 141:             src = colon(argv[i]);
 142:             if (src) {      /* remote to remote */
 143:                 *src++ = 0;
 144:                 if (*src == 0)
 145:                     src = ".";
 146:                 host = index(argv[i], '@');
 147:                 if (host) {
 148:                     *host++ = 0;
 149:                     suser = argv[i];
 150:                     if (*suser == '\0')
 151:                         suser = pwd->pw_name;
 152:                     else if (!okname(suser))
 153:                         continue;
 154:         (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s%s%s:%s'",
 155:                         host, suser, cmd, src, tuser,
 156:                         tuser ? "@" : "",
 157:                         thost, targ);
 158:                 } else
 159:         (void) sprintf(buf, "rsh %s -n %s %s '%s%s%s:%s'",
 160:                         argv[i], cmd, src, tuser,
 161:                         tuser ? "@" : "",
 162:                         thost, targ);
 163:                 (void) susystem(buf);
 164:             } else {        /* local to remote */
 165:                 if (rem == -1) {
 166:                     (void) sprintf(buf, "%s -t %s",
 167:                         cmd, targ);
 168:                     host = thost;
 169:                     rem = rcmd(&host, port, pwd->pw_name,
 170:                         tuser ? tuser : pwd->pw_name,
 171:                         buf, 0);
 172:                     if (rem < 0)
 173:                         exit(1);
 174:                     if (response() < 0)
 175:                         exit(1);
 176:                     (void) setuid(userid);
 177:                 }
 178:                 source(1, argv+i);
 179:             }
 180:         }
 181:     } else {                /* ... to local */
 182:         if (targetshouldbedirectory)
 183:             verifydir(argv[argc - 1]);
 184:         for (i = 0; i < argc - 1; i++) {
 185:             src = colon(argv[i]);
 186:             if (src == 0) {     /* local to local */
 187:                 (void) sprintf(buf, "/bin/cp%s%s %s %s",
 188:                     iamrecursive ? " -r" : "",
 189:                     pflag ? " -p" : "",
 190:                     argv[i], argv[argc - 1]);
 191:                 (void) susystem(buf);
 192:             } else {        /* remote to local */
 193:                 *src++ = 0;
 194:                 if (*src == 0)
 195:                     src = ".";
 196:                 host = index(argv[i], '@');
 197:                 if (host) {
 198:                     *host++ = 0;
 199:                     suser = argv[i];
 200:                     if (*suser == '\0')
 201:                         suser = pwd->pw_name;
 202:                     else if (!okname(suser))
 203:                         continue;
 204:                 } else {
 205:                     host = argv[i];
 206:                     suser = pwd->pw_name;
 207:                 }
 208:                 (void) sprintf(buf, "%s -f %s", cmd, src);
 209:                 rem = rcmd(&host, port, pwd->pw_name, suser,
 210:                     buf, 0);
 211:                 if (rem < 0)
 212:                     continue;
 213:                 (void) setreuid(0, userid);
 214:                 sink(1, argv+argc-1);
 215:                 (void) setreuid(userid, 0);
 216:                 (void) close(rem);
 217:                 rem = -1;
 218:             }
 219:         }
 220:     }
 221:     exit(errs);
 222: }
 223: 
 224: verifydir(cp)
 225:     char *cp;
 226: {
 227:     struct stat stb;
 228: 
 229:     if (stat(cp, &stb) >= 0) {
 230:         if ((stb.st_mode & S_IFMT) == S_IFDIR)
 231:             return;
 232:         errno = ENOTDIR;
 233:     }
 234:     error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
 235:     exit(1);
 236: }
 237: 
 238: char *
 239: colon(cp)
 240:     char *cp;
 241: {
 242: 
 243:     while (*cp) {
 244:         if (*cp == ':')
 245:             return (cp);
 246:         if (*cp == '/')
 247:             return (0);
 248:         cp++;
 249:     }
 250:     return (0);
 251: }
 252: 
 253: okname(cp0)
 254:     char *cp0;
 255: {
 256:     register char *cp = cp0;
 257:     register int c;
 258: 
 259:     do {
 260:         c = *cp;
 261:         if (c & 0200)
 262:             goto bad;
 263:         if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
 264:             goto bad;
 265:         cp++;
 266:     } while (*cp);
 267:     return (1);
 268: bad:
 269:     fprintf(stderr, "rcp: invalid user name %s\n", cp0);
 270:     return (0);
 271: }
 272: 
 273: susystem(s)
 274:     char *s;
 275: {
 276:     int status, pid, w;
 277:     register int (*istat)(), (*qstat)();
 278: 
 279:     if ((pid = vfork()) == 0) {
 280:         (void) setuid(userid);
 281:         execl("/bin/sh", "sh", "-c", s, (char *)0);
 282:         _exit(127);
 283:     }
 284:     istat = signal(SIGINT, SIG_IGN);
 285:     qstat = signal(SIGQUIT, SIG_IGN);
 286:     while ((w = wait(&status)) != pid && w != -1)
 287:         ;
 288:     if (w == -1)
 289:         status = -1;
 290:     (void) signal(SIGINT, istat);
 291:     (void) signal(SIGQUIT, qstat);
 292:     return (status);
 293: }
 294: 
 295: source(argc, argv)
 296:     int argc;
 297:     char **argv;
 298: {
 299:     char *last, *name;
 300:     struct stat stb;
 301:     static struct buffer buffer;
 302:     struct buffer *bp;
 303:     int x, sizerr, f, amt;
 304:     off_t i;
 305:     char buf[BUFSIZ];
 306: 
 307:     for (x = 0; x < argc; x++) {
 308:         name = argv[x];
 309:         if ((f = open(name, 0)) < 0) {
 310:             error("rcp: %s: %s\n", name, sys_errlist[errno]);
 311:             continue;
 312:         }
 313:         if (fstat(f, &stb) < 0)
 314:             goto notreg;
 315:         switch (stb.st_mode&S_IFMT) {
 316: 
 317:         case S_IFREG:
 318:             break;
 319: 
 320:         case S_IFDIR:
 321:             if (iamrecursive) {
 322:                 (void) close(f);
 323:                 rsource(name, &stb);
 324:                 continue;
 325:             }
 326:             /* fall into ... */
 327:         default:
 328: notreg:
 329:             (void) close(f);
 330:             error("rcp: %s: not a plain file\n", name);
 331:             continue;
 332:         }
 333:         last = rindex(name, '/');
 334:         if (last == 0)
 335:             last = name;
 336:         else
 337:             last++;
 338:         if (pflag) {
 339:             /*
 340: 			 * Make it compatible with possible future
 341: 			 * versions expecting microseconds.
 342: 			 */
 343:             (void) sprintf(buf, "T%ld 0 %ld 0\n",
 344:                 stb.st_mtime, stb.st_atime);
 345:             (void) write(rem, buf, strlen(buf));
 346:             if (response() < 0) {
 347:                 (void) close(f);
 348:                 continue;
 349:             }
 350:         }
 351:         (void) sprintf(buf, "C%04o %ld %s\n",
 352:             stb.st_mode&07777, stb.st_size, last);
 353:         (void) write(rem, buf, strlen(buf));
 354:         if (response() < 0) {
 355:             (void) close(f);
 356:             continue;
 357:         }
 358:         if ((bp = allocbuf(&buffer, f, BUFSIZ)) < 0) {
 359:             (void) close(f);
 360:             continue;
 361:         }
 362:         sizerr = 0;
 363:         for (i = 0; i < stb.st_size; i += bp->cnt) {
 364:             amt = bp->cnt;
 365:             if (i + amt > stb.st_size)
 366:                 amt = stb.st_size - i;
 367:             if (sizerr == 0 && read(f, bp->buf, amt) != amt)
 368:                 sizerr = 1;
 369:             (void) write(rem, bp->buf, amt);
 370:         }
 371:         (void) close(f);
 372:         if (sizerr == 0)
 373:             ga();
 374:         else
 375:             error("rcp: %s: file changed size\n", name);
 376:         (void) response();
 377:     }
 378: }
 379: 
 380: #include <sys/dir.h>
 381: 
 382: rsource(name, statp)
 383:     char *name;
 384:     struct stat *statp;
 385: {
 386:     DIR *d = opendir(name);
 387:     char *last;
 388:     struct direct *dp;
 389:     char buf[BUFSIZ];
 390:     char *bufv[1];
 391: 
 392:     if (d == 0) {
 393:         error("rcp: %s: %s\n", name, sys_errlist[errno]);
 394:         return;
 395:     }
 396:     last = rindex(name, '/');
 397:     if (last == 0)
 398:         last = name;
 399:     else
 400:         last++;
 401:     if (pflag) {
 402:         (void) sprintf(buf, "T%ld 0 %ld 0\n",
 403:             statp->st_mtime, statp->st_atime);
 404:         (void) write(rem, buf, strlen(buf));
 405:         if (response() < 0) {
 406:             closedir(d);
 407:             return;
 408:         }
 409:     }
 410:     (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
 411:     (void) write(rem, buf, strlen(buf));
 412:     if (response() < 0) {
 413:         closedir(d);
 414:         return;
 415:     }
 416:     while (dp = readdir(d)) {
 417:         if (dp->d_ino == 0)
 418:             continue;
 419:         if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
 420:             continue;
 421:         if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
 422:             error("%s/%s: Name too long.\n", name, dp->d_name);
 423:             continue;
 424:         }
 425:         (void) sprintf(buf, "%s/%s", name, dp->d_name);
 426:         bufv[0] = buf;
 427:         source(1, bufv);
 428:     }
 429:     closedir(d);
 430:     (void) write(rem, "E\n", 2);
 431:     (void) response();
 432: }
 433: 
 434: response()
 435: {
 436:     char resp, c, rbuf[BUFSIZ], *cp = rbuf;
 437: 
 438:     if (read(rem, &resp, 1) != 1)
 439:         lostconn();
 440:     switch (resp) {
 441: 
 442:     case 0:             /* ok */
 443:         return (0);
 444: 
 445:     default:
 446:         *cp++ = resp;
 447:         /* fall into... */
 448:     case 1:             /* error, followed by err msg */
 449:     case 2:             /* fatal error, "" */
 450:         do {
 451:             if (read(rem, &c, 1) != 1)
 452:                 lostconn();
 453:             *cp++ = c;
 454:         } while (cp < &rbuf[BUFSIZ] && c != '\n');
 455:         if (iamremote == 0)
 456:             (void) write(2, rbuf, cp - rbuf);
 457:         errs++;
 458:         if (resp == 1)
 459:             return (-1);
 460:         exit(1);
 461:     }
 462:     /*NOTREACHED*/
 463: }
 464: 
 465: lostconn()
 466: {
 467: 
 468:     if (iamremote == 0)
 469:         fprintf(stderr, "rcp: lost connection\n");
 470:     exit(1);
 471: }
 472: 
 473: sink(argc, argv)
 474:     int argc;
 475:     char **argv;
 476: {
 477:     off_t i, j;
 478:     char *targ, *whopp, *cp;
 479:     int of, mode, wrerr, exists, first, count, amt, size;
 480:     struct buffer *bp;
 481:     static struct buffer buffer;
 482:     struct stat stb;
 483:     int targisdir = 0;
 484:     int mask = umask(0);
 485:     char *myargv[1];
 486:     char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
 487:     int setimes = 0;
 488:     struct timeval tv[2];
 489: #define atime   tv[0]
 490: #define mtime   tv[1]
 491: #define SCREWUP(str)    { whopp = str; goto screwup; }
 492: 
 493:     if (!pflag)
 494:         (void) umask(mask);
 495:     if (argc != 1) {
 496:         error("rcp: ambiguous target\n");
 497:         exit(1);
 498:     }
 499:     targ = *argv;
 500:     if (targetshouldbedirectory)
 501:         verifydir(targ);
 502:     ga();
 503:     if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
 504:         targisdir = 1;
 505:     for (first = 1; ; first = 0) {
 506:         cp = cmdbuf;
 507:         if (read(rem, cp, 1) <= 0)
 508:             return;
 509:         if (*cp++ == '\n')
 510:             SCREWUP("unexpected '\\n'");
 511:         do {
 512:             if (read(rem, cp, 1) != 1)
 513:                 SCREWUP("lost connection");
 514:         } while (*cp++ != '\n');
 515:         *cp = 0;
 516:         if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
 517:             if (iamremote == 0)
 518:                 (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
 519:             if (cmdbuf[0] == '\02')
 520:                 exit(1);
 521:             errs++;
 522:             continue;
 523:         }
 524:         *--cp = 0;
 525:         cp = cmdbuf;
 526:         if (*cp == 'E') {
 527:             ga();
 528:             return;
 529:         }
 530: 
 531: #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
 532:         if (*cp == 'T') {
 533:             setimes++;
 534:             cp++;
 535:             getnum(mtime.tv_sec);
 536:             if (*cp++ != ' ')
 537:                 SCREWUP("mtime.sec not delimited");
 538:             getnum(mtime.tv_usec);
 539:             if (*cp++ != ' ')
 540:                 SCREWUP("mtime.usec not delimited");
 541:             getnum(atime.tv_sec);
 542:             if (*cp++ != ' ')
 543:                 SCREWUP("atime.sec not delimited");
 544:             getnum(atime.tv_usec);
 545:             if (*cp++ != '\0')
 546:                 SCREWUP("atime.usec not delimited");
 547:             ga();
 548:             continue;
 549:         }
 550:         if (*cp != 'C' && *cp != 'D') {
 551:             /*
 552: 			 * Check for the case "rcp remote:foo\* local:bar".
 553: 			 * In this case, the line "No match." can be returned
 554: 			 * by the shell before the rcp command on the remote is
 555: 			 * executed so the ^Aerror_message convention isn't
 556: 			 * followed.
 557: 			 */
 558:             if (first) {
 559:                 error("%s\n", cp);
 560:                 exit(1);
 561:             }
 562:             SCREWUP("expected control record");
 563:         }
 564:         cp++;
 565:         mode = 0;
 566:         for (; cp < cmdbuf+5; cp++) {
 567:             if (*cp < '0' || *cp > '7')
 568:                 SCREWUP("bad mode");
 569:             mode = (mode << 3) | (*cp - '0');
 570:         }
 571:         if (*cp++ != ' ')
 572:             SCREWUP("mode not delimited");
 573:         size = 0;
 574:         while (isdigit(*cp))
 575:             size = size * 10 + (*cp++ - '0');
 576:         if (*cp++ != ' ')
 577:             SCREWUP("size not delimited");
 578:         if (targisdir)
 579:             (void) sprintf(nambuf, "%s%s%s", targ,
 580:                 *targ ? "/" : "", cp);
 581:         else
 582:             (void) strcpy(nambuf, targ);
 583:         exists = stat(nambuf, &stb) == 0;
 584:         if (cmdbuf[0] == 'D') {
 585:             if (exists) {
 586:                 if ((stb.st_mode&S_IFMT) != S_IFDIR) {
 587:                     errno = ENOTDIR;
 588:                     goto bad;
 589:                 }
 590:                 if (pflag)
 591:                     (void) chmod(nambuf, mode);
 592:             } else if (mkdir(nambuf, mode) < 0)
 593:                 goto bad;
 594:             myargv[0] = nambuf;
 595:             sink(1, myargv);
 596:             if (setimes) {
 597:                 setimes = 0;
 598:                 if (utimes(nambuf, tv) < 0)
 599:                     error("rcp: can't set times on %s: %s\n",
 600:                         nambuf, sys_errlist[errno]);
 601:             }
 602:             continue;
 603:         }
 604:         if ((of = creat(nambuf, mode)) < 0) {
 605:     bad:
 606:             error("rcp: %s: %s\n", nambuf, sys_errlist[errno]);
 607:             continue;
 608:         }
 609:         if (exists && pflag)
 610:             (void) fchmod(of, mode);
 611:         ga();
 612:         if ((bp = allocbuf(&buffer, of, BUFSIZ)) < 0) {
 613:             (void) close(of);
 614:             continue;
 615:         }
 616:         cp = bp->buf;
 617:         count = 0;
 618:         wrerr = 0;
 619:         for (i = 0; i < size; i += BUFSIZ) {
 620:             amt = BUFSIZ;
 621:             if (i + amt > size)
 622:                 amt = size - i;
 623:             count += amt;
 624:             do {
 625:                 j = read(rem, cp, amt);
 626:                 if (j <= 0) {
 627:                     if (j == 0)
 628:                         error("rcp: dropped connection");
 629:                     else
 630:                         error("rcp: %s\n",
 631:                         sys_errlist[errno]);
 632:                     exit(1);
 633:                 }
 634:                 amt -= j;
 635:                 cp += j;
 636:             } while (amt > 0);
 637:             if (count == bp->cnt) {
 638:                 if (wrerr == 0 &&
 639:                     write(of, bp->buf, count) != count)
 640:                     wrerr++;
 641:                 count = 0;
 642:                 cp = bp->buf;
 643:             }
 644:         }
 645:         if (count != 0 && wrerr == 0 &&
 646:             write(of, bp->buf, count) != count)
 647:             wrerr++;
 648:         (void) close(of);
 649:         (void) response();
 650:         if (setimes) {
 651:             setimes = 0;
 652:             if (utimes(nambuf, tv) < 0)
 653:                 error("rcp: can't set times on %s: %s\n",
 654:                     nambuf, sys_errlist[errno]);
 655:         }
 656:         if (wrerr)
 657:             error("rcp: %s: %s\n", nambuf, sys_errlist[errno]);
 658:         else
 659:             ga();
 660:     }
 661: screwup:
 662:     error("rcp: protocol screwup: %s\n", whopp);
 663:     exit(1);
 664: }
 665: 
 666: struct buffer *
 667: allocbuf(bp, fd, blksize)
 668:     struct buffer *bp;
 669:     int fd, blksize;
 670: {
 671:     struct stat stb;
 672:     int size;
 673: 
 674:     if (fstat(fd, &stb) < 0) {
 675:         error("rcp: fstat: %s\n", sys_errlist[errno]);
 676:         return ((struct buffer *)-1);
 677:     }
 678:     size = roundup(stb.st_blksize, blksize);
 679:     if (size == 0)
 680:         size = blksize;
 681:     if (bp->cnt < size) {
 682:         if (bp->buf != 0)
 683:             free(bp->buf);
 684:         bp->buf = (char *)malloc((unsigned) size);
 685:         if (bp->buf == 0) {
 686:             error("rcp: malloc: out of memory\n");
 687:             return ((struct buffer *)-1);
 688:         }
 689:     }
 690:     bp->cnt = size;
 691:     return (bp);
 692: }
 693: 
 694: /*VARARGS1*/
 695: error(fmt, a1, a2, a3, a4, a5)
 696:     char *fmt;
 697:     int a1, a2, a3, a4, a5;
 698: {
 699:     char buf[BUFSIZ], *cp = buf;
 700: 
 701:     errs++;
 702:     *cp++ = 1;
 703:     (void) sprintf(cp, fmt, a1, a2, a3, a4, a5);
 704:     (void) write(rem, buf, strlen(buf));
 705:     if (iamremote == 0)
 706:         (void) write(2, buf+1, strlen(buf+1));
 707: }

Defined functions

allocbuf defined in line 666; used 3 times
colon defined in line 238; used 4 times
error defined in line 695; used 18 times
lostconn defined in line 465; used 4 times
main defined in line 58; never used
okname defined in line 253; used 3 times
response defined in line 434; used 9 times
rsource defined in line 382; used 1 times
sink defined in line 473; used 3 times
source defined in line 295; used 3 times
susystem defined in line 273; used 2 times
verifydir defined in line 224; used 2 times

Defined variables

copyright defined in line 8; never used
errno defined in line 38; used 11 times
errs defined in line 36; used 6 times
iamrecursive defined in line 41; used 4 times
iamremote defined in line 40; used 6 times
pflag defined in line 42; used 8 times
port defined in line 46; used 3 times
pwd defined in line 43; used 8 times
rem defined in line 34; used 21 times
sccsid defined in line 14; never used
sys_errlist defined in line 39; used 9 times
targetshouldbedirectory defined in line 40; used 5 times
userid defined in line 45; used 7 times

Defined struct's

buffer defined in line 48; used 16 times

Defined macros

SCREWUP defined in line 491; used 10 times
atime defined in line 489; used 2 times
ga defined in line 56; used 6 times
getnum defined in line 531; used 4 times
mtime defined in line 490; used 2 times
Last modified: 1986-02-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1962
Valid CSS Valid XHTML 1.0 Strict