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