SFTP Status Bar..

mouring mouring at etoh.eviladmin.org
Thu Feb 7 06:23:10 EST 2002


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;
 	}
 



More information about the openssh-unix-dev mailing list