diff progressmeter.c @ 330:5488db2e9e4e

merge of 332f709a4cb39cde4cedab7c3be89e05f3023067 and ca4ca78b82c5d430c69ce01bf794e8886ce81431
author Matt Johnston <matt@ucc.asn.au>
date Sat, 10 Jun 2006 16:39:40 +0000
parents b72f98803e46
children
line wrap: on
line diff
--- a/progressmeter.c	Sat Jun 10 16:39:37 2006 +0000
+++ b/progressmeter.c	Sat Jun 10 16:39:40 2006 +0000
@@ -24,7 +24,7 @@
  */
 
 #include "includes.h"
-/*RCSID("OpenBSD: progressmeter.c,v 1.15 2003/08/31 12:14:22 markus Exp ");*/
+/*RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");*/
 
 #include "progressmeter.h"
 #include "atomicio.h"
@@ -43,21 +43,26 @@
 static void format_size(char *, int, off_t);
 static void format_rate(char *, int, off_t);
 
+/* window resizing */
+static void sig_winch(int);
+static void setscreensize(void);
+
 /* updates the progressmeter to reflect the current state of the transfer */
 void refresh_progress_meter(void);
 
 /* signal handler for updating the progress meter */
 static void update_progress_meter(int);
 
-static time_t start; 		/* start progress */
-static time_t last_update; 	/* last progress update */
-static char *file; 		/* name of the file being transferred */
-static off_t end_pos; 		/* ending position of transfer */
-static off_t cur_pos; 		/* transfer position as of last refresh */
+static time_t start;		/* start progress */
+static time_t last_update;	/* last progress update */
+static char *file;		/* name of the file being transferred */
+static off_t end_pos;		/* ending position of transfer */
+static off_t cur_pos;		/* transfer position as of last refresh */
 static volatile off_t *counter;	/* progress counter */
-static long stalled; 		/* how long we have been stalled */
-static int bytes_per_second; 	/* current speed in bytes per second */
-static int win_size; 		/* terminal window size */
+static long stalled;		/* how long we have been stalled */
+static int bytes_per_second;	/* current speed in bytes per second */
+static int win_size;		/* terminal window size */
+static volatile sig_atomic_t win_resized; /* for window resizing */
 
 /* units for format_size */
 static const char unit[] = " KMGT";
@@ -81,8 +86,8 @@
 		bytes = (bytes + 512) / 1024;
 	}
 	snprintf(buf, size, "%3lld.%1lld%c%s",
-	    (int64_t) bytes / 100,
-	    (int64_t) (bytes + 5) / 10 % 10,
+	    (long long) (bytes + 5) / 100,
+	    (long long) (bytes + 5) / 10 % 10,
 	    unit[i],
 	    i ? "B" : " ");
 }
@@ -95,7 +100,7 @@
 	for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
 		bytes = (bytes + 512) / 1024;
 	snprintf(buf, size, "%4lld%c%s",
-	    (int64_t) bytes,
+	    (long long) bytes,
 	    unit[i],
 	    i ? "B" : " ");
 }
@@ -108,7 +113,7 @@
 	off_t transferred;
 	double elapsed;
 	int percent;
-	int bytes_left;
+	off_t bytes_left;
 	int cur_speed;
 	int hours, minutes, seconds;
 	int i, len;
@@ -121,14 +126,18 @@
 
 	if (bytes_left > 0)
 		elapsed = now - last_update;
-	else
+	else {
 		elapsed = now - start;
+		/* Calculate true total speed when done */
+		transferred = end_pos;
+		bytes_per_second = 0;
+	}
 
 	/* calculate speed */
 	if (elapsed != 0)
 		cur_speed = (transferred / elapsed);
 	else
-		cur_speed = 0;
+		cur_speed = transferred;
 
 #define AGE_FACTOR 0.9
 	if (bytes_per_second != 0) {
@@ -144,6 +153,8 @@
 		len = snprintf(buf, file_len + 1, "\r%s", file);
 		if (len < 0)
 			len = 0;
+		if (len >= file_len + 1)
+			len = file_len;
 		for (i = len;  i < file_len; i++ )
 			buf[i] = ' ';
 		buf[file_len] = '\0';
@@ -164,7 +175,7 @@
 
 	/* bandwidth usage */
 	format_rate(buf + strlen(buf), win_size - strlen(buf),
-	    bytes_per_second);
+	    (off_t)bytes_per_second);
 	strlcat(buf, "/s ", win_size);
 
 	/* ETA */
@@ -201,7 +212,7 @@
 			strlcat(buf, "    ", win_size);
 	}
 
-	atomicio(vwrite, STDOUT_FILENO, buf, win_size);
+	atomicio(vwrite, STDOUT_FILENO, buf, win_size - 1);
 	last_update = now;
 }
 
@@ -212,6 +223,10 @@
 
 	save_errno = errno;
 
+	if (win_resized) {
+		setscreensize();
+		win_resized = 0;
+	}
 	if (can_output())
 		refresh_progress_meter();
 
@@ -221,32 +236,22 @@
 }
 
 void
-start_progress_meter(char *f, off_t filesize, off_t *stat)
+start_progress_meter(char *f, off_t filesize, off_t *ctr)
 {
-	struct winsize winsize;
-
 	start = last_update = time(NULL);
 	file = f;
 	end_pos = filesize;
 	cur_pos = 0;
-	counter = stat;
+	counter = ctr;
 	stalled = 0;
 	bytes_per_second = 0;
 
-	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
-	    winsize.ws_col != 0) {
-		if (winsize.ws_col > MAX_WINSIZE)
-			win_size = MAX_WINSIZE;
-		else
-			win_size = winsize.ws_col;
-	} else
-		win_size = DEFAULT_WINSIZE;
-	win_size += 1;					/* trailing \0 */
-
+	setscreensize();
 	if (can_output())
 		refresh_progress_meter();
 
 	signal(SIGALRM, update_progress_meter);
+	signal(SIGWINCH, sig_winch);
 	alarm(UPDATE_INTERVAL);
 }
 
@@ -264,4 +269,26 @@
 
 	atomicio(vwrite, STDOUT_FILENO, "\n", 1);
 }
+
+static void
+sig_winch(int sig)
+{
+	win_resized = 1;
+}
+
+static void
+setscreensize(void)
+{
+	struct winsize winsize;
+
+	if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize) != -1 &&
+	    winsize.ws_col != 0) {
+		if (winsize.ws_col > MAX_WINSIZE)
+			win_size = MAX_WINSIZE;
+		else
+			win_size = winsize.ws_col;
+	} else
+		win_size = DEFAULT_WINSIZE;
+	win_size += 1;					/* trailing \0 */
+}
 #endif /* PROGRESS_METER */