Quick sftp status indicator.

mouring mouring at etoh.eviladmin.org
Wed Jan 30 11:16:20 EST 2002


I think my first send was eaten by elm.. Yuck I hate this programm..

Anyawys, first the disclaimer:

	This is barely tests, I submit this to the general population, but
	I will not submit this for review of rest of the OpenSSH team.
	Mainly because it is horrible at best.  dealing with alarm() in
	a sane way is not fun.  It does not compile clean, but works.
	IF anyone cares to clean it up.. fine.

Issues:

1) progressmeter() args are off, sftp-client.c arguments are unsigned 64bit.

2) Had to globalize a few variables to use the current design of the
indicator.

3) It is from OpenBSD cvs tree... Therefor scp.c fails to patch right.  One
has to manual patch it.

With that being said.. have fun..  BTW.. Embeded in this patch is another
patch I submited to clean up handling the alocation of the progress bar.  

- Ben


Index: misc.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/misc.c,v
retrieving revision 1.15
diff -u -r1.15 misc.c
--- misc.c	2002/01/24 21:09:25	1.15
+++ misc.c	2002/01/29 23:16:28
@@ -310,3 +310,133 @@
 	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));
+}
+
+void
+progressmeter(int flag, off_t statbytes, off_t totalbytes, char *curfile)
+{
+#define STALLTIME       5 /* number of seconds before xfer assumed "stalled" */
+	static const char prefixes[] = " KMGTP";
+	static struct timeval lastupdate;
+	static off_t lastsize;
+	static u_char *progressbar = NULL;
+	static size_t progressbar_size = 0;
+	static struct timeval start;
+	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;
+
+	(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;
+	if (barlength > progressbar_size) {
+		progressbar_size = barlength;
+		progressbar = xrealloc(progressbar, barlength);
+		memset(progressbar, '*', barlength);
+	}
+	
+	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 (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) {
+		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);
+}
Index: misc.h
===================================================================
RCS file: /cvs/src/usr.bin/ssh/misc.h,v
retrieving revision 1.11
diff -u -r1.11 misc.h
--- misc.h	2002/01/24 21:09:25	1.11
+++ misc.h	2002/01/29 23:16:28
@@ -30,4 +30,9 @@
         int     num;
         int     nalloc;
 };
+
 void	 addargs(arglist *, char *, ...) __attribute__((format(printf, 2, 3)));
+void 	 progressmeter(int flag, off_t statbytes, off_t totalbytes, char *curfile);
+
+#define PROGRESSTIME    1 /* alarm() interval for updating progress meter */
+
Index: scp.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/scp.c,v
retrieving revision 1.86
diff -u -r1.86 scp.c
--- scp.c	2001/12/05 03:56:39	1.86
+++ scp.c	2002/01/29 23:16:29
@@ -83,24 +83,12 @@
 #include "log.h"
 #include "misc.h"
 
-/* For progressmeter() -- number of seconds before xfer considered "stalled" */
-#define STALLTIME	5
-/* alarm() interval for updating progress meter */
-#define PROGRESSTIME	1
-
-/* Visual statistics about files as they are transferred. */
-void progressmeter(int);
-
-/* Returns width of the terminal (for progress meter calculations). */
-int getttywidth(void);
+void updateprogressmeter(int ignore);
 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;
 
@@ -542,7 +530,9 @@
 		}
 		if (showprogress) {
 			totalbytes = stb.st_size;
-			progressmeter(-1);
+			progressmeter(-1, statbytes, totalbytes, curfile);
+			signal(SIGALRM, updateprogressmeter);
+			alarm(PROGRESSTIME);
 		}
 		/* Keep writing after an error so that we stay sync'd up. */
 		for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
@@ -564,7 +554,7 @@
 			}
 		}
 		if (showprogress)
-			progressmeter(1);
+			progressmeter(1, statbytes, totalbytes, curfile);
 
 		if (close(fd) < 0 && !haderr)
 			haderr = errno;
@@ -808,7 +798,9 @@
 
 		if (showprogress) {
 			totalbytes = size;
-			progressmeter(-1);
+			progressmeter(-1, statbytes, totalbytes, curfile);
+			signal(SIGALRM, updateprogressmeter);
+			alarm(PROGRESSTIME);
 		}
 		statbytes = 0;
 		for (count = i = 0; i < size; i += 4096) {
@@ -844,7 +836,8 @@
 			}
 		}
 		if (showprogress)
-			progressmeter(1);
+			progressmeter(1, statbytes, totalbytes, curfile);
+
 		if (count != 0 && wrerr == NO &&
 		    (j = atomicio(write, ofd, bp->buf, count)) != count) {
 			wrerr = YES;
@@ -1039,140 +1032,14 @@
 		exit(1);
 }
 
-static void
+void
 updateprogressmeter(int ignore)
-{
-	int save_errno = errno;
-
-	progressmeter(0);
-	signal(SIGALRM, updateprogressmeter);
-	alarm(PROGRESSTIME);
-	errno = save_errno;
-}
-
-static int
-foregroundproc(void)
 {
-	static pid_t pgrp = -1;
-	int ctty_pgrp;
+        int save_errno = errno;
 
-	if (pgrp == -1)
-		pgrp = getpgrp();
-
-	return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 &&
-		 ctty_pgrp == pgrp));
+	progressmeter(0, statbytes, totalbytes, curfile);
+        signal(SIGALRM, updateprogressmeter);
+        alarm(PROGRESSTIME);
+        errno = save_errno;
 }
 
-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;
-
-	(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;
-	if (barlength > 0) {
-		i = barlength * ratio / 100;
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-		    "|%.*s%*s|", i,
-		    "***************************************"
-		    "***************************************"
-		    "***************************************"
-		    "***************************************",
-		    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 (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) {
-		signal(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);
-}
Index: sftp-client.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/sftp-client.c,v
retrieving revision 1.19
diff -u -r1.19 sftp-client.c
--- sftp-client.c	2001/12/19 07:18:56	1.19
+++ sftp-client.c	2002/01/29 23:16:31
@@ -37,6 +37,7 @@
 #include "xmalloc.h"
 #include "log.h"
 #include "atomicio.h"
+#include "misc.h"
 
 #include "sftp.h"
 #include "sftp-common.h"
@@ -49,6 +50,11 @@
 /* Message ID */
 static u_int msg_id = 1;
 
+/* Shit required for processmeter() to work BLECH */
+u_int64_t offset;
+u_int64_t file_size;
+u_int64_t filename;
+
 static void
 send_msg(int fd, Buffer *m)
 {
@@ -668,13 +674,23 @@
 	return(filename);
 }
 
+void
+updateprogressmeter(int ignore)
+{
+        int save_errno = errno;
+
+        progressmeter(0, offset, file_size, filename);
+        signal(SIGALRM, updateprogressmeter);
+        alarm(PROGRESSTIME);
+        errno = save_errno;
+}
+
 int
 do_download(int fd_in, int fd_out, char *remote_path, char *local_path,
     int pflag)
 {
 	int local_fd;
 	u_int expected_id, handle_len, mode, type, id;
-	u_int64_t offset;
 	char *handle;
 	Buffer msg;
 	Attrib junk, *a;
@@ -723,6 +739,12 @@
 		return(-1);
 	}
 
+	file_size = a->size;
+	filename = remote_path;
+	progressmeter(-1, offset, file_size, filename);
+	signal(SIGALRM, updateprogressmeter);
+	alarm(PROGRESSTIME);
+
 	/* Read from remote and write to local */
 	offset = 0;
 	for (;;) {
@@ -786,6 +808,7 @@
 		xfree(data);
 	}
 	status = do_close(fd_in, fd_out, handle, handle_len);
+	progressmeter(1, offset, file_size, filename);
 
 	/* Override umask and utimes if asked */
 	if (pflag && fchmod(local_fd, mode) == -1)
@@ -814,7 +837,6 @@
 {
 	int local_fd;
 	u_int handle_len, id;
-	u_int64_t offset;
 	char *handle;
 	Buffer msg;
 	struct stat sb;
@@ -861,6 +883,12 @@
 		return(-1);
 	}
 
+	file_size = a.size;
+	filename = local_path;
+	progressmeter(-1, offset, file_size, filename);
+	signal(SIGALRM, updateprogressmeter);
+	alarm(PROGRESSTIME);
+
 	/* Read from local and write to remote */
 	offset = 0;
 	for (;;) {
@@ -904,6 +932,7 @@
 
 		offset += len;
 	}
+	progressmeter(1, offset, file_size, filename);
 
 	if (close(local_fd) == -1) {
 		error("Couldn't close local file \"%s\": %s", local_path,
Index: sftp-int.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/sftp-int.c,v
retrieving revision 1.41
diff -u -r1.41 sftp-int.c
--- sftp-int.c	2001/12/19 07:18:56	1.41
+++ sftp-int.c	2002/01/29 23:16:32
@@ -382,7 +382,6 @@
 			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);
 		goto out;
 	}
@@ -464,7 +463,6 @@
 			}
 			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);
 		goto out;
 	}




More information about the openssh-unix-dev mailing list