summaryrefslogtreecommitdiff
path: root/scp.c
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 /scp.c
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)
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c89
1 files changed, 86 insertions, 3 deletions
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");