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