=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/scp.c,v retrieving revision 1.98 retrieving revision 1.99 diff -u -r1.98 -r1.99 --- src/usr.bin/ssh/scp.c 2003/01/10 10:29:35 1.98 +++ src/usr.bin/ssh/scp.c 2003/01/23 14:01:53 1.99 @@ -75,7 +75,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: scp.c,v 1.98 2003/01/10 10:29:35 djm Exp $"); +RCSID("$OpenBSD: scp.c,v 1.99 2003/01/23 14:01:53 markus Exp $"); #include "xmalloc.h" #include "atomicio.h" @@ -86,9 +86,14 @@ int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); +void bwlimit(int); + /* Struct for addargs */ arglist args; +/* Bandwidth limit */ +off_t limit = 0; + /* Name of current file being transferred. */ char *curfile; @@ -202,7 +207,8 @@ char *argv[]; { int ch, fflag, tflag, status; - char *targ; + double speed; + char *targ, *endp; extern char *optarg; extern int optind; @@ -213,7 +219,7 @@ addargs(&args, "-oClearAllForwardings yes"); fflag = tflag = 0; - while ((ch = getopt(argc, argv, "dfprtvBCc:i:P:q46S:o:F:")) != -1) + while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q46S:o:F:")) != -1) switch (ch) { /* User-visible flags. */ case '4': @@ -233,6 +239,12 @@ case 'B': addargs(&args, "-oBatchmode yes"); break; + case 'l': + speed = strtod(optarg, &endp); + if (speed <= 0 || *endp != '\0') + usage(); + limit = speed * 1024; + break; case 'p': pflag = 1; break; @@ -562,6 +574,8 @@ haderr = result >= 0 ? EIO : errno; statbytes += result; } + if (limit) + bwlimit(amt); } if (showprogress) stop_progress_meter(); @@ -632,6 +646,60 @@ } void +bwlimit(int amount) +{ + static struct timeval bwstart, bwend; + static int lamt, thresh = 16384; + u_int64_t wait; + struct timespec ts, rm; + + if (!timerisset(&bwstart)) { + gettimeofday(&bwstart, NULL); + return; + } + + lamt += amount; + if (lamt < thresh) + return; + + gettimeofday(&bwend, NULL); + timersub(&bwend, &bwstart, &bwend); + if (!timerisset(&bwend)) + return; + + lamt *= 8; + wait = (double)1000000L * lamt / limit; + + bwstart.tv_sec = wait / 1000000L; + bwstart.tv_usec = wait % 1000000L; + + if (timercmp(&bwstart, &bwend, >)) { + timersub(&bwstart, &bwend, &bwend); + + /* Adjust the wait time */ + if (bwend.tv_sec) { + thresh /= 2; + if (thresh < 2048) + thresh = 2048; + } else if (bwend.tv_usec < 100) { + thresh *= 2; + if (thresh > 32768) + thresh = 32768; + } + + TIMEVAL_TO_TIMESPEC(&bwend, &ts); + while (nanosleep(&ts, &rm) == -1) { + if (errno != EINTR) + break; + ts = rm; + } + } + + lamt = 0; + gettimeofday(&bwstart, NULL); +} + +void sink(argc, argv) int argc; char *argv[]; @@ -828,6 +896,10 @@ cp += j; statbytes += j; } while (amt > 0); + + if (limit) + bwlimit(4096); + if (count == bp->cnt) { /* Keep reading so we stay sync'd up. */ if (wrerr == NO) { @@ -930,7 +1002,7 @@ { (void) fprintf(stderr, "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n" - " [-c cipher] [-i identity] [-o option]\n" + " [-c cipher] [-i identity] [-l limit] [-o option]\n" " [[user@]host1:]file1 [...] [[user@]host2:]file2\n"); exit(1); }