diff options
Diffstat (limited to 'scp.c')
-rw-r--r-- | scp.c | 80 |
1 files changed, 76 insertions, 4 deletions
@@ -75,7 +75,7 @@ | |||
75 | */ | 75 | */ |
76 | 76 | ||
77 | #include "includes.h" | 77 | #include "includes.h" |
78 | RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $"); | 78 | RCSID("$OpenBSD: scp.c,v 1.99 2003/01/23 14:01:53 markus Exp $"); |
79 | 79 | ||
80 | #include "xmalloc.h" | 80 | #include "xmalloc.h" |
81 | #include "atomicio.h" | 81 | #include "atomicio.h" |
@@ -90,9 +90,14 @@ extern char *__progname; | |||
90 | char *__progname; | 90 | char *__progname; |
91 | #endif | 91 | #endif |
92 | 92 | ||
93 | void bwlimit(int); | ||
94 | |||
93 | /* Struct for addargs */ | 95 | /* Struct for addargs */ |
94 | arglist args; | 96 | arglist args; |
95 | 97 | ||
98 | /* Bandwidth limit */ | ||
99 | off_t limit = 0; | ||
100 | |||
96 | /* Name of current file being transferred. */ | 101 | /* Name of current file being transferred. */ |
97 | char *curfile; | 102 | char *curfile; |
98 | 103 | ||
@@ -206,7 +211,8 @@ main(argc, argv) | |||
206 | char *argv[]; | 211 | char *argv[]; |
207 | { | 212 | { |
208 | int ch, fflag, tflag, status; | 213 | int ch, fflag, tflag, status; |
209 | char *targ; | 214 | double speed; |
215 | char *targ, *endp; | ||
210 | extern char *optarg; | 216 | extern char *optarg; |
211 | extern int optind; | 217 | extern int optind; |
212 | 218 | ||
@@ -219,7 +225,7 @@ main(argc, argv) | |||
219 | addargs(&args, "-oClearAllForwardings yes"); | 225 | addargs(&args, "-oClearAllForwardings yes"); |
220 | 226 | ||
221 | fflag = tflag = 0; | 227 | fflag = tflag = 0; |
222 | while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) | 228 | while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q46S:o:F:")) != -1) |
223 | switch (ch) { | 229 | switch (ch) { |
224 | /* User-visible flags. */ | 230 | /* User-visible flags. */ |
225 | case '4': | 231 | case '4': |
@@ -239,6 +245,12 @@ main(argc, argv) | |||
239 | case 'B': | 245 | case 'B': |
240 | addargs(&args, "-oBatchmode yes"); | 246 | addargs(&args, "-oBatchmode yes"); |
241 | break; | 247 | break; |
248 | case 'l': | ||
249 | speed = strtod(optarg, &endp); | ||
250 | if (speed <= 0 || *endp != '\0') | ||
251 | usage(); | ||
252 | limit = speed * 1024; | ||
253 | break; | ||
242 | case 'p': | 254 | case 'p': |
243 | pflag = 1; | 255 | pflag = 1; |
244 | break; | 256 | break; |
@@ -578,6 +590,8 @@ next: (void) close(fd); | |||
578 | haderr = result >= 0 ? EIO : errno; | 590 | haderr = result >= 0 ? EIO : errno; |
579 | statbytes += result; | 591 | statbytes += result; |
580 | } | 592 | } |
593 | if (limit) | ||
594 | bwlimit(amt); | ||
581 | } | 595 | } |
582 | if (showprogress) | 596 | if (showprogress) |
583 | stop_progress_meter(); | 597 | stop_progress_meter(); |
@@ -648,6 +662,60 @@ rsource(name, statp) | |||
648 | } | 662 | } |
649 | 663 | ||
650 | void | 664 | void |
665 | bwlimit(int amount) | ||
666 | { | ||
667 | static struct timeval bwstart, bwend; | ||
668 | static int lamt, thresh = 16384; | ||
669 | u_int64_t wait; | ||
670 | struct timespec ts, rm; | ||
671 | |||
672 | if (!timerisset(&bwstart)) { | ||
673 | gettimeofday(&bwstart, NULL); | ||
674 | return; | ||
675 | } | ||
676 | |||
677 | lamt += amount; | ||
678 | if (lamt < thresh) | ||
679 | return; | ||
680 | |||
681 | gettimeofday(&bwend, NULL); | ||
682 | timersub(&bwend, &bwstart, &bwend); | ||
683 | if (!timerisset(&bwend)) | ||
684 | return; | ||
685 | |||
686 | lamt *= 8; | ||
687 | wait = (double)1000000L * lamt / limit; | ||
688 | |||
689 | bwstart.tv_sec = wait / 1000000L; | ||
690 | bwstart.tv_usec = wait % 1000000L; | ||
691 | |||
692 | if (timercmp(&bwstart, &bwend, >)) { | ||
693 | timersub(&bwstart, &bwend, &bwend); | ||
694 | |||
695 | /* Adjust the wait time */ | ||
696 | if (bwend.tv_sec) { | ||
697 | thresh /= 2; | ||
698 | if (thresh < 2048) | ||
699 | thresh = 2048; | ||
700 | } else if (bwend.tv_usec < 100) { | ||
701 | thresh *= 2; | ||
702 | if (thresh > 32768) | ||
703 | thresh = 32768; | ||
704 | } | ||
705 | |||
706 | TIMEVAL_TO_TIMESPEC(&bwend, &ts); | ||
707 | while (nanosleep(&ts, &rm) == -1) { | ||
708 | if (errno != EINTR) | ||
709 | break; | ||
710 | ts = rm; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | lamt = 0; | ||
715 | gettimeofday(&bwstart, NULL); | ||
716 | } | ||
717 | |||
718 | void | ||
651 | sink(argc, argv) | 719 | sink(argc, argv) |
652 | int argc; | 720 | int argc; |
653 | char *argv[]; | 721 | char *argv[]; |
@@ -844,6 +912,10 @@ bad: run_err("%s: %s", np, strerror(errno)); | |||
844 | cp += j; | 912 | cp += j; |
845 | statbytes += j; | 913 | statbytes += j; |
846 | } while (amt > 0); | 914 | } while (amt > 0); |
915 | |||
916 | if (limit) | ||
917 | bwlimit(4096); | ||
918 | |||
847 | if (count == bp->cnt) { | 919 | if (count == bp->cnt) { |
848 | /* Keep reading so we stay sync'd up. */ | 920 | /* Keep reading so we stay sync'd up. */ |
849 | if (wrerr == NO) { | 921 | if (wrerr == NO) { |
@@ -954,7 +1026,7 @@ usage(void) | |||
954 | { | 1026 | { |
955 | (void) fprintf(stderr, | 1027 | (void) fprintf(stderr, |
956 | "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" | 1028 | "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" |
957 | " [-c cipher] [-i identity] [-o option]\n" | 1029 | " [-c cipher] [-i identity] [-l limit] [-o option]\n" |
958 | " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); | 1030 | " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); |
959 | exit(1); | 1031 | exit(1); |
960 | } | 1032 | } |