summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-01-06 22:40:30 +1100
committerDamien Miller <djm@mindrot.org>2011-01-06 22:40:30 +1100
commitf12114366b4ffcd34e3a638dd187f29ac03fbdbd (patch)
tree56fffcf6943140aa7fde6c54c5021e873aa19c25
parent30a69e7bba0161eabb678b9902fbd04e7495d86e (diff)
- markus@cvs.openbsd.org 2010/12/08 22:46:03
[scp.1 scp.c] add a new -3 option to scp: Copies between two remote hosts are transferred through the local host. Without this option the data is copied directly between the two remote hosts. ok djm@ (bugzilla #1837)
-rw-r--r--ChangeLog8
-rw-r--r--scp.111
-rw-r--r--scp.c89
3 files changed, 102 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 135ad48fa..aa98f9906 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
120110106
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
120110104 920110104
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.
diff --git a/scp.1 b/scp.1
index 346e5e311..28bac5671 100644
--- a/scp.1
+++ b/scp.1
@@ -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.
75Forces 75Forces
76.Nm 76.Nm
77to use protocol 2. 77to use protocol 2.
78.It Fl 3
79Copies between two remote hosts are transferred through the local host.
80Without this option the data is copied directly between the two remote
81hosts.
82Note that this options disables the progress meter.
78.It Fl 4 83.It Fl 4
79Forces 84Forces
80.Nm 85.Nm
diff --git a/scp.c b/scp.c
index 774e602f2..1262e0aff 100644
--- a/scp.c
+++ b/scp.c
@@ -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
121int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); 121int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
122int do_cmd2(char *host, char *remuser, char *cmd, int fdin, int fdout);
122 123
123/* Struct for addargs */ 124/* Struct for addargs */
124arglist args; 125arglist 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. */
138int showprogress = 1; 139int showprogress = 1;
139 140
141/*
142 * This is set to non-zero if remote-remote copy should be piped
143 * through this process.
144 */
145int 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) */
141char *ssh_program = _PATH_SSH_PROGRAM; 148char *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 */
302int
303do_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
290typedef struct { 341typedef 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");