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