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