SFTP Status Bar..

Wendy Palm wendyp at cray.com
Thu Feb 7 08:31:10 EST 2002


how do you "turn it on"?  is it automatic/default?

mouring wrote:
> 
> This is the LAST version I plan on doing.. If I hear no feed back good
> or bad.  Then I'll assume I've wasted my time on a feature that people
> whine about but don't care to try.  This is against 3.0.2pX so it
> should be VERY easy for anyone to test.
> 
> - Ben
> 
> diff -ur openssh-3.0.2p1/misc.c openssh/misc.c
> --- openssh-3.0.2p1/misc.c      Tue Jul  3 23:46:58 2001
> +++ openssh/misc.c      Wed Feb  6 13:15:55 2002
> @@ -30,6 +30,7 @@
>  #include "misc.h"
>  #include "log.h"
>  #include "xmalloc.h"
> +#include "atomicio.h"
> 
>  /* remove newline at end of string */
>  char *
> @@ -304,6 +305,139 @@
>         args->list = xrealloc(args->list, args->nalloc * sizeof(char *));
>         args->list[args->num++] = xstrdup(buf);
>         args->list[args->num] = NULL;
> +}
> +
> +/* scp/sftp progression meter (from src/usr.bin/ftp/util.c) */
> +static int
> +foregroundproc(void)
> +{
> +       static pid_t pgrp = -1;
> +       int ctty_pgrp;
> +
> +       if (pgrp == -1)
> +               pgrp = getpgrp();
> +
> +       return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
> +                ctty_pgrp == pgrp));
> +}
> +
> +int
> +getttywidth(void)
> +{
> +       struct winsize winsize;
> +
> +       if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
> +               return (winsize.ws_col ? winsize.ws_col : 80);
> +       else
> +               return (80);
> +}
> +
> +void
> +progressmeter(off_t statbytes, off_t totalbytes, char *filename)
> +{
> +#define STALLTIME       5 /* number of seconds before xfer assumed "stalled" */
> +       static const char prefixes[] = " KMGTP";
> +       static char *progressbar = NULL;
> +       static struct timeval *start = NULL, lastupdate;
> +       static off_t lastsize;
> +       static size_t progressbar_size = 0;
> +       struct timeval now, td, wait;
> +       off_t cursize, abbrevsize;
> +       double elapsed;
> +       int ratio, barlength, i, remaining;
> +       char buf[256];
> +
> +       if (!start) {
> +               start = xmalloc(sizeof(struct timeval));
> +               (void) gettimeofday(start, (struct timezone *) 0);
> +               lastupdate = *start;
> +               lastsize = 0;
> +       }
> +       if (foregroundproc() == 0)
> +               return;
> +
> +       (void) gettimeofday(&now, (struct timezone *) 0);
> +       cursize = statbytes;
> +       if (totalbytes != 0) {
> +               ratio = 100.0 * cursize / totalbytes;
> +               ratio = MAX(ratio, 0);
> +               ratio = MIN(ratio, 100);
> +       } else
> +               ratio = 100;
> +
> +       barlength = getttywidth() - 51;
> +       if (barlength > progressbar_size) {
> +               progressbar_size = barlength;
> +               progressbar = xrealloc(progressbar, barlength);
> +               memset(progressbar, '*', barlength);
> +       }
> +
> +       snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ",
> +           (filename?filename:""), ratio);
> +       if (barlength > 0) {
> +               i = barlength * ratio / 100;
> +               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                        "|%.*s%*s|", i, progressbar, barlength - i, "");
> +       }
> +       i = 0;
> +       abbrevsize = cursize;
> +       while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
> +               i++;
> +               abbrevsize >>= 10;
> +       }
> +       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5llu %c%c ",
> +           (unsigned long long) abbrevsize, prefixes[i],
> +           prefixes[i] == ' ' ? ' ' : 'B');
> +
> +       timersub(&now, &lastupdate, &wait);
> +       if (cursize > lastsize) {
> +               lastupdate = now;
> +               lastsize = cursize;
> +               if (wait.tv_sec >= STALLTIME) {
> +                       start->tv_sec += wait.tv_sec;
> +                       start->tv_usec += wait.tv_usec;
> +               }
> +               wait.tv_sec = 0;
> +       }
> +       timersub(&now, start, &td);
> +       elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
> +
> +       if ((totalbytes != statbytes) &&
> +           (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
> +               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                   "   --:-- ETA");
> +       } else if (wait.tv_sec >= STALLTIME) {
> +               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                   " - stalled -");
> +       } else {
> +               if (totalbytes != statbytes)
> +                       remaining = (int)(totalbytes / (statbytes / elapsed) -
> +                           elapsed);
> +               else
> +                       remaining = elapsed;
> +
> +               i = remaining / 3600;
> +               if (i)
> +                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                           "%2d:", i);
> +               else
> +                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                           "   ");
> +               i = remaining % 3600;
> +               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> +                   "%02d:%02d%s", i / 60, i % 60,
> +                     (totalbytes != statbytes) ? " ETA" : "    ");
> +       }
> +       atomicio(write, fileno(stdout), buf, strlen(buf));
> +
> +       if (totalbytes == statbytes) {
> +               atomicio(write, fileno(stdout), "\n", 1);
> +
> +               /* Clean up for next usage */
> +               xfree(start);
> +               start = NULL;
> +               statbytes = 0;
> +       }
>  }
> 
>  mysig_t
> Only in openssh: misc.c.orig
> diff -ur openssh-3.0.2p1/misc.h openssh/misc.h
> --- openssh-3.0.2p1/misc.h      Wed Jul  4 12:25:55 2001
> +++ openssh/misc.h      Wed Feb  6 13:02:33 2002
> @@ -29,7 +29,11 @@
>          int     num;
>          int     nalloc;
>  };
> +
>  void    addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
> +void    progressmeter(off_t statbytes, off_t totalbytes, char *curfile);
> +
> +#define PROGRESSTIME    1 /* alarm() interval for updating progress meter */
> 
>  /* wrapper for signal interface */
>  typedef void (*mysig_t)(int);
> diff -ur openssh-3.0.2p1/scp.c openssh/scp.c
> --- openssh-3.0.2p1/scp.c       Sun Oct 21 19:53:59 2001
> +++ openssh/scp.c       Wed Feb  6 13:07:33 2002
> @@ -89,32 +89,12 @@
>  char *__progname;
>  #endif
> 
> -/* For progressmeter() -- number of seconds before xfer considered "stalled" */
> -#define STALLTIME      5
> -/* alarm() interval for updating progress meter */
> -#define PROGRESSTIME   1
> -
> -/* Progress meter bar */
> -#define BAR \
> -       "************************************************************"\
> -       "************************************************************"\
> -       "************************************************************"\
> -       "************************************************************"
> -#define MAX_BARLENGTH (sizeof(BAR) - 1)
> -
> -/* Visual statistics about files as they are transferred. */
> -void progressmeter(int);
> -
> -/* Returns width of the terminal (for progress meter calculations). */
> -int getttywidth(void);
> +static void updateprogressmeter(int done);
>  int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc);
> 
>  /* Struct for addargs */
>  arglist args;
> 
> -/* Time a transfer started. */
> -static struct timeval start;
> -
>  /* Number of bytes of current file transferred so far. */
>  volatile off_t statbytes;
> 
> @@ -569,7 +549,7 @@
>                 }
>                 if (showprogress) {
>                         totalbytes = stb.st_size;
> -                       progressmeter(-1);
> +                       updateprogressmeter(0);
>                 }
>                 /* Keep writing after an error so that we stay sync'd up. */
>                 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
> @@ -591,7 +571,7 @@
>                         }
>                 }
>                 if (showprogress)
> -                       progressmeter(1);
> +                       updateprogressmeter(1);
> 
>                 if (close(fd) < 0 && !haderr)
>                         haderr = errno;
> @@ -835,7 +815,7 @@
> 
>                 if (showprogress) {
>                         totalbytes = size;
> -                       progressmeter(-1);
> +                       updateprogressmeter(0);
>                 }
>                 statbytes = 0;
>                 for (count = i = 0; i < size; i += 4096) {
> @@ -871,7 +851,8 @@
>                         }
>                 }
>                 if (showprogress)
> -                       progressmeter(1);
> +                       updateprogressmeter(1);
> +
>                 if (count != 0 && wrerr == NO &&
>                     (j = atomicio(write, ofd, bp->buf, count)) != count) {
>                         wrerr = YES;
> @@ -1079,140 +1060,17 @@
>  }
> 
>  static void
> -updateprogressmeter(int ignore)
> +updateprogressmeter(int done)
>  {
> -       int save_errno = errno;
> -
> -       progressmeter(0);
> -       mysignal(SIGALRM, updateprogressmeter);
> -       alarm(PROGRESSTIME);
> -       errno = save_errno;
> -}
> -
> -static int
> -foregroundproc(void)
> -{
> -       static pid_t pgrp = -1;
> -       int ctty_pgrp;
> -
> -       if (pgrp == -1)
> -               pgrp = getpgrp();
> +        int save_errno = errno;
> 
> -#ifdef HAVE_TCGETPGRP
> -       return ((ctty_pgrp = tcgetpgrp(STDOUT_FILENO)) != -1 &&
> -               ctty_pgrp == pgrp);
> -#else
> -       return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
> -                ctty_pgrp == pgrp));
> -#endif
> -}
> 
> -void
> -progressmeter(int flag)
> -{
> -       static const char prefixes[] = " KMGTP";
> -       static struct timeval lastupdate;
> -       static off_t lastsize;
> -       struct timeval now, td, wait;
> -       off_t cursize, abbrevsize;
> -       double elapsed;
> -       int ratio, barlength, i, remaining;
> -       char buf[256];
> -
> -       if (flag == -1) {
> -               (void) gettimeofday(&start, (struct timezone *) 0);
> -               lastupdate = start;
> -               lastsize = 0;
> -       }
> -       if (foregroundproc() == 0)
> -               return;
> +        progressmeter(statbytes, totalbytes, curfile);
> +        if (done == 0) {
> +                mysignal(SIGALRM, updateprogressmeter);
> +                alarm(PROGRESSTIME);
> +        } else
> +                alarm(0);
> 
> -       (void) gettimeofday(&now, (struct timezone *) 0);
> -       cursize = statbytes;
> -       if (totalbytes != 0) {
> -               ratio = 100.0 * cursize / totalbytes;
> -               ratio = MAX(ratio, 0);
> -               ratio = MIN(ratio, 100);
> -       } else
> -               ratio = 100;
> -
> -       snprintf(buf, sizeof(buf), "\r%-20.20s %3d%% ", curfile, ratio);
> -
> -       barlength = getttywidth() - 51;
> -       barlength = (barlength <= MAX_BARLENGTH)?barlength:MAX_BARLENGTH;
> -       if (barlength > 0) {
> -               i = barlength * ratio / 100;
> -               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                        "|%.*s%*s|", i, BAR, barlength - i, "");
> -       }
> -       i = 0;
> -       abbrevsize = cursize;
> -       while (abbrevsize >= 100000 && i < sizeof(prefixes)) {
> -               i++;
> -               abbrevsize >>= 10;
> -       }
> -       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), " %5lu %c%c ",
> -           (unsigned long) abbrevsize, prefixes[i],
> -           prefixes[i] == ' ' ? ' ' : 'B');
> -
> -       timersub(&now, &lastupdate, &wait);
> -       if (cursize > lastsize) {
> -               lastupdate = now;
> -               lastsize = cursize;
> -               if (wait.tv_sec >= STALLTIME) {
> -                       start.tv_sec += wait.tv_sec;
> -                       start.tv_usec += wait.tv_usec;
> -               }
> -               wait.tv_sec = 0;
> -       }
> -       timersub(&now, &start, &td);
> -       elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
> -
> -       if (flag != 1 &&
> -           (statbytes <= 0 || elapsed <= 0.0 || cursize > totalbytes)) {
> -               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                   "   --:-- ETA");
> -       } else if (wait.tv_sec >= STALLTIME) {
> -               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                   " - stalled -");
> -       } else {
> -               if (flag != 1)
> -                       remaining = (int)(totalbytes / (statbytes / elapsed) -
> -                           elapsed);
> -               else
> -                       remaining = elapsed;
> -
> -               i = remaining / 3600;
> -               if (i)
> -                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                           "%2d:", i);
> -               else
> -                       snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                           "   ");
> -               i = remaining % 3600;
> -               snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
> -                   "%02d:%02d%s", i / 60, i % 60,
> -                   (flag != 1) ? " ETA" : "    ");
> -       }
> -       atomicio(write, fileno(stdout), buf, strlen(buf));
> -
> -       if (flag == -1) {
> -               mysignal(SIGALRM, updateprogressmeter);
> -               alarm(PROGRESSTIME);
> -       } else if (flag == 1) {
> -               alarm(0);
> -               atomicio(write, fileno(stdout), "\n", 1);
> -               statbytes = 0;
> -       }
> -}
> -
> -int
> -getttywidth(void)
> -{
> -       struct winsize winsize;
> -
> -       if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
> -               return (winsize.ws_col ? winsize.ws_col : 80);
> -       else
> -               return (80);
> +        errno = save_errno;
>  }
> diff -ur openssh-3.0.2p1/sftp-client.c openssh/sftp-client.c
> --- openssh-3.0.2p1/sftp-client.c       Wed Jul 18 10:45:45 2001
> +++ openssh/sftp-client.c       Wed Feb  6 13:02:34 2002
> @@ -49,6 +49,11 @@
>  /* Message ID */
>  static u_int msg_id = 1;
> 
> +/* Progress Meter items */
> +off_t statbytes = 0;
> +off_t totalbytes = 0;
> +char *curfile = NULL;
> +
>  static void
>  send_msg(int fd, Buffer *m)
>  {
> @@ -671,7 +676,7 @@
> 
>  int
>  do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
> -    int pflag)
> +    int pflag, void (*progressbar)(int))
>  {
>         int local_fd;
>         u_int expected_id, handle_len, mode, type, id;
> @@ -724,6 +729,11 @@
>                 return(-1);
>         }
> 
> +       totalbytes  = a->size;
> +       curfile = remote_path;
> +       if (progressbar)
> +               (progressbar)(0);
> +
>         /* Read from remote and write to local */
>         offset = 0;
>         for(;;) {
> @@ -785,6 +795,7 @@
> 
>                 offset += len;
>                 xfree(data);
> +               statbytes = offset;
>         }
>         status = do_close(fd_in, fd_out, handle, handle_len);
> 
> @@ -807,15 +818,18 @@
>         }
> 
>  done:
> +       if (progressbar)
> +               (progressbar)(1);
>         close(local_fd);
>         buffer_free(&msg);
>         xfree(handle);
> +
>         return status;
>  }
> 
>  int
>  do_upload(int fd_in, int fd_out, char *local_path, char *remote_path,
> -    int pflag)
> +    int pflag, void (*progressbar)(int))
>  {
>         int local_fd;
>         u_int handle_len, id;
> @@ -865,6 +879,10 @@
>                 buffer_free(&msg);
>                 return(-1);
>         }
> +       totalbytes  = a.size;
> +       curfile = local_path;
> +       if (progressbar)
> +               (progressbar)(0);
> 
>         /* Read from local and write to remote */
>         offset = 0;
> @@ -908,6 +926,7 @@
>                     (u_int64_t)offset);
> 
>                 offset += len;
> +               statbytes = offset;
>         }
> 
>         if (close(local_fd) == -1) {
> @@ -925,8 +944,10 @@
>         status = do_close(fd_in, fd_out, handle, handle_len);
> 
>  done:
> +       if (progressbar)
> +               (progressbar)(1);
>         xfree(handle);
>         buffer_free(&msg);
> +
>         return status;
>  }
> -
> diff -ur openssh-3.0.2p1/sftp-client.h openssh/sftp-client.h
> --- openssh-3.0.2p1/sftp-client.h       Tue Jul  3 23:07:13 2001
> +++ openssh/sftp-client.h       Wed Feb  6 13:02:34 2002
> @@ -88,16 +88,14 @@
>  /* Return target of symlink 'path' - caller must free result */
>  char *do_readlink(int, int, char *);
> 
> -/* XXX: add callbacks to do_download/do_upload so we can do progress meter */
> -
>  /*
>   * Download 'remote_path' to 'local_path'. Preserve permissions and times
>   * if 'pflag' is set
>   */
> -int do_download(int, int, char *, char *, int);
> +int do_download(int, int, char *, char *, int, void (*)(int));
> 
>  /*
>   * Upload 'local_path' to 'remote_path'. Preserve permissions and times
>   * if 'pflag' is set
>   */
> -int do_upload(int, int, char *, char *, int);
> +int do_upload(int, int, char *, char *, int, void (*)(int));
> diff -ur openssh-3.0.2p1/sftp-int.c openssh/sftp-int.c
> --- openssh-3.0.2p1/sftp-int.c  Wed Aug 15 18:22:57 2001
> +++ openssh/sftp-int.c  Wed Feb  6 13:02:34 2002
> @@ -32,6 +32,7 @@
>  #include "xmalloc.h"
>  #include "log.h"
>  #include "pathnames.h"
> +#include "misc.h"
> 
>  #include "sftp.h"
>  #include "sftp-common.h"
> @@ -113,6 +114,24 @@
>  };
> 
>  static void
> +updateprogressmeter(int done)
> +{
> +        int save_errno = errno;
> +       extern off_t statbytes;
> +       extern off_t totalbytes;
> +       extern char *curfile;
> +
> +        progressmeter(statbytes, totalbytes, curfile);
> +       if (done == 0) {
> +               mysignal(SIGALRM, updateprogressmeter);
> +               alarm(PROGRESSTIME);
> +       } else
> +               alarm(0);
> +
> +        errno = save_errno;
> +}
> +
> +static void
>  help(void)
>  {
>         printf("Available commands:\n");
> @@ -380,8 +399,8 @@
>                         err = -1;
>                         goto out;
>                 }
> -               printf("Fetching %s to %s\n", g.gl_pathv[0], abs_dst);
> -               err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag);
> +               err = do_download(in, out, g.gl_pathv[0], abs_dst, pflag,
> +                   NULL);
>                 goto out;
>         }
> 
> @@ -404,8 +423,8 @@
>                 } else
>                         abs_dst = tmp;
> 
> -               printf("Fetching %s to %s\n", g.gl_pathv[i], abs_dst);
> -               if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag) == -1)
> +               if (do_download(in, out, g.gl_pathv[i], abs_dst, pflag,
> +                   updateprogressmeter) == -1)
>                         err = -1;
>                 xfree(abs_dst);
>                 abs_dst = NULL;
> @@ -462,8 +481,8 @@
>                         }
>                         abs_dst = make_absolute(abs_dst, pwd);
>                 }
> -               printf("Uploading %s to %s\n", g.gl_pathv[0], abs_dst);
> -               err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag);
> +               err = do_upload(in, out, g.gl_pathv[0], abs_dst, pflag,
> +                   updateprogressmeter);
>                 goto out;
>         }
> 
> @@ -486,8 +505,8 @@
>                 } else
>                         abs_dst = make_absolute(tmp, pwd);
> 
> -               printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
> -               if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag) == -1)
> +               if (do_upload(in, out, g.gl_pathv[i], abs_dst, pflag,
> +                   updateprogressmeter) == -1)
>                         err = -1;
>         }
> 
> _______________________________________________
> openssh-unix-dev at mindrot.org mailing list
> http://www.mindrot.org/mailman/listinfo/openssh-unix-dev

-- 
wendy palm
Cray OS Sustaining Engineering, Cray Inc.
wendyp at cray.com, 651-605-9154



More information about the openssh-unix-dev mailing list