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: }