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