1 /* 2 * Copyright (c) 1983, 1990, 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1983, 1990, 1992 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)rcp.c 5.35.1.1 (Berkeley) 12/02/92"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/stat.h> 20 #include <sys/time.h> 21 #include <sys/socket.h> 22 #include <netinet/in.h> 23 #include <netinet/in_systm.h> 24 #include <netinet/ip.h> 25 26 #include <ctype.h> 27 #include <dirent.h> 28 #include <errno.h> 29 #include <fcntl.h> 30 #include <netdb.h> 31 #include <pwd.h> 32 #include <signal.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include "pathnames.h" 40 #include "extern.h" 41 42 #ifdef KERBEROS 43 #include <kerberosIV/des.h> 44 #include <kerberosIV/krb.h> 45 46 char dst_realm_buf[REALM_SZ]; 47 char *dest_realm = NULL; 48 int use_kerberos = 1; 49 CREDENTIALS cred; 50 Key_schedule schedule; 51 extern char *krb_realmofhost(); 52 #define OPTIONS "dfKk:prt" 53 #else 54 #define OPTIONS "dfprt" 55 #endif 56 57 struct passwd *pwd; 58 u_short port; 59 uid_t userid; 60 int errs, rem; 61 int pflag, iamremote, iamrecursive, targetshouldbedirectory; 62 63 #define CMDNEEDS 64 64 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ 65 66 #ifdef KERBEROS 67 int kerberos __P((char **, char *, char *, char *)); 68 void oldw __P((const char *, ...)); 69 #endif 70 int response __P((void)); 71 void rsource __P((char *, struct stat *)); 72 void sink __P((int, char *[])); 73 void source __P((int, char *[])); 74 void tolocal __P((int, char *[])); 75 void toremote __P((char *, int, char *[])); 76 void usage __P((void)); 77 78 int 79 main(argc, argv) 80 int argc; 81 char *argv[]; 82 { 83 struct servent *sp; 84 int ch, fflag, tflag; 85 char *targ, *shell; 86 87 fflag = tflag = 0; 88 while ((ch = getopt(argc, argv, OPTIONS)) != EOF) 89 switch(ch) { /* User-visible flags. */ 90 case 'K': 91 #ifdef KERBEROS 92 use_kerberos = 0; 93 #endif 94 break; 95 #ifdef KERBEROS 96 case 'k': 97 dest_realm = dst_realm_buf; 98 (void)strncpy(dst_realm_buf, optarg, REALM_SZ); 99 break; 100 #endif 101 case 'p': 102 pflag = 1; 103 break; 104 case 'r': 105 iamrecursive = 1; 106 break; 107 /* Server options. */ 108 case 'd': 109 targetshouldbedirectory = 1; 110 break; 111 case 'f': /* "from" */ 112 iamremote = 1; 113 fflag = 1; 114 break; 115 case 't': /* "to" */ 116 iamremote = 1; 117 tflag = 1; 118 break; 119 case '?': 120 default: 121 usage(); 122 } 123 argc -= optind; 124 argv += optind; 125 126 #ifdef KERBEROS 127 if (use_kerberos) { 128 shell = "kshell"; 129 if ((sp = getservbyname(shell, "tcp")) == NULL) { 130 use_kerberos = 0; 131 oldw("can't get entry for %s/tcp service", shell); 132 sp = getservbyname(shell = "shell", "tcp"); 133 } 134 } else 135 sp = getservbyname(shell = "shell", "tcp"); 136 #else 137 sp = getservbyname(shell = "shell", "tcp"); 138 #endif 139 if (sp == NULL) { 140 (void)fprintf(stderr, "rcp: %s/tcp: unknown service\n", shell); 141 exit(1); 142 } 143 port = sp->s_port; 144 145 if ((pwd = getpwuid(userid = getuid())) == NULL) { 146 (void)fprintf(stderr, "rcp: unknown user %d.\n", (int)userid); 147 exit(1); 148 } 149 150 rem = STDIN_FILENO; /* XXX */ 151 152 if (fflag) { /* Follow "protocol", send data. */ 153 (void)response(); 154 (void)setuid(userid); 155 source(argc, argv); 156 exit(errs); 157 } 158 159 if (tflag) { /* Receive data. */ 160 (void)setuid(userid); 161 sink(argc, argv); 162 exit(errs); 163 } 164 165 if (argc < 2) 166 usage(); 167 if (argc > 2) 168 targetshouldbedirectory = 1; 169 170 rem = -1; 171 /* Command to be executed on remote system using "rsh". */ 172 #ifdef KERBEROS 173 (void)snprintf(cmd, sizeof(cmd), 174 "rcp%s%s%s%s", iamrecursive ? " -r" : "", 175 "", 176 pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); 177 #else 178 (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s", 179 iamrecursive ? " -r" : "", pflag ? " -p" : "", 180 targetshouldbedirectory ? " -d" : ""); 181 #endif 182 183 (void)signal(SIGPIPE, lostconn); 184 185 if (targ = colon(argv[argc - 1])) /* Dest is remote host. */ 186 toremote(targ, argc, argv); 187 else { 188 tolocal(argc, argv); /* Dest is local host. */ 189 if (targetshouldbedirectory) 190 verifydir(argv[argc - 1]); 191 } 192 exit(errs); 193 } 194 195 void 196 toremote(targ, argc, argv) 197 char *targ, *argv[]; 198 int argc; 199 { 200 int i, len, tos; 201 char *bp, *host, *src, *suser, *thost, *tuser; 202 203 *targ++ = 0; 204 if (*targ == 0) 205 targ = "."; 206 207 if (thost = index(argv[argc - 1], '@')) { 208 /* user@host */ 209 *thost++ = 0; 210 tuser = argv[argc - 1]; 211 if (*tuser == '\0') 212 tuser = NULL; 213 else if (!okname(tuser)) 214 exit(1); 215 } else { 216 thost = argv[argc - 1]; 217 tuser = NULL; 218 } 219 220 for (i = 0; i < argc - 1; i++) { 221 src = colon(argv[i]); 222 if (src) { /* remote to remote */ 223 *src++ = 0; 224 if (*src == 0) 225 src = "."; 226 host = index(argv[i], '@'); 227 len = strlen(_PATH_RSH) + strlen(argv[i]) + 228 strlen(src) + (tuser ? strlen(tuser) : 0) + 229 strlen(thost) + strlen(targ) + CMDNEEDS + 20; 230 if (!(bp = malloc(len))) 231 nospace(); 232 if (host) { 233 *host++ = 0; 234 suser = argv[i]; 235 if (*suser == '\0') 236 suser = pwd->pw_name; 237 else if (!okname(suser)) 238 continue; 239 (void)snprintf(bp, len, 240 "%s %s -l %s -n %s %s '%s%s%s:%s'", 241 _PATH_RSH, host, suser, cmd, src, 242 tuser ? tuser : "", tuser ? "@" : "", 243 thost, targ); 244 } else 245 (void)snprintf(bp, len, 246 "%s %s -n %s %s '%s%s%s:%s'", 247 _PATH_RSH, argv[i], cmd, src, 248 tuser ? tuser : "", tuser ? "@" : "", 249 thost, targ); 250 (void)susystem(bp, userid); 251 (void)free(bp); 252 } else { /* local to remote */ 253 if (rem == -1) { 254 len = strlen(targ) + CMDNEEDS + 20; 255 if (!(bp = malloc(len))) 256 nospace(); 257 (void)snprintf(bp, len, "%s -t %s", cmd, targ); 258 host = thost; 259 #ifdef KERBEROS 260 if (use_kerberos) 261 rem = kerberos(&host, bp, 262 pwd->pw_name, 263 tuser ? tuser : pwd->pw_name); 264 else 265 #endif 266 rem = rcmd(&host, port, pwd->pw_name, 267 tuser ? tuser : pwd->pw_name, 268 bp, 0); 269 if (rem < 0) 270 exit(1); 271 tos = IPTOS_THROUGHPUT; 272 if (setsockopt(rem, IPPROTO_IP, IP_TOS, 273 &tos, sizeof(int)) < 0) 274 (void)fprintf(stderr, 275 "rcp: TOS (ignored): %s\n", 276 strerror(errno)); 277 if (response() < 0) 278 exit(1); 279 (void)free(bp); 280 (void)setuid(userid); 281 } 282 source(1, argv+i); 283 } 284 } 285 } 286 287 void 288 tolocal(argc, argv) 289 int argc; 290 char *argv[]; 291 { 292 int i, len, tos; 293 char *bp, *host, *src, *suser; 294 295 for (i = 0; i < argc - 1; i++) { 296 if (!(src = colon(argv[i]))) { /* Local to local. */ 297 len = strlen(_PATH_CP) + strlen(argv[i]) + 298 strlen(argv[argc - 1]) + 20; 299 if (!(bp = malloc(len))) 300 nospace(); 301 (void)snprintf(bp, len, "%s%s%s %s %s", _PATH_CP, 302 iamrecursive ? " -r" : "", pflag ? " -p" : "", 303 argv[i], argv[argc - 1]); 304 if (susystem(bp, userid)) 305 ++errs; 306 (void)free(bp); 307 continue; 308 } 309 *src++ = 0; 310 if (*src == 0) 311 src = "."; 312 if ((host = index(argv[i], '@')) == NULL) { 313 host = argv[i]; 314 suser = pwd->pw_name; 315 } else { 316 *host++ = 0; 317 suser = argv[i]; 318 if (*suser == '\0') 319 suser = pwd->pw_name; 320 else if (!okname(suser)) 321 continue; 322 } 323 len = strlen(src) + CMDNEEDS + 20; 324 if ((bp = malloc(len)) == NULL) 325 nospace(); 326 (void)snprintf(bp, len, "%s -f %s", cmd, src); 327 rem = 328 #ifdef KERBEROS 329 use_kerberos ? 330 kerberos(&host, bp, pwd->pw_name, suser) : 331 #endif 332 rcmd(&host, port, pwd->pw_name, suser, bp, 0); 333 (void)free(bp); 334 if (rem < 0) { 335 ++errs; 336 continue; 337 } 338 (void)seteuid(userid); 339 tos = IPTOS_THROUGHPUT; 340 if (setsockopt(rem, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) 341 (void)fprintf(stderr, "rcp: TOS (ignored): %s\n", 342 strerror(errno)); 343 sink(1, argv + argc - 1); 344 (void)seteuid(0); 345 (void)close(rem); 346 rem = -1; 347 } 348 } 349 350 void 351 source(argc, argv) 352 int argc; 353 char *argv[]; 354 { 355 struct stat stb; 356 static BUF buffer; 357 BUF *bp; 358 off_t i; 359 int amt, fd, haderr, indx, result; 360 char *last, *name, buf[BUFSIZ]; 361 362 for (indx = 0; indx < argc; ++indx) { 363 name = argv[indx]; 364 if ((fd = open(name, O_RDONLY, 0)) < 0) 365 goto syserr; 366 if (fstat(fd, &stb)) { 367 syserr: err("%s: %s", name, strerror(errno)); 368 goto next; 369 } 370 switch (stb.st_mode & S_IFMT) { 371 case S_IFREG: 372 break; 373 case S_IFDIR: 374 if (iamrecursive) { 375 rsource(name, &stb); 376 goto next; 377 } 378 /* FALLTHROUGH */ 379 default: 380 err("%s: not a regular file", name); 381 goto next; 382 } 383 if ((last = rindex(name, '/')) == NULL) 384 last = name; 385 else 386 ++last; 387 if (pflag) { 388 /* 389 * Make it compatible with possible future 390 * versions expecting microseconds. 391 */ 392 (void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n", 393 stb.st_mtimespec.ts_sec, stb.st_atimespec.ts_sec); 394 (void)write(rem, buf, strlen(buf)); 395 if (response() < 0) 396 goto next; 397 } 398 #define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) 399 (void)snprintf(buf, sizeof(buf), "C%04o %qd %s\n", 400 stb.st_mode & MODEMASK, stb.st_size, last); 401 (void)write(rem, buf, strlen(buf)); 402 if (response() < 0) 403 goto next; 404 if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) { 405 next: (void)close(fd); 406 continue; 407 } 408 409 /* Keep writing after an error so that we stay sync'd up. */ 410 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 411 amt = bp->cnt; 412 if (i + amt > stb.st_size) 413 amt = stb.st_size - i; 414 if (!haderr) { 415 result = read(fd, bp->buf, amt); 416 if (result != amt) 417 haderr = result >= 0 ? EIO : errno; 418 } 419 if (haderr) 420 (void)write(rem, bp->buf, amt); 421 else { 422 result = write(rem, bp->buf, amt); 423 if (result != amt) 424 haderr = result >= 0 ? EIO : errno; 425 } 426 } 427 if (close(fd) && !haderr) 428 haderr = errno; 429 if (!haderr) 430 (void)write(rem, "", 1); 431 else 432 err("%s: %s", name, strerror(haderr)); 433 (void)response(); 434 } 435 } 436 437 void 438 rsource(name, statp) 439 char *name; 440 struct stat *statp; 441 { 442 DIR *dirp; 443 struct dirent *dp; 444 char *last, *vect[1], path[MAXPATHLEN]; 445 446 if (!(dirp = opendir(name))) { 447 err("%s: %s", name, strerror(errno)); 448 return; 449 } 450 last = rindex(name, '/'); 451 if (last == 0) 452 last = name; 453 else 454 last++; 455 if (pflag) { 456 (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", 457 statp->st_mtimespec.ts_sec, statp->st_atimespec.ts_sec); 458 (void)write(rem, path, strlen(path)); 459 if (response() < 0) { 460 closedir(dirp); 461 return; 462 } 463 } 464 (void)snprintf(path, sizeof(path), 465 "D%04o %d %s\n", statp->st_mode & MODEMASK, 0, last); 466 (void)write(rem, path, strlen(path)); 467 if (response() < 0) { 468 closedir(dirp); 469 return; 470 } 471 while (dp = readdir(dirp)) { 472 if (dp->d_ino == 0) 473 continue; 474 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) 475 continue; 476 if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) { 477 err("%s/%s: name too long", name, dp->d_name); 478 continue; 479 } 480 (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name); 481 vect[0] = path; 482 source(1, vect); 483 } 484 (void)closedir(dirp); 485 (void)write(rem, "E\n", 2); 486 (void)response(); 487 } 488 489 void 490 sink(argc, argv) 491 int argc; 492 char *argv[]; 493 { 494 static BUF buffer; 495 register char *cp; 496 struct stat stb; 497 struct timeval tv[2]; 498 enum { YES, NO, DISPLAYED } wrerr; 499 BUF *bp; 500 off_t i, j; 501 int amt, count, exists, first, mask, mode, ofd, omode; 502 int setimes, size, targisdir, wrerrno; 503 char ch, *np, *targ, *why, *vect[1], buf[BUFSIZ]; 504 505 #define atime tv[0] 506 #define mtime tv[1] 507 #define SCREWUP(str) { why = str; goto screwup; } 508 509 setimes = targisdir = 0; 510 mask = umask(0); 511 if (!pflag) 512 (void)umask(mask); 513 if (argc != 1) { 514 err("ambiguous target"); 515 exit(1); 516 } 517 targ = *argv; 518 if (targetshouldbedirectory) 519 verifydir(targ); 520 (void)write(rem, "", 1); 521 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) 522 targisdir = 1; 523 for (first = 1;; first = 0) { 524 cp = buf; 525 if (read(rem, cp, 1) <= 0) 526 return; 527 if (*cp++ == '\n') 528 SCREWUP("unexpected <newline>"); 529 do { 530 if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) 531 SCREWUP("lost connection"); 532 *cp++ = ch; 533 } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); 534 *cp = 0; 535 536 if (buf[0] == '\01' || buf[0] == '\02') { 537 if (iamremote == 0) 538 (void)write(STDERR_FILENO, 539 buf + 1, strlen(buf + 1)); 540 if (buf[0] == '\02') 541 exit(1); 542 ++errs; 543 continue; 544 } 545 if (buf[0] == 'E') { 546 (void)write(rem, "", 1); 547 return; 548 } 549 550 if (ch == '\n') 551 *--cp = 0; 552 553 #define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); 554 cp = buf; 555 if (*cp == 'T') { 556 setimes++; 557 cp++; 558 getnum(mtime.tv_sec); 559 if (*cp++ != ' ') 560 SCREWUP("mtime.sec not delimited"); 561 getnum(mtime.tv_usec); 562 if (*cp++ != ' ') 563 SCREWUP("mtime.usec not delimited"); 564 getnum(atime.tv_sec); 565 if (*cp++ != ' ') 566 SCREWUP("atime.sec not delimited"); 567 getnum(atime.tv_usec); 568 if (*cp++ != '\0') 569 SCREWUP("atime.usec not delimited"); 570 (void)write(rem, "", 1); 571 continue; 572 } 573 if (*cp != 'C' && *cp != 'D') { 574 /* 575 * Check for the case "rcp remote:foo\* local:bar". 576 * In this case, the line "No match." can be returned 577 * by the shell before the rcp command on the remote is 578 * executed so the ^Aerror_message convention isn't 579 * followed. 580 */ 581 if (first) { 582 err("%s", cp); 583 exit(1); 584 } 585 SCREWUP("expected control record"); 586 } 587 mode = 0; 588 for (++cp; cp < buf + 5; cp++) { 589 if (*cp < '0' || *cp > '7') 590 SCREWUP("bad mode"); 591 mode = (mode << 3) | (*cp - '0'); 592 } 593 if (*cp++ != ' ') 594 SCREWUP("mode not delimited"); 595 596 for (size = 0; isdigit(*cp);) 597 size = size * 10 + (*cp++ - '0'); 598 if (*cp++ != ' ') 599 SCREWUP("size not delimited"); 600 if (targisdir) { 601 static char *namebuf; 602 static int cursize; 603 size_t need; 604 605 need = strlen(targ) + strlen(cp) + 250; 606 if (need > cursize) { 607 if (!(namebuf = malloc(need))) 608 err("%s", strerror(errno)); 609 } 610 (void)snprintf(namebuf, need, "%s%s%s", targ, 611 *targ ? "/" : "", cp); 612 np = namebuf; 613 } else 614 np = targ; 615 exists = stat(np, &stb) == 0; 616 if (buf[0] == 'D') { 617 int mod_flag = pflag; 618 if (exists) { 619 if (!S_ISDIR(stb.st_mode)) { 620 errno = ENOTDIR; 621 goto bad; 622 } 623 if (pflag) 624 (void)chmod(np, mode); 625 } else { 626 /* Handle copying from a read-only directory */ 627 mod_flag = 1; 628 if (mkdir(np, mode | S_IRWXU) < 0) 629 goto bad; 630 } 631 vect[0] = np; 632 sink(1, vect); 633 if (setimes) { 634 setimes = 0; 635 if (utimes(np, tv) < 0) 636 err("can't set times on %s: %s", 637 np, strerror(errno)); 638 } 639 if (mod_flag) 640 (void)chmod(np, mode); 641 continue; 642 } 643 omode = mode; 644 mode |= S_IWRITE; 645 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { 646 bad: err("%s: %s", np, strerror(errno)); 647 continue; 648 } 649 (void)write(rem, "", 1); 650 if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) { 651 (void)close(ofd); 652 continue; 653 } 654 cp = bp->buf; 655 wrerr = NO; 656 for (count = i = 0; i < size; i += BUFSIZ) { 657 amt = BUFSIZ; 658 if (i + amt > size) 659 amt = size - i; 660 count += amt; 661 do { 662 j = read(rem, cp, amt); 663 if (j <= 0) { 664 err("%s", j ? strerror(errno) : 665 "dropped connection"); 666 exit(1); 667 } 668 amt -= j; 669 cp += j; 670 } while (amt > 0); 671 if (count == bp->cnt) { 672 /* Keep reading so we stay sync'd up. */ 673 if (wrerr == NO) { 674 j = write(ofd, bp->buf, count); 675 if (j != count) { 676 wrerr = YES; 677 wrerrno = j >= 0 ? EIO : errno; 678 } 679 } 680 count = 0; 681 cp = bp->buf; 682 } 683 } 684 if (count != 0 && wrerr == NO && 685 (j = write(ofd, bp->buf, count)) != count) { 686 wrerr = YES; 687 wrerrno = j >= 0 ? EIO : errno; 688 } 689 if (ftruncate(ofd, size)) { 690 err("can't truncate %s: %s", np, strerror(errno)); 691 wrerr = DISPLAYED; 692 } 693 if (pflag) { 694 if (exists || omode != mode) 695 (void)fchmod(ofd, omode); 696 } else { 697 if (!exists && omode != mode) 698 (void)fchmod(ofd, omode & ~mask); 699 } 700 (void)close(ofd); 701 (void)response(); 702 if (setimes && wrerr == NO) { 703 setimes = 0; 704 if (utimes(np, tv) < 0) { 705 err("can't set times on %s: %s", 706 np, strerror(errno)); 707 wrerr = DISPLAYED; 708 } 709 } 710 switch(wrerr) { 711 case YES: 712 err("%s: %s", np, strerror(wrerrno)); 713 break; 714 case NO: 715 (void)write(rem, "", 1); 716 break; 717 case DISPLAYED: 718 break; 719 } 720 } 721 screwup: 722 err("protocol error: %s", why); 723 exit(1); 724 } 725 726 #ifdef KERBEROS 727 int 728 kerberos(host, bp, locuser, user) 729 char **host, *bp, *locuser, *user; 730 { 731 struct servent *sp; 732 733 again: 734 if (use_kerberos) { 735 rem = KSUCCESS; 736 errno = 0; 737 if (dest_realm == NULL) 738 dest_realm = krb_realmofhost(*host); 739 rem = 740 krcmd(host, port, user, bp, 0, dest_realm); 741 742 if (rem < 0) { 743 use_kerberos = 0; 744 if ((sp = getservbyname("shell", "tcp")) == NULL) { 745 (void)fprintf(stderr, 746 "rcp: unknown service shell/tcp\n"); 747 exit(1); 748 } 749 if (errno == ECONNREFUSED) 750 oldw("remote host doesn't support Kerberos"); 751 else if (errno == ENOENT) 752 oldw("can't provide Kerberos authentication data"); 753 port = sp->s_port; 754 goto again; 755 } 756 } else { 757 rem = rcmd(host, port, locuser, user, bp, 0); 758 } 759 return (rem); 760 } 761 #endif /* KERBEROS */ 762 763 int 764 response() 765 { 766 register char *cp; 767 char ch, resp, rbuf[BUFSIZ]; 768 769 if (read(rem, &resp, sizeof(resp)) != sizeof(resp)) 770 lostconn(0); 771 772 cp = rbuf; 773 switch(resp) { 774 case 0: /* ok */ 775 return (0); 776 default: 777 *cp++ = resp; 778 /* FALLTHROUGH */ 779 case 1: /* error, followed by error msg */ 780 case 2: /* fatal error, "" */ 781 do { 782 if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) 783 lostconn(0); 784 *cp++ = ch; 785 } while (cp < &rbuf[BUFSIZ] && ch != '\n'); 786 787 if (!iamremote) 788 (void)write(STDERR_FILENO, rbuf, cp - rbuf); 789 ++errs; 790 if (resp == 1) 791 return (-1); 792 exit(1); 793 } 794 /* NOTREACHED */ 795 } 796 797 void 798 usage() 799 { 800 #ifdef KERBEROS 801 (void)fprintf(stderr, "%s\n\t%s\n", 802 "usage: rcp [-Kp] [-k realm] f1 f2", 803 "or: rcp [-Kpr] [-k realm] f1 ... fn directory"); 804 #else 805 (void)fprintf(stderr, 806 "usage: rcp [-p] f1 f2; or: rcp [-pr] f1 ... fn directory\n"); 807 #endif 808 exit(1); 809 } 810 811 #if __STDC__ 812 #include <stdarg.h> 813 #else 814 #include <varargs.h> 815 #endif 816 817 #ifdef KERBEROS 818 void 819 #if __STDC__ 820 oldw(const char *fmt, ...) 821 #else 822 oldw(fmt, va_alist) 823 char *fmt; 824 va_dcl 825 #endif 826 { 827 va_list ap; 828 #if __STDC__ 829 va_start(ap, fmt); 830 #else 831 va_start(ap); 832 #endif 833 (void)fprintf(stderr, "rcp: "); 834 (void)vfprintf(stderr, fmt, ap); 835 (void)fprintf(stderr, ", using standard rcp\n"); 836 va_end(ap); 837 } 838 #endif 839 840 void 841 #if __STDC__ 842 err(const char *fmt, ...) 843 #else 844 err(fmt, va_alist) 845 char *fmt; 846 va_dcl 847 #endif 848 { 849 static FILE *fp; 850 va_list ap; 851 #if __STDC__ 852 va_start(ap, fmt); 853 #else 854 va_start(ap); 855 #endif 856 857 ++errs; 858 if (!fp && !(fp = fdopen(rem, "w"))) 859 return; 860 (void)fprintf(fp, "%c", 0x01); 861 (void)fprintf(fp, "rcp: "); 862 (void)vfprintf(fp, fmt, ap); 863 (void)fprintf(fp, "\n"); 864 if (!iamremote) { 865 (void)fprintf(stderr, "rcp: "); 866 (void)vfprintf(stderr, fmt, ap); 867 (void)fprintf(stderr, "\n"); 868 } 869 va_end(ap); 870 (void)fflush(fp); 871 } 872