lint
[unix-history] / usr / src / bin / rcp / rcp.c
CommitLineData
22e155fc
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
b7ff3bb3 13#ifndef lint
0ed6b55e 14static char sccsid[] = "@(#)rcp.c 5.3 (Berkeley) %G%";
22e155fc 15#endif not lint
b7ff3bb3 16
4ca10280
SL
17/*
18 * rcp
19 */
ed0072ae 20#include <sys/param.h>
b7ff3bb3 21#include <sys/stat.h>
af86e024 22#include <sys/time.h>
b7ff3bb3 23#include <sys/ioctl.h>
94a2d2a7
SL
24
25#include <netinet/in.h>
26
27#include <stdio.h>
28#include <signal.h>
b7ff3bb3
BJ
29#include <pwd.h>
30#include <ctype.h>
92e58d95 31#include <netdb.h>
b7ff3bb3 32#include <errno.h>
4ca10280 33
b7ff3bb3
BJ
34int rem;
35char *colon(), *index(), *rindex(), *malloc(), *strcpy(), *sprintf();
36int errs;
37int lostconn();
b7ff3bb3
BJ
38int errno;
39char *sys_errlist[];
40int iamremote, targetshouldbedirectory;
41int iamrecursive;
af86e024 42int pflag;
b7ff3bb3
BJ
43struct passwd *pwd;
44struct passwd *getpwuid();
11bfe9c9
RC
45int userid;
46int port;
b7ff3bb3 47
371655cc
KM
48struct buffer {
49 int cnt;
50 char *buf;
51} *allocbuf();
52
b7ff3bb3
BJ
53/*VARARGS*/
54int error();
55
56#define ga() (void) write(rem, "", 1)
57
58main(argc, argv)
59 int argc;
60 char **argv;
61{
62 char *targ, *host, *src;
0ebcddfe
RC
63#ifndef NAMESERVER
64 char *suser, *tuser;
65#else NAMESERVER
9f526ab5 66 char *suser, *tuser, *thost;
0ebcddfe 67#endif NAMESERVER
b7ff3bb3
BJ
68 int i;
69 char buf[BUFSIZ], cmd[16];
11bfe9c9 70 struct servent *sp;
92e58d95
RC
71
72 sp = getservbyname("shell", "tcp");
73 if (sp == NULL) {
74 fprintf(stderr, "rcp: shell/tcp: unknown service\n");
75 exit(1);
76 }
11bfe9c9
RC
77 port = sp->s_port;
78 pwd = getpwuid(userid = getuid());
b7ff3bb3
BJ
79 if (pwd == 0) {
80 fprintf(stderr, "who are you?\n");
81 exit(1);
82 }
af86e024
JL
83
84 for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
85 (*argv)++;
86 while (**argv) switch (*(*argv)++) {
87
88 case 'r':
89 iamrecursive++;
90 break;
91
92 case 'p': /* preserve mtimes and atimes */
93 pflag++;
94 break;
95
96 /* The rest of these are not for users. */
97 case 'd':
98 targetshouldbedirectory = 1;
99 break;
100
101 case 'f': /* "from" */
102 iamremote = 1;
103 (void) response();
104 (void) setuid(userid);
105 source(--argc, ++argv);
106 exit(errs);
107
108 case 't': /* "to" */
109 iamremote = 1;
110 (void) setuid(userid);
111 sink(--argc, ++argv);
112 exit(errs);
113
114 default:
115 fprintf(stderr,
116 "Usage: rcp [-rp] f1 f2, or: rcp [-rp] f1 ... fn d2\n");
117 exit(1);
118 }
b7ff3bb3
BJ
119 }
120 rem = -1;
121 if (argc > 2)
122 targetshouldbedirectory = 1;
af86e024
JL
123 (void) sprintf(cmd, "rcp%s%s%s",
124 iamrecursive ? " -r" : "", pflag ? " -p" : "",
125 targetshouldbedirectory ? " -d" : "");
126 (void) signal(SIGPIPE, lostconn);
b7ff3bb3 127 targ = colon(argv[argc - 1]);
af86e024 128 if (targ) { /* ... to remote */
b7ff3bb3 129 *targ++ = 0;
06fb72f5
SL
130 if (*targ == 0)
131 targ = ".";
0ebcddfe
RC
132#ifndef NAMESERVER
133 tuser = rindex(argv[argc - 1], '.');
134 if (tuser) {
135 *tuser++ = 0;
136 if (!okname(tuser))
137 exit(1);
138 } else
139 tuser = pwd->pw_name;
140#else NAMESERVER
9f526ab5
RC
141 thost = index(argv[argc - 1], '@');
142 if (thost) {
143 *thost++ = 0;
144 tuser = argv[argc - 1];
145 if (*tuser == '\0')
146 tuser = pwd->pw_name;
147 else if (!okname(tuser))
b7ff3bb3 148 exit(1);
9f526ab5
RC
149 } else {
150 thost = argv[argc - 1];
b7ff3bb3 151 tuser = pwd->pw_name;
9f526ab5 152 }
0ebcddfe 153#endif NAMESERVER
b7ff3bb3
BJ
154 for (i = 0; i < argc - 1; i++) {
155 src = colon(argv[i]);
af86e024 156 if (src) { /* remote to remote */
b7ff3bb3 157 *src++ = 0;
06fb72f5 158 if (*src == 0)
195c1de2 159 src = ".";
0ebcddfe
RC
160#ifndef NAMESERVER
161 suser = rindex(argv[i], '.');
162 if (suser) {
163 *suser++ = 0;
164 if (!okname(suser))
165#else NAMESERVER
9f526ab5
RC
166 host = index(argv[i], '@');
167 if (host) {
168 *host++ = 0;
169 suser = argv[i];
170 if (*suser == '\0')
171 suser = pwd->pw_name;
172 else if (!okname(suser))
0ebcddfe 173#endif NAMESERVER
b7ff3bb3 174 continue;
0ebcddfe
RC
175#ifndef NAMESERVER
176 (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s.%s:%s'",
177 argv[i], suser, cmd, src,
178 argv[argc - 1], tuser, targ);
179 } else
180 (void) sprintf(buf, "rsh %s -n %s %s '%s.%s:%s'",
181 argv[i], cmd, src,
182 argv[argc - 1], tuser, targ);
183#else NAMESERVER
9f526ab5
RC
184 (void) sprintf(buf, "rsh %s -l %s -n %s %s '%s@%s:%s'",
185 host, suser, cmd, src,
186 tuser, thost, targ);
b7ff3bb3 187 } else
9f526ab5 188 (void) sprintf(buf, "rsh %s -n %s %s '%s@%s:%s'",
bd864c30 189 argv[i], cmd, src,
9f526ab5 190 tuser, thost, targ);
0ebcddfe 191#endif NAMESERVER
b7ff3bb3 192 (void) susystem(buf);
af86e024 193 } else { /* local to remote */
b7ff3bb3
BJ
194 if (rem == -1) {
195 (void) sprintf(buf, "%s -t %s",
196 cmd, targ);
0ebcddfe
RC
197#ifndef NAMESERVER
198 host = argv[argc - 1];
199#else NAMESERVER
9f526ab5 200 host = thost;
0ebcddfe 201#endif NAMESERVER
11bfe9c9 202 rem = rcmd(&host, port, pwd->pw_name, tuser,
b7ff3bb3
BJ
203 buf, 0);
204 if (rem < 0)
205 exit(1);
206 if (response() < 0)
207 exit(1);
11bfe9c9 208 (void) setuid(userid);
b7ff3bb3
BJ
209 }
210 source(1, argv+i);
211 }
212 }
af86e024 213 } else { /* ... to local */
b7ff3bb3
BJ
214 if (targetshouldbedirectory)
215 verifydir(argv[argc - 1]);
216 for (i = 0; i < argc - 1; i++) {
217 src = colon(argv[i]);
af86e024
JL
218 if (src == 0) { /* local to local */
219 (void) sprintf(buf, "/bin/cp%s%s %s %s",
b7ff3bb3 220 iamrecursive ? " -r" : "",
af86e024 221 pflag ? " -p" : "",
b7ff3bb3
BJ
222 argv[i], argv[argc - 1]);
223 (void) susystem(buf);
af86e024 224 } else { /* remote to local */
b7ff3bb3 225 *src++ = 0;
06fb72f5
SL
226 if (*src == 0)
227 src = ".";
0ebcddfe
RC
228#ifndef NAMESERVER
229 suser = rindex(argv[i], '.');
230 if (suser) {
231 *suser++ = 0;
232 if (!okname(suser))
233#else NAMESERVER
9f526ab5
RC
234 host = index(argv[i], '@');
235 if (host) {
236 *host++ = 0;
237 suser = argv[i];
238 if (*suser == '\0')
239 suser = pwd->pw_name;
240 else if (!okname(suser))
0ebcddfe 241#endif NAMESERVER
b7ff3bb3 242 continue;
0ebcddfe
RC
243#ifndef NAMESERVER
244 } else
245#else NAMESERVER
9f526ab5
RC
246 } else {
247 host = argv[i];
0ebcddfe 248#endif NAMESERVER
b7ff3bb3 249 suser = pwd->pw_name;
0ebcddfe 250#ifdef NAMESERVER
9f526ab5 251 }
0ebcddfe 252#endif NAMESERVER
b7ff3bb3 253 (void) sprintf(buf, "%s -f %s", cmd, src);
0ebcddfe
RC
254#ifndef NAMESERVER
255 host = argv[i];
256#endif NAMESERVER
11bfe9c9 257 rem = rcmd(&host, port, pwd->pw_name, suser,
b7ff3bb3
BJ
258 buf, 0);
259 if (rem < 0)
9f526ab5 260 continue;
11bfe9c9 261 (void) setreuid(0, userid);
b7ff3bb3 262 sink(1, argv+argc-1);
11bfe9c9 263 (void) setreuid(userid, 0);
b7ff3bb3
BJ
264 (void) close(rem);
265 rem = -1;
266 }
267 }
268 }
269 exit(errs);
270}
271
272verifydir(cp)
273 char *cp;
274{
275 struct stat stb;
276
11bfe9c9
RC
277 if (stat(cp, &stb) >= 0) {
278 if ((stb.st_mode & S_IFMT) == S_IFDIR)
279 return;
280 errno = ENOTDIR;
281 }
b7ff3bb3
BJ
282 error("rcp: %s: %s.\n", cp, sys_errlist[errno]);
283 exit(1);
284}
285
286char *
287colon(cp)
288 char *cp;
289{
290
291 while (*cp) {
292 if (*cp == ':')
293 return (cp);
294 if (*cp == '/')
295 return (0);
296 cp++;
297 }
298 return (0);
299}
300
301okname(cp0)
302 char *cp0;
303{
304 register char *cp = cp0;
305 register int c;
306
307 do {
308 c = *cp;
309 if (c & 0200)
310 goto bad;
311 if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
312 goto bad;
313 cp++;
314 } while (*cp);
315 return (1);
316bad:
317 fprintf(stderr, "rcp: invalid user name %s\n", cp0);
318 return (0);
319}
320
48755084
S
321susystem(s)
322 char *s;
b7ff3bb3 323{
48755084
S
324 int status, pid, w;
325 register int (*istat)(), (*qstat)();
b7ff3bb3 326
48755084 327 if ((pid = vfork()) == 0) {
af86e024 328 (void) setuid(userid);
48755084
S
329 execl("/bin/sh", "sh", "-c", s, (char *)0);
330 _exit(127);
331 }
332 istat = signal(SIGINT, SIG_IGN);
333 qstat = signal(SIGQUIT, SIG_IGN);
334 while ((w = wait(&status)) != pid && w != -1)
335 ;
336 if (w == -1)
337 status = -1;
af86e024
JL
338 (void) signal(SIGINT, istat);
339 (void) signal(SIGQUIT, qstat);
48755084 340 return (status);
b7ff3bb3
BJ
341}
342
343source(argc, argv)
344 int argc;
345 char **argv;
346{
347 char *last, *name;
348 struct stat stb;
371655cc
KM
349 static struct buffer buffer;
350 struct buffer *bp;
351 int x, sizerr, f, amt;
5f10dd79 352 off_t i;
371655cc 353 char buf[BUFSIZ];
b7ff3bb3
BJ
354
355 for (x = 0; x < argc; x++) {
356 name = argv[x];
11bfe9c9 357 if ((f = open(name, 0)) < 0) {
b7ff3bb3
BJ
358 error("rcp: %s: %s\n", name, sys_errlist[errno]);
359 continue;
360 }
361 if (fstat(f, &stb) < 0)
362 goto notreg;
363 switch (stb.st_mode&S_IFMT) {
364
365 case S_IFREG:
366 break;
367
368 case S_IFDIR:
369 if (iamrecursive) {
370 (void) close(f);
af86e024 371 rsource(name, &stb);
b7ff3bb3
BJ
372 continue;
373 }
374 /* fall into ... */
375 default:
376notreg:
377 (void) close(f);
378 error("rcp: %s: not a plain file\n", name);
379 continue;
380 }
381 last = rindex(name, '/');
382 if (last == 0)
383 last = name;
384 else
385 last++;
af86e024
JL
386 if (pflag) {
387 /*
388 * Make it compatible with possible future
389 * versions expecting microseconds.
390 */
391 (void) sprintf(buf, "T%ld 0 %ld 0\n",
392 stb.st_mtime, stb.st_atime);
393 (void) write(rem, buf, strlen(buf));
394 if (response() < 0) {
395 (void) close(f);
396 continue;
397 }
398 }
399 (void) sprintf(buf, "C%04o %ld %s\n",
b7ff3bb3
BJ
400 stb.st_mode&07777, stb.st_size, last);
401 (void) write(rem, buf, strlen(buf));
402 if (response() < 0) {
403 (void) close(f);
404 continue;
405 }
371655cc
KM
406 if ((bp = allocbuf(&buffer, f, BUFSIZ)) < 0) {
407 (void) close(f);
408 continue;
409 }
b7ff3bb3 410 sizerr = 0;
371655cc
KM
411 for (i = 0; i < stb.st_size; i += bp->cnt) {
412 amt = bp->cnt;
b7ff3bb3
BJ
413 if (i + amt > stb.st_size)
414 amt = stb.st_size - i;
371655cc 415 if (sizerr == 0 && read(f, bp->buf, amt) != amt)
b7ff3bb3 416 sizerr = 1;
371655cc 417 (void) write(rem, bp->buf, amt);
b7ff3bb3
BJ
418 }
419 (void) close(f);
420 if (sizerr == 0)
421 ga();
422 else
423 error("rcp: %s: file changed size\n", name);
424 (void) response();
425 }
426}
427
06fb72f5 428#include <sys/dir.h>
b7ff3bb3 429
af86e024 430rsource(name, statp)
b7ff3bb3 431 char *name;
af86e024 432 struct stat *statp;
b7ff3bb3
BJ
433{
434 DIR *d = opendir(name);
435 char *last;
436 struct direct *dp;
437 char buf[BUFSIZ];
438 char *bufv[1];
439
440 if (d == 0) {
11bfe9c9 441 error("rcp: %s: %s\n", name, sys_errlist[errno]);
b7ff3bb3
BJ
442 return;
443 }
444 last = rindex(name, '/');
445 if (last == 0)
446 last = name;
447 else
448 last++;
af86e024
JL
449 if (pflag) {
450 (void) sprintf(buf, "T%ld 0 %ld 0\n",
451 statp->st_mtime, statp->st_atime);
452 (void) write(rem, buf, strlen(buf));
453 if (response() < 0) {
454 closedir(d);
455 return;
456 }
457 }
458 (void) sprintf(buf, "D%04o %d %s\n", statp->st_mode&07777, 0, last);
b7ff3bb3
BJ
459 (void) write(rem, buf, strlen(buf));
460 if (response() < 0) {
461 closedir(d);
462 return;
463 }
464 while (dp = readdir(d)) {
465 if (dp->d_ino == 0)
466 continue;
467 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
468 continue;
469 if (strlen(name) + 1 + strlen(dp->d_name) >= BUFSIZ - 1) {
470 error("%s/%s: Name too long.\n", name, dp->d_name);
471 continue;
472 }
473 (void) sprintf(buf, "%s/%s", name, dp->d_name);
474 bufv[0] = buf;
475 source(1, bufv);
476 }
477 closedir(d);
478 (void) write(rem, "E\n", 2);
479 (void) response();
480}
481
482response()
483{
484 char resp, c, rbuf[BUFSIZ], *cp = rbuf;
485
486 if (read(rem, &resp, 1) != 1)
487 lostconn();
488 switch (resp) {
489
af86e024 490 case 0: /* ok */
b7ff3bb3
BJ
491 return (0);
492
493 default:
494 *cp++ = resp;
495 /* fall into... */
af86e024
JL
496 case 1: /* error, followed by err msg */
497 case 2: /* fatal error, "" */
b7ff3bb3
BJ
498 do {
499 if (read(rem, &c, 1) != 1)
500 lostconn();
501 *cp++ = c;
502 } while (cp < &rbuf[BUFSIZ] && c != '\n');
503 if (iamremote == 0)
504 (void) write(2, rbuf, cp - rbuf);
505 errs++;
506 if (resp == 1)
507 return (-1);
508 exit(1);
509 }
510 /*NOTREACHED*/
511}
512
513lostconn()
514{
515
516 if (iamremote == 0)
517 fprintf(stderr, "rcp: lost connection\n");
518 exit(1);
519}
520
521sink(argc, argv)
522 int argc;
523 char **argv;
524{
371655cc
KM
525 off_t i, j;
526 char *targ, *whopp, *cp;
527 int of, mode, wrerr, exists, first, count, amt, size;
528 struct buffer *bp;
529 static struct buffer buffer;
530 struct stat stb;
531 int targisdir = 0;
b7ff3bb3
BJ
532 int mask = umask(0);
533 char *myargv[1];
af86e024
JL
534 char cmdbuf[BUFSIZ], nambuf[BUFSIZ];
535 int setimes = 0;
536 struct timeval tv[2];
537#define atime tv[0]
538#define mtime tv[1]
371655cc 539#define SCREWUP(str) { whopp = str; goto screwup; }
b7ff3bb3 540
af86e024 541 (void) umask(mask);
11bfe9c9 542 if (argc != 1) {
b7ff3bb3
BJ
543 error("rcp: ambiguous target\n");
544 exit(1);
545 }
546 targ = *argv;
547 if (targetshouldbedirectory)
548 verifydir(targ);
549 ga();
550 if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
551 targisdir = 1;
4550ab9e 552 for (first = 1; ; first = 0) {
b7ff3bb3
BJ
553 cp = cmdbuf;
554 if (read(rem, cp, 1) <= 0)
555 return;
556 if (*cp++ == '\n')
557 SCREWUP("unexpected '\\n'");
558 do {
559 if (read(rem, cp, 1) != 1)
560 SCREWUP("lost connection");
561 } while (*cp++ != '\n');
562 *cp = 0;
563 if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
564 if (iamremote == 0)
06fb72f5 565 (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
b7ff3bb3
BJ
566 if (cmdbuf[0] == '\02')
567 exit(1);
568 errs++;
569 continue;
570 }
571 *--cp = 0;
572 cp = cmdbuf;
573 if (*cp == 'E') {
574 ga();
575 return;
576 }
af86e024
JL
577
578#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0');
579 if (*cp == 'T') {
580 setimes++;
581 cp++;
582 getnum(mtime.tv_sec);
583 if (*cp++ != ' ')
584 SCREWUP("mtime.sec not delimited");
585 getnum(mtime.tv_usec);
586 if (*cp++ != ' ')
587 SCREWUP("mtime.usec not delimited");
588 getnum(atime.tv_sec);
589 if (*cp++ != ' ')
590 SCREWUP("atime.sec not delimited");
591 getnum(atime.tv_usec);
592 if (*cp++ != '\0')
593 SCREWUP("atime.usec not delimited");
594 ga();
595 continue;
596 }
4550ab9e
RC
597 if (*cp != 'C' && *cp != 'D') {
598 /*
599 * Check for the case "rcp remote:foo\* local:bar".
600 * In this case, the line "No match." can be returned
601 * by the shell before the rcp command on the remote is
602 * executed so the ^Aerror_message convention isn't
603 * followed.
604 */
605 if (first) {
606 error("%s\n", cp);
607 exit(1);
608 }
b7ff3bb3 609 SCREWUP("expected control record");
4550ab9e 610 }
b7ff3bb3
BJ
611 cp++;
612 mode = 0;
613 for (; cp < cmdbuf+5; cp++) {
614 if (*cp < '0' || *cp > '7')
615 SCREWUP("bad mode");
616 mode = (mode << 3) | (*cp - '0');
617 }
618 if (*cp++ != ' ')
619 SCREWUP("mode not delimited");
620 size = 0;
621 while (*cp >= '0' && *cp <= '9')
622 size = size * 10 + (*cp++ - '0');
623 if (*cp++ != ' ')
624 SCREWUP("size not delimited");
625 if (targisdir)
626 (void) sprintf(nambuf, "%s%s%s", targ,
627 *targ ? "/" : "", cp);
628 else
629 (void) strcpy(nambuf, targ);
630 exists = stat(nambuf, &stb) == 0;
11bfe9c9
RC
631 if (cmdbuf[0] == 'D') {
632 if (exists) {
b7ff3bb3
BJ
633 if ((stb.st_mode&S_IFMT) != S_IFDIR) {
634 errno = ENOTDIR;
635 goto bad;
636 }
11bfe9c9 637 } else if (mkdir(nambuf, mode) < 0)
b7ff3bb3
BJ
638 goto bad;
639 myargv[0] = nambuf;
640 sink(1, myargv);
af86e024
JL
641 if (setimes) {
642 setimes = 0;
643 if (utimes(nambuf, tv) < 0)
644 error("rcp: can't set times on %s: %s\n",
645 nambuf, sys_errlist[errno]);
646 }
b7ff3bb3 647 continue;
11bfe9c9
RC
648 }
649 if ((of = creat(nambuf, mode)) < 0) {
b7ff3bb3 650 bad:
b7ff3bb3
BJ
651 error("rcp: %s: %s\n", nambuf, sys_errlist[errno]);
652 continue;
b7ff3bb3
BJ
653 }
654 ga();
371655cc 655 if ((bp = allocbuf(&buffer, of, BUFSIZ)) < 0) {
af86e024 656 (void) close(of);
371655cc
KM
657 continue;
658 }
659 cp = bp->buf;
660 count = 0;
b7ff3bb3
BJ
661 wrerr = 0;
662 for (i = 0; i < size; i += BUFSIZ) {
371655cc 663 amt = BUFSIZ;
b7ff3bb3
BJ
664 if (i + amt > size)
665 amt = size - i;
371655cc 666 count += amt;
b7ff3bb3 667 do {
371655cc 668 j = read(rem, cp, amt);
b7ff3bb3
BJ
669 if (j <= 0)
670 exit(1);
671 amt -= j;
672 cp += j;
673 } while (amt > 0);
371655cc
KM
674 if (count == bp->cnt) {
675 if (wrerr == 0 &&
676 write(of, bp->buf, count) != count)
677 wrerr++;
678 count = 0;
679 cp = bp->buf;
680 }
b7ff3bb3 681 }
371655cc
KM
682 if (count != 0 && wrerr == 0 &&
683 write(of, bp->buf, count) != count)
684 wrerr++;
b7ff3bb3
BJ
685 (void) close(of);
686 (void) response();
af86e024
JL
687 if (setimes) {
688 setimes = 0;
689 if (utimes(nambuf, tv) < 0)
690 error("rcp: can't set times on %s: %s\n",
691 nambuf, sys_errlist[errno]);
692 }
b7ff3bb3 693 if (wrerr)
af86e024 694 error("rcp: %s: %s\n", nambuf, sys_errlist[errno]);
b7ff3bb3
BJ
695 else
696 ga();
697 }
698screwup:
699 error("rcp: protocol screwup: %s\n", whopp);
700 exit(1);
701}
702
371655cc
KM
703struct buffer *
704allocbuf(bp, fd, blksize)
705 struct buffer *bp;
706 int fd, blksize;
707{
708 struct stat stb;
709 int size;
710
711 if (fstat(fd, &stb) < 0) {
712 error("rcp: fstat: %s\n", sys_errlist[errno]);
713 return ((struct buffer *)-1);
714 }
715 size = roundup(stb.st_blksize, blksize);
716 if (size == 0)
717 size = blksize;
718 if (bp->cnt < size) {
719 if (bp->buf != 0)
720 free(bp->buf);
af86e024 721 bp->buf = (char *)malloc((unsigned) size);
371655cc
KM
722 if (bp->buf == 0) {
723 error("rcp: malloc: out of memory\n");
724 return ((struct buffer *)-1);
725 }
726 }
727 bp->cnt = size;
728 return (bp);
729}
730
af86e024 731/*VARARGS1*/
b7ff3bb3
BJ
732error(fmt, a1, a2, a3, a4, a5)
733 char *fmt;
734 int a1, a2, a3, a4, a5;
735{
736 char buf[BUFSIZ], *cp = buf;
737
738 errs++;
739 *cp++ = 1;
740 (void) sprintf(cp, fmt, a1, a2, a3, a4, a5);
741 (void) write(rem, buf, strlen(buf));
742 if (iamremote == 0)
743 (void) write(2, buf+1, strlen(buf+1));
744}