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