[LICENCE progressmeter.c]
     replace 4 clause BSD licensed progressmeter code with a replacement
     from Nils Nordman and myself; ok deraadt@
     (copied from OpenBSD an re-applied portable changes)
This commit is contained in:
Darren Tucker 2003-08-02 23:28:38 +10:00
parent 019cefeaad
commit 06ef75bf0c
3 changed files with 216 additions and 260 deletions

View File

@ -18,6 +18,11 @@
Support for generating Diffie-Hellman groups (/etc/moduli) from ssh-keygen.
Based on code from Phil Karn, William Allen Simpson and Niels Provos.
ok markus@, thanks jmc@
- markus@cvs.openbsd.org 2003/07/29 18:24:00
[LICENCE progressmeter.c]
replace 4 clause BSD licensed progressmeter code with a replacement
from Nils Nordman and myself; ok deraadt@
(copied from OpenBSD an re-applied portable changes)
20030730
- (djm) [auth-pam.c] Don't use crappy APIs like sprintf. Thanks bal
@ -756,4 +761,4 @@
- Fix sshd BindAddress and -b options for systems using fake-getaddrinfo.
Report from murple@murple.net, diagnosis from dtucker@zip.com.au
$Id: ChangeLog,v 1.2871 2003/08/02 12:40:07 dtucker Exp $
$Id: ChangeLog,v 1.2872 2003/08/02 13:28:38 dtucker Exp $

44
LICENCE
View File

@ -166,48 +166,6 @@ OpenSSH contains no GPL code.
* SUCH DAMAGE.
6)
The progresssmeter code used by scp(1) and sftp(1) is copyright by
the NetBSD Foundation.
* Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
7)
Remaining components of the software are provided under a standard
2-term BSD licence with the following names as copyright holders:
@ -370,4 +328,4 @@ OpenSSH contains no GPL code.
------
$OpenBSD: LICENCE,v 1.15 2003/06/12 12:22:47 djm Exp $
$OpenBSD: LICENCE,v 1.16 2003/07/29 18:24:00 markus Exp $

View File

@ -1,6 +1,5 @@
/*
* Copyright (c) 1999 Theo de Raadt. All rights reserved.
* Copyright (c) 1999 Aaron Campbell. All rights reserved.
* Copyright (c) 2003 Nils Nordman. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -23,248 +22,242 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Luke Mewburn.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
* NASA Ames Research Center.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "includes.h"
RCSID("$OpenBSD: progressmeter.c,v 1.8 2003/06/28 16:23:06 deraadt Exp $");
RCSID("$OpenBSD: progressmeter.c,v 1.13 2003/07/31 22:34:03 markus Exp $");
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
#endif
#include "atomicio.h"
#include "progressmeter.h"
#include "atomicio.h"
#include "misc.h"
/* Number of seconds before xfer considered "stalled". */
#define STALLTIME 5
/* alarm() interval for updating progress meter. */
#define PROGRESSTIME 1
#define DEFAULT_WINSIZE 80
#define MAX_WINSIZE 512
#define PADDING 1 /* padding between the progress indicators */
#define UPDATE_INTERVAL 1 /* update the progress meter every second */
#define STALL_TIME 5 /* we're stalled after this many seconds */
/* Signal handler used for updating the progress meter. */
/* determines whether we can output to the terminal */
static int can_output(void);
/* formats and inserts the specified size into the given buffer */
static void format_size(char *, int, off_t);
static void format_rate(char *, int, off_t);
/* 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);
/* Returns non-zero if we are the foreground process. */
static int foregroundproc(void);
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 */
/* Returns width of the terminal (for progress meter calculations). */
static int get_tty_width(void);
/* units for format_size */
static const char unit[] = " KMGT";
/* Visual statistics about files as they are transferred. */
static void draw_progress_meter(void);
static int
can_output(void)
{
return (getpgrp() == tcgetpgrp(STDOUT_FILENO));
}
/* Time a transfer started. */
static struct timeval start;
static void
format_rate(char *buf, int size, off_t bytes)
{
int i;
/* Number of bytes of current file transferred so far. */
static volatile off_t *statbytes;
bytes *= 100;
for (i = 0; bytes >= 100*1000 && unit[i] != 'T'; i++)
bytes = (bytes + 512) / 1024;
if (i == 0) {
i++;
bytes = (bytes + 512) / 1024;
}
snprintf(buf, size, "%3lld.%1lld%c%s",
(int64_t) bytes / 100,
(int64_t) (bytes + 5) / 10 % 10,
unit[i],
i ? "B" : " ");
}
/* Total size of current file. */
static off_t totalbytes;
static void
format_size(char *buf, int size, off_t bytes)
{
int i;
/* Name of current file being transferred. */
static char *curfile;
/* Time of last update. */
static struct timeval lastupdate;
/* Size at the time of the last update. */
static off_t lastsize;
for (i = 0; bytes >= 10000 && unit[i] != 'T'; i++)
bytes = (bytes + 512) / 1024;
snprintf(buf, size, "%4lld%c%s",
(int64_t) bytes,
unit[i],
i ? "B" : " ");
}
void
start_progress_meter(char *file, off_t filesize, off_t *counter)
refresh_progress_meter(void)
{
if ((curfile = basename(file)) == NULL)
curfile = file;
char buf[MAX_WINSIZE + 1];
time_t now;
off_t transferred;
double elapsed;
int percent;
int bytes_left;
int cur_speed;
int hours, minutes, seconds;
int i, len;
int file_len;
totalbytes = filesize;
statbytes = counter;
(void) gettimeofday(&start, (struct timezone *) 0);
lastupdate = start;
lastsize = 0;
transferred = *counter - cur_pos;
cur_pos = *counter;
now = time(NULL);
bytes_left = end_pos - cur_pos;
if (bytes_left > 0)
elapsed = now - last_update;
else
elapsed = now - start;
/* calculate speed */
if (elapsed != 0)
cur_speed = (transferred / elapsed);
else
cur_speed = 0;
#define AGE_FACTOR 0.9
if (bytes_per_second != 0) {
bytes_per_second = (bytes_per_second * AGE_FACTOR) +
(cur_speed * (1.0 - AGE_FACTOR));
} else
bytes_per_second = cur_speed;
/* filename */
buf[0] = '\0';
file_len = win_size - 35;
if (file_len > 0) {
len = snprintf(buf, file_len, "\r%s", file);
for (i = len; i < file_len; i++ )
buf[i] = ' ';
buf[file_len] = '\0';
}
/* percent of transfer done */
if (end_pos != 0)
percent = ((float)cur_pos / end_pos) * 100;
else
percent = 100;
snprintf(buf + strlen(buf), win_size - strlen(buf),
" %3d%% ", percent);
/* amount transferred */
format_size(buf + strlen(buf), win_size - strlen(buf),
cur_pos);
strlcat(buf, " ", win_size);
/* bandwidth usage */
format_rate(buf + strlen(buf), win_size - strlen(buf),
bytes_per_second);
strlcat(buf, "/s ", win_size);
/* ETA */
if (!transferred)
stalled += elapsed;
else
stalled = 0;
if (stalled >= STALL_TIME)
strlcat(buf, "- stalled -", win_size);
else if (bytes_per_second == 0 && bytes_left)
strlcat(buf, " --:-- ETA", win_size);
else {
if (bytes_left > 0)
seconds = bytes_left / bytes_per_second;
else
seconds = elapsed;
hours = seconds / 3600;
seconds -= hours * 3600;
minutes = seconds / 60;
seconds -= minutes * 60;
if (hours != 0)
snprintf(buf + strlen(buf), win_size - strlen(buf),
"%d:%02d:%02d", hours, minutes, seconds);
else
snprintf(buf + strlen(buf), win_size - strlen(buf),
" %02d:%02d", minutes, seconds);
if (bytes_left > 0)
strlcat(buf, " ETA", win_size);
else
strlcat(buf, " ", win_size);
}
atomicio(vwrite, STDOUT_FILENO, buf, win_size);
last_update = now;
}
static void
update_progress_meter(int ignore)
{
int save_errno;
save_errno = errno;
if (can_output())
refresh_progress_meter();
draw_progress_meter();
mysignal(SIGALRM, update_progress_meter);
alarm(PROGRESSTIME);
alarm(UPDATE_INTERVAL);
errno = save_errno;
}
void
start_progress_meter(char *f, off_t filesize, off_t *stat)
{
struct winsize winsize;
start = last_update = time(NULL);
file = f;
end_pos = filesize;
cur_pos = 0;
counter = stat;
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 */
if (can_output())
refresh_progress_meter();
mysignal(SIGALRM, update_progress_meter);
alarm(UPDATE_INTERVAL);
}
void
stop_progress_meter(void)
{
alarm(0);
draw_progress_meter();
if (foregroundproc() != 0)
atomicio(vwrite, fileno(stdout), "\n", 1);
}
static void
update_progress_meter(int ignore)
{
int save_errno = errno;
draw_progress_meter();
mysignal(SIGALRM, update_progress_meter);
alarm(PROGRESSTIME);
errno = save_errno;
}
static int
foregroundproc(void)
{
static pid_t pgrp = -1;
int ctty_pgrp;
if (pgrp == -1)
pgrp = getpgrp();
#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
}
static void
draw_progress_meter(void)
{
static const char spaces[] = " "
" "
" "
" "
" "
" ";
static const char prefixes[] = " KMGTP";
struct timeval now, td, wait;
off_t cursize, abbrevsize, bytespersec;
double elapsed;
int ratio, remaining, i, ai, bi, nspaces;
char buf[512];
if (foregroundproc() == 0)
if (!can_output())
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;
/* Ensure we complete the progress */
if (cur_pos != end_pos)
refresh_progress_meter();
abbrevsize = cursize;
for (ai = 0; abbrevsize >= 10000 && ai < sizeof(prefixes); ai++)
abbrevsize >>= 10;
timersub(&now, &lastupdate, &wait);
if (cursize > lastsize) {
lastupdate = now;
lastsize = cursize;
wait.tv_sec = 0;
}
timersub(&now, &start, &td);
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
bytespersec = 0;
if (cursize > 0) {
bytespersec = cursize;
if (elapsed > 0.0)
bytespersec /= elapsed;
}
for (bi = 1; bytespersec >= 1024000 && bi < sizeof(prefixes); bi++)
bytespersec >>= 10;
nspaces = MIN(get_tty_width() - 79, sizeof(spaces) - 1);
snprintf(buf, sizeof(buf),
"\r%-45.45s%.*s%3d%% %4lld%c%c %3lld.%01d%cB/s",
curfile,
nspaces,
spaces,
ratio,
(int64_t)abbrevsize,
prefixes[ai],
ai == 0 ? ' ' : 'B',
(int64_t)(bytespersec / 1024),
(int)((bytespersec % 1024) * 10 / 1024),
prefixes[bi]
);
if (cursize <= 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 (cursize != totalbytes)
remaining = (int)(totalbytes / (cursize / 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,
(cursize != totalbytes) ? " ETA" : " ");
}
atomicio(vwrite, fileno(stdout), buf, strlen(buf));
}
static int
get_tty_width(void)
{
struct winsize winsize;
if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
return (winsize.ws_col ? winsize.ws_col : 80);
else
return (80);
atomicio(vwrite, STDOUT_FILENO, "\n", 1);
}