]> andersk Git - openssh.git/blobdiff - scp.c
- (bal) scp.c 'limit' conflicts with Cray. Rename to 'limitbw'
[openssh.git] / scp.c
diff --git a/scp.c b/scp.c
index 44b5b4582b204dc5e76769bce184ae79998b015a..35d4c5f7143e5a23bdf659f7a8200125fb7fdcab 100644 (file)
--- a/scp.c
+++ b/scp.c
@@ -75,7 +75,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.97 2003/01/10 08:19:07 fgsch Exp $");
+RCSID("$OpenBSD: scp.c,v 1.102 2003/03/05 22:33:43 markus Exp $");
 
 #include "xmalloc.h"
 #include "atomicio.h"
@@ -90,9 +90,14 @@ extern char *__progname;
 char *__progname;
 #endif
 
+void bwlimit(int);
+
 /* Struct for addargs */
 arglist args;
 
+/* Bandwidth limit */
+off_t limitbw = 0;
+
 /* Name of current file being transferred. */
 char *curfile;
 
@@ -206,7 +211,8 @@ main(argc, argv)
        char *argv[];
 {
        int ch, fflag, tflag, status;
-       char *targ;
+       double speed;
+       char *targ, *endp;
        extern char *optarg;
        extern int optind;
 
@@ -219,9 +225,11 @@ main(argc, argv)
        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:q1246S:o:F:")) != -1)
                switch (ch) {
                /* User-visible flags. */
+               case '1':
+               case '2':
                case '4':
                case '6':
                case 'C':
@@ -239,6 +247,12 @@ main(argc, argv)
                case 'B':
                        addargs(&args, "-oBatchmode yes");
                        break;
+               case 'l':
+                       speed = strtod(optarg, &endp);
+                       if (speed <= 0 || *endp != '\0')
+                               usage();
+                       limitbw = speed * 1024;
+                       break;
                case 'p':
                        pflag = 1;
                        break;
@@ -356,8 +370,6 @@ toremote(targ, argc, argv)
                tuser = argv[argc - 1];
                if (*tuser == '\0')
                        tuser = NULL;
-               else if (!okname(tuser))
-                       exit(1);
        } else {
                thost = argv[argc - 1];
                tuser = NULL;
@@ -383,8 +395,14 @@ toremote(targ, argc, argv)
                                suser = argv[i];
                                if (*suser == '\0')
                                        suser = pwd->pw_name;
-                               else if (!okname(suser))
+                               else if (!okname(suser)) {
+                                       xfree(bp);
+                                       continue;
+                               }
+                               if (tuser && !okname(tuser)) {
+                                       xfree(bp);
                                        continue;
+                               }
                                snprintf(bp, len,
                                    "%s%s %s -n "
                                    "-l %s %s %s %s '%s%s%s:%s'",
@@ -458,8 +476,6 @@ tolocal(argc, argv)
                        suser = argv[i];
                        if (*suser == '\0')
                                suser = pwd->pw_name;
-                       else if (!okname(suser))
-                               continue;
                }
                host = cleanhostname(host);
                len = strlen(src) + CMDNEEDS + 20;
@@ -578,6 +594,8 @@ next:                       (void) close(fd);
                                        haderr = result >= 0 ? EIO : errno;
                                statbytes += result;
                        }
+                       if (limitbw)
+                               bwlimit(amt);
                }
                if (showprogress)
                        stop_progress_meter();
@@ -647,6 +665,60 @@ rsource(name, statp)
        (void) response();
 }
 
+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 / limitbw;
+
+       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;
@@ -844,6 +916,10 @@ bad:                       run_err("%s: %s", np, strerror(errno));
                                cp += j;
                                statbytes += j;
                        } while (amt > 0);
+               
+                       if (limitbw)
+                               bwlimit(4096);
+
                        if (count == bp->cnt) {
                                /* Keep reading so we stay sync'd up. */
                                if (wrerr == NO) {
@@ -864,7 +940,7 @@ bad:                        run_err("%s: %s", np, strerror(errno));
                        wrerr = YES;
                        wrerrno = j >= 0 ? EIO : errno;
                }
-               if (ftruncate(ofd, size)) {
+               if (wrerr == NO && ftruncate(ofd, size) != 0) {
                        run_err("%s: truncate: %s", np, strerror(errno));
                        wrerr = DISPLAYED;
                }
@@ -953,8 +1029,8 @@ void
 usage(void)
 {
        (void) fprintf(stderr,
-           "usage: scp [-pqrvBC46] [-F config] [-S program] [-P port]\n"
-           "           [-c cipher] [-i identity] [-o option]\n"
+           "usage: scp [-pqrvBC1246] [-F config] [-S program] [-P port]\n"
+           "           [-c cipher] [-i identity] [-l limit] [-o option]\n"
            "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
        exit(1);
 }
@@ -1011,9 +1087,18 @@ okname(cp0)
                c = (int)*cp;
                if (c & 0200)
                        goto bad;
-               if (!isalpha(c) && !isdigit(c) &&
-                   c != '@' && c != '_' && c != '-' && c != '.' && c != '+')
-                       goto bad;
+               if (!isalpha(c) && !isdigit(c)) {
+                       switch (c) {
+                       case '\'':
+                       case '"':
+                       case '`':
+                       case ' ':
+                       case '#':
+                               goto bad;
+                       default:
+                               break;
+                       }
+               }
        } while (*++cp);
        return (1);
 
This page took 0.046815 seconds and 4 git commands to generate.