|
|
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.