version 1.96, 2002/12/13 15:20:52 |
version 1.97, 2003/01/10 08:19:07 |
|
|
#include "pathnames.h" |
#include "pathnames.h" |
#include "log.h" |
#include "log.h" |
#include "misc.h" |
#include "misc.h" |
|
#include "progressmeter.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); |
|
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); |
int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc); |
|
|
/* Struct for addargs */ |
/* Struct for addargs */ |
arglist args; |
arglist args; |
|
|
/* Time a transfer started. */ |
|
static struct timeval start; |
|
|
|
/* Number of bytes of current file transferred so far. */ |
|
volatile off_t statbytes; |
|
|
|
/* Total size of current file. */ |
|
off_t totalbytes = 0; |
|
|
|
/* Name of current file being transferred. */ |
/* Name of current file being transferred. */ |
char *curfile; |
char *curfile; |
|
|
|
|
struct stat stb; |
struct stat stb; |
static BUF buffer; |
static BUF buffer; |
BUF *bp; |
BUF *bp; |
off_t i, amt, result; |
off_t i, amt, result, statbytes; |
int fd, haderr, indx; |
int fd, haderr, indx; |
char *last, *name, buf[2048]; |
char *last, *name, buf[2048]; |
int len; |
int len; |
|
|
next: (void) close(fd); |
next: (void) close(fd); |
continue; |
continue; |
} |
} |
if (showprogress) { |
if (showprogress) |
totalbytes = stb.st_size; |
start_progress_meter(curfile, stb.st_size, &statbytes); |
progressmeter(-1); |
|
} |
|
/* Keep writing after an error so that we stay sync'd up. */ |
/* Keep writing after an error so that we stay sync'd up. */ |
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { |
for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { |
amt = bp->cnt; |
amt = bp->cnt; |
|
|
} |
} |
} |
} |
if (showprogress) |
if (showprogress) |
progressmeter(1); |
stop_progress_meter(); |
|
|
if (close(fd) < 0 && !haderr) |
if (close(fd) < 0 && !haderr) |
haderr = errno; |
haderr = errno; |
|
|
BUF *bp; |
BUF *bp; |
off_t i, j; |
off_t i, j; |
int amt, count, exists, first, mask, mode, ofd, omode; |
int amt, count, exists, first, mask, mode, ofd, omode; |
off_t size; |
off_t size, statbytes; |
int setimes, targisdir, wrerrno = 0; |
int setimes, targisdir, wrerrno = 0; |
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
char ch, *cp, *np, *targ, *why, *vect[1], buf[2048]; |
struct timeval tv[2]; |
struct timeval tv[2]; |
|
|
cp = bp->buf; |
cp = bp->buf; |
wrerr = NO; |
wrerr = NO; |
|
|
if (showprogress) { |
|
totalbytes = size; |
|
progressmeter(-1); |
|
} |
|
statbytes = 0; |
statbytes = 0; |
|
if (showprogress) |
|
start_progress_meter(curfile, size, &statbytes); |
for (count = i = 0; i < size; i += 4096) { |
for (count = i = 0; i < size; i += 4096) { |
amt = 4096; |
amt = 4096; |
if (i + amt > size) |
if (i + amt > size) |
|
|
} |
} |
} |
} |
if (showprogress) |
if (showprogress) |
progressmeter(1); |
stop_progress_meter(); |
if (count != 0 && wrerr == NO && |
if (count != 0 && wrerr == NO && |
(j = atomicio(write, ofd, bp->buf, count)) != count) { |
(j = atomicio(write, ofd, bp->buf, count)) != count) { |
wrerr = YES; |
wrerr = YES; |
|
|
_exit(1); |
_exit(1); |
else |
else |
exit(1); |
exit(1); |
} |
|
|
|
static 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; |
|
|
|
if (pgrp == -1) |
|
pgrp = getpgrp(); |
|
|
|
return ((ioctl(STDOUT_FILENO, TIOCGPGRP, &ctty_pgrp) != -1 && |
|
ctty_pgrp == pgrp)); |
|
} |
|
|
|
void |
|
progressmeter(int flag) |
|
{ |
|
static const char spaces[] = " " |
|
" " |
|
" " |
|
" " |
|
" " |
|
" "; |
|
static const char prefixes[] = " KMGTP"; |
|
static struct timeval lastupdate; |
|
static off_t lastsize; |
|
struct timeval now, td, wait; |
|
off_t cursize, abbrevsize, bytespersec; |
|
double elapsed; |
|
int ratio, remaining, i, ai, bi, nspaces; |
|
char buf[512]; |
|
|
|
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; |
|
|
|
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 (statbytes > 0) { |
|
bytespersec = statbytes; |
|
if (elapsed > 0.0) |
|
bytespersec /= elapsed; |
|
} |
|
for (bi = 1; bytespersec >= 1024000 && bi < sizeof(prefixes); bi++) |
|
bytespersec >>= 10; |
|
|
|
nspaces = MIN(getttywidth() - 79, sizeof(spaces) - 1); |
|
|
|
snprintf(buf, sizeof(buf), |
|
"\r%-45.45s%.*s%3d%% %4lld%c%c %3lld.%01d%cB/s", |
|
curfile, |
|
nspaces, |
|
spaces, |
|
ratio, |
|
(long long)abbrevsize, |
|
prefixes[ai], |
|
ai == 0 ? ' ' : 'B', |
|
(long long)(bytespersec / 1024), |
|
(int)((bytespersec % 1024) * 10 / 1024), |
|
prefixes[bi] |
|
); |
|
|
|
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); |
|
} |
} |