diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | scp.1 | 11 | ||||
-rw-r--r-- | scp.c | 89 |
3 files changed, 102 insertions, 6 deletions
@@ -1,3 +1,11 @@ | |||
1 | 20110106 | ||
2 | - (djm) OpenBSD CVS Sync | ||
3 | - markus@cvs.openbsd.org 2010/12/08 22:46:03 | ||
4 | [scp.1 scp.c] | ||
5 | add a new -3 option to scp: Copies between two remote hosts are | ||
6 | transferred through the local host. Without this option the data | ||
7 | is copied directly between the two remote hosts. ok djm@ (bugzilla #1837) | ||
8 | |||
1 | 20110104 | 9 | 20110104 |
2 | - (djm) [configure.ac Makefile.in] Use mandoc as preferred manpage | 10 | - (djm) [configure.ac Makefile.in] Use mandoc as preferred manpage |
3 | formatter if it is present, followed by nroff and groff respectively. | 11 | formatter if it is present, followed by nroff and groff respectively. |
@@ -8,9 +8,9 @@ | |||
8 | .\" | 8 | .\" |
9 | .\" Created: Sun May 7 00:14:37 1995 ylo | 9 | .\" Created: Sun May 7 00:14:37 1995 ylo |
10 | .\" | 10 | .\" |
11 | .\" $OpenBSD: scp.1,v 1.54 2010/11/18 15:01:00 jmc Exp $ | 11 | .\" $OpenBSD: scp.1,v 1.55 2010/12/08 22:46:03 markus Exp $ |
12 | .\" | 12 | .\" |
13 | .Dd $Mdocdate: November 18 2010 $ | 13 | .Dd $Mdocdate: December 8 2010 $ |
14 | .Dt SCP 1 | 14 | .Dt SCP 1 |
15 | .Os | 15 | .Os |
16 | .Sh NAME | 16 | .Sh NAME |
@@ -19,7 +19,7 @@ | |||
19 | .Sh SYNOPSIS | 19 | .Sh SYNOPSIS |
20 | .Nm scp | 20 | .Nm scp |
21 | .Bk -words | 21 | .Bk -words |
22 | .Op Fl 1246BCpqrv | 22 | .Op Fl 12346BCpqrv |
23 | .Op Fl c Ar cipher | 23 | .Op Fl c Ar cipher |
24 | .Op Fl F Ar ssh_config | 24 | .Op Fl F Ar ssh_config |
25 | .Op Fl i Ar identity_file | 25 | .Op Fl i Ar identity_file |
@@ -75,6 +75,11 @@ to use protocol 1. | |||
75 | Forces | 75 | Forces |
76 | .Nm | 76 | .Nm |
77 | to use protocol 2. | 77 | to use protocol 2. |
78 | .It Fl 3 | ||
79 | Copies between two remote hosts are transferred through the local host. | ||
80 | Without this option the data is copied directly between the two remote | ||
81 | hosts. | ||
82 | Note that this options disables the progress meter. | ||
78 | .It Fl 4 | 83 | .It Fl 4 |
79 | Forces | 84 | Forces |
80 | .Nm | 85 | .Nm |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: scp.c,v 1.168 2010/11/26 05:52:49 djm Exp $ */ | 1 | /* $OpenBSD: scp.c,v 1.169 2010/12/08 22:46:03 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * scp - secure remote copy. This is basically patched BSD rcp which | 3 | * scp - secure remote copy. This is basically patched BSD rcp which |
4 | * uses ssh to do the data transfer (instead of using rcmd). | 4 | * uses ssh to do the data transfer (instead of using rcmd). |
@@ -119,6 +119,7 @@ extern char *__progname; | |||
119 | #define COPY_BUFLEN 16384 | 119 | #define COPY_BUFLEN 16384 |
120 | 120 | ||
121 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); | 121 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); |
122 | int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout); | ||
122 | 123 | ||
123 | /* Struct for addargs */ | 124 | /* Struct for addargs */ |
124 | arglist args; | 125 | arglist args; |
@@ -137,6 +138,12 @@ int verbose_mode = 0; | |||
137 | /* This is set to zero if the progressmeter is not desired. */ | 138 | /* This is set to zero if the progressmeter is not desired. */ |
138 | int showprogress = 1; | 139 | int showprogress = 1; |
139 | 140 | ||
141 | /* | ||
142 | * This is set to non-zero if remote-remote copy should be piped | ||
143 | * through this process. | ||
144 | */ | ||
145 | int throughlocal = 0; | ||
146 | |||
140 | /* This is the program to execute for the secured connection. ("ssh" or -S) */ | 147 | /* This is the program to execute for the secured connection. ("ssh" or -S) */ |
141 | char *ssh_program = _PATH_SSH_PROGRAM; | 148 | char *ssh_program = _PATH_SSH_PROGRAM; |
142 | 149 | ||
@@ -287,6 +294,50 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
287 | return 0; | 294 | return 0; |
288 | } | 295 | } |
289 | 296 | ||
297 | /* | ||
298 | * This functions executes a command simlar to do_cmd(), but expects the | ||
299 | * input and output descriptors to be setup by a previous call to do_cmd(). | ||
300 | * This way the input and output of two commands can be connected. | ||
301 | */ | ||
302 | int | ||
303 | do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout) | ||
304 | { | ||
305 | pid_t pid; | ||
306 | int status; | ||
307 | |||
308 | if (verbose_mode) | ||
309 | fprintf(stderr, | ||
310 | "Executing: 2nd program %s host %s, user %s, command %s\n", | ||
311 | ssh_program, host, | ||
312 | remuser ? remuser : "(unspecified)", cmd); | ||
313 | |||
314 | /* Fork a child to execute the command on the remote host using ssh. */ | ||
315 | pid = fork(); | ||
316 | if (pid == 0) { | ||
317 | dup2(fdin, 0); | ||
318 | dup2(fdout, 1); | ||
319 | |||
320 | replacearg(&args, 0, "%s", ssh_program); | ||
321 | if (remuser != NULL) { | ||
322 | addargs(&args, "-l"); | ||
323 | addargs(&args, "%s", remuser); | ||
324 | } | ||
325 | addargs(&args, "--"); | ||
326 | addargs(&args, "%s", host); | ||
327 | addargs(&args, "%s", cmd); | ||
328 | |||
329 | execvp(ssh_program, args.list); | ||
330 | perror(ssh_program); | ||
331 | exit(1); | ||
332 | } else if (pid == -1) { | ||
333 | fatal("fork: %s", strerror(errno)); | ||
334 | } | ||
335 | while (waitpid(pid, &status, 0) == -1) | ||
336 | if (errno != EINTR) | ||
337 | fatal("do_cmd2: waitpid: %s", strerror(errno)); | ||
338 | return 0; | ||
339 | } | ||
340 | |||
290 | typedef struct { | 341 | typedef struct { |
291 | size_t cnt; | 342 | size_t cnt; |
292 | char *buf; | 343 | char *buf; |
@@ -344,7 +395,7 @@ main(int argc, char **argv) | |||
344 | addargs(&args, "-oClearAllForwardings=yes"); | 395 | addargs(&args, "-oClearAllForwardings=yes"); |
345 | 396 | ||
346 | fflag = tflag = 0; | 397 | fflag = tflag = 0; |
347 | while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) | 398 | while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) |
348 | switch (ch) { | 399 | switch (ch) { |
349 | /* User-visible flags. */ | 400 | /* User-visible flags. */ |
350 | case '1': | 401 | case '1': |
@@ -355,6 +406,9 @@ main(int argc, char **argv) | |||
355 | addargs(&args, "-%c", ch); | 406 | addargs(&args, "-%c", ch); |
356 | addargs(&remote_remote_args, "-%c", ch); | 407 | addargs(&remote_remote_args, "-%c", ch); |
357 | break; | 408 | break; |
409 | case '3': | ||
410 | throughlocal = 1; | ||
411 | break; | ||
358 | case 'o': | 412 | case 'o': |
359 | case 'c': | 413 | case 'c': |
360 | case 'i': | 414 | case 'i': |
@@ -530,7 +584,36 @@ toremote(char *targ, int argc, char **argv) | |||
530 | 584 | ||
531 | for (i = 0; i < argc - 1; i++) { | 585 | for (i = 0; i < argc - 1; i++) { |
532 | src = colon(argv[i]); | 586 | src = colon(argv[i]); |
533 | if (src) { /* remote to remote */ | 587 | if (src && throughlocal) { /* extended remote to remote */ |
588 | *src++ = 0; | ||
589 | if (*src == 0) | ||
590 | src = "."; | ||
591 | host = strrchr(argv[i], '@'); | ||
592 | if (host) { | ||
593 | *host++ = 0; | ||
594 | host = cleanhostname(host); | ||
595 | suser = argv[i]; | ||
596 | if (*suser == '\0') | ||
597 | suser = pwd->pw_name; | ||
598 | else if (!okname(suser)) | ||
599 | continue; | ||
600 | } else { | ||
601 | host = cleanhostname(argv[i]); | ||
602 | suser = NULL; | ||
603 | } | ||
604 | xasprintf(&bp, "%s -f -- %s", cmd, src); | ||
605 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) | ||
606 | exit(1); | ||
607 | (void) xfree(bp); | ||
608 | host = cleanhostname(thost); | ||
609 | xasprintf(&bp, "%s -t -- %s", cmd, targ); | ||
610 | if (do_cmd2(host, tuser, bp, remin, remout) < 0) | ||
611 | exit(1); | ||
612 | (void) xfree(bp); | ||
613 | (void) close(remin); | ||
614 | (void) close(remout); | ||
615 | remin = remout = -1; | ||
616 | } else if (src) { /* standard remote to remote */ | ||
534 | freeargs(&alist); | 617 | freeargs(&alist); |
535 | addargs(&alist, "%s", ssh_program); | 618 | addargs(&alist, "%s", ssh_program); |
536 | addargs(&alist, "-x"); | 619 | addargs(&alist, "-x"); |