scp.c revision 1.24 1 /* $NetBSD: scp.c,v 1.24 2019/10/12 18:32:22 christos Exp $ */
2 /* $OpenBSD: scp.c,v 1.206 2019/09/09 02:31:19 dtucker Exp $ */
3 /*
4 * scp - secure remote copy. This is basically patched BSD rcp which
5 * uses ssh to do the data transfer (instead of using rcmd).
6 *
7 * NOTE: This version should NOT be suid root. (This uses ssh to
8 * do the transfer and ssh has the necessary privileges.)
9 *
10 * 1995 Timo Rinne <tri (at) iki.fi>, Tatu Ylonen <ylo (at) cs.hut.fi>
11 *
12 * As far as I am concerned, the code I have written for this software
13 * can be used freely for any purpose. Any derived versions of this
14 * software must be clearly marked as such, and if the derived work is
15 * incompatible with the protocol description in the RFC file, it must be
16 * called by a name other than "ssh" or "Secure Shell".
17 */
18 /*
19 * Copyright (c) 1999 Theo de Raadt. All rights reserved.
20 * Copyright (c) 1999 Aaron Campbell. All rights reserved.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the above copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
33 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
34 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
35 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
40 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 /*
44 * Parts from:
45 *
46 * Copyright (c) 1983, 1990, 1992, 1993, 1995
47 * The Regents of the University of California. All rights reserved.
48 *
49 * Redistribution and use in source and binary forms, with or without
50 * modification, are permitted provided that the following conditions
51 * are met:
52 * 1. Redistributions of source code must retain the above copyright
53 * notice, this list of conditions and the following disclaimer.
54 * 2. Redistributions in binary form must reproduce the above copyright
55 * notice, this list of conditions and the following disclaimer in the
56 * documentation and/or other materials provided with the distribution.
57 * 3. Neither the name of the University nor the names of its contributors
58 * may be used to endorse or promote products derived from this software
59 * without specific prior written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 * SUCH DAMAGE.
72 *
73 */
74
75 #include "includes.h"
76 __RCSID("$NetBSD: scp.c,v 1.24 2019/10/12 18:32:22 christos Exp $");
77
78 #include <sys/param.h> /* roundup MAX */
79 #include <sys/types.h>
80 #include <sys/poll.h>
81 #include <sys/wait.h>
82 #include <sys/stat.h>
83 #include <sys/time.h>
84 #include <sys/uio.h>
85
86 #include <ctype.h>
87 #include <dirent.h>
88 #include <errno.h>
89 #include <fcntl.h>
90 #include <fnmatch.h>
91 #include <locale.h>
92 #include <pwd.h>
93 #include <signal.h>
94 #include <stdarg.h>
95 #include <stdint.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <time.h>
100 #include <unistd.h>
101 #include <limits.h>
102 #include <vis.h>
103
104 #include "xmalloc.h"
105 #include "ssh.h"
106 #include "atomicio.h"
107 #include "pathnames.h"
108 #include "log.h"
109 #include "misc.h"
110 #include "progressmeter.h"
111 #include "utf8.h"
112
113 #define COPY_BUFLEN 16384
114
115 int do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout);
116 int do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout);
117
118 static char empty[] = "";
119
120 /* Struct for addargs */
121 arglist args;
122 arglist remote_remote_args;
123
124 /* Bandwidth limit */
125 long long limit_kbps = 0;
126 struct bwlimit bwlimit;
127
128 /* Name of current file being transferred. */
129 char *curfile;
130
131 /* This is set to non-zero to enable verbose mode. */
132 int verbose_mode = 0;
133
134 /* This is set to zero if the progressmeter is not desired. */
135 int showprogress = 1;
136
137 /*
138 * This is set to non-zero if remote-remote copy should be piped
139 * through this process.
140 */
141 int throughlocal = 0;
142
143 /* Non-standard port to use for the ssh connection or -1. */
144 int sshport = -1;
145
146 /* This is the program to execute for the secured connection. ("ssh" or -S) */
147 #ifdef RESCUEDIR
148 const char *ssh_program = RESCUEDIR "/ssh";
149 #else
150 const char *ssh_program = _PATH_SSH_PROGRAM;
151 #endif
152
153 /* This is used to store the pid of ssh_program */
154 pid_t do_cmd_pid = -1;
155
156 __dead static void
157 killchild(int signo)
158 {
159 if (do_cmd_pid > 1) {
160 kill(do_cmd_pid, signo ? signo : SIGTERM);
161 waitpid(do_cmd_pid, NULL, 0);
162 }
163
164 if (signo)
165 _exit(1);
166 exit(1);
167 }
168
169 static void
170 suspchild(int signo)
171 {
172 int status;
173
174 if (do_cmd_pid > 1) {
175 kill(do_cmd_pid, signo);
176 while (waitpid(do_cmd_pid, &status, WUNTRACED) == -1 &&
177 errno == EINTR)
178 ;
179 kill(getpid(), SIGSTOP);
180 }
181 }
182
183 static int
184 do_local_cmd(arglist *a)
185 {
186 u_int i;
187 int status;
188 pid_t pid;
189
190 if (a->num == 0)
191 fatal("do_local_cmd: no arguments");
192
193 if (verbose_mode) {
194 fprintf(stderr, "Executing:");
195 for (i = 0; i < a->num; i++)
196 fmprintf(stderr, " %s", a->list[i]);
197 fprintf(stderr, "\n");
198 }
199 if ((pid = fork()) == -1)
200 fatal("do_local_cmd: fork: %s", strerror(errno));
201
202 if (pid == 0) {
203 execvp(a->list[0], a->list);
204 perror(a->list[0]);
205 exit(1);
206 }
207
208 do_cmd_pid = pid;
209 signal(SIGTERM, killchild);
210 signal(SIGINT, killchild);
211 signal(SIGHUP, killchild);
212
213 while (waitpid(pid, &status, 0) == -1)
214 if (errno != EINTR)
215 fatal("do_local_cmd: waitpid: %s", strerror(errno));
216
217 do_cmd_pid = -1;
218
219 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
220 return (-1);
221
222 return (0);
223 }
224
225 /*
226 * This function executes the given command as the specified user on the
227 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This
228 * assigns the input and output file descriptors on success.
229 */
230
231 int
232 do_cmd(char *host, char *remuser, int port, char *cmd, int *fdin, int *fdout)
233 {
234 int pin[2], pout[2], reserved[2];
235
236 if (verbose_mode)
237 fmprintf(stderr,
238 "Executing: program %s host %s, user %s, command %s\n",
239 ssh_program, host,
240 remuser ? remuser : "(unspecified)", cmd);
241
242 if (port == -1)
243 port = sshport;
244
245 /*
246 * Reserve two descriptors so that the real pipes won't get
247 * descriptors 0 and 1 because that will screw up dup2 below.
248 */
249 if (pipe(reserved) == -1)
250 fatal("pipe: %s", strerror(errno));
251
252 /* Create a socket pair for communicating with ssh. */
253 if (pipe(pin) == -1)
254 fatal("pipe: %s", strerror(errno));
255 if (pipe(pout) == -1)
256 fatal("pipe: %s", strerror(errno));
257
258 /* Free the reserved descriptors. */
259 close(reserved[0]);
260 close(reserved[1]);
261
262 signal(SIGTSTP, suspchild);
263 signal(SIGTTIN, suspchild);
264 signal(SIGTTOU, suspchild);
265
266 /* Fork a child to execute the command on the remote host using ssh. */
267 do_cmd_pid = fork();
268 if (do_cmd_pid == 0) {
269 /* Child. */
270 close(pin[1]);
271 close(pout[0]);
272 dup2(pin[0], 0);
273 dup2(pout[1], 1);
274 close(pin[0]);
275 close(pout[1]);
276
277 replacearg(&args, 0, "%s", ssh_program);
278 if (port != -1) {
279 addargs(&args, "-p");
280 addargs(&args, "%d", port);
281 }
282 if (remuser != NULL) {
283 addargs(&args, "-l");
284 addargs(&args, "%s", remuser);
285 }
286 addargs(&args, "--");
287 addargs(&args, "%s", host);
288 addargs(&args, "%s", cmd);
289
290 execvp(ssh_program, args.list);
291 perror(ssh_program);
292 exit(1);
293 } else if (do_cmd_pid == -1) {
294 fatal("fork: %s", strerror(errno));
295 }
296 /* Parent. Close the other side, and return the local side. */
297 close(pin[0]);
298 *fdout = pin[1];
299 close(pout[1]);
300 *fdin = pout[0];
301 signal(SIGTERM, killchild);
302 signal(SIGINT, killchild);
303 signal(SIGHUP, killchild);
304 return 0;
305 }
306
307 /*
308 * This function executes a command similar to do_cmd(), but expects the
309 * input and output descriptors to be setup by a previous call to do_cmd().
310 * This way the input and output of two commands can be connected.
311 */
312 int
313 do_cmd2(char *host, char *remuser, int port, char *cmd, int fdin, int fdout)
314 {
315 pid_t pid;
316 int status;
317
318 if (verbose_mode)
319 fmprintf(stderr,
320 "Executing: 2nd program %s host %s, user %s, command %s\n",
321 ssh_program, host,
322 remuser ? remuser : "(unspecified)", cmd);
323
324 if (port == -1)
325 port = sshport;
326
327 /* Fork a child to execute the command on the remote host using ssh. */
328 pid = fork();
329 if (pid == 0) {
330 dup2(fdin, 0);
331 dup2(fdout, 1);
332
333 replacearg(&args, 0, "%s", ssh_program);
334 if (port != -1) {
335 addargs(&args, "-p");
336 addargs(&args, "%d", port);
337 }
338 if (remuser != NULL) {
339 addargs(&args, "-l");
340 addargs(&args, "%s", remuser);
341 }
342 addargs(&args, "--");
343 addargs(&args, "%s", host);
344 addargs(&args, "%s", cmd);
345
346 execvp(ssh_program, args.list);
347 perror(ssh_program);
348 exit(1);
349 } else if (pid == -1) {
350 fatal("fork: %s", strerror(errno));
351 }
352 while (waitpid(pid, &status, 0) == -1)
353 if (errno != EINTR)
354 fatal("do_cmd2: waitpid: %s", strerror(errno));
355 return 0;
356 }
357
358 typedef struct {
359 size_t cnt;
360 char *buf;
361 } BUF;
362
363 BUF *allocbuf(BUF *, int, int);
364 __dead static void lostconn(int);
365 int okname(char *);
366 void run_err(const char *,...) __printflike(1, 2);
367 void verifydir(char *);
368
369 struct passwd *pwd;
370 uid_t userid;
371 int errs, remin, remout;
372 int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
373
374 #define CMDNEEDS 64
375 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
376
377 int response(void);
378 void rsource(char *, struct stat *);
379 void sink(int, char *[], const char *);
380 void source(int, char *[]);
381 static void tolocal(int, char *[]);
382 static void toremote(int, char *[]);
383 __dead static void usage(void);
384
385 int
386 main(int argc, char **argv)
387 {
388 int ch, fflag, tflag, status, n;
389 char **newargv;
390 const char *errstr;
391 extern char *optarg;
392 extern int optind;
393
394 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
395 sanitise_stdfd();
396
397 setlocale(LC_CTYPE, "");
398
399 /* Copy argv, because we modify it */
400 newargv = xcalloc(MAXIMUM(argc + 1, 1), sizeof(*newargv));
401 for (n = 0; n < argc; n++)
402 newargv[n] = xstrdup(argv[n]);
403 argv = newargv;
404
405 memset(&args, '\0', sizeof(args));
406 memset(&remote_remote_args, '\0', sizeof(remote_remote_args));
407 args.list = remote_remote_args.list = NULL;
408 addargs(&args, "%s", ssh_program);
409 addargs(&args, "-x");
410 addargs(&args, "-oForwardAgent=no");
411 addargs(&args, "-oPermitLocalCommand=no");
412 addargs(&args, "-oClearAllForwardings=yes");
413 addargs(&args, "-oRemoteCommand=none");
414 addargs(&args, "-oRequestTTY=no");
415
416 fflag = Tflag = tflag = 0;
417 while ((ch = getopt(argc, argv,
418 "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) {
419 switch (ch) {
420 /* User-visible flags. */
421 case '1':
422 fatal("SSH protocol v.1 is no longer supported");
423 break;
424 case '2':
425 /* Ignored */
426 break;
427 case '4':
428 case '6':
429 case 'C':
430 addargs(&args, "-%c", ch);
431 addargs(&remote_remote_args, "-%c", ch);
432 break;
433 case '3':
434 throughlocal = 1;
435 break;
436 case 'o':
437 case 'c':
438 case 'i':
439 case 'F':
440 case 'J':
441 addargs(&remote_remote_args, "-%c", ch);
442 addargs(&remote_remote_args, "%s", optarg);
443 addargs(&args, "-%c", ch);
444 addargs(&args, "%s", optarg);
445 break;
446 case 'P':
447 sshport = a2port(optarg);
448 if (sshport <= 0)
449 fatal("bad port \"%s\"\n", optarg);
450 break;
451 case 'B':
452 addargs(&remote_remote_args, "-oBatchmode=yes");
453 addargs(&args, "-oBatchmode=yes");
454 break;
455 case 'l':
456 limit_kbps = strtonum(optarg, 1, 100 * 1024 * 1024,
457 &errstr);
458 if (errstr != NULL)
459 usage();
460 limit_kbps *= 1024; /* kbps */
461 bandwidth_limit_init(&bwlimit, limit_kbps, COPY_BUFLEN);
462 break;
463 case 'p':
464 pflag = 1;
465 break;
466 case 'r':
467 iamrecursive = 1;
468 break;
469 case 'S':
470 ssh_program = xstrdup(optarg);
471 break;
472 case 'v':
473 addargs(&args, "-v");
474 addargs(&remote_remote_args, "-v");
475 verbose_mode = 1;
476 break;
477 case 'q':
478 addargs(&args, "-q");
479 addargs(&remote_remote_args, "-q");
480 showprogress = 0;
481 break;
482
483 /* Server options. */
484 case 'd':
485 targetshouldbedirectory = 1;
486 break;
487 case 'f': /* "from" */
488 iamremote = 1;
489 fflag = 1;
490 break;
491 case 't': /* "to" */
492 iamremote = 1;
493 tflag = 1;
494 break;
495 case 'T':
496 Tflag = 1;
497 break;
498 default:
499 usage();
500 }
501 }
502 argc -= optind;
503 argv += optind;
504
505 if ((pwd = getpwuid(userid = getuid())) == NULL)
506 fatal("unknown user %u", (u_int) userid);
507
508 if (!isatty(STDOUT_FILENO))
509 showprogress = 0;
510
511 if (pflag) {
512 /* Cannot pledge: -p allows setuid/setgid files... */
513 } else {
514 #ifdef __OpenBSD__
515 if (pledge("stdio rpath wpath cpath fattr tty proc exec",
516 NULL) == -1) {
517 perror("pledge");
518 exit(1);
519 }
520 #endif
521 }
522
523 remin = STDIN_FILENO;
524 remout = STDOUT_FILENO;
525
526 if (fflag) {
527 /* Follow "protocol", send data. */
528 (void) response();
529 source(argc, argv);
530 exit(errs != 0);
531 }
532 if (tflag) {
533 /* Receive data. */
534 sink(argc, argv, NULL);
535 exit(errs != 0);
536 }
537 if (argc < 2)
538 usage();
539 if (argc > 2)
540 targetshouldbedirectory = 1;
541
542 remin = remout = -1;
543 do_cmd_pid = -1;
544 /* Command to be executed on remote system using "ssh". */
545 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s",
546 verbose_mode ? " -v" : "",
547 iamrecursive ? " -r" : "", pflag ? " -p" : "",
548 targetshouldbedirectory ? " -d" : "");
549
550 (void) signal(SIGPIPE, lostconn);
551
552 if (colon(argv[argc - 1])) /* Dest is remote host. */
553 toremote(argc, argv);
554 else {
555 if (targetshouldbedirectory)
556 verifydir(argv[argc - 1]);
557 tolocal(argc, argv); /* Dest is local host. */
558 }
559 /*
560 * Finally check the exit status of the ssh process, if one was forked
561 * and no error has occurred yet
562 */
563 if (do_cmd_pid != -1 && errs == 0) {
564 if (remin != -1)
565 (void) close(remin);
566 if (remout != -1)
567 (void) close(remout);
568 if (waitpid(do_cmd_pid, &status, 0) == -1)
569 errs = 1;
570 else {
571 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
572 errs = 1;
573 }
574 }
575 exit(errs != 0);
576 }
577
578 /* Callback from atomicio6 to update progress meter and limit bandwidth */
579 static int
580 scpio(void *_cnt, size_t s)
581 {
582 off_t *cnt = (off_t *)_cnt;
583
584 *cnt += s;
585 refresh_progress_meter(0);
586 if (limit_kbps > 0)
587 bandwidth_limit(&bwlimit, s);
588 return 0;
589 }
590
591 static int
592 do_times(int fd, int verb, const struct stat *sb)
593 {
594 /* strlen(2^64) == 20; strlen(10^6) == 7 */
595 char buf[(20 + 7 + 2) * 2 + 2];
596
597 (void)snprintf(buf, sizeof(buf), "T%llu 0 %llu 0\n",
598 (unsigned long long) (sb->st_mtime < 0 ? 0 : sb->st_mtime),
599 (unsigned long long) (sb->st_atime < 0 ? 0 : sb->st_atime));
600 if (verb) {
601 fprintf(stderr, "File mtime %lld atime %lld\n",
602 (long long)sb->st_mtime, (long long)sb->st_atime);
603 fprintf(stderr, "Sending file timestamps: %s", buf);
604 }
605 (void) atomicio(vwrite, fd, buf, strlen(buf));
606 return (response());
607 }
608
609 static int
610 parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
611 const char **pathp)
612 {
613 int r;
614
615 r = parse_uri("scp", uri, userp, hostp, portp, pathp);
616 if (r == 0 && *pathp == NULL)
617 *pathp = xstrdup(".");
618 return r;
619 }
620
621 /* Appends a string to an array; returns 0 on success, -1 on alloc failure */
622 static int
623 append(char *cp, char ***ap, size_t *np)
624 {
625 char **tmp;
626
627 if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
628 return -1;
629 tmp[(*np)] = cp;
630 (*np)++;
631 *ap = tmp;
632 return 0;
633 }
634
635 /*
636 * Finds the start and end of the first brace pair in the pattern.
637 * returns 0 on success or -1 for invalid patterns.
638 */
639 static int
640 find_brace(const char *pattern, int *startp, int *endp)
641 {
642 int i;
643 int in_bracket, brace_level;
644
645 *startp = *endp = -1;
646 in_bracket = brace_level = 0;
647 for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
648 switch (pattern[i]) {
649 case '\\':
650 /* skip next character */
651 if (pattern[i + 1] != '\0')
652 i++;
653 break;
654 case '[':
655 in_bracket = 1;
656 break;
657 case ']':
658 in_bracket = 0;
659 break;
660 case '{':
661 if (in_bracket)
662 break;
663 if (pattern[i + 1] == '}') {
664 /* Protect a single {}, for find(1), like csh */
665 i++; /* skip */
666 break;
667 }
668 if (*startp == -1)
669 *startp = i;
670 brace_level++;
671 break;
672 case '}':
673 if (in_bracket)
674 break;
675 if (*startp < 0) {
676 /* Unbalanced brace */
677 return -1;
678 }
679 if (--brace_level <= 0)
680 *endp = i;
681 break;
682 }
683 }
684 /* unbalanced brackets/braces */
685 if (*endp < 0 && (*startp >= 0 || in_bracket))
686 return -1;
687 return 0;
688 }
689
690 /*
691 * Assembles and records a successfully-expanded pattern, returns -1 on
692 * alloc failure.
693 */
694 static int
695 emit_expansion(const char *pattern, int brace_start, int brace_end,
696 int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
697 {
698 char *cp;
699 int o = 0, tail_len = strlen(pattern + brace_end + 1);
700
701 if ((cp = malloc(brace_start + (sel_end - sel_start) +
702 tail_len + 1)) == NULL)
703 return -1;
704
705 /* Pattern before initial brace */
706 if (brace_start > 0) {
707 memcpy(cp, pattern, brace_start);
708 o = brace_start;
709 }
710 /* Current braced selection */
711 if (sel_end - sel_start > 0) {
712 memcpy(cp + o, pattern + sel_start,
713 sel_end - sel_start);
714 o += sel_end - sel_start;
715 }
716 /* Remainder of pattern after closing brace */
717 if (tail_len > 0) {
718 memcpy(cp + o, pattern + brace_end + 1, tail_len);
719 o += tail_len;
720 }
721 cp[o] = '\0';
722 if (append(cp, patternsp, npatternsp) != 0) {
723 free(cp);
724 return -1;
725 }
726 return 0;
727 }
728
729 /*
730 * Expand the first encountered brace in pattern, appending the expanded
731 * patterns it yielded to the *patternsp array.
732 *
733 * Returns 0 on success or -1 on allocation failure.
734 *
735 * Signals whether expansion was performed via *expanded and whether
736 * pattern was invalid via *invalid.
737 */
738 static int
739 brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
740 int *expanded, int *invalid)
741 {
742 int i;
743 int in_bracket, brace_start, brace_end, brace_level;
744 int sel_start, sel_end;
745
746 *invalid = *expanded = 0;
747
748 if (find_brace(pattern, &brace_start, &brace_end) != 0) {
749 *invalid = 1;
750 return 0;
751 } else if (brace_start == -1)
752 return 0;
753
754 in_bracket = brace_level = 0;
755 for (i = sel_start = brace_start + 1; i < brace_end; i++) {
756 switch (pattern[i]) {
757 case '{':
758 if (in_bracket)
759 break;
760 brace_level++;
761 break;
762 case '}':
763 if (in_bracket)
764 break;
765 brace_level--;
766 break;
767 case '[':
768 in_bracket = 1;
769 break;
770 case ']':
771 in_bracket = 0;
772 break;
773 case '\\':
774 if (i < brace_end - 1)
775 i++; /* skip */
776 break;
777 }
778 if (pattern[i] == ',' || i == brace_end - 1) {
779 if (in_bracket || brace_level > 0)
780 continue;
781 /* End of a selection, emit an expanded pattern */
782
783 /* Adjust end index for last selection */
784 sel_end = (i == brace_end - 1) ? brace_end : i;
785 if (emit_expansion(pattern, brace_start, brace_end,
786 sel_start, sel_end, patternsp, npatternsp) != 0)
787 return -1;
788 /* move on to the next selection */
789 sel_start = i + 1;
790 continue;
791 }
792 }
793 if (in_bracket || brace_level > 0) {
794 *invalid = 1;
795 return 0;
796 }
797 /* success */
798 *expanded = 1;
799 return 0;
800 }
801
802 /* Expand braces from pattern. Returns 0 on success, -1 on failure */
803 static int
804 brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
805 {
806 char *cp, *cp2, **active = NULL, **done = NULL;
807 size_t i, nactive = 0, ndone = 0;
808 int ret = -1, invalid = 0, expanded = 0;
809
810 *patternsp = NULL;
811 *npatternsp = 0;
812
813 /* Start the worklist with the original pattern */
814 if ((cp = strdup(pattern)) == NULL)
815 return -1;
816 if (append(cp, &active, &nactive) != 0) {
817 free(cp);
818 return -1;
819 }
820 while (nactive > 0) {
821 cp = active[nactive - 1];
822 nactive--;
823 if (brace_expand_one(cp, &active, &nactive,
824 &expanded, &invalid) == -1) {
825 free(cp);
826 goto fail;
827 }
828 if (invalid)
829 fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
830 if (expanded) {
831 /*
832 * Current entry expanded to new entries on the
833 * active list; discard the progenitor pattern.
834 */
835 free(cp);
836 continue;
837 }
838 /*
839 * Pattern did not expand; append the finename component to
840 * the completed list
841 */
842 if ((cp2 = strrchr(cp, '/')) != NULL)
843 *cp2++ = '\0';
844 else
845 cp2 = cp;
846 if (append(xstrdup(cp2), &done, &ndone) != 0) {
847 free(cp);
848 goto fail;
849 }
850 free(cp);
851 }
852 /* success */
853 *patternsp = done;
854 *npatternsp = ndone;
855 done = NULL;
856 ndone = 0;
857 ret = 0;
858 fail:
859 for (i = 0; i < nactive; i++)
860 free(active[i]);
861 free(active);
862 for (i = 0; i < ndone; i++)
863 free(done[i]);
864 free(done);
865 return ret;
866 }
867
868 void
869 toremote(int argc, char **argv)
870 {
871 char *suser = NULL, *host = NULL;
872 const char *src = NULL;
873 char *bp, *tuser, *thost;
874 const char *targ;
875 int sport = -1, tport = -1;
876 arglist alist;
877 int i, r;
878 u_int j;
879
880 memset(&alist, '\0', sizeof(alist));
881 alist.list = NULL;
882
883 /* Parse target */
884 r = parse_scp_uri(argv[argc - 1], &tuser, &thost, &tport, &targ);
885 if (r == -1) {
886 fmprintf(stderr, "%s: invalid uri\n", argv[argc - 1]);
887 ++errs;
888 goto out;
889 }
890 if (r != 0) {
891 if (parse_user_host_path(argv[argc - 1], &tuser, &thost,
892 &targ) == -1) {
893 fmprintf(stderr, "%s: invalid target\n", argv[argc - 1]);
894 ++errs;
895 goto out;
896 }
897 }
898 if (tuser != NULL && !okname(tuser)) {
899 ++errs;
900 goto out;
901 }
902
903 /* Parse source files */
904 for (i = 0; i < argc - 1; i++) {
905 free(suser);
906 free(host);
907 free(__UNCONST(src));
908 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
909 if (r == -1) {
910 fmprintf(stderr, "%s: invalid uri\n", argv[i]);
911 ++errs;
912 continue;
913 }
914 if (r != 0) {
915 parse_user_host_path(argv[i], &suser, &host, &src);
916 }
917 if (suser != NULL && !okname(suser)) {
918 ++errs;
919 continue;
920 }
921 if (host && throughlocal) { /* extended remote to remote */
922 xasprintf(&bp, "%s -f %s%s", cmd,
923 *src == '-' ? "-- " : "", src);
924 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0)
925 exit(1);
926 free(bp);
927 xasprintf(&bp, "%s -t %s%s", cmd,
928 *targ == '-' ? "-- " : "", targ);
929 if (do_cmd2(thost, tuser, tport, bp, remin, remout) < 0)
930 exit(1);
931 free(bp);
932 (void) close(remin);
933 (void) close(remout);
934 remin = remout = -1;
935 } else if (host) { /* standard remote to remote */
936 if (tport != -1 && tport != SSH_DEFAULT_PORT) {
937 /* This would require the remote support URIs */
938 fatal("target port not supported with two "
939 "remote hosts without the -3 option");
940 }
941
942 freeargs(&alist);
943 addargs(&alist, "%s", ssh_program);
944 addargs(&alist, "-x");
945 addargs(&alist, "-oClearAllForwardings=yes");
946 addargs(&alist, "-n");
947 for (j = 0; j < remote_remote_args.num; j++) {
948 addargs(&alist, "%s",
949 remote_remote_args.list[j]);
950 }
951 if (sport != -1) {
952 addargs(&alist, "-p");
953 addargs(&alist, "%d", sport);
954 }
955 if (suser) {
956 addargs(&alist, "-l");
957 addargs(&alist, "%s", suser);
958 }
959 addargs(&alist, "--");
960 addargs(&alist, "%s", host);
961 addargs(&alist, "%s", cmd);
962 addargs(&alist, "%s", src);
963 addargs(&alist, "%s%s%s:%s",
964 tuser ? tuser : "", tuser ? "@" : "",
965 thost, targ);
966 if (do_local_cmd(&alist) != 0)
967 errs = 1;
968 } else { /* local to remote */
969 if (remin == -1) {
970 xasprintf(&bp, "%s -t %s%s", cmd,
971 *targ == '-' ? "-- " : "", targ);
972 if (do_cmd(thost, tuser, tport, bp, &remin,
973 &remout) < 0)
974 exit(1);
975 if (response() < 0)
976 exit(1);
977 free(bp);
978 }
979 source(1, argv + i);
980 }
981 }
982 out:
983 free(tuser);
984 free(thost);
985 free(__UNCONST(targ));
986 free(suser);
987 free(host);
988 free(__UNCONST(src));
989 }
990
991 static void
992 tolocal(int argc, char **argv)
993 {
994 char *bp, *host = NULL, *suser = NULL;
995 const char *src = NULL;
996 arglist alist;
997 int i, r, sport = -1;
998
999 memset(&alist, '\0', sizeof(alist));
1000 alist.list = NULL;
1001
1002 for (i = 0; i < argc - 1; i++) {
1003 free(suser);
1004 free(host);
1005 free(__UNCONST(src));
1006 r = parse_scp_uri(argv[i], &suser, &host, &sport, &src);
1007 if (r == -1) {
1008 fmprintf(stderr, "%s: invalid uri\n", argv[i]);
1009 ++errs;
1010 continue;
1011 }
1012 if (r != 0)
1013 parse_user_host_path(argv[i], &suser, &host, &src);
1014 if (suser != NULL && !okname(suser)) {
1015 ++errs;
1016 continue;
1017 }
1018 if (!host) { /* Local to local. */
1019 freeargs(&alist);
1020 addargs(&alist, "%s", _PATH_CP);
1021 if (iamrecursive)
1022 addargs(&alist, "-r");
1023 if (pflag)
1024 addargs(&alist, "-p");
1025 addargs(&alist, "--");
1026 addargs(&alist, "%s", argv[i]);
1027 addargs(&alist, "%s", argv[argc-1]);
1028 if (do_local_cmd(&alist))
1029 ++errs;
1030 continue;
1031 }
1032 /* Remote to local. */
1033 xasprintf(&bp, "%s -f %s%s",
1034 cmd, *src == '-' ? "-- " : "", src);
1035 if (do_cmd(host, suser, sport, bp, &remin, &remout) < 0) {
1036 free(bp);
1037 ++errs;
1038 continue;
1039 }
1040 free(bp);
1041 sink(1, argv + argc - 1, src);
1042 (void) close(remin);
1043 remin = remout = -1;
1044 }
1045 free(suser);
1046 free(host);
1047 free(__UNCONST(src));
1048 }
1049
1050 void
1051 source(int argc, char **argv)
1052 {
1053 struct stat stb;
1054 static BUF buffer;
1055 BUF *bp;
1056 off_t i, statbytes;
1057 size_t amt, nr;
1058 int fd = -1, haderr, indx;
1059 char *last, *name, buf[PATH_MAX + 128], encname[PATH_MAX];
1060 int len;
1061
1062 for (indx = 0; indx < argc; ++indx) {
1063 fd = -1;
1064 name = argv[indx];
1065 statbytes = 0;
1066 len = strlen(name);
1067 while (len > 1 && name[len-1] == '/')
1068 name[--len] = '\0';
1069 if ((fd = open(name, O_RDONLY|O_NONBLOCK, 0)) == -1)
1070 goto syserr;
1071 if (strchr(name, '\n') != NULL) {
1072 strvisx(encname, name, len, VIS_NL);
1073 name = encname;
1074 }
1075 if (fstat(fd, &stb) == -1) {
1076 syserr: run_err("%s: %s", name, strerror(errno));
1077 goto next;
1078 }
1079 if (stb.st_size < 0) {
1080 run_err("%s: %s", name, "Negative file size");
1081 goto next;
1082 }
1083 unset_nonblock(fd);
1084 switch (stb.st_mode & S_IFMT) {
1085 case S_IFREG:
1086 break;
1087 case S_IFDIR:
1088 if (iamrecursive) {
1089 rsource(name, &stb);
1090 goto next;
1091 }
1092 /* FALLTHROUGH */
1093 default:
1094 run_err("%s: not a regular file", name);
1095 goto next;
1096 }
1097 if ((last = strrchr(name, '/')) == NULL)
1098 last = name;
1099 else
1100 ++last;
1101 curfile = last;
1102 if (pflag) {
1103 if (do_times(remout, verbose_mode, &stb) < 0)
1104 goto next;
1105 }
1106 #define FILEMODEMASK (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
1107 snprintf(buf, sizeof buf, "C%04o %lld %s\n",
1108 (u_int) (stb.st_mode & FILEMODEMASK),
1109 (long long)stb.st_size, last);
1110 if (verbose_mode)
1111 fmprintf(stderr, "Sending file modes: %s", buf);
1112 (void) atomicio(vwrite, remout, buf, strlen(buf));
1113 if (response() < 0)
1114 goto next;
1115 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
1116 next: if (fd != -1) {
1117 (void) close(fd);
1118 fd = -1;
1119 }
1120 continue;
1121 }
1122 if (showprogress)
1123 start_progress_meter(curfile, stb.st_size, &statbytes);
1124 set_nonblock(remout);
1125 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
1126 amt = bp->cnt;
1127 if (i + (off_t)amt > stb.st_size)
1128 amt = stb.st_size - i;
1129 if (!haderr) {
1130 if ((nr = atomicio(read, fd,
1131 bp->buf, amt)) != amt) {
1132 haderr = errno;
1133 memset(bp->buf + nr, 0, amt - nr);
1134 }
1135 }
1136 /* Keep writing after error to retain sync */
1137 if (haderr) {
1138 (void)atomicio(vwrite, remout, bp->buf, amt);
1139 memset(bp->buf, 0, amt);
1140 continue;
1141 }
1142 if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
1143 &statbytes) != amt)
1144 haderr = errno;
1145 }
1146 unset_nonblock(remout);
1147
1148 if (fd != -1) {
1149 if (close(fd) == -1 && !haderr)
1150 haderr = errno;
1151 fd = -1;
1152 }
1153 if (!haderr)
1154 (void) atomicio(vwrite, remout, empty, 1);
1155 else
1156 run_err("%s: %s", name, strerror(haderr));
1157 (void) response();
1158 if (showprogress)
1159 stop_progress_meter();
1160 }
1161 }
1162
1163 void
1164 rsource(char *name, struct stat *statp)
1165 {
1166 DIR *dirp;
1167 struct dirent *dp;
1168 char *last, *vect[1], path[PATH_MAX + 20];
1169
1170 if (!(dirp = opendir(name))) {
1171 run_err("%s: %s", name, strerror(errno));
1172 return;
1173 }
1174 last = strrchr(name, '/');
1175 if (last == NULL)
1176 last = name;
1177 else
1178 last++;
1179 if (pflag) {
1180 if (do_times(remout, verbose_mode, statp) < 0) {
1181 closedir(dirp);
1182 return;
1183 }
1184 }
1185 (void) snprintf(path, sizeof path, "D%04o %d %.1024s\n",
1186 (u_int) (statp->st_mode & FILEMODEMASK), 0, last);
1187 if (verbose_mode)
1188 fmprintf(stderr, "Entering directory: %s", path);
1189 (void) atomicio(vwrite, remout, path, strlen(path));
1190 if (response() < 0) {
1191 closedir(dirp);
1192 return;
1193 }
1194 while ((dp = readdir(dirp)) != NULL) {
1195 if (dp->d_ino == 0)
1196 continue;
1197 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
1198 continue;
1199 if (strlen(name) + 1 + strlen(dp->d_name) >= sizeof(path) - 1) {
1200 run_err("%s/%s: name too long", name, dp->d_name);
1201 continue;
1202 }
1203 (void) snprintf(path, sizeof path, "%s/%s", name, dp->d_name);
1204 vect[0] = path;
1205 source(1, vect);
1206 }
1207 (void) closedir(dirp);
1208 (void) atomicio(vwrite, remout, __UNCONST("E\n"), 2);
1209 (void) response();
1210 }
1211
1212 #define TYPE_OVERFLOW(type, val) \
1213 ((sizeof(type) == 4 && (val) > INT32_MAX) || \
1214 (sizeof(type) == 8 && (val) > INT64_MAX) || \
1215 (sizeof(type) != 4 && sizeof(type) != 8))
1216
1217 void
1218 sink(int argc, char **argv, const char *src)
1219 {
1220 static BUF buffer;
1221 struct stat stb;
1222 enum {
1223 YES, NO, DISPLAYED
1224 } wrerr;
1225 BUF *bp;
1226 off_t i;
1227 size_t j, count;
1228 int amt, exists, first, ofd;
1229 mode_t mode, omode, mask;
1230 off_t size, statbytes;
1231 unsigned long long ull;
1232 int setimes, targisdir, wrerrno = 0;
1233 char ch, *cp, *np, *targ, *vect[1], buf[2048], visbuf[2048];
1234 const char *why;
1235 char **patterns = NULL;
1236 size_t n, npatterns = 0;
1237 struct timeval tv[2];
1238
1239 #define atime tv[0]
1240 #define mtime tv[1]
1241 #define SCREWUP(str) { why = str; goto screwup; }
1242
1243 if (TYPE_OVERFLOW(time_t, 0) || TYPE_OVERFLOW(off_t, 0))
1244 SCREWUP("Unexpected off_t/time_t size");
1245
1246 setimes = targisdir = 0;
1247 mask = umask(0);
1248 if (!pflag)
1249 (void) umask(mask);
1250 if (argc != 1) {
1251 run_err("ambiguous target");
1252 exit(1);
1253 }
1254 targ = *argv;
1255 if (targetshouldbedirectory)
1256 verifydir(targ);
1257
1258 (void) atomicio(vwrite, remout, empty, 1);
1259 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
1260 targisdir = 1;
1261 if (src != NULL && !iamrecursive && !Tflag) {
1262 /*
1263 * Prepare to try to restrict incoming filenames to match
1264 * the requested destination file glob.
1265 */
1266 if (brace_expand(src, &patterns, &npatterns) != 0)
1267 fatal("%s: could not expand pattern", __func__);
1268 }
1269 for (first = 1;; first = 0) {
1270 cp = buf;
1271 if (atomicio(read, remin, cp, 1) != 1)
1272 goto done;
1273 if (*cp++ == '\n')
1274 SCREWUP("unexpected <newline>");
1275 do {
1276 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
1277 SCREWUP("lost connection");
1278 *cp++ = ch;
1279 } while (cp < &buf[sizeof(buf) - 1] && ch != '\n');
1280 *cp = 0;
1281 if (verbose_mode)
1282 fmprintf(stderr, "Sink: %s", buf);
1283
1284 if (buf[0] == '\01' || buf[0] == '\02') {
1285 if (iamremote == 0) {
1286 (void) snmprintf(visbuf, sizeof(visbuf),
1287 NULL, "%s", buf + 1);
1288 (void) atomicio(vwrite, STDERR_FILENO,
1289 visbuf, strlen(visbuf));
1290 }
1291 if (buf[0] == '\02')
1292 exit(1);
1293 ++errs;
1294 continue;
1295 }
1296 if (buf[0] == 'E') {
1297 (void) atomicio(vwrite, remout, __UNCONST(""), 1);
1298 goto done;
1299 }
1300 if (ch == '\n')
1301 *--cp = 0;
1302
1303 cp = buf;
1304 if (*cp == 'T') {
1305 setimes++;
1306 cp++;
1307 if (!isdigit((unsigned char)*cp))
1308 SCREWUP("mtime.sec not present");
1309 ull = strtoull(cp, &cp, 10);
1310 if (!cp || *cp++ != ' ')
1311 SCREWUP("mtime.sec not delimited");
1312 if (TYPE_OVERFLOW(time_t, ull))
1313 setimes = 0; /* out of range */
1314 mtime.tv_sec = ull;
1315 mtime.tv_usec = strtol(cp, &cp, 10);
1316 if (!cp || *cp++ != ' ' || mtime.tv_usec < 0 ||
1317 mtime.tv_usec > 999999)
1318 SCREWUP("mtime.usec not delimited");
1319 if (!isdigit((unsigned char)*cp))
1320 SCREWUP("atime.sec not present");
1321 ull = strtoull(cp, &cp, 10);
1322 if (!cp || *cp++ != ' ')
1323 SCREWUP("atime.sec not delimited");
1324 if (TYPE_OVERFLOW(time_t, ull))
1325 setimes = 0; /* out of range */
1326 atime.tv_sec = ull;
1327 atime.tv_usec = strtol(cp, &cp, 10);
1328 if (!cp || *cp++ != '\0' || atime.tv_usec < 0 ||
1329 atime.tv_usec > 999999)
1330 SCREWUP("atime.usec not delimited");
1331 (void) atomicio(vwrite, remout, empty, 1);
1332 continue;
1333 }
1334 if (*cp != 'C' && *cp != 'D') {
1335 /*
1336 * Check for the case "rcp remote:foo\* local:bar".
1337 * In this case, the line "No match." can be returned
1338 * by the shell before the rcp command on the remote is
1339 * executed so the ^Aerror_message convention isn't
1340 * followed.
1341 */
1342 if (first) {
1343 run_err("%s", cp);
1344 exit(1);
1345 }
1346 SCREWUP("expected control record");
1347 }
1348 mode = 0;
1349 for (++cp; cp < buf + 5; cp++) {
1350 if (*cp < '0' || *cp > '7')
1351 SCREWUP("bad mode");
1352 mode = (mode << 3) | (*cp - '0');
1353 }
1354 if (!pflag)
1355 mode &= ~mask;
1356 if (*cp++ != ' ')
1357 SCREWUP("mode not delimited");
1358
1359 if (!isdigit((unsigned char)*cp))
1360 SCREWUP("size not present");
1361 ull = strtoull(cp, &cp, 10);
1362 if (!cp || *cp++ != ' ')
1363 SCREWUP("size not delimited");
1364 if (TYPE_OVERFLOW(off_t, ull))
1365 SCREWUP("size out of range");
1366 size = (off_t)ull;
1367
1368 if (*cp == '\0' || strchr(cp, '/') != NULL ||
1369 strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
1370 run_err("error: unexpected filename: %s", cp);
1371 exit(1);
1372 }
1373 if (npatterns > 0) {
1374 for (n = 0; n < npatterns; n++) {
1375 if (fnmatch(patterns[n], cp, 0) == 0)
1376 break;
1377 }
1378 if (n >= npatterns)
1379 SCREWUP("filename does not match request");
1380 }
1381 if (targisdir) {
1382 static char *namebuf;
1383 static size_t cursize;
1384 size_t need;
1385
1386 need = strlen(targ) + strlen(cp) + 250;
1387 if (need > cursize) {
1388 free(namebuf);
1389 namebuf = xmalloc(need);
1390 cursize = need;
1391 }
1392 (void) snprintf(namebuf, need, "%s%s%s", targ,
1393 strcmp(targ, "/") ? "/" : "", cp);
1394 np = namebuf;
1395 } else
1396 np = targ;
1397 curfile = cp;
1398 exists = stat(np, &stb) == 0;
1399 if (buf[0] == 'D') {
1400 int mod_flag = pflag;
1401 if (!iamrecursive)
1402 SCREWUP("received directory without -r");
1403 if (exists) {
1404 if (!S_ISDIR(stb.st_mode)) {
1405 errno = ENOTDIR;
1406 goto bad;
1407 }
1408 if (pflag)
1409 (void) chmod(np, mode);
1410 } else {
1411 /* Handle copying from a read-only
1412 directory */
1413 mod_flag = 1;
1414 if (mkdir(np, mode | S_IRWXU) == -1)
1415 goto bad;
1416 }
1417 vect[0] = xstrdup(np);
1418 sink(1, vect, src);
1419 if (setimes) {
1420 setimes = 0;
1421 if (utimes(vect[0], tv) == -1)
1422 run_err("%s: set times: %s",
1423 vect[0], strerror(errno));
1424 }
1425 if (mod_flag)
1426 (void) chmod(vect[0], mode);
1427 free(vect[0]);
1428 continue;
1429 }
1430 omode = mode;
1431 mode |= S_IWUSR;
1432 if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) {
1433 bad: run_err("%s: %s", np, strerror(errno));
1434 continue;
1435 }
1436 (void) atomicio(vwrite, remout, empty, 1);
1437 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
1438 (void) close(ofd);
1439 continue;
1440 }
1441 cp = bp->buf;
1442 wrerr = NO;
1443
1444 statbytes = 0;
1445 if (showprogress)
1446 start_progress_meter(curfile, size, &statbytes);
1447 set_nonblock(remin);
1448 for (count = i = 0; i < size; i += bp->cnt) {
1449 amt = bp->cnt;
1450 if (i + amt > size)
1451 amt = size - i;
1452 count += amt;
1453 do {
1454 j = atomicio6(read, remin, cp, amt,
1455 scpio, &statbytes);
1456 if (j == 0) {
1457 run_err("%s", j != EPIPE ?
1458 strerror(errno) :
1459 "dropped connection");
1460 exit(1);
1461 }
1462 amt -= j;
1463 cp += j;
1464 } while (amt > 0);
1465
1466 if (count == bp->cnt) {
1467 /* Keep reading so we stay sync'd up. */
1468 if (wrerr == NO) {
1469 if (atomicio(vwrite, ofd, bp->buf,
1470 count) != count) {
1471 wrerr = YES;
1472 wrerrno = errno;
1473 }
1474 }
1475 count = 0;
1476 cp = bp->buf;
1477 }
1478 }
1479 unset_nonblock(remin);
1480 if (count != 0 && wrerr == NO &&
1481 atomicio(vwrite, ofd, bp->buf, count) != count) {
1482 wrerr = YES;
1483 wrerrno = errno;
1484 }
1485 if (wrerr == NO && (!exists || S_ISREG(stb.st_mode)) &&
1486 ftruncate(ofd, size) != 0) {
1487 run_err("%s: truncate: %s", np, strerror(errno));
1488 wrerr = DISPLAYED;
1489 }
1490 if (pflag) {
1491 if (exists || omode != mode)
1492 if (fchmod(ofd, omode)) {
1493 run_err("%s: set mode: %s",
1494 np, strerror(errno));
1495 wrerr = DISPLAYED;
1496 }
1497 } else {
1498 if (!exists && omode != mode)
1499 if (fchmod(ofd, omode & ~mask)) {
1500 run_err("%s: set mode: %s",
1501 np, strerror(errno));
1502 wrerr = DISPLAYED;
1503 }
1504 }
1505 if (close(ofd) == -1) {
1506 wrerr = YES;
1507 wrerrno = errno;
1508 }
1509 (void) response();
1510 if (showprogress)
1511 stop_progress_meter();
1512 if (setimes && wrerr == NO) {
1513 setimes = 0;
1514 if (utimes(np, tv) == -1) {
1515 run_err("%s: set times: %s",
1516 np, strerror(errno));
1517 wrerr = DISPLAYED;
1518 }
1519 }
1520 switch (wrerr) {
1521 case YES:
1522 run_err("%s: %s", np, strerror(wrerrno));
1523 break;
1524 case NO:
1525 (void) atomicio(vwrite, remout, empty, 1);
1526 break;
1527 case DISPLAYED:
1528 break;
1529 }
1530 }
1531 done:
1532 for (n = 0; n < npatterns; n++)
1533 free(patterns[n]);
1534 free(patterns);
1535 return;
1536 screwup:
1537 for (n = 0; n < npatterns; n++)
1538 free(patterns[n]);
1539 free(patterns);
1540 run_err("protocol error: %s", why);
1541 exit(1);
1542 }
1543
1544 int
1545 response(void)
1546 {
1547 char ch, *cp, resp, rbuf[2048], visbuf[2048];
1548
1549 if (atomicio(read, remin, &resp, sizeof(resp)) != sizeof(resp))
1550 lostconn(0);
1551
1552 cp = rbuf;
1553 switch (resp) {
1554 case 0: /* ok */
1555 return (0);
1556 default:
1557 *cp++ = resp;
1558 /* FALLTHROUGH */
1559 case 1: /* error, followed by error msg */
1560 case 2: /* fatal error, "" */
1561 do {
1562 if (atomicio(read, remin, &ch, sizeof(ch)) != sizeof(ch))
1563 lostconn(0);
1564 *cp++ = ch;
1565 } while (cp < &rbuf[sizeof(rbuf) - 1] && ch != '\n');
1566
1567 if (!iamremote) {
1568 cp[-1] = '\0';
1569 (void) snmprintf(visbuf, sizeof(visbuf),
1570 NULL, "%s\n", rbuf);
1571 (void) atomicio(vwrite, STDERR_FILENO,
1572 visbuf, strlen(visbuf));
1573 }
1574 ++errs;
1575 if (resp == 1)
1576 return (-1);
1577 exit(1);
1578 }
1579 /* NOTREACHED */
1580 }
1581
1582 void
1583 usage(void)
1584 {
1585 (void) fprintf(stderr,
1586 "usage: scp [-346BCpqrTv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
1587 " [-J destination] [-l limit] [-o ssh_option] [-P port]\n"
1588 " [-S program] source ... target\n");
1589 exit(1);
1590 }
1591
1592 void
1593 run_err(const char *fmt,...)
1594 {
1595 static FILE *fp;
1596 va_list ap;
1597
1598 ++errs;
1599 if (fp != NULL || (remout != -1 && (fp = fdopen(remout, "w")))) {
1600 (void) fprintf(fp, "%c", 0x01);
1601 (void) fprintf(fp, "scp: ");
1602 va_start(ap, fmt);
1603 (void) vfprintf(fp, fmt, ap);
1604 va_end(ap);
1605 (void) fprintf(fp, "\n");
1606 (void) fflush(fp);
1607 }
1608
1609 if (!iamremote) {
1610 va_start(ap, fmt);
1611 vfmprintf(stderr, fmt, ap);
1612 va_end(ap);
1613 fprintf(stderr, "\n");
1614 }
1615 }
1616
1617 void
1618 verifydir(char *cp)
1619 {
1620 struct stat stb;
1621
1622 if (!stat(cp, &stb)) {
1623 if (S_ISDIR(stb.st_mode))
1624 return;
1625 errno = ENOTDIR;
1626 }
1627 run_err("%s: %s", cp, strerror(errno));
1628 killchild(0);
1629 }
1630
1631 int
1632 okname(char *cp0)
1633 {
1634 int c;
1635 char *cp;
1636
1637 cp = cp0;
1638 do {
1639 c = (int)*cp;
1640 if (c & 0200)
1641 goto bad;
1642 if (!isalpha(c) && !isdigit((unsigned char)c)) {
1643 switch (c) {
1644 case '\'':
1645 case '"':
1646 case '`':
1647 case ' ':
1648 case '#':
1649 goto bad;
1650 default:
1651 break;
1652 }
1653 }
1654 } while (*++cp);
1655 return (1);
1656
1657 bad: fmprintf(stderr, "%s: invalid user name\n", cp0);
1658 return (0);
1659 }
1660
1661 BUF *
1662 allocbuf(BUF *bp, int fd, int blksize)
1663 {
1664 size_t size;
1665 struct stat stb;
1666
1667 if (fstat(fd, &stb) == -1) {
1668 run_err("fstat: %s", strerror(errno));
1669 return (0);
1670 }
1671 size = ROUNDUP(stb.st_blksize, blksize);
1672 if (size == 0)
1673 size = blksize;
1674 if (bp->cnt >= size)
1675 return (bp);
1676 bp->buf = xrecallocarray(bp->buf, bp->cnt, size, 1);
1677 bp->cnt = size;
1678 return (bp);
1679 }
1680
1681 static void
1682 lostconn(int signo)
1683 {
1684 if (!iamremote)
1685 (void)write(STDERR_FILENO, "lost connection\n", 16);
1686 if (signo)
1687 _exit(1);
1688 else
1689 exit(1);
1690 }
1691