00001
00002
00003
00004
00005
00006
00007 #ifndef lint
00008 char copyright[] =
00009 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
00010 All rights reserved.\n";
00011 #endif
00012
00013 #ifndef lint
00014 static char sccsid[] = "@(#)rcp.c 1.1 87/12/21 SMI";
00015 #endif
00016
00017
00018
00019
00020
00021 #undef _MINIX
00022 #define NAMESERVER
00023
00024 #include <ctype.h>
00025 #include <errno.h>
00026 #include <stdarg.h>
00027 #include <stdio.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <time.h>
00031 #include <utime.h>
00032
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <sys/wait.h>
00036
00037 #include <dirent.h>
00038 #include <fcntl.h>
00039 #include <pwd.h>
00040 #include <signal.h>
00041 #include <unistd.h>
00042
00043 #include <net/gen/netdb.h>
00044 #include <net/netlib.h>
00045
00046 #if __STDC__
00047 #define PROTO(func, args) func args
00048 #else
00049 #define PROTO(func, args) func ()
00050 #endif
00051
00052 PROTO (int main, (int argc, char *argv[]));
00053 PROTO (void lostconn, (int sig));
00054 PROTO (void error, (char *fmt, ...) );
00055 PROTO (int response, (void) );
00056 PROTO (void source, (int argc, char *argv[]) );
00057 PROTO (void sink, (int argc, char *argv[]) );
00058 PROTO (void usage, (void) );
00059 PROTO (char *colon, (char *cp) );
00060 PROTO (int okname, (char *cp0) );
00061 PROTO (int susystem, (char *s) );
00062 PROTO (void verifydir, (char *cp) );
00063 PROTO (void rsource, (char *name, struct stat *statp) );
00064 PROTO (struct buffer *allocbuf, (struct buffer *bp, int fd, int blksize) );
00065
00066 #define vfork fork
00067
00068 int rem;
00069 int errs;
00070 int errno;
00071 int iamremote, targetshouldbedirectory;
00072 int iamrecursive;
00073 int myuid;
00074 int pflag;
00075 struct passwd *pwd;
00076 int userid;
00077 int port;
00078
00079 struct buffer {
00080 int cnt;
00081 char *buf;
00082 };
00083
00084
00085 #define ga() (void) write(rem, "", 1)
00086
00087 main(argc, argv)
00088 int argc;
00089 char **argv;
00090 {
00091 char *targ, *host, *src;
00092 #ifndef NAMESERVER
00093 char *suser, *tuser;
00094 #else
00095 char *suser, *tuser, *thost;
00096 #endif
00097 int i;
00098 char buf[BUFSIZ], cmd[16];
00099 struct servent *sp;
00100
00101 sp = getservbyname("shell", "tcp");
00102 if (sp == NULL) {
00103 fprintf(stderr, "rcp: shell/tcp: unknown service\n");
00104 exit(1);
00105 }
00106 port = sp->s_port;
00107 pwd = getpwuid(userid = getuid());
00108 if (pwd == 0) {
00109 fprintf(stderr, "who are you?\n");
00110 exit(1);
00111 }
00112
00113 #ifdef NOT_DEF
00114
00115
00116
00117
00118
00119 myuid = getuid();
00120 if (setruid(0) < 0) {
00121 perror("setruid root");
00122 exit(1);
00123 }
00124 seteuid(myuid);
00125 #endif
00126
00127 for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
00128 (*argv)++;
00129 while (**argv) switch (*(*argv)++) {
00130
00131 case 'r':
00132 iamrecursive++;
00133 break;
00134
00135 case 'p':
00136 pflag++;
00137 break;
00138
00139
00140 case 'd':
00141 targetshouldbedirectory = 1;
00142 break;
00143
00144 case 'f':
00145 iamremote = 1;
00146 (void) response();
00147 source(--argc, ++argv);
00148 exit(errs);
00149
00150 case 't':
00151 iamremote = 1;
00152 sink(--argc, ++argv);
00153 exit(errs);
00154
00155 default:
00156 usage();
00157 exit(1);
00158 }
00159 }
00160 if (iamremote)
00161 {
00162 close(2);
00163 open("/dev/tty", 2);
00164 }
00165
00166 if (argc < 2) {
00167 usage();
00168 exit(1);
00169 }
00170 rem = -1;
00171 if (argc > 2)
00172 targetshouldbedirectory = 1;
00173 (void) sprintf(cmd, "rcp%s%s%s",
00174 iamrecursive ? " -r" : "", pflag ? " -p" : "",
00175 targetshouldbedirectory ? " -d" : "");
00176 (void) signal(SIGPIPE, lostconn);
00177 targ = colon(argv[argc - 1]);
00178 if (targ) {
00179 *targ++ = 0;
00180 if (*targ == 0)
00181 targ = ".";
00182 #ifndef NAMESERVER
00183 tuser = strrchr(argv[argc - 1], '.');
00184 if (tuser) {
00185 *tuser++ = 0;
00186 if (!okname(tuser))
00187 exit(1);
00188 } else
00189 tuser = pwd->pw_name;
00190 #else
00191 thost = strchr(argv[argc - 1], '@');
00192 if (thost) {
00193 *thost++ = 0;
00194 tuser = argv[argc - 1];
00195 if (*tuser == '\0')
00196 tuser = pwd->pw_name;
00197 else if (!okname(tuser))
00198 exit(1);
00199 } else {
00200 thost = argv[argc - 1];
00201 tuser = pwd->pw_name;
00202 }
00203 #endif
00204 for (i = 0; i < argc - 1; i++) {
00205 src = colon(argv[i]);
00206 if (src) {
00207 *src++ = 0;
00208 if (*src == 0)
00209 src = ".";
00210 #ifndef NAMESERVER
00211 suser = strrchr(argv[i], '.');
00212 if (suser) {
00213 *suser++ = 0;
00214 if (!okname(suser))
00215 #else
00216 host = strchr(argv[i], '@');
00217 if (host) {
00218 *host++ = 0;
00219 suser = argv[i];
00220 if (*suser == '\0')
00221 suser = pwd->pw_name;
00222 else if (!okname(suser))
00223 #endif
00224 continue;
00225 #ifndef NAMESERVER
00226 (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'",
00227 argv[i], suser, cmd, src,
00228 argv[argc - 1], tuser, targ);
00229 } else
00230 (void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'",
00231 argv[i], cmd, src,
00232 argv[argc - 1], tuser, targ);
00233 #else
00234 (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s@%s:%s'",
00235 host, suser, cmd, src,
00236 tuser, thost, targ);
00237 } else
00238 (void) sprintf(buf, "rsh %s -n %s %s '%s@%s:%s'",
00239 argv[i], cmd, src,
00240 tuser, thost, targ);
00241 #endif
00242 (void) susystem(buf);
00243 } else {
00244 if (rem == -1) {
00245 (void) sprintf(buf, "%s -t %s",
00246 cmd, targ);
00247 #ifndef NAMESERVER
00248 host = argv[argc - 1];
00249 #else
00250 host = thost;
00251 #endif
00252 #ifdef NOT_DEF
00253 if (seteuid(0) < 0) {
00254 perror("seteuid root");
00255 exit(1);
00256 }
00257 #endif
00258 rem = rcmd(&host, port, pwd->pw_name,
00259 tuser, buf, 0);
00260 #ifdef NO_DEF
00261 seteuid(myuid);
00262 #endif
00263 if (rem < 0)
00264 exit(1);
00265 if (response() < 0)
00266 exit(1);
00267 }
00268 source(1, argv+i);
00269 }
00270 }
00271 } else {
00272 if (targetshouldbedirectory)
00273 verifydir(argv[argc - 1]);
00274 for (i = 0; i < argc - 1; i++) {
00275 src = colon(argv[i]);
00276 if (src == 0) {
00277 (void) sprintf(buf, "cp%s%s %s %s",
00278 iamrecursive ? " -r" : "",
00279 pflag ? " -p" : "",
00280 argv[i], argv[argc - 1]);
00281 (void) susystem(buf);
00282 } else {
00283 *src++ = 0;
00284 if (*src == 0)
00285 src = ".";
00286 #ifndef NAMESERVER
00287 suser = strrchr(argv[i], '.');
00288 if (suser) {
00289 *suser++ = 0;
00290 if (!okname(suser))
00291 #else
00292 host = strchr(argv[i], '@');
00293 if (host) {
00294 *host++ = 0;
00295 suser = argv[i];
00296 if (*suser == '\0')
00297 suser = pwd->pw_name;
00298 else if (!okname(suser))
00299 #endif
00300 continue;
00301 #ifndef NAMESERVER
00302 } else
00303 #else
00304 } else {
00305 host = argv[i];
00306 #endif
00307 suser = pwd->pw_name;
00308 #ifdef NAMESERVER
00309 }
00310 #endif
00311 (void) sprintf(buf, "%s -f %s", cmd, src);
00312 #ifndef NAMESERVER
00313 host = argv[i];
00314 #endif
00315 #ifdef NOT_DEF
00316 if (seteuid(0) < 0) {
00317 perror("seteuid root");
00318 exit(1);
00319 }
00320 #endif
00321 rem = rcmd(&host, port, pwd->pw_name, suser,
00322 buf, 0);
00323 #ifdef NOT_DEF
00324 seteuid(myuid);
00325 #endif
00326 if (rem < 0) {
00327 errs++;
00328 continue;
00329 }
00330 sink(1, argv+argc-1);
00331 (void) close(rem);
00332 rem = -1;
00333 }
00334 }
00335 }
00336 exit(errs);
00337 }
00338
00339 void
00340 verifydir(cp)
00341 char *cp;
00342 {
00343 struct stat stb;
00344
00345 if (stat(cp, &stb) >= 0) {
00346 if ((stb.st_mode & S_IFMT) == S_IFDIR)
00347 return;
00348 errno = ENOTDIR;
00349 }
00350 error("rcp: %s: %s.\n", cp, strerror(errno));
00351 exit(1);
00352 }
00353
00354 char *
00355 colon(cp)
00356 char *cp;
00357 {
00358
00359 while (*cp) {
00360 if (*cp == ':')
00361 return (cp);
00362 if (*cp == '/')
00363 return (0);
00364 cp++;
00365 }
00366 return (0);
00367 }
00368
00369
00370 int
00371 okname(cp0)
00372 char *cp0;
00373 {
00374 register char *cp = cp0;
00375 register int c;
00376
00377 do {
00378 c = *cp;
00379 if (c & 0200)
00380 goto bad;
00381 if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
00382 goto bad;
00383 cp++;
00384 } while (*cp);
00385 return (1);
00386 bad:
00387 fprintf(stderr, "rcp: invalid user name %s\n", cp0);
00388 return (0);
00389 }
00390
00391 int
00392 susystem(s)
00393 char *s;
00394 {
00395 int status, pid, w;
00396 register void PROTO ((*istat), (int) ), PROTO ((*qstat), (int) );
00397
00398 if ((pid = vfork()) == 0) {
00399 #ifdef NOT_DEF
00400 (void) setruid(myuid);
00401 #endif
00402 execl("/bin/sh", "sh", "-c", s, (char *)0);
00403 _exit(127);
00404 }
00405 istat = signal(SIGINT, SIG_IGN);
00406 qstat = signal(SIGQUIT, SIG_IGN);
00407 while ((w = wait(&status)) != pid && w != -1)
00408 ;
00409 if (w == -1)
00410 status = -1;
00411 (void) signal(SIGINT, istat);
00412 (void) signal(SIGQUIT, qstat);
00413 return (status);
00414 }
00415
00416 void
00417 source(argc, argv)
00418 int argc;
00419 char **argv;
00420 {
00421 char *last, *name;
00422 struct stat stb;
00423 static struct buffer buffer;
00424 struct buffer *bp;
00425 int x, sizerr, f, amt;
00426 off_t i;
00427 char buf[BUFSIZ];
00428
00429 for (x = 0; x < argc; x++) {
00430 name = argv[x];
00431 if ((f = open(name, 0)) < 0) {
00432 error("rcp: %s: %s\n", name, strerror(errno));
00433 continue;
00434 }
00435 if (fstat(f, &stb) < 0)
00436 goto notreg;
00437 switch (stb.st_mode&S_IFMT) {
00438
00439 case S_IFREG:
00440 break;
00441
00442 case S_IFDIR:
00443 if (iamrecursive) {
00444 (void) close(f);
00445 rsource(name, &stb);
00446 continue;
00447 }
00448
00449 default:
00450 notreg:
00451 (void) close(f);
00452 error("rcp: %s: not a plain file\n", name);
00453 continue;
00454 }
00455 last = strrchr(name, '/');
00456 if (last == 0)
00457 last = name;
00458 else
00459 last++;
00460 if (pflag) {
00461
00462
00463
00464
00465 (void) sprintf(buf, "T%ld 0 %ld 0\n",
00466 stb.st_mtime, stb.st_atime);
00467 (void) write(rem, buf, strlen(buf));
00468 if (response() < 0) {
00469 (void) close(f);
00470 continue;
00471 }
00472 }
00473 (void) sprintf(buf, "C%04o %ld %s\n",
00474 stb.st_mode&07777, stb.st_size, last);
00475 (void) write(rem, buf, strlen(buf));
00476 if (response() < 0) {
00477 (void) close(f);
00478 continue;
00479 }
00480 if ((bp = allocbuf(&buffer, f, BUFSIZ)) == 0) {
00481 (void) close(f);
00482 continue;
00483 }
00484 sizerr = 0;
00485 for (i = 0; i < stb.st_size; i += bp->cnt) {
00486 amt = bp->cnt;
00487 if (i + amt > stb.st_size)
00488 amt = stb.st_size - i;
00489 if (sizerr == 0 && read(f, bp->buf, amt) != amt)
00490 sizerr = 1;
00491 (void) write(rem, bp->buf, amt);
00492 }
00493 (void) close(f);
00494 if (sizerr == 0)
00495 ga();
00496 else
00497 error("rcp: %s: file changed size\n", name);
00498 (void) response();
00499 }
00500 }
00501
00502
00503 void
00504 rsource(name, statp)
00505 char *name;
00506 struct stat *statp;
00507 {
00508 DIR *d = opendir(name);
00509 char *last;
00510 struct dirent *dp;
00511 char buf[BUFSIZ];
00512 char *bufv[1];
00513
00514 if (d == 0) {
00515 error("rcp: %s: %s\n", name, strerror(errno));
00516 return;
00517 }
00518 last = strrchr(name, '/');
00519 if (last == 0)
00520 last = name;
00521 else
00522 last++;
00523 if (pflag) {
00524 (void) sprintf(buf, "T%ld 0 %ld 0\n",
00525 statp->st_mtime, statp->st_atime);
00526 (void) write(rem, buf, strlen(buf));
00527 if (response() < 0) {
00528 closedir(d);
00529 return;
00530 }
00531 }
00532 (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
00533 (void) write(rem, buf, strlen(buf));
00534 if (response() < 0) {
00535 closedir(d);
00536 return;
00537 }
00538 while (dp = readdir(d)) {
00539 if (dp->d_ino == 0)
00540 continue;
00541 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
00542 continue;
00543 if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
00544 error("%s/%s: Name too long.\n", name, dp->d_name);
00545 continue;
00546 }
00547 (void) sprintf(buf, "%s/%s", name, dp->d_name);
00548 bufv[0] = buf;
00549 source(1, bufv);
00550 }
00551 closedir(d);
00552 (void) write(rem, "E\n", 2);
00553 (void) response();
00554 }
00555
00556 int
00557 response()
00558 {
00559 char resp, c, rbuf[BUFSIZ], *cp = rbuf;
00560
00561 if (read(rem, &resp, 1) != 1)
00562 lostconn(0);
00563 switch (resp) {
00564
00565 case 0:
00566 return (0);
00567
00568 default:
00569 *cp++ = resp;
00570
00571 case 1:
00572 case 2:
00573 do {
00574 if (read(rem, &c, 1) != 1)
00575 lostconn(0);
00576 *cp++ = c;
00577 } while (cp < &rbuf[BUFSIZ] && c != '\n');
00578 if (iamremote == 0)
00579 (void) write(2, rbuf, cp - rbuf);
00580 errs++;
00581 if (resp == 1)
00582 return (-1);
00583 exit(1);
00584 }
00585
00586 }
00587
00588 void
00589 lostconn(sig)
00590 int sig;
00591 {
00592
00593 if (iamremote == 0)
00594 fprintf(stderr, "rcp: lost connection\n");
00595 exit(1);
00596 }
00597
00598 void
00599 sink(argc, argv)
00600 int argc;
00601 char **argv;
00602 {
00603 off_t i, j, size;
00604 char *targ, *whopp, *cp;
00605 int of, mode, wrerr, exists, first, count, amt;
00606 struct buffer *bp;
00607 static struct buffer buffer;
00608 struct stat stb;
00609 int targisdir = 0;
00610 int mask = umask(0);
00611 char *myargv[1];
00612 char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
00613 int setimes = 0;
00614 struct utimbuf utimbuf;
00615 #define atime utimbuf.actime
00616 #define mtime utimbuf.modtime
00617 time_t dummy;
00618 #define SCREWUP(str) { whopp = str; goto screwup; }
00619
00620 #ifdef NOT_DEF
00621 seteuid(pwd->pw_uid);
00622 #endif
00623 if (!pflag)
00624 (void) umask(mask);
00625 if (argc != 1) {
00626 error("rcp: ambiguous target\n");
00627 exit(1);
00628 }
00629 targ = *argv;
00630 if (targetshouldbedirectory)
00631 verifydir(targ);
00632 ga();
00633 if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
00634 targisdir = 1;
00635 for (first = 1; ; first = 0) {
00636 cp = cmdbuf;
00637 if (read(rem, cp, 1) <= 0)
00638 return;
00639 if (*cp++ == '\n')
00640 SCREWUP("unexpected '\\n'");
00641 do {
00642 if (read(rem, cp, 1) != 1)
00643 SCREWUP("lost connection");
00644 } while (*cp++ != '\n');
00645 *cp = 0;
00646 if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
00647 if (iamremote == 0)
00648 (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
00649 if (cmdbuf[0] == '\02')
00650 exit(1);
00651 errs++;
00652 continue;
00653 }
00654 *--cp = 0;
00655 cp = cmdbuf;
00656 if (*cp == 'E') {
00657 ga();
00658 return;
00659 }
00660
00661 #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
00662 if (*cp == 'T') {
00663 setimes++;
00664 cp++;
00665 getnum(mtime);
00666 if (*cp++ != ' ')
00667 SCREWUP("mtime.sec not delimited");
00668 getnum(dummy);
00669 if (*cp++ != ' ')
00670 SCREWUP("mtime.usec not delimited");
00671 getnum(atime);
00672 if (*cp++ != ' ')
00673 SCREWUP("atime.sec not delimited");
00674 getnum(dummy);
00675 if (*cp++ != '\0')
00676 SCREWUP("atime.usec not delimited");
00677 ga();
00678 continue;
00679 }
00680 if (*cp != 'C' && *cp != 'D') {
00681
00682
00683
00684
00685
00686
00687
00688 if (first) {
00689 error("%s\n", cp);
00690 exit(1);
00691 }
00692 SCREWUP("expected control record");
00693 }
00694 cp++;
00695 mode = 0;
00696 for (; cp < cmdbuf+5; cp++) {
00697 if (*cp < '0' || *cp > '7')
00698 SCREWUP("bad mode");
00699 mode = (mode << 3) | (*cp - '0');
00700 }
00701 if (*cp++ != ' ')
00702 SCREWUP("mode not delimited");
00703 size = 0;
00704 while (isdigit(*cp))
00705 size = size * 10 + (*cp++ - '0');
00706 if (*cp++ != ' ')
00707 SCREWUP("size not delimited");
00708 if (targisdir)
00709 (void) sprintf(nambuf, "%s%s%s", targ,
00710 *targ ? "/" : "", cp);
00711 else
00712 (void) strcpy(nambuf, targ);
00713 exists = stat(nambuf, &stb) == 0;
00714 if (cmdbuf[0] == 'D') {
00715 if (exists) {
00716 if ((stb.st_mode&S_IFMT) != S_IFDIR) {
00717 errno = ENOTDIR;
00718 goto bad;
00719 }
00720 if (pflag)
00721 (void) chmod(nambuf, mode);
00722 } else if (mkdir(nambuf, mode) < 0)
00723 goto bad;
00724 myargv[0] = nambuf;
00725 sink(1, myargv);
00726 if (setimes) {
00727 setimes = 0;
00728 if (utime(nambuf, &utimbuf) < 0)
00729 error("rcp: can't set times on %s: %s\n",
00730 nambuf, strerror(errno));
00731 }
00732 continue;
00733 }
00734 if ((of = creat(nambuf, mode)) < 0) {
00735 bad:
00736 error("rcp: %s: %s\n", nambuf, strerror(errno));
00737 continue;
00738 }
00739 if (exists && pflag)
00740 (void) chmod(nambuf, mode);
00741 ga();
00742 if ((bp = allocbuf(&buffer, of, BUFSIZ)) == 0) {
00743 (void) close(of);
00744 continue;
00745 }
00746 cp = bp->buf;
00747 count = 0;
00748 wrerr = 0;
00749 for (i = 0; i < size; i += BUFSIZ) {
00750 amt = BUFSIZ;
00751 if (i + amt > size)
00752 amt = size - i;
00753 count += amt;
00754 do {
00755 j = read(rem, cp, amt);
00756 if (j <= 0)
00757 exit(1);
00758 amt -= j;
00759 cp += j;
00760 } while (amt > 0);
00761 if (count == bp->cnt) {
00762 if (wrerr == 0 &&
00763 write(of, bp->buf, count) != count)
00764 wrerr++;
00765 count = 0;
00766 cp = bp->buf;
00767 }
00768 }
00769 if (count != 0 && wrerr == 0 &&
00770 write(of, bp->buf, count) != count)
00771 wrerr++;
00772 (void) close(of);
00773 (void) response();
00774 if (setimes) {
00775 setimes = 0;
00776 if (utime(nambuf, &utimbuf) < 0)
00777 error("rcp: can't set times on %s: %s\n",
00778 nambuf, strerror(errno));
00779 }
00780 if (wrerr)
00781 error("rcp: %s: %s\n", nambuf, strerror(errno));
00782 else
00783 ga();
00784 }
00785 screwup:
00786 error("rcp: protocol screwup: %s\n", whopp);
00787 exit(1);
00788 }
00789
00790 struct buffer *
00791 allocbuf(bp, fd, blksize)
00792 struct buffer *bp;
00793 int fd, blksize;
00794 {
00795 struct stat stb;
00796 int size;
00797
00798 if (fstat(fd, &stb) < 0) {
00799 error("rcp: fstat: %s\n", strerror(errno));
00800 return ((struct buffer *)0);
00801 }
00802 size= 0;
00803 #if NOT_DEF
00804 size = roundup(stb.st_blksize, blksize);
00805 #endif
00806 if (size == 0)
00807 size = blksize;
00808 if (bp->cnt < size) {
00809 if (bp->buf != 0)
00810 free(bp->buf);
00811 bp->buf = (char *)malloc((unsigned) size);
00812 if (bp->buf == 0) {
00813 error("rcp: malloc: out of memory\n");
00814 return ((struct buffer *)0);
00815 }
00816 }
00817 bp->cnt = size;
00818 return (bp);
00819 }
00820
00821
00822 #if __STDC__
00823 void
00824 error (char *fmt, ...)
00825 #else
00826 error(fmt)
00827 char *fmt;
00828 #endif
00829 {
00830 char buf[BUFSIZ], *cp = buf;
00831 va_list ap;
00832
00833 va_start(ap, fmt);
00834
00835 errs++;
00836 *cp++ = 1;
00837 (void) vsprintf(cp, fmt, ap);
00838 va_end(ap);
00839 (void) write(rem, buf, strlen(buf));
00840 if (iamremote == 0)
00841 (void) write(2, buf+1, strlen(buf+1));
00842 }
00843
00844 void
00845 usage()
00846 {
00847 fprintf(stderr, "Usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n");
00848 }