scp.c (107857) | scp.c (113911) |
---|---|
1/* 2 * scp - secure remote copy. This is basically patched BSD rcp which 3 * uses ssh to do the data transfer (instead of using rcmd). 4 * 5 * NOTE: This version should NOT be suid root. (This uses ssh to 6 * do the transfer and ssh has the necessary privileges.) 7 * 8 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> --- 61 unchanged lines hidden (view full) --- 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 */ 76 77#include "includes.h" | 1/* 2 * scp - secure remote copy. This is basically patched BSD rcp which 3 * uses ssh to do the data transfer (instead of using rcmd). 4 * 5 * NOTE: This version should NOT be suid root. (This uses ssh to 6 * do the transfer and ssh has the necessary privileges.) 7 * 8 * 1995 Timo Rinne <tri@iki.fi>, Tatu Ylonen <ylo@cs.hut.fi> --- 61 unchanged lines hidden (view full) --- 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 */ 76 77#include "includes.h" |
78RCSID("$OpenBSD: scp.c,v 1.91 2002/06/19 00:27:55 deraadt Exp $"); 79RCSID("$FreeBSD: head/crypto/openssh/scp.c 107857 2002-12-14 13:38:49Z des $"); | 78RCSID("$OpenBSD: scp.c,v 1.102 2003/03/05 22:33:43 markus Exp $"); 79RCSID("$FreeBSD: head/crypto/openssh/scp.c 113911 2003-04-23 17:13:13Z des $"); |
80 81#include "xmalloc.h" 82#include "atomicio.h" 83#include "pathnames.h" 84#include "log.h" 85#include "misc.h" | 80 81#include "xmalloc.h" 82#include "atomicio.h" 83#include "pathnames.h" 84#include "log.h" 85#include "misc.h" |
86#include "progressmeter.h" |
|
86 87#ifdef HAVE___PROGNAME 88extern char *__progname; 89#else 90char *__progname; 91#endif 92 | 87 88#ifdef HAVE___PROGNAME 89extern char *__progname; 90#else 91char *__progname; 92#endif 93 |
93/* For progressmeter() -- number of seconds before xfer considered "stalled" */ 94#define STALLTIME 5 95/* alarm() interval for updating progress meter */ 96#define PROGRESSTIME 1 | 94void bwlimit(int); |
97 | 95 |
98/* Visual statistics about files as they are transferred. */ 99void progressmeter(int); 100 101/* Returns width of the terminal (for progress meter calculations). */ 102int getttywidth(void); 103int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); 104 | |
105/* Struct for addargs */ 106arglist args; 107 | 96/* Struct for addargs */ 97arglist args; 98 |
108/* Time a transfer started. */ 109static struct timeval start; | 99/* Bandwidth limit */ 100off_t limitbw = 0; |
110 | 101 |
111/* Number of bytes of current file transferred so far. */ 112volatile off_t statbytes; 113 114/* Total size of current file. */ 115off_t totalbytes = 0; 116 | |
117/* Name of current file being transferred. */ 118char *curfile; 119 120/* This is set to non-zero to enable verbose mode. */ 121int verbose_mode = 0; 122 123/* This is set to zero if the progressmeter is not desired. */ 124int showprogress = 1; 125 126/* This is the program to execute for the secured connection. ("ssh" or -S) */ 127char *ssh_program = _PATH_SSH_PROGRAM; 128 | 102/* Name of current file being transferred. */ 103char *curfile; 104 105/* This is set to non-zero to enable verbose mode. */ 106int verbose_mode = 0; 107 108/* This is set to zero if the progressmeter is not desired. */ 109int showprogress = 1; 110 111/* This is the program to execute for the secured connection. ("ssh" or -S) */ 112char *ssh_program = _PATH_SSH_PROGRAM; 113 |
114/* This is used to store the pid of ssh_program */ 115pid_t do_cmd_pid; 116 |
|
129/* 130 * This function executes the given command as the specified user on the 131 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 132 * assigns the input and output file descriptors on success. 133 */ 134 135int 136do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) --- 18 unchanged lines hidden (view full) --- 155 if (pipe(pout) < 0) 156 fatal("pipe: %s", strerror(errno)); 157 158 /* Free the reserved descriptors. */ 159 close(reserved[0]); 160 close(reserved[1]); 161 162 /* For a child to execute the command on the remote host using ssh. */ | 117/* 118 * This function executes the given command as the specified user on the 119 * given host. This returns < 0 if execution fails, and >= 0 otherwise. This 120 * assigns the input and output file descriptors on success. 121 */ 122 123int 124do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc) --- 18 unchanged lines hidden (view full) --- 143 if (pipe(pout) < 0) 144 fatal("pipe: %s", strerror(errno)); 145 146 /* Free the reserved descriptors. */ 147 close(reserved[0]); 148 close(reserved[1]); 149 150 /* For a child to execute the command on the remote host using ssh. */ |
163 if (fork() == 0) { | 151 do_cmd_pid = fork(); 152 if (do_cmd_pid == 0) { |
164 /* Child. */ 165 close(pin[1]); 166 close(pout[0]); 167 dup2(pin[0], 0); 168 dup2(pout[1], 1); 169 close(pin[0]); 170 close(pout[1]); 171 172 args.list[0] = ssh_program; 173 if (remuser != NULL) 174 addargs(&args, "-l%s", remuser); 175 addargs(&args, "%s", host); 176 addargs(&args, "%s", cmd); 177 178 execvp(ssh_program, args.list); 179 perror(ssh_program); 180 exit(1); | 153 /* Child. */ 154 close(pin[1]); 155 close(pout[0]); 156 dup2(pin[0], 0); 157 dup2(pout[1], 1); 158 close(pin[0]); 159 close(pout[1]); 160 161 args.list[0] = ssh_program; 162 if (remuser != NULL) 163 addargs(&args, "-l%s", remuser); 164 addargs(&args, "%s", host); 165 addargs(&args, "%s", cmd); 166 167 execvp(ssh_program, args.list); 168 perror(ssh_program); 169 exit(1); |
170 } else if (do_cmd_pid == -1) { 171 fatal("fork: %s", strerror(errno)); |
|
181 } 182 /* Parent. Close the other side, and return the local side. */ 183 close(pin[0]); 184 *fdout = pin[1]; 185 close(pout[1]); 186 *fdin = pout[0]; 187 return 0; 188} --- 26 unchanged lines hidden (view full) --- 215void toremote(char *, int, char *[]); 216void usage(void); 217 218int 219main(argc, argv) 220 int argc; 221 char *argv[]; 222{ | 172 } 173 /* Parent. Close the other side, and return the local side. */ 174 close(pin[0]); 175 *fdout = pin[1]; 176 close(pout[1]); 177 *fdin = pout[0]; 178 return 0; 179} --- 26 unchanged lines hidden (view full) --- 206void toremote(char *, int, char *[]); 207void usage(void); 208 209int 210main(argc, argv) 211 int argc; 212 char *argv[]; 213{ |
223 int ch, fflag, tflag; 224 char *targ; | 214 int ch, fflag, tflag, status; 215 double speed; 216 char *targ, *endp; |
225 extern char *optarg; 226 extern int optind; 227 228 __progname = get_progname(argv[0]); 229 230 args.list = NULL; 231 addargs(&args, "ssh"); /* overwritten with ssh_program */ 232 addargs(&args, "-x"); 233 addargs(&args, "-oForwardAgent no"); 234 addargs(&args, "-oClearAllForwardings yes"); 235 236 fflag = tflag = 0; | 217 extern char *optarg; 218 extern int optind; 219 220 __progname = get_progname(argv[0]); 221 222 args.list = NULL; 223 addargs(&args, "ssh"); /* overwritten with ssh_program */ 224 addargs(&args, "-x"); 225 addargs(&args, "-oForwardAgent no"); 226 addargs(&args, "-oClearAllForwardings yes"); 227 228 fflag = tflag = 0; |
237 while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) | 229 while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1) |
238 switch (ch) { 239 /* User-visible flags. */ | 230 switch (ch) { 231 /* User-visible flags. */ |
232 case '1': 233 case '2': |
|
240 case '4': 241 case '6': 242 case 'C': 243 addargs(&args, "-%c", ch); 244 break; 245 case 'o': 246 case 'c': 247 case 'i': 248 case 'F': 249 addargs(&args, "-%c%s", ch, optarg); 250 break; 251 case 'P': 252 addargs(&args, "-p%s", optarg); 253 break; 254 case 'B': 255 addargs(&args, "-oBatchmode yes"); 256 break; | 234 case '4': 235 case '6': 236 case 'C': 237 addargs(&args, "-%c", ch); 238 break; 239 case 'o': 240 case 'c': 241 case 'i': 242 case 'F': 243 addargs(&args, "-%c%s", ch, optarg); 244 break; 245 case 'P': 246 addargs(&args, "-p%s", optarg); 247 break; 248 case 'B': 249 addargs(&args, "-oBatchmode yes"); 250 break; |
251 case 'l': 252 speed = strtod(optarg, &endp); 253 if (speed <= 0 || *endp != '\0') 254 usage(); 255 limitbw = speed * 1024; 256 break; |
|
257 case 'p': 258 pflag = 1; 259 break; 260 case 'r': 261 iamrecursive = 1; 262 break; 263 case 'S': 264 ssh_program = xstrdup(optarg); --- 48 unchanged lines hidden (view full) --- 313 exit(errs != 0); 314 } 315 if (argc < 2) 316 usage(); 317 if (argc > 2) 318 targetshouldbedirectory = 1; 319 320 remin = remout = -1; | 257 case 'p': 258 pflag = 1; 259 break; 260 case 'r': 261 iamrecursive = 1; 262 break; 263 case 'S': 264 ssh_program = xstrdup(optarg); --- 48 unchanged lines hidden (view full) --- 313 exit(errs != 0); 314 } 315 if (argc < 2) 316 usage(); 317 if (argc > 2) 318 targetshouldbedirectory = 1; 319 320 remin = remout = -1; |
321 do_cmd_pid = -1; |
|
321 /* Command to be executed on remote system using "ssh". */ 322 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 323 verbose_mode ? " -v" : "", 324 iamrecursive ? " -r" : "", pflag ? " -p" : "", 325 targetshouldbedirectory ? " -d" : ""); 326 327 (void) signal(SIGPIPE, lostconn); 328 329 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ 330 toremote(targ, argc, argv); 331 else { 332 tolocal(argc, argv); /* Dest is local host. */ 333 if (targetshouldbedirectory) 334 verifydir(argv[argc - 1]); 335 } | 322 /* Command to be executed on remote system using "ssh". */ 323 (void) snprintf(cmd, sizeof cmd, "scp%s%s%s%s", 324 verbose_mode ? " -v" : "", 325 iamrecursive ? " -r" : "", pflag ? " -p" : "", 326 targetshouldbedirectory ? " -d" : ""); 327 328 (void) signal(SIGPIPE, lostconn); 329 330 if ((targ = colon(argv[argc - 1]))) /* Dest is remote host. */ 331 toremote(targ, argc, argv); 332 else { 333 tolocal(argc, argv); /* Dest is local host. */ 334 if (targetshouldbedirectory) 335 verifydir(argv[argc - 1]); 336 } |
337 /* 338 * Finally check the exit status of the ssh process, if one was forked 339 * and no error has occured yet 340 */ 341 if (do_cmd_pid != -1 && errs == 0) { 342 if (remin != -1) 343 (void) close(remin); 344 if (remout != -1) 345 (void) close(remout); 346 if (waitpid(do_cmd_pid, &status, 0) == -1) 347 errs = 1; 348 else { 349 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) 350 errs = 1; 351 } 352 } |
|
336 exit(errs != 0); 337} 338 339void 340toremote(targ, argc, argv) 341 char *targ, *argv[]; 342 int argc; 343{ 344 int i, len; 345 char *bp, *host, *src, *suser, *thost, *tuser; 346 347 *targ++ = 0; 348 if (*targ == 0) 349 targ = "."; 350 | 353 exit(errs != 0); 354} 355 356void 357toremote(targ, argc, argv) 358 char *targ, *argv[]; 359 int argc; 360{ 361 int i, len; 362 char *bp, *host, *src, *suser, *thost, *tuser; 363 364 *targ++ = 0; 365 if (*targ == 0) 366 targ = "."; 367 |
351 if ((thost = strchr(argv[argc - 1], '@'))) { | 368 if ((thost = strrchr(argv[argc - 1], '@'))) { |
352 /* user@host */ 353 *thost++ = 0; 354 tuser = argv[argc - 1]; 355 if (*tuser == '\0') 356 tuser = NULL; | 369 /* user@host */ 370 *thost++ = 0; 371 tuser = argv[argc - 1]; 372 if (*tuser == '\0') 373 tuser = NULL; |
357 else if (!okname(tuser)) 358 exit(1); | |
359 } else { 360 thost = argv[argc - 1]; 361 tuser = NULL; 362 } 363 364 for (i = 0; i < argc - 1; i++) { 365 src = colon(argv[i]); 366 if (src) { /* remote to remote */ 367 static char *ssh_options = 368 "-x -o'ClearAllForwardings yes'"; 369 *src++ = 0; 370 if (*src == 0) 371 src = "."; | 374 } else { 375 thost = argv[argc - 1]; 376 tuser = NULL; 377 } 378 379 for (i = 0; i < argc - 1; i++) { 380 src = colon(argv[i]); 381 if (src) { /* remote to remote */ 382 static char *ssh_options = 383 "-x -o'ClearAllForwardings yes'"; 384 *src++ = 0; 385 if (*src == 0) 386 src = "."; |
372 host = strchr(argv[i], '@'); | 387 host = strrchr(argv[i], '@'); |
373 len = strlen(ssh_program) + strlen(argv[i]) + 374 strlen(src) + (tuser ? strlen(tuser) : 0) + 375 strlen(thost) + strlen(targ) + 376 strlen(ssh_options) + CMDNEEDS + 20; 377 bp = xmalloc(len); 378 if (host) { 379 *host++ = 0; 380 host = cleanhostname(host); 381 suser = argv[i]; 382 if (*suser == '\0') 383 suser = pwd->pw_name; | 388 len = strlen(ssh_program) + strlen(argv[i]) + 389 strlen(src) + (tuser ? strlen(tuser) : 0) + 390 strlen(thost) + strlen(targ) + 391 strlen(ssh_options) + CMDNEEDS + 20; 392 bp = xmalloc(len); 393 if (host) { 394 *host++ = 0; 395 host = cleanhostname(host); 396 suser = argv[i]; 397 if (*suser == '\0') 398 suser = pwd->pw_name; |
384 else if (!okname(suser)) | 399 else if (!okname(suser)) { 400 xfree(bp); |
385 continue; | 401 continue; |
402 } 403 if (tuser && !okname(tuser)) { 404 xfree(bp); 405 continue; 406 } |
|
386 snprintf(bp, len, 387 "%s%s %s -n " 388 "-l %s %s %s %s '%s%s%s:%s'", 389 ssh_program, verbose_mode ? " -v" : "", 390 ssh_options, suser, host, cmd, src, 391 tuser ? tuser : "", tuser ? "@" : "", 392 thost, targ); 393 } else { --- 49 unchanged lines hidden (view full) --- 443 if (system(bp)) 444 ++errs; 445 (void) xfree(bp); 446 continue; 447 } 448 *src++ = 0; 449 if (*src == 0) 450 src = "."; | 407 snprintf(bp, len, 408 "%s%s %s -n " 409 "-l %s %s %s %s '%s%s%s:%s'", 410 ssh_program, verbose_mode ? " -v" : "", 411 ssh_options, suser, host, cmd, src, 412 tuser ? tuser : "", tuser ? "@" : "", 413 thost, targ); 414 } else { --- 49 unchanged lines hidden (view full) --- 464 if (system(bp)) 465 ++errs; 466 (void) xfree(bp); 467 continue; 468 } 469 *src++ = 0; 470 if (*src == 0) 471 src = "."; |
451 if ((host = strchr(argv[i], '@')) == NULL) { | 472 if ((host = strrchr(argv[i], '@')) == NULL) { |
452 host = argv[i]; 453 suser = NULL; 454 } else { 455 *host++ = 0; 456 suser = argv[i]; 457 if (*suser == '\0') 458 suser = pwd->pw_name; | 473 host = argv[i]; 474 suser = NULL; 475 } else { 476 *host++ = 0; 477 suser = argv[i]; 478 if (*suser == '\0') 479 suser = pwd->pw_name; |
459 else if (!okname(suser)) 460 continue; | |
461 } 462 host = cleanhostname(host); 463 len = strlen(src) + CMDNEEDS + 20; 464 bp = xmalloc(len); 465 (void) snprintf(bp, len, "%s -f %s", cmd, src); 466 if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { 467 (void) xfree(bp); 468 ++errs; --- 9 unchanged lines hidden (view full) --- 478void 479source(argc, argv) 480 int argc; 481 char *argv[]; 482{ 483 struct stat stb; 484 static BUF buffer; 485 BUF *bp; | 480 } 481 host = cleanhostname(host); 482 len = strlen(src) + CMDNEEDS + 20; 483 bp = xmalloc(len); 484 (void) snprintf(bp, len, "%s -f %s", cmd, src); 485 if (do_cmd(host, suser, bp, &remin, &remout, argc) < 0) { 486 (void) xfree(bp); 487 ++errs; --- 9 unchanged lines hidden (view full) --- 497void 498source(argc, argv) 499 int argc; 500 char *argv[]; 501{ 502 struct stat stb; 503 static BUF buffer; 504 BUF *bp; |
486 off_t i, amt, result; | 505 off_t i, amt, result, statbytes; |
487 int fd, haderr, indx; 488 char *last, *name, buf[2048]; 489 int len; 490 491 for (indx = 0; indx < argc; ++indx) { 492 name = argv[indx]; 493 statbytes = 0; 494 len = strlen(name); --- 48 unchanged lines hidden (view full) --- 543#else 544 /* XXX: Handle integer overflow? */ 545 snprintf(buf, sizeof buf, "C%04o %lu %s\n", 546 (u_int) (stb.st_mode & FILEMODEMASK), 547 (u_long) stb.st_size, last); 548#endif 549 if (verbose_mode) { 550 fprintf(stderr, "Sending file modes: %s", buf); | 506 int fd, haderr, indx; 507 char *last, *name, buf[2048]; 508 int len; 509 510 for (indx = 0; indx < argc; ++indx) { 511 name = argv[indx]; 512 statbytes = 0; 513 len = strlen(name); --- 48 unchanged lines hidden (view full) --- 562#else 563 /* XXX: Handle integer overflow? */ 564 snprintf(buf, sizeof buf, "C%04o %lu %s\n", 565 (u_int) (stb.st_mode & FILEMODEMASK), 566 (u_long) stb.st_size, last); 567#endif 568 if (verbose_mode) { 569 fprintf(stderr, "Sending file modes: %s", buf); |
551 fflush(stderr); | |
552 } 553 (void) atomicio(write, remout, buf, strlen(buf)); 554 if (response() < 0) 555 goto next; 556 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { 557next: (void) close(fd); 558 continue; 559 } | 570 } 571 (void) atomicio(write, remout, buf, strlen(buf)); 572 if (response() < 0) 573 goto next; 574 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { 575next: (void) close(fd); 576 continue; 577 } |
560 if (showprogress) { 561 totalbytes = stb.st_size; 562 progressmeter(-1); 563 } | 578 if (showprogress) 579 start_progress_meter(curfile, stb.st_size, &statbytes); |
564 /* Keep writing after an error so that we stay sync'd up. */ 565 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 566 amt = bp->cnt; 567 if (i + amt > stb.st_size) 568 amt = stb.st_size - i; 569 if (!haderr) { 570 result = atomicio(read, fd, bp->buf, amt); 571 if (result != amt) 572 haderr = result >= 0 ? EIO : errno; 573 } 574 if (haderr) 575 (void) atomicio(write, remout, bp->buf, amt); 576 else { 577 result = atomicio(write, remout, bp->buf, amt); 578 if (result != amt) 579 haderr = result >= 0 ? EIO : errno; 580 statbytes += result; 581 } | 580 /* Keep writing after an error so that we stay sync'd up. */ 581 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 582 amt = bp->cnt; 583 if (i + amt > stb.st_size) 584 amt = stb.st_size - i; 585 if (!haderr) { 586 result = atomicio(read, fd, bp->buf, amt); 587 if (result != amt) 588 haderr = result >= 0 ? EIO : errno; 589 } 590 if (haderr) 591 (void) atomicio(write, remout, bp->buf, amt); 592 else { 593 result = atomicio(write, remout, bp->buf, amt); 594 if (result != amt) 595 haderr = result >= 0 ? EIO : errno; 596 statbytes += result; 597 } |
598 if (limitbw) 599 bwlimit(amt); |
|
582 } 583 if (showprogress) | 600 } 601 if (showprogress) |
584 progressmeter(1); | 602 stop_progress_meter(); |
585 586 if (close(fd) < 0 && !haderr) 587 haderr = errno; 588 if (!haderr) 589 (void) atomicio(write, remout, "", 1); 590 else 591 run_err("%s: %s", name, strerror(haderr)); 592 (void) response(); --- 51 unchanged lines hidden (view full) --- 644 source(1, vect); 645 } 646 (void) closedir(dirp); 647 (void) atomicio(write, remout, "E\n", 2); 648 (void) response(); 649} 650 651void | 603 604 if (close(fd) < 0 && !haderr) 605 haderr = errno; 606 if (!haderr) 607 (void) atomicio(write, remout, "", 1); 608 else 609 run_err("%s: %s", name, strerror(haderr)); 610 (void) response(); --- 51 unchanged lines hidden (view full) --- 662 source(1, vect); 663 } 664 (void) closedir(dirp); 665 (void) atomicio(write, remout, "E\n", 2); 666 (void) response(); 667} 668 669void |
670bwlimit(int amount) 671{ 672 static struct timeval bwstart, bwend; 673 static int lamt, thresh = 16384; 674 u_int64_t wait; 675 struct timespec ts, rm; 676 677 if (!timerisset(&bwstart)) { 678 gettimeofday(&bwstart, NULL); 679 return; 680 } 681 682 lamt += amount; 683 if (lamt < thresh) 684 return; 685 686 gettimeofday(&bwend, NULL); 687 timersub(&bwend, &bwstart, &bwend); 688 if (!timerisset(&bwend)) 689 return; 690 691 lamt *= 8; 692 wait = (double)1000000L * lamt / limitbw; 693 694 bwstart.tv_sec = wait / 1000000L; 695 bwstart.tv_usec = wait % 1000000L; 696 697 if (timercmp(&bwstart, &bwend, >)) { 698 timersub(&bwstart, &bwend, &bwend); 699 700 /* Adjust the wait time */ 701 if (bwend.tv_sec) { 702 thresh /= 2; 703 if (thresh < 2048) 704 thresh = 2048; 705 } else if (bwend.tv_usec < 100) { 706 thresh *= 2; 707 if (thresh > 32768) 708 thresh = 32768; 709 } 710 711 TIMEVAL_TO_TIMESPEC(&bwend, &ts); 712 while (nanosleep(&ts, &rm) == -1) { 713 if (errno != EINTR) 714 break; 715 ts = rm; 716 } 717 } 718 719 lamt = 0; 720 gettimeofday(&bwstart, NULL); 721} 722 723void |
|
652sink(argc, argv) 653 int argc; 654 char *argv[]; 655{ 656 static BUF buffer; 657 struct stat stb; 658 enum { 659 YES, NO, DISPLAYED 660 } wrerr; 661 BUF *bp; 662 off_t i, j; 663 int amt, count, exists, first, mask, mode, ofd, omode; | 724sink(argc, argv) 725 int argc; 726 char *argv[]; 727{ 728 static BUF buffer; 729 struct stat stb; 730 enum { 731 YES, NO, DISPLAYED 732 } wrerr; 733 BUF *bp; 734 off_t i, j; 735 int amt, count, exists, first, mask, mode, ofd, omode; |
664 off_t size; | 736 off_t size, statbytes; |
665 int setimes, targisdir, wrerrno = 0; 666 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 667 struct timeval tv[2]; 668 669#define atime tv[0] 670#define mtime tv[1] 671#define SCREWUP(str) do { why = str; goto screwup; } while (0) 672 --- 145 unchanged lines hidden (view full) --- 818 (void) atomicio(write, remout, "", 1); 819 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { 820 (void) close(ofd); 821 continue; 822 } 823 cp = bp->buf; 824 wrerr = NO; 825 | 737 int setimes, targisdir, wrerrno = 0; 738 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; 739 struct timeval tv[2]; 740 741#define atime tv[0] 742#define mtime tv[1] 743#define SCREWUP(str) do { why = str; goto screwup; } while (0) 744 --- 145 unchanged lines hidden (view full) --- 890 (void) atomicio(write, remout, "", 1); 891 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { 892 (void) close(ofd); 893 continue; 894 } 895 cp = bp->buf; 896 wrerr = NO; 897 |
826 if (showprogress) { 827 totalbytes = size; 828 progressmeter(-1); 829 } | |
830 statbytes = 0; | 898 statbytes = 0; |
899 if (showprogress) 900 start_progress_meter(curfile, size, &statbytes); |
|
831 for (count = i = 0; i < size; i += 4096) { 832 amt = 4096; 833 if (i + amt > size) 834 amt = size - i; 835 count += amt; 836 do { 837 j = read(remin, cp, amt); 838 if (j == -1 && (errno == EINTR || 839 errno == EAGAIN)) { 840 continue; 841 } else if (j <= 0) { 842 run_err("%s", j ? strerror(errno) : 843 "dropped connection"); 844 exit(1); 845 } 846 amt -= j; 847 cp += j; 848 statbytes += j; 849 } while (amt > 0); | 901 for (count = i = 0; i < size; i += 4096) { 902 amt = 4096; 903 if (i + amt > size) 904 amt = size - i; 905 count += amt; 906 do { 907 j = read(remin, cp, amt); 908 if (j == -1 && (errno == EINTR || 909 errno == EAGAIN)) { 910 continue; 911 } else if (j <= 0) { 912 run_err("%s", j ? strerror(errno) : 913 "dropped connection"); 914 exit(1); 915 } 916 amt -= j; 917 cp += j; 918 statbytes += j; 919 } while (amt > 0); |
920 921 if (limitbw) 922 bwlimit(4096); 923 |
|
850 if (count == bp->cnt) { 851 /* Keep reading so we stay sync'd up. */ 852 if (wrerr == NO) { 853 j = atomicio(write, ofd, bp->buf, count); 854 if (j != count) { 855 wrerr = YES; 856 wrerrno = j >= 0 ? EIO : errno; 857 } 858 } 859 count = 0; 860 cp = bp->buf; 861 } 862 } 863 if (showprogress) | 924 if (count == bp->cnt) { 925 /* Keep reading so we stay sync'd up. */ 926 if (wrerr == NO) { 927 j = atomicio(write, ofd, bp->buf, count); 928 if (j != count) { 929 wrerr = YES; 930 wrerrno = j >= 0 ? EIO : errno; 931 } 932 } 933 count = 0; 934 cp = bp->buf; 935 } 936 } 937 if (showprogress) |
864 progressmeter(1); | 938 stop_progress_meter(); |
865 if (count != 0 && wrerr == NO && 866 (j = atomicio(write, ofd, bp->buf, count)) != count) { 867 wrerr = YES; 868 wrerrno = j >= 0 ? EIO : errno; 869 } | 939 if (count != 0 && wrerr == NO && 940 (j = atomicio(write, ofd, bp->buf, count)) != count) { 941 wrerr = YES; 942 wrerrno = j >= 0 ? EIO : errno; 943 } |
870 if (ftruncate(ofd, size)) { | 944 if (wrerr == NO && ftruncate(ofd, size) != 0) { |
871 run_err("%s: truncate: %s", np, strerror(errno)); 872 wrerr = DISPLAYED; 873 } 874 if (pflag) { 875 if (exists || omode != mode) 876#ifdef HAVE_FCHMOD 877 if (fchmod(ofd, omode)) 878#else /* HAVE_FCHMOD */ --- 72 unchanged lines hidden (view full) --- 951 } 952 /* NOTREACHED */ 953} 954 955void 956usage(void) 957{ 958 (void) fprintf(stderr, | 945 run_err("%s: truncate: %s", np, strerror(errno)); 946 wrerr = DISPLAYED; 947 } 948 if (pflag) { 949 if (exists || omode != mode) 950#ifdef HAVE_FCHMOD 951 if (fchmod(ofd, omode)) 952#else /* HAVE_FCHMOD */ --- 72 unchanged lines hidden (view full) --- 1025 } 1026 /* NOTREACHED */ 1027} 1028 1029void 1030usage(void) 1031{ 1032 (void) fprintf(stderr, |
959 "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" 960 " [-c cipher] [-i identity] [-o option]\n" | 1033 "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n" 1034 " [-c cipher] [-i identity] [-l limit] [-o option]\n" |
961 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); 962 exit(1); 963} 964 965void 966run_err(const char *fmt,...) 967{ 968 static FILE *fp; --- 40 unchanged lines hidden (view full) --- 1009 int c; 1010 char *cp; 1011 1012 cp = cp0; 1013 do { 1014 c = (int)*cp; 1015 if (c & 0200) 1016 goto bad; | 1035 " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); 1036 exit(1); 1037} 1038 1039void 1040run_err(const char *fmt,...) 1041{ 1042 static FILE *fp; --- 40 unchanged lines hidden (view full) --- 1083 int c; 1084 char *cp; 1085 1086 cp = cp0; 1087 do { 1088 c = (int)*cp; 1089 if (c & 0200) 1090 goto bad; |
1017 if (!isalpha(c) && !isdigit(c) && 1018 c != '_' && c != '-' && c != '.' && c != '+') 1019 goto bad; | 1091 if (!isalpha(c) && !isdigit(c)) { 1092 switch (c) { 1093 case '\'': 1094 case '"': 1095 case '`': 1096 case ' ': 1097 case '#': 1098 goto bad; 1099 default: 1100 break; 1101 } 1102 } |
1020 } while (*++cp); 1021 return (1); 1022 1023bad: fprintf(stderr, "%s: invalid user name\n", cp0); 1024 return (0); 1025} 1026 1027BUF * --- 4 unchanged lines hidden (view full) --- 1032 size_t size; 1033#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1034 struct stat stb; 1035 1036 if (fstat(fd, &stb) < 0) { 1037 run_err("fstat: %s", strerror(errno)); 1038 return (0); 1039 } | 1103 } while (*++cp); 1104 return (1); 1105 1106bad: fprintf(stderr, "%s: invalid user name\n", cp0); 1107 return (0); 1108} 1109 1110BUF * --- 4 unchanged lines hidden (view full) --- 1115 size_t size; 1116#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE 1117 struct stat stb; 1118 1119 if (fstat(fd, &stb) < 0) { 1120 run_err("fstat: %s", strerror(errno)); 1121 return (0); 1122 } |
1040 if (stb.st_blksize == 0) | 1123 size = roundup(stb.st_blksize, blksize); 1124 if (size == 0) |
1041 size = blksize; | 1125 size = blksize; |
1042 else 1043 size = roundup(stb.st_blksize, blksize); | |
1044#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1045 size = blksize; 1046#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1047 if (bp->cnt >= size) 1048 return (bp); 1049 if (bp->buf == NULL) 1050 bp->buf = xmalloc(size); 1051 else --- 9 unchanged lines hidden (view full) --- 1061{ 1062 if (!iamremote) 1063 write(STDERR_FILENO, "lost connection\n", 16); 1064 if (signo) 1065 _exit(1); 1066 else 1067 exit(1); 1068} | 1126#else /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1127 size = blksize; 1128#endif /* HAVE_STRUCT_STAT_ST_BLKSIZE */ 1129 if (bp->cnt >= size) 1130 return (bp); 1131 if (bp->buf == NULL) 1132 bp->buf = xmalloc(size); 1133 else --- 9 unchanged lines hidden (view full) --- 1143{ 1144 if (!iamremote) 1145 write(STDERR_FILENO, "lost connection\n", 16); 1146 if (signo) 1147 _exit(1); 1148 else 1149 exit(1); 1150} |
1069 1070static void 1071updateprogressmeter(int ignore) 1072{ 1073 int save_errno = errno; 1074 1075 progressmeter(0); 1076 signal(SIGALRM, updateprogressmeter); 1077 alarm(PROGRESSTIME); 1078 errno = save_errno; 1079} 1080 1081static int 1082foregroundproc(void) 1083{ 1084 static pid_t pgrp = -1; 1085 int ctty_pgrp; 1086 1087 if (pgrp == -1) 1088 pgrp = getpgrp(); 1089 1090#ifdef HAVE_TCGETPGRP 1091 return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 && 1092 ctty_pgrp == pgrp); 1093#else 1094 return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 && 1095 ctty_pgrp == pgrp)); 1096#endif 1097} 1098 1099void 1100progressmeter(int flag) 1101{ 1102 static const char prefixes[] = " KMGTP"; 1103 static struct timeval lastupdate; 1104 static off_t lastsize; 1105 struct timeval now, td, wait; 1106 off_t cursize, abbrevsize; 1107 double elapsed; 1108 int ratio, barlength, i, remaining; 1109 char buf[512]; 1110 1111 if (flag == -1) { 1112 (void) gettimeofday(&start, (struct timezone *) 0); 1113 lastupdate = start; 1114 lastsize = 0; 1115 } 1116 if (foregroundproc() == 0) 1117 return; 1118 1119 (void) gettimeofday(&now, (struct timezone *) 0); 1120 cursize = statbytes; 1121 if (totalbytes != 0) { 1122 ratio = 100.0 * cursize / totalbytes; 1123 ratio = MAX(ratio, 0); 1124 ratio = MIN(ratio, 100); 1125 } else 1126 ratio = 100; 1127 1128 snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio); 1129 1130 barlength = getttywidth() - 51; 1131 if (barlength > 0) { 1132 i = barlength * ratio / 100; 1133 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1134 "|%.*s%*s|", i, 1135 "*******************************************************" 1136 "*******************************************************" 1137 "*******************************************************" 1138 "*******************************************************" 1139 "*******************************************************" 1140 "*******************************************************" 1141 "*******************************************************", 1142 barlength - i, ""); 1143 } 1144 i = 0; 1145 abbrevsize = cursize; 1146 while (abbrevsize >= 100000 && i < sizeof(prefixes)) { 1147 i++; 1148 abbrevsize >>= 10; 1149 } 1150 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ", 1151 (unsigned long) abbrevsize, prefixes[i], 1152 prefixes[i] == ' ' ? ' ' : 'B'); 1153 1154 timersub(&now, &lastupdate, &wait); 1155 if (cursize > lastsize) { 1156 lastupdate = now; 1157 lastsize = cursize; 1158 if (wait.tv_sec >= STALLTIME) { 1159 start.tv_sec += wait.tv_sec; 1160 start.tv_usec += wait.tv_usec; 1161 } 1162 wait.tv_sec = 0; 1163 } 1164 timersub(&now, &start, &td); 1165 elapsed = td.tv_sec + (td.tv_usec / 1000000.0); 1166 1167 if (flag != 1 && 1168 (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) { 1169 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1170 " --:-- ETA"); 1171 } else if (wait.tv_sec >= STALLTIME) { 1172 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1173 " - stalled -"); 1174 } else { 1175 if (flag != 1) 1176 remaining = (int)(totalbytes / (statbytes / elapsed) - 1177 elapsed); 1178 else 1179 remaining = elapsed; 1180 1181 i = remaining / 3600; 1182 if (i) 1183 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1184 "%2d:", i); 1185 else 1186 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1187 " "); 1188 i = remaining % 3600; 1189 snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), 1190 "%02d:%02d%s", i / 60, i % 60, 1191 (flag != 1) ? " ETA" : " "); 1192 } 1193 atomicio(write, fileno(stdout), buf, strlen(buf)); 1194 1195 if (flag == -1) { 1196 mysignal(SIGALRM, updateprogressmeter); 1197 alarm(PROGRESSTIME); 1198 } else if (flag == 1) { 1199 alarm(0); 1200 atomicio(write, fileno(stdout), "\n", 1); 1201 statbytes = 0; 1202 } 1203} 1204 1205int 1206getttywidth(void) 1207{ 1208 struct winsize winsize; 1209 1210 if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1) 1211 return (winsize.ws_col ? winsize.ws_col : 80); 1212 else 1213 return (80); 1214} | |