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