|
|
1.1 ! root 1: /* ! 2: * rcp ! 3: */ ! 4: #include <sys/param.h> ! 5: #include <sys/stat.h> ! 6: #include <sys/ioctl.h> ! 7: ! 8: #include <stdio.h> ! 9: #include <signal.h> ! 10: #include <pwd.h> ! 11: #include <ctype.h> ! 12: #include <errno.h> ! 13: #include <ndir.h> ! 14: #include <libc.h> ! 15: #include <ipc.h> ! 16: ! 17: int rem; ! 18: char *colon(), *index(), *malloc(), *strcpy(), *sprintf(); ! 19: int errs; ! 20: int lostconn(); ! 21: int iamremote; ! 22: ! 23: int errno; ! 24: char *sys_errlist[]; ! 25: int iamremote, targetshouldbedirectory; ! 26: int iamrecursive; ! 27: struct passwd *pwd; ! 28: struct passwd *getpwuid(); ! 29: ! 30: /*VARARGS*/ ! 31: int error(); ! 32: ! 33: #define ga() (void) write(rem, "", 1) ! 34: ! 35: main(argc, argv) ! 36: int argc; ! 37: char **argv; ! 38: { ! 39: char *targ, *host, *src; ! 40: char *suser, *tuser; ! 41: int i; ! 42: char buf[BUFSIZ], cmd[16]; ! 43: ! 44: setpwent(); ! 45: pwd = getpwuid(getuid()); ! 46: endpwent(); ! 47: if (pwd == 0) { ! 48: fprintf(stderr, "who are you?\n"); ! 49: exit(1); ! 50: } ! 51: argc--, argv++; ! 52: if (argc > 0 && !strcmp(*argv, "-r")) { ! 53: iamrecursive++; ! 54: argc--, argv++; ! 55: } ! 56: if (argc > 0 && !strcmp(*argv, "-d")) { ! 57: targetshouldbedirectory = 1; ! 58: argc--, argv++; ! 59: } ! 60: if (argc > 0 && !strcmp(*argv, "-f")) { ! 61: argc--, argv++; iamremote = 1; ! 62: (void) response(); ! 63: (void) setuid(getuid()); ! 64: source(argc, argv); ! 65: exit(errs); ! 66: } ! 67: if (argc > 0 && !strcmp(*argv, "-t")) { ! 68: argc--, argv++; iamremote = 1; ! 69: (void) setuid(getuid()); ! 70: sink(argc, argv); ! 71: exit(errs); ! 72: } ! 73: rem = -1; ! 74: if (argc > 2) ! 75: targetshouldbedirectory = 1; ! 76: (void) sprintf(cmd, "rcp%s%s", ! 77: iamrecursive ? " -r" : "", targetshouldbedirectory ? " -d" : ""); ! 78: signal(SIGPIPE, lostconn); ! 79: targ = colon(argv[argc - 1]); ! 80: if (targ) { ! 81: *targ++ = 0; ! 82: if (*targ == 0) ! 83: targ = "."; ! 84: tuser = strrchr(argv[argc - 1], '.'); ! 85: if (tuser) { ! 86: *tuser++ = 0; ! 87: if (!okname(tuser)) ! 88: exit(1); ! 89: } else ! 90: tuser = pwd->pw_name; ! 91: for (i = 0; i < argc - 1; i++) { ! 92: src = colon(argv[i]); ! 93: if (src) { ! 94: *src++ = 0; ! 95: if (*src == 0) ! 96: src = "."; ! 97: suser = strrchr(argv[i], '.'); ! 98: if (suser) { ! 99: *suser++ = 0; ! 100: if (!okname(suser)) ! 101: continue; ! 102: (void) sprintf(buf, "rsh %s -L %s -n %s %s '%s:%s'", ! 103: argv[i], suser, cmd, ! 104: src, argv[argc - 1], targ); ! 105: } else ! 106: (void) sprintf(buf, "rsh %s -n %s %s '%s:%s'", ! 107: argv[i], cmd, ! 108: src, argv[argc - 1], targ); ! 109: (void) susystem(buf); ! 110: } else { ! 111: if (rem == -1) { ! 112: (void) sprintf(buf, "%s -t %s", ! 113: cmd, targ); ! 114: host = argv[argc - 1]; ! 115: rem = ipcrexec(host, "heavy hup", buf); ! 116: if (rem < 0) { ! 117: fprintf(stderr,"rcp: %s\n",errstr); ! 118: exit(1); ! 119: } ! 120: if (response() < 0) ! 121: exit(1); ! 122: } ! 123: source(1, argv+i); ! 124: } ! 125: } ! 126: } else { ! 127: if (targetshouldbedirectory) ! 128: verifydir(argv[argc - 1]); ! 129: for (i = 0; i < argc - 1; i++) { ! 130: src = colon(argv[i]); ! 131: if (src == 0) { ! 132: (void) sprintf(buf, "/bin/cp%s %s %s", ! 133: iamrecursive ? " -r" : "", ! 134: argv[i], argv[argc - 1]); ! 135: (void) susystem(buf); ! 136: } else { ! 137: *src++ = 0; ! 138: if (*src == 0) ! 139: src = "."; ! 140: suser = strrchr(argv[i], '.'); ! 141: if (suser) { ! 142: *suser++ = 0; ! 143: if (!okname(suser)) ! 144: continue; ! 145: } else ! 146: suser = pwd->pw_name; ! 147: (void) sprintf(buf, "%s -f %s", cmd, src); ! 148: host = argv[i]; ! 149: rem = ipcrexec(host, "heavy hup", buf); ! 150: if (rem < 0){ ! 151: fprintf(stderr,"rcp: %s\n",errstr); ! 152: exit(1); ! 153: } ! 154: sink(1, argv+argc-1); ! 155: (void) close(rem); ! 156: rem = -1; ! 157: } ! 158: } ! 159: } ! 160: exit(errs); ! 161: } ! 162: ! 163: verifydir(cp) ! 164: char *cp; ! 165: { ! 166: struct stat stb; ! 167: ! 168: if (stat(cp, &stb) < 0) ! 169: goto bad; ! 170: if ((stb.st_mode & S_IFMT) == S_IFDIR) ! 171: return; ! 172: errno = ENOTDIR; ! 173: bad: ! 174: error("rcp: %s: %s.\n", cp, sys_errlist[errno]); ! 175: exit(1); ! 176: } ! 177: ! 178: char * ! 179: colon(cp) ! 180: char *cp; ! 181: { ! 182: ! 183: while (*cp) { ! 184: if (*cp == ':') ! 185: return (cp); ! 186: if (*cp == '/') ! 187: return (0); ! 188: cp++; ! 189: } ! 190: return (0); ! 191: } ! 192: ! 193: okname(cp0) ! 194: char *cp0; ! 195: { ! 196: register char *cp = cp0; ! 197: register int c; ! 198: ! 199: do { ! 200: c = *cp; ! 201: if (c & 0200) ! 202: goto bad; ! 203: if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') ! 204: goto bad; ! 205: cp++; ! 206: } while (*cp); ! 207: return (1); ! 208: bad: ! 209: fprintf(stderr, "rcp: invalid user name %s\n", cp0); ! 210: return (0); ! 211: } ! 212: ! 213: susystem(buf) ! 214: char *buf; ! 215: { ! 216: ! 217: if (fork() == 0) { ! 218: (void) setuid(getuid()); ! 219: (void) system(buf); ! 220: _exit(0); ! 221: } else ! 222: (void) wait((int *)0); ! 223: } ! 224: ! 225: source(argc, argv) ! 226: int argc; ! 227: char **argv; ! 228: { ! 229: char *last, *name; ! 230: struct stat stb; ! 231: char buf[BUFSIZ]; ! 232: int x, sizerr, f; ! 233: off_t i; ! 234: ! 235: for (x = 0; x < argc; x++) { ! 236: name = argv[x]; ! 237: if (access(name, 4) < 0 || (f = open(name, 0)) < 0) { ! 238: error("rcp: %s: %s\n", name, sys_errlist[errno]); ! 239: continue; ! 240: } ! 241: if (fstat(f, &stb) < 0) ! 242: goto notreg; ! 243: switch (stb.st_mode&S_IFMT) { ! 244: ! 245: case S_IFREG: ! 246: break; ! 247: ! 248: case S_IFDIR: ! 249: if (iamrecursive) { ! 250: (void) close(f); ! 251: rsource(name, (int)stb.st_mode); ! 252: continue; ! 253: } ! 254: /* fall into ... */ ! 255: default: ! 256: notreg: ! 257: (void) close(f); ! 258: error("rcp: %s: not a plain file\n", name); ! 259: continue; ! 260: } ! 261: last = strrchr(name, '/'); ! 262: if (last == 0) ! 263: last = name; ! 264: else ! 265: last++; ! 266: (void) sprintf(buf, "C%04o %d %s\n", ! 267: stb.st_mode&07777, stb.st_size, last); ! 268: (void) write(rem, buf, strlen(buf)); ! 269: if (response() < 0) { ! 270: (void) close(f); ! 271: continue; ! 272: } ! 273: sizerr = 0; ! 274: for (i = 0; i < stb.st_size; i += BUFSIZ) { ! 275: int amt = BUFSIZ; ! 276: if (i + amt > stb.st_size) ! 277: amt = stb.st_size - i; ! 278: if (sizerr == 0 && read(f, buf, amt) != amt) ! 279: sizerr = 1; ! 280: (void) write(rem, buf, amt); ! 281: } ! 282: (void) close(f); ! 283: if (sizerr == 0) ! 284: ga(); ! 285: else ! 286: error("rcp: %s: file changed size\n", name); ! 287: (void) response(); ! 288: } ! 289: } ! 290: ! 291: #ifdef COMMENT ! 292: #include <sys/dir.h> ! 293: #endif COMMENT ! 294: ! 295: rsource(name, mode) ! 296: char *name; ! 297: int mode; ! 298: { ! 299: DIR *d = opendir(name); ! 300: char *last; ! 301: struct direct *dp; ! 302: char buf[BUFSIZ]; ! 303: char *bufv[1]; ! 304: ! 305: if (d == 0) { ! 306: error("%s: %s\n", name, sys_errlist[errno]); ! 307: return; ! 308: } ! 309: last = strrchr(name, '/'); ! 310: if (last == 0) ! 311: last = name; ! 312: else ! 313: last++; ! 314: (void) sprintf(buf, "D%04o %d %s\n", mode&07777, 0, last); ! 315: (void) write(rem, buf, strlen(buf)); ! 316: if (response() < 0) { ! 317: closedir(d); ! 318: return; ! 319: } ! 320: while (dp = readdir(d)) { ! 321: if (dp->d_ino == 0) ! 322: continue; ! 323: if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) ! 324: continue; ! 325: if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) { ! 326: error("%s/%s: Name too long.\n", name, dp->d_name); ! 327: continue; ! 328: } ! 329: (void) sprintf(buf, "%s/%s", name, dp->d_name); ! 330: bufv[0] = buf; ! 331: source(1, bufv); ! 332: } ! 333: closedir(d); ! 334: (void) write(rem, "E\n", 2); ! 335: (void) response(); ! 336: } ! 337: ! 338: response() ! 339: { ! 340: char resp, c, rbuf[BUFSIZ], *cp = rbuf; ! 341: ! 342: if (read(rem, &resp, 1) != 1) ! 343: lostconn(); ! 344: switch (resp) { ! 345: ! 346: case 0: ! 347: return (0); ! 348: ! 349: default: ! 350: *cp++ = resp; ! 351: /* fall into... */ ! 352: case 1: ! 353: case 2: ! 354: do { ! 355: if (read(rem, &c, 1) != 1) ! 356: lostconn(); ! 357: *cp++ = c; ! 358: } while (cp < &rbuf[BUFSIZ] && c != '\n'); ! 359: if (iamremote == 0) ! 360: (void) write(2, rbuf, cp - rbuf); ! 361: errs++; ! 362: if (resp == 1) ! 363: return (-1); ! 364: exit(1); ! 365: } ! 366: /*NOTREACHED*/ ! 367: } ! 368: ! 369: lostconn() ! 370: { ! 371: ! 372: if (iamremote == 0) ! 373: fprintf(stderr, "rcp: lost connection\n"); ! 374: exit(1); ! 375: } ! 376: ! 377: sink(argc, argv) ! 378: int argc; ! 379: char **argv; ! 380: { ! 381: char *targ; ! 382: char cmdbuf[BUFSIZ], nambuf[BUFSIZ], buf[BUFSIZ], *cp; ! 383: int of, mode, wrerr, exists, first; ! 384: off_t i, size; ! 385: char *whopp; ! 386: struct stat stb; int targisdir = 0; ! 387: #define SCREWUP(str) { whopp = str; goto screwup; } ! 388: int mask = umask(0); ! 389: char *myargv[1]; ! 390: ! 391: umask(mask); ! 392: if (argc > 1) { ! 393: error("rcp: ambiguous target\n"); ! 394: exit(1); ! 395: } ! 396: targ = *argv; ! 397: if (targetshouldbedirectory) ! 398: verifydir(targ); ! 399: ga(); ! 400: if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR) ! 401: targisdir = 1; ! 402: for (first = 1; ; first = 0) { ! 403: cp = cmdbuf; ! 404: if (read(rem, cp, 1) <= 0) ! 405: return; ! 406: if (*cp++ == '\n') ! 407: SCREWUP("unexpected '\\n'"); ! 408: do { ! 409: if (read(rem, cp, 1) != 1) ! 410: SCREWUP("lost connection"); ! 411: } while (*cp++ != '\n'); ! 412: *cp = 0; ! 413: if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') { ! 414: if (iamremote == 0) ! 415: (void) write(2, cmdbuf+1, strlen(cmdbuf+1)); ! 416: if (cmdbuf[0] == '\02') ! 417: exit(1); ! 418: errs++; ! 419: continue; ! 420: } ! 421: *--cp = 0; ! 422: cp = cmdbuf; ! 423: if (*cp == 'E') { ! 424: ga(); ! 425: return; ! 426: } ! 427: if (*cp != 'C' && *cp != 'D') { ! 428: /* ! 429: * Check for the case "rcp remote:foo\* local:bar". ! 430: * In this case, the line "No match." can be returned ! 431: * by the shell before the rcp command on the remote is ! 432: * executed so the ^Aerror_message convention isn't ! 433: * followed. ! 434: */ ! 435: if (first) { ! 436: error("%s\n", cp); ! 437: exit(1); ! 438: } ! 439: SCREWUP("expected control record"); ! 440: } ! 441: cp++; ! 442: mode = 0; ! 443: for (; cp < cmdbuf+5; cp++) { ! 444: if (*cp < '0' || *cp > '7') ! 445: SCREWUP("bad mode"); ! 446: mode = (mode << 3) | (*cp - '0'); ! 447: } ! 448: if (*cp++ != ' ') ! 449: SCREWUP("mode not delimited"); ! 450: size = 0; ! 451: while (*cp >= '0' && *cp <= '9') ! 452: size = size * 10 + (*cp++ - '0'); ! 453: if (*cp++ != ' ') ! 454: SCREWUP("size not delimited"); ! 455: if (targisdir) ! 456: (void) sprintf(nambuf, "%s%s%s", targ, ! 457: *targ ? "/" : "", cp); ! 458: else ! 459: (void) strcpy(nambuf, targ); ! 460: exists = stat(nambuf, &stb) == 0; ! 461: if (exists && access(nambuf, 2) < 0) ! 462: goto bad2; ! 463: { char *slash = strrchr(nambuf, '/'), *dir; ! 464: if (slash == 0) { ! 465: slash = "/"; ! 466: dir = "."; ! 467: } else { ! 468: *slash = 0; ! 469: dir = nambuf; ! 470: } ! 471: if (exists == 0 && access(dir, 2) < 0) ! 472: goto bad; ! 473: *slash = '/'; ! 474: if (cmdbuf[0] == 'D') { ! 475: if (stat(nambuf, &stb) == 0) { ! 476: if ((stb.st_mode&S_IFMT) != S_IFDIR) { ! 477: errno = ENOTDIR; ! 478: goto bad; ! 479: } ! 480: } else if (mkdir(nambuf, mode) < 0) ! 481: goto bad; ! 482: myargv[0] = nambuf; ! 483: sink(1, myargv); ! 484: continue; ! 485: } ! 486: if ((of = creat(nambuf, mode)) < 0) { ! 487: bad: ! 488: *slash = '/'; ! 489: bad2: ! 490: error("rcp: %s: %s\n", nambuf, sys_errlist[errno]); ! 491: continue; ! 492: } ! 493: } ! 494: if (exists == 0) { ! 495: (void) stat(nambuf, &stb); ! 496: (void) chown(nambuf, pwd->pw_uid, stb.st_gid); ! 497: (void) chmod(nambuf, mode &~ mask); ! 498: } ! 499: ga(); ! 500: wrerr = 0; ! 501: for (i = 0; i < size; i += BUFSIZ) { ! 502: int amt = BUFSIZ; ! 503: char *cp = buf; ! 504: ! 505: if (i + amt > size) ! 506: amt = size - i; ! 507: do { ! 508: int j = read(rem, cp, amt); ! 509: ! 510: if (j <= 0) ! 511: exit(1); ! 512: amt -= j; ! 513: cp += j; ! 514: } while (amt > 0); ! 515: amt = BUFSIZ; ! 516: if (i + amt > size) ! 517: amt = size - i; ! 518: if (wrerr == 0 && write(of, buf, amt) != amt) ! 519: wrerr++; ! 520: } ! 521: (void) close(of); ! 522: (void) response(); ! 523: if (wrerr) ! 524: error("rcp: %s: %s\n", cp, sys_errlist[errno]); ! 525: else ! 526: ga(); ! 527: } ! 528: screwup: ! 529: error("rcp: protocol screwup: %s\n", whopp); ! 530: exit(1); ! 531: } ! 532: ! 533: /*VARARGS*/ ! 534: error(fmt, a1, a2, a3, a4, a5) ! 535: char *fmt; ! 536: int a1, a2, a3, a4, a5; ! 537: { ! 538: char buf[BUFSIZ], *cp = buf; ! 539: ! 540: errs++; ! 541: *cp++ = 1; ! 542: (void) sprintf(cp, fmt, a1, a2, a3, a4, a5); ! 543: (void) write(rem, buf, strlen(buf)); ! 544: if (iamremote == 0) ! 545: (void) write(2, buf+1, strlen(buf+1)); ! 546: } ! 547: ! 548: mkdir(name, mode) ! 549: char *name; ! 550: int mode; ! 551: { ! 552: char *argv[4]; ! 553: int pid, rc; ! 554: ! 555: argv[0] = "mkdir"; ! 556: argv[1] = name; ! 557: argv[2] = 0; ! 558: pid = fork(); ! 559: if (pid < 0) { ! 560: perror("cp"); ! 561: return (1); ! 562: } ! 563: if (pid) { ! 564: while (wait(&rc) != pid) ! 565: continue; ! 566: if (rc == 0) ! 567: if (chmod(name, mode) < 0) { ! 568: perror(name); ! 569: rc = 1; ! 570: } ! 571: return (rc); ! 572: } ! 573: (void) setuid(getuid()); ! 574: execv("/bin/mkdir", argv); ! 575: execv("/usr/bin/mkdir", argv); ! 576: perror("mkdir"); ! 577: _exit(1); ! 578: /*NOTREACHED*/ ! 579: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.