diff options
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 137 |
1 files changed, 53 insertions, 84 deletions
@@ -11,6 +11,8 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * Parts from: | ||
15 | * | ||
14 | * Copyright (c) 1983, 1990, 1992, 1993, 1995 | 16 | * Copyright (c) 1983, 1990, 1992, 1993, 1995 |
15 | * The Regents of the University of California. All rights reserved. | 17 | * The Regents of the University of California. All rights reserved. |
16 | * | 18 | * |
@@ -45,7 +47,7 @@ | |||
45 | */ | 47 | */ |
46 | 48 | ||
47 | #include "includes.h" | 49 | #include "includes.h" |
48 | RCSID("$OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $"); | 50 | RCSID("$OpenBSD: scp.c,v 1.35 2000/08/19 02:50:07 deraadt Exp $"); |
49 | 51 | ||
50 | #include "ssh.h" | 52 | #include "ssh.h" |
51 | #include "xmalloc.h" | 53 | #include "xmalloc.h" |
@@ -69,6 +71,7 @@ void progressmeter(int); | |||
69 | 71 | ||
70 | /* Returns width of the terminal (for progress meter calculations). */ | 72 | /* Returns width of the terminal (for progress meter calculations). */ |
71 | int getttywidth(void); | 73 | int getttywidth(void); |
74 | int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); | ||
72 | 75 | ||
73 | /* Time a transfer started. */ | 76 | /* Time a transfer started. */ |
74 | static struct timeval start; | 77 | static struct timeval start; |
@@ -111,6 +114,9 @@ char *identity = NULL; | |||
111 | /* This is the port to use in contacting the remote site (is non-NULL). */ | 114 | /* This is the port to use in contacting the remote site (is non-NULL). */ |
112 | char *port = NULL; | 115 | char *port = NULL; |
113 | 116 | ||
117 | /* This is the program to execute for the secured connection. ("ssh" or -S) */ | ||
118 | char *ssh_program = SSH_PROGRAM; | ||
119 | |||
114 | /* | 120 | /* |
115 | * This function executes the given command as the specified user on the | 121 | * This function executes the given command as the specified user on the |
116 | * given host. This returns < 0 if execution fails, and >= 0 otherwise. This | 122 | * given host. This returns < 0 if execution fails, and >= 0 otherwise. This |
@@ -118,13 +124,13 @@ char *port = NULL; | |||
118 | */ | 124 | */ |
119 | 125 | ||
120 | int | 126 | int |
121 | do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | 127 | do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) |
122 | { | 128 | { |
123 | int pin[2], pout[2], reserved[2]; | 129 | int pin[2], pout[2], reserved[2]; |
124 | 130 | ||
125 | if (verbose_mode) | 131 | if (verbose_mode) |
126 | fprintf(stderr, "Executing: host %s, user %s, command %s\n", | 132 | fprintf(stderr, "Executing: host %s, user %s, command %s\n", |
127 | host, remuser ? remuser : "(unspecified)", cmd); | 133 | host, remuser ? remuser : "(unspecified)", cmd); |
128 | 134 | ||
129 | /* | 135 | /* |
130 | * Reserve two descriptors so that the real pipes won't get | 136 | * Reserve two descriptors so that the real pipes won't get |
@@ -144,7 +150,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
144 | 150 | ||
145 | /* For a child to execute the command on the remote host using ssh. */ | 151 | /* For a child to execute the command on the remote host using ssh. */ |
146 | if (fork() == 0) { | 152 | if (fork() == 0) { |
147 | char *args[100]; | 153 | char *args[100]; /* XXX careful */ |
148 | unsigned int i; | 154 | unsigned int i; |
149 | 155 | ||
150 | /* Child. */ | 156 | /* Child. */ |
@@ -156,7 +162,7 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
156 | close(pout[1]); | 162 | close(pout[1]); |
157 | 163 | ||
158 | i = 0; | 164 | i = 0; |
159 | args[i++] = SSH_PROGRAM; | 165 | args[i++] = ssh_program; |
160 | args[i++] = "-x"; | 166 | args[i++] = "-x"; |
161 | args[i++] = "-oFallBackToRsh no"; | 167 | args[i++] = "-oFallBackToRsh no"; |
162 | if (IPv4) | 168 | if (IPv4) |
@@ -189,8 +195,8 @@ do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout) | |||
189 | args[i++] = cmd; | 195 | args[i++] = cmd; |
190 | args[i++] = NULL; | 196 | args[i++] = NULL; |
191 | 197 | ||
192 | execvp(SSH_PROGRAM, args); | 198 | execvp(ssh_program, args); |
193 | perror(SSH_PROGRAM); | 199 | perror(ssh_program); |
194 | exit(1); | 200 | exit(1); |
195 | } | 201 | } |
196 | /* Parent. Close the other side, and return the local side. */ | 202 | /* Parent. Close the other side, and return the local side. */ |
@@ -214,8 +220,6 @@ fatal(const char *fmt,...) | |||
214 | exit(255); | 220 | exit(255); |
215 | } | 221 | } |
216 | 222 | ||
217 | /* This stuff used to be in BSD rcp extern.h. */ | ||
218 | |||
219 | typedef struct { | 223 | typedef struct { |
220 | int cnt; | 224 | int cnt; |
221 | char *buf; | 225 | char *buf; |
@@ -231,8 +235,6 @@ int okname(char *); | |||
231 | void run_err(const char *,...); | 235 | void run_err(const char *,...); |
232 | void verifydir(char *); | 236 | void verifydir(char *); |
233 | 237 | ||
234 | /* Stuff from BSD rcp.c continues. */ | ||
235 | |||
236 | struct passwd *pwd; | 238 | struct passwd *pwd; |
237 | uid_t userid; | 239 | uid_t userid; |
238 | int errs, remin, remout; | 240 | int errs, remin, remout; |
@@ -260,7 +262,7 @@ main(argc, argv) | |||
260 | extern int optind; | 262 | extern int optind; |
261 | 263 | ||
262 | fflag = tflag = 0; | 264 | fflag = tflag = 0; |
263 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46")) != EOF) | 265 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S")) != EOF) |
264 | switch (ch) { | 266 | switch (ch) { |
265 | /* User-visible flags. */ | 267 | /* User-visible flags. */ |
266 | case '4': | 268 | case '4': |
@@ -278,6 +280,10 @@ main(argc, argv) | |||
278 | case 'r': | 280 | case 'r': |
279 | iamrecursive = 1; | 281 | iamrecursive = 1; |
280 | break; | 282 | break; |
283 | case 'S': | ||
284 | ssh_program = optarg; | ||
285 | break; | ||
286 | |||
281 | /* Server options. */ | 287 | /* Server options. */ |
282 | case 'd': | 288 | case 'd': |
283 | targetshouldbedirectory = 1; | 289 | targetshouldbedirectory = 1; |
@@ -343,8 +349,8 @@ main(argc, argv) | |||
343 | remin = remout = -1; | 349 | remin = remout = -1; |
344 | /* Command to be executed on remote system using "ssh". */ | 350 | /* Command to be executed on remote system using "ssh". */ |
345 | (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", | 351 | (void) sprintf(cmd, "scp%s%s%s%s", verbose_mode ? " -v" : "", |
346 | iamrecursive ? " -r" : "", pflag ? " -p" : "", | 352 | iamrecursive ? " -r" : "", pflag ? " -p" : "", |
347 | targetshouldbedirectory ? " -d" : ""); | 353 | targetshouldbedirectory ? " -d" : ""); |
348 | 354 | ||
349 | (void) signal(SIGPIPE, lostconn); | 355 | (void) signal(SIGPIPE, lostconn); |
350 | 356 | ||
@@ -401,9 +407,9 @@ toremote(targ, argc, argv) | |||
401 | if (*src == 0) | 407 | if (*src == 0) |
402 | src = "."; | 408 | src = "."; |
403 | host = strchr(argv[i], '@'); | 409 | host = strchr(argv[i], '@'); |
404 | len = strlen(SSH_PROGRAM) + strlen(argv[i]) + | 410 | len = strlen(ssh_program) + strlen(argv[i]) + |
405 | strlen(src) + (tuser ? strlen(tuser) : 0) + | 411 | strlen(src) + (tuser ? strlen(tuser) : 0) + |
406 | strlen(thost) + strlen(targ) + CMDNEEDS + 32; | 412 | strlen(thost) + strlen(targ) + CMDNEEDS + 32; |
407 | bp = xmalloc(len); | 413 | bp = xmalloc(len); |
408 | if (host) { | 414 | if (host) { |
409 | *host++ = 0; | 415 | *host++ = 0; |
@@ -414,19 +420,19 @@ toremote(targ, argc, argv) | |||
414 | else if (!okname(suser)) | 420 | else if (!okname(suser)) |
415 | continue; | 421 | continue; |
416 | (void) sprintf(bp, | 422 | (void) sprintf(bp, |
417 | "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'", | 423 | "%s%s -x -o'FallBackToRsh no' -n -l %s %s %s %s '%s%s%s:%s'", |
418 | SSH_PROGRAM, verbose_mode ? " -v" : "", | 424 | ssh_program, verbose_mode ? " -v" : "", |
419 | suser, host, cmd, src, | 425 | suser, host, cmd, src, |
420 | tuser ? tuser : "", tuser ? "@" : "", | 426 | tuser ? tuser : "", tuser ? "@" : "", |
421 | thost, targ); | 427 | thost, targ); |
422 | } else { | 428 | } else { |
423 | host = cleanhostname(argv[i]); | 429 | host = cleanhostname(argv[i]); |
424 | (void) sprintf(bp, | 430 | (void) sprintf(bp, |
425 | "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'", | 431 | "exec %s%s -x -o'FallBackToRsh no' -n %s %s %s '%s%s%s:%s'", |
426 | SSH_PROGRAM, verbose_mode ? " -v" : "", | 432 | ssh_program, verbose_mode ? " -v" : "", |
427 | host, cmd, src, | 433 | host, cmd, src, |
428 | tuser ? tuser : "", tuser ? "@" : "", | 434 | tuser ? tuser : "", tuser ? "@" : "", |
429 | thost, targ); | 435 | thost, targ); |
430 | } | 436 | } |
431 | if (verbose_mode) | 437 | if (verbose_mode) |
432 | fprintf(stderr, "Executing: %s\n", bp); | 438 | fprintf(stderr, "Executing: %s\n", bp); |
@@ -438,8 +444,8 @@ toremote(targ, argc, argv) | |||
438 | bp = xmalloc(len); | 444 | bp = xmalloc(len); |
439 | (void) sprintf(bp, "%s -t %s", cmd, targ); | 445 | (void) sprintf(bp, "%s -t %s", cmd, targ); |
440 | host = cleanhostname(thost); | 446 | host = cleanhostname(thost); |
441 | if (do_cmd(host, tuser, | 447 | if (do_cmd(host, tuser, bp, &remin, |
442 | bp, &remin, &remout) < 0) | 448 | &remout, argc) < 0) |
443 | exit(1); | 449 | exit(1); |
444 | if (response() < 0) | 450 | if (response() < 0) |
445 | exit(1); | 451 | exit(1); |
@@ -461,11 +467,11 @@ tolocal(argc, argv) | |||
461 | for (i = 0; i < argc - 1; i++) { | 467 | for (i = 0; i < argc - 1; i++) { |
462 | if (!(src = colon(argv[i]))) { /* Local to local. */ | 468 | if (!(src = colon(argv[i]))) { /* Local to local. */ |
463 | len = strlen(_PATH_CP) + strlen(argv[i]) + | 469 | len = strlen(_PATH_CP) + strlen(argv[i]) + |
464 | strlen(argv[argc - 1]) + 20; | 470 | strlen(argv[argc - 1]) + 20; |
465 | bp = xmalloc(len); | 471 | bp = xmalloc(len); |
466 | (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP, | 472 | (void) sprintf(bp, "exec %s%s%s %s %s", _PATH_CP, |
467 | iamrecursive ? " -r" : "", pflag ? " -p" : "", | 473 | iamrecursive ? " -r" : "", pflag ? " -p" : "", |
468 | argv[i], argv[argc - 1]); | 474 | argv[i], argv[argc - 1]); |
469 | if (verbose_mode) | 475 | if (verbose_mode) |
470 | fprintf(stderr, "Executing: %s\n", bp); | 476 | fprintf(stderr, "Executing: %s\n", bp); |
471 | if (system(bp)) | 477 | if (system(bp)) |
@@ -491,7 +497,7 @@ tolocal(argc, argv) | |||
491 | len = strlen(src) + CMDNEEDS + 20; | 497 | len = strlen(src) + CMDNEEDS + 20; |
492 | bp = xmalloc(len); | 498 | bp = xmalloc(len); |
493 | (void) sprintf(bp, "%s -f %s", cmd, src); | 499 | (void) sprintf(bp, "%s -f %s", cmd, src); |
494 | if (do_cmd(host, suser, bp, &remin, &remout) < 0) { | 500 | if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { |
495 | (void) xfree(bp); | 501 | (void) xfree(bp); |
496 | ++errs; | 502 | ++errs; |
497 | continue; | 503 | continue; |
@@ -548,8 +554,8 @@ syserr: run_err("%s: %s", name, strerror(errno)); | |||
548 | * versions expecting microseconds. | 554 | * versions expecting microseconds. |
549 | */ | 555 | */ |
550 | (void) sprintf(buf, "T%lu 0 %lu 0\n", | 556 | (void) sprintf(buf, "T%lu 0 %lu 0\n", |
551 | (unsigned long) stb.st_mtime, | 557 | (unsigned long) stb.st_mtime, |
552 | (unsigned long) stb.st_atime); | 558 | (unsigned long) stb.st_atime); |
553 | (void) atomicio(write, remout, buf, strlen(buf)); | 559 | (void) atomicio(write, remout, buf, strlen(buf)); |
554 | if (response() < 0) | 560 | if (response() < 0) |
555 | goto next; | 561 | goto next; |
@@ -626,8 +632,8 @@ rsource(name, statp) | |||
626 | last++; | 632 | last++; |
627 | if (pflag) { | 633 | if (pflag) { |
628 | (void) sprintf(path, "T%lu 0 %lu 0\n", | 634 | (void) sprintf(path, "T%lu 0 %lu 0\n", |
629 | (unsigned long) statp->st_mtime, | 635 | (unsigned long) statp->st_mtime, |
630 | (unsigned long) statp->st_atime); | 636 | (unsigned long) statp->st_atime); |
631 | (void) atomicio(write, remout, path, strlen(path)); | 637 | (void) atomicio(write, remout, path, strlen(path)); |
632 | if (response() < 0) { | 638 | if (response() < 0) { |
633 | closedir(dirp); | 639 | closedir(dirp); |
@@ -635,8 +641,7 @@ rsource(name, statp) | |||
635 | } | 641 | } |
636 | } | 642 | } |
637 | (void) sprintf(path, "D%04o %d %.1024s\n", | 643 | (void) sprintf(path, "D%04o %d %.1024s\n", |
638 | (unsigned int) (statp->st_mode & FILEMODEMASK), | 644 | (unsigned int) (statp->st_mode & FILEMODEMASK), 0, last); |
639 | 0, last); | ||
640 | if (verbose_mode) | 645 | if (verbose_mode) |
641 | fprintf(stderr, "Entering directory: %s", path); | 646 | fprintf(stderr, "Entering directory: %s", path); |
642 | (void) atomicio(write, remout, path, strlen(path)); | 647 | (void) atomicio(write, remout, path, strlen(path)); |
@@ -783,7 +788,7 @@ sink(argc, argv) | |||
783 | if (need > cursize) | 788 | if (need > cursize) |
784 | namebuf = xmalloc(need); | 789 | namebuf = xmalloc(need); |
785 | (void) sprintf(namebuf, "%s%s%s", targ, | 790 | (void) sprintf(namebuf, "%s%s%s", targ, |
786 | *targ ? "/" : "", cp); | 791 | *targ ? "/" : "", cp); |
787 | np = namebuf; | 792 | np = namebuf; |
788 | } else | 793 | } else |
789 | np = targ; | 794 | np = targ; |
@@ -954,8 +959,9 @@ response() | |||
954 | void | 959 | void |
955 | usage() | 960 | usage() |
956 | { | 961 | { |
957 | (void) fprintf(stderr, | 962 | (void) fprintf(stderr, "usage: scp " |
958 | "usage: scp [-pqrvC46] [-P port] [-c cipher] [-i identity] f1 f2; or:\n scp [options] f1 ... fn directory\n"); | 963 | "[-pqrvC46] [-S ssh] [-P port] [-c cipher] [-i identity] f1 f2; or:\n" |
964 | " scp [options] f1 ... fn directory\n"); | ||
959 | exit(1); | 965 | exit(1); |
960 | } | 966 | } |
961 | 967 | ||
@@ -984,43 +990,6 @@ run_err(const char *fmt,...) | |||
984 | } | 990 | } |
985 | } | 991 | } |
986 | 992 | ||
987 | /* Stuff below is from BSD rcp util.c. */ | ||
988 | |||
989 | /*- | ||
990 | * Copyright (c) 1992, 1993 | ||
991 | * The Regents of the University of California. All rights reserved. | ||
992 | * | ||
993 | * Redistribution and use in source and binary forms, with or without | ||
994 | * modification, are permitted provided that the following conditions | ||
995 | * are met: | ||
996 | * 1. Redistributions of source code must retain the above copyright | ||
997 | * notice, this list of conditions and the following disclaimer. | ||
998 | * 2. Redistributions in binary form must reproduce the above copyright | ||
999 | * notice, this list of conditions and the following disclaimer in the | ||
1000 | * documentation and/or other materials provided with the distribution. | ||
1001 | * 3. All advertising materials mentioning features or use of this software | ||
1002 | * must display the following acknowledgement: | ||
1003 | * This product includes software developed by the University of | ||
1004 | * California, Berkeley and its contributors. | ||
1005 | * 4. Neither the name of the University nor the names of its contributors | ||
1006 | * may be used to endorse or promote products derived from this software | ||
1007 | * without specific prior written permission. | ||
1008 | * | ||
1009 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
1010 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
1011 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
1012 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
1013 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
1014 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
1015 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
1016 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
1017 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
1018 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
1019 | * SUCH DAMAGE. | ||
1020 | * | ||
1021 | * $OpenBSD: scp.c,v 1.33 2000/07/13 23:19:31 provos Exp $ | ||
1022 | */ | ||
1023 | |||
1024 | char * | 993 | char * |
1025 | colon(cp) | 994 | colon(cp) |
1026 | char *cp; | 995 | char *cp; |
@@ -1097,7 +1066,7 @@ allocbuf(bp, fd, blksize) | |||
1097 | size = blksize; | 1066 | size = blksize; |
1098 | else | 1067 | else |
1099 | size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % | 1068 | size = blksize + (stb.st_blksize - blksize % stb.st_blksize) % |
1100 | stb.st_blksize; | 1069 | stb.st_blksize; |
1101 | if (bp->cnt >= size) | 1070 | if (bp->cnt >= size) |
1102 | return (bp); | 1071 | return (bp); |
1103 | if (bp->buf == NULL) | 1072 | if (bp->buf == NULL) |
@@ -1228,14 +1197,14 @@ progressmeter(int flag) | |||
1228 | i = remaining / 3600; | 1197 | i = remaining / 3600; |
1229 | if (i) | 1198 | if (i) |
1230 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1199 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1231 | "%2d:", i); | 1200 | "%2d:", i); |
1232 | else | 1201 | else |
1233 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1202 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1234 | " "); | 1203 | " "); |
1235 | i = remaining % 3600; | 1204 | i = remaining % 3600; |
1236 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | 1205 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), |
1237 | "%02d:%02d%s", i / 60, i % 60, | 1206 | "%02d:%02d%s", i / 60, i % 60, |
1238 | (flag != 1) ? " ETA" : " "); | 1207 | (flag != 1) ? " ETA" : " "); |
1239 | } | 1208 | } |
1240 | atomicio(write, fileno(stdout), buf, strlen(buf)); | 1209 | atomicio(write, fileno(stdout), buf, strlen(buf)); |
1241 | 1210 | ||