|
|
1.1 root 1: /*
2: * rcp
3: */
4: #include <sys/param.h>
5: #include <sys/stat.h>
6:
7: #include <stdio.h>
8: #include <signal.h>
9: #include <pwd.h>
10: #include <ctype.h>
11: #include <errno.h>
12: #include <ndir.h>
13: #include <libc.h>
14: #include <ipc.h>
15:
16: #define RCPBUFSIZ (4*1024)
17:
18: int rem;
19: char *colon(), *index(), *malloc(), *strcpy();
20: int errs;
21: int lostconn();
22: int iamremote;
23:
24: int errno;
25: char *sys_errlist[];
26: int iamremote, targetshouldbedirectory;
27: int iamrecursive;
28: struct passwd *pwd;
29: struct passwd *getpwuid();
30:
31: /*VARARGS*/
32: int error();
33:
34: #define ga() (void) write(rem, "", 1)
35:
36: main(argc, argv)
37: int argc;
38: char **argv;
39: {
40: char *targ, *host, *src;
41: char *suser, *tuser;
42: int i;
43: char buf[RCPBUFSIZ], cmd[16];
44:
45: setpwent();
46: pwd = getpwuid(getuid());
47: endpwent();
48: if (pwd == 0) {
49: fprintf(stderr, "who are you?\n");
50: exit(1);
51: }
52: argc--, argv++;
53: if (argc > 0 && !strcmp(*argv, "-r")) {
54: iamrecursive++;
55: argc--, argv++;
56: }
57: if (argc > 0 && !strcmp(*argv, "-d")) {
58: targetshouldbedirectory = 1;
59: argc--, argv++;
60: }
61: if (argc > 0 && !strcmp(*argv, "-f")) {
62: argc--, argv++; iamremote = 1;
63: (void) response();
64: (void) setuid(getuid());
65: source(argc, argv);
66: exit(errs);
67: }
68: if (argc > 0 && !strcmp(*argv, "-t")) {
69: argc--, argv++; iamremote = 1;
70: (void) setuid(getuid());
71: sink(argc, argv);
72: exit(errs);
73: }
74: rem = -1;
75: if (argc > 2)
76: targetshouldbedirectory = 1;
77: (void) sprintf(cmd, "rcp%s%s",
78: iamrecursive ? " -r" : "", targetshouldbedirectory ? " -d" : "");
79: signal(SIGPIPE, lostconn);
80: targ = colon(argv[argc - 1]);
81: if (targ) {
82: *targ++ = 0;
83: if (*targ == 0)
84: targ = ".";
85: tuser = strrchr(argv[argc - 1], '.');
86: if (tuser) {
87: *tuser++ = 0;
88: if (!okname(tuser))
89: exit(1);
90: } else
91: tuser = pwd->pw_name;
92: for (i = 0; i < argc - 1; i++) {
93: src = colon(argv[i]);
94: if (src) {
95: *src++ = 0;
96: if (*src == 0)
97: src = ".";
98: suser = strrchr(argv[i], '.');
99: if (suser) {
100: *suser++ = 0;
101: if (!okname(suser))
102: continue;
103: (void) sprintf(buf, "rsh %s -L %s -n %s %s '%s:%s'",
104: argv[i], suser, cmd,
105: src, argv[argc - 1], targ);
106: } else
107: (void) sprintf(buf, "rsh %s -n %s %s '%s:%s'",
108: argv[i], cmd,
109: src, argv[argc - 1], targ);
110: (void) susystem(buf);
111: } else {
112: if (rem == -1) {
113: (void) sprintf(buf, "%s -t %s",
114: cmd, targ);
115: host = argv[argc - 1];
116: rem = ipcrexec(host, "heavy hup", buf);
117: if (rem < 0) {
118: fprintf(stderr,"rcp: %s\n",errstr);
119: exit(1);
120: }
121: if (response() < 0)
122: exit(1);
123: }
124: source(1, argv+i);
125: }
126: }
127: } else {
128: if (targetshouldbedirectory)
129: verifydir(argv[argc - 1]);
130: for (i = 0; i < argc - 1; i++) {
131: src = colon(argv[i]);
132: if (src == 0) {
133: (void) sprintf(buf, "/bin/cp%s %s %s",
134: iamrecursive ? " -r" : "",
135: argv[i], argv[argc - 1]);
136: (void) susystem(buf);
137: } else {
138: *src++ = 0;
139: if (*src == 0)
140: src = ".";
141: suser = strrchr(argv[i], '.');
142: if (suser) {
143: *suser++ = 0;
144: if (!okname(suser))
145: continue;
146: } else
147: suser = pwd->pw_name;
148: (void) sprintf(buf, "%s -f %s", cmd, src);
149: host = argv[i];
150: rem = ipcrexec(host, "heavy hup", buf);
151: if (rem < 0){
152: fprintf(stderr,"rcp: %s\n",errstr);
153: exit(1);
154: }
155: sink(1, argv+argc-1);
156: (void) close(rem);
157: rem = -1;
158: }
159: }
160: }
161: exit(errs);
162: }
163:
164: verifydir(cp)
165: char *cp;
166: {
167: struct stat stb;
168:
169: if (stat(cp, &stb) < 0)
170: goto bad;
171: if ((stb.st_mode & S_IFMT) == S_IFDIR)
172: return;
173: errno = ENOTDIR;
174: bad:
175: error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
176: exit(1);
177: }
178:
179: char *
180: colon(cp)
181: char *cp;
182: {
183:
184: while (*cp) {
185: if (*cp == ':')
186: return (cp);
187: if (*cp == '/')
188: return (0);
189: cp++;
190: }
191: return (0);
192: }
193:
194: okname(cp0)
195: char *cp0;
196: {
197: register char *cp = cp0;
198: register int c;
199:
200: do {
201: c = *cp;
202: if (c & 0200)
203: goto bad;
204: if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
205: goto bad;
206: cp++;
207: } while (*cp);
208: return (1);
209: bad:
210: fprintf(stderr, "rcp: invalid user name %s\n", cp0);
211: return (0);
212: }
213:
214: susystem(buf)
215: char *buf;
216: {
217:
218: if (fork() == 0) {
219: (void) setuid(getuid());
220: (void) system(buf);
221: _exit(0);
222: } else
223: (void) wait((int *)0);
224: }
225:
226: source(argc, argv)
227: int argc;
228: char **argv;
229: {
230: char *last, *name;
231: struct stat stb;
232: char buf[RCPBUFSIZ];
233: int x, sizerr, f;
234: off_t i;
235:
236: for (x = 0; x < argc; x++) {
237: name = argv[x];
238: if (access(name, 4) < 0 || (f = open(name, 0)) < 0) {
239: error("rcp: %s: %s\n", name, sys_errlist[errno]);
240: continue;
241: }
242: if (fstat(f, &stb) < 0)
243: goto notreg;
244: switch (stb.st_mode&S_IFMT) {
245:
246: case S_IFREG:
247: break;
248:
249: case S_IFDIR:
250: if (iamrecursive) {
251: (void) close(f);
252: rsource(name, (int)stb.st_mode);
253: continue;
254: }
255: /* fall into ... */
256: default:
257: notreg:
258: (void) close(f);
259: error("rcp: %s: not a plain file\n", name);
260: continue;
261: }
262: last = strrchr(name, '/');
263: if (last == 0)
264: last = name;
265: else
266: last++;
267: (void) sprintf(buf, "C%04o %D %s\n",
268: stb.st_mode&07777, stb.st_size, last);
269: (void) write(rem, buf, strlen(buf));
270: if (response() < 0) {
271: (void) close(f);
272: continue;
273: }
274: sizerr = 0;
275: for (i = 0; i < stb.st_size; i += RCPBUFSIZ) {
276: int amt = RCPBUFSIZ;
277: if (i + amt > stb.st_size)
278: amt = stb.st_size - i;
279: if (sizerr == 0 && read(f, buf, amt) != amt)
280: sizerr = 1;
281: (void) write(rem, buf, amt);
282: }
283: (void) close(f);
284: if (sizerr == 0)
285: ga();
286: else
287: error("rcp: %s: file changed size\n", name);
288: (void) response();
289: }
290: }
291:
292: #ifdef COMMENT
293: #include <sys/dir.h>
294: #endif COMMENT
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[RCPBUFSIZ];
304: char *bufv[1];
305:
306: if (d == 0) {
307: error("%s: %s\n", name, sys_errlist[errno]);
308: return;
309: }
310: last = strrchr(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) >= RCPBUFSIZ - 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[RCPBUFSIZ], *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[RCPBUFSIZ] && 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: return (0);
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[RCPBUFSIZ], nambuf[RCPBUFSIZ], buf[RCPBUFSIZ], *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 = strrchr(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 += RCPBUFSIZ) {
504: int amt = RCPBUFSIZ;
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 = RCPBUFSIZ;
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[RCPBUFSIZ], *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: return(0);
582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.