NetBSD/usr.bin/ftp/util.c

615 lines
15 KiB
C
Raw Normal View History

[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
/* $NetBSD: util.c,v 1.3 1997/02/01 10:45:08 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* 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 University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
*/
#ifndef lint
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
static char rcsid[] = "$NetBSD: util.c,v 1.3 1997/02/01 10:45:08 lukem Exp $";
#endif /* not lint */
/*
* FTP User Program -- Misc support routines
*/
#include <sys/ioctl.h>
#include <sys/time.h>
#include <arpa/ftp.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <glob.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "ftp_var.h"
#include "pathnames.h"
/*
* Connect to peer server and
* auto-login, if possible.
*/
void
setpeer(argc, argv)
int argc;
char *argv[];
{
char *host;
short port;
if (connected) {
printf("Already connected to %s, use close first.\n",
hostname);
code = -1;
return;
}
if (argc < 2)
(void) another(&argc, &argv, "to");
if (argc < 2 || argc > 3) {
printf("usage: %s host-name [port]\n", argv[0]);
code = -1;
return;
}
port = ftpport;
if (argc > 2) {
port = atoi(argv[2]);
if (port <= 0) {
printf("%s: bad port number-- %s\n", argv[1], argv[2]);
printf ("usage: %s host-name [port]\n", argv[0]);
code = -1;
return;
}
port = htons(port);
}
host = hookup(argv[1], port);
if (host) {
int overbose;
connected = 1;
/*
* Set up defaults for FTP.
*/
(void) strcpy(typename, "ascii"), type = TYPE_A;
curtype = TYPE_A;
(void) strcpy(formname, "non-print"), form = FORM_N;
(void) strcpy(modename, "stream"), mode = MODE_S;
(void) strcpy(structname, "file"), stru = STRU_F;
(void) strcpy(bytename, "8"), bytesize = 8;
if (autologin)
(void) login(argv[1]);
overbose = verbose;
if (debug == 0)
verbose = -1;
if (command("SYST") == COMPLETE && overbose) {
char *cp, c;
c = 0;
cp = strchr(reply_string+4, ' ');
if (cp == NULL)
cp = strchr(reply_string+4, '\r');
if (cp) {
if (cp[-1] == '.')
cp--;
c = *cp;
*cp = '\0';
}
printf("Remote system type is %s.\n",
reply_string+4);
if (cp)
*cp = c;
}
if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) {
if (proxy)
unix_proxy = 1;
else
unix_server = 1;
/*
* Set type to 0 (not specified by user),
* meaning binary by default, but don't bother
* telling server. We can use binary
* for text files unless changed by the user.
*/
type = 0;
(void) strcpy(typename, "binary");
if (overbose)
printf("Using %s mode to transfer files.\n",
typename);
} else {
if (proxy)
unix_proxy = 0;
else
unix_server = 0;
if (overbose &&
!strncmp(reply_string, "215 TOPS20", 10))
printf("Remember to set tenex mode when "
"transferring binary files from this "
"machine.\n");
}
verbose = overbose;
}
}
/*
* `Another' gets another argument, and stores the new argc and argv.
* It reverts to the top level (via main.c's intr()) on EOF/error.
*
* Returns false if no new arguments have been added.
*/
int
another(pargc, pargv, prompt)
int *pargc;
char ***pargv;
const char *prompt;
{
int len = strlen(line), ret;
if (len >= sizeof(line) - 3) {
printf("sorry, arguments too long\n");
intr();
}
printf("(%s) ", prompt);
line[len++] = ' ';
if (fgets(&line[len], sizeof(line) - len, stdin) == NULL)
intr();
len += strlen(&line[len]);
if (len > 0 && line[len - 1] == '\n')
line[len - 1] = '\0';
makeargv();
ret = margc > *pargc;
*pargc = margc;
*pargv = margv;
return (ret);
}
char *
remglob(argv, doswitch)
char *argv[];
int doswitch;
{
char temp[MAXPATHLEN];
static char buf[MAXPATHLEN];
static FILE *ftemp = NULL;
static char **args;
int oldverbose, oldhash, fd;
char *cp, *mode;
if (!mflag) {
if (!doglob) {
args = NULL;
}
else {
if (ftemp) {
(void) fclose(ftemp);
ftemp = NULL;
}
}
return (NULL);
}
if (!doglob) {
if (args == NULL)
args = argv;
if ((cp = *++args) == NULL)
args = NULL;
return (cp);
}
if (ftemp == NULL) {
(void) snprintf(temp, sizeof(temp), "%s%s", _PATH_TMP, TMPFILE)
;
fd = mkstemp(temp);
if (fd < 0) {
warn("unable to create temporary file %s", temp);
return (NULL);
}
close(fd);
oldverbose = verbose, verbose = 0;
oldhash = hash, hash = 0;
if (doswitch) {
pswitch(!proxy);
}
for (mode = "w"; *++argv != NULL; mode = "a")
recvrequest ("NLST", temp, *argv, mode, 0);
if (doswitch) {
pswitch(!proxy);
}
verbose = oldverbose; hash = oldhash;
ftemp = fopen(temp, "r");
(void) unlink(temp);
if (ftemp == NULL) {
printf("can't find list of remote files, oops\n");
return (NULL);
}
}
if (fgets(buf, sizeof (buf), ftemp) == NULL) {
(void) fclose(ftemp), ftemp = NULL;
return (NULL);
}
if ((cp = strchr(buf, '\n')) != NULL)
*cp = '\0';
return (buf);
}
int
confirm(cmd, file)
const char *cmd, *file;
{
char line[BUFSIZ];
if (!interactive || confirmrest)
return (1);
printf("%s %s? ", cmd, file);
(void) fflush(stdout);
if (fgets(line, sizeof(line), stdin) == NULL)
return (0);
switch (tolower(*line)) {
case 'n':
return (0);
case 'p':
interactive = 0;
printf("Interactive mode: off\n");
break;
case 'a':
confirmrest = 1;
printf("Prompting off for duration of %s\n", cmd);
break;
}
return (1);
}
/*
* Glob a local file name specification with
* the expectation of a single return value.
* Can't control multiple values being expanded
* from the expression, we return only the first.
*/
int
globulize(cpp)
char **cpp;
{
glob_t gl;
int flags;
if (!doglob)
return (1);
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
memset(&gl, 0, sizeof(gl));
if (glob(*cpp, flags, NULL, &gl) ||
gl.gl_pathc == 0) {
warnx("%s: not found", *cpp);
globfree(&gl);
return (0);
}
*cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */
globfree(&gl);
return (1);
}
/*
* determine size of remote file
*/
off_t
remotesize(file, noisy)
const char *file;
int noisy;
{
int overbose;
off_t size;
overbose = verbose;
size = -1;
if (debug == 0)
verbose = -1;
if (command("SIZE %s", file) == COMPLETE)
sscanf(reply_string, "%*s %qd", &size);
else if (noisy && debug == 0)
printf("%s\n", reply_string);
verbose = overbose;
return (size);
}
/*
* determine last modification time (in GMT) of remote file
*/
time_t
remotemodtime(file, noisy)
const char *file;
int noisy;
{
int overbose;
time_t rtime;
overbose = verbose;
rtime = -1;
if (debug == 0)
verbose = -1;
if (command("MDTM %s", file) == COMPLETE) {
struct tm timebuf;
int yy, mo, day, hour, min, sec;
sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo,
&day, &hour, &min, &sec);
memset(&timebuf, 0, sizeof(timebuf));
timebuf.tm_sec = sec;
timebuf.tm_min = min;
timebuf.tm_hour = hour;
timebuf.tm_mday = day;
timebuf.tm_mon = mo - 1;
timebuf.tm_year = yy - 1900;
timebuf.tm_isdst = -1;
rtime = mktime(&timebuf);
if (rtime == -1 && (noisy || debug != 0))
printf("Can't convert %s to a time\n", reply_string);
else
rtime += timebuf.tm_gmtoff; /* conv. local -> GMT */
} else if (noisy && debug == 0)
printf("%s\n", reply_string);
verbose = overbose;
return (rtime);
}
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
void
updateprogressmeter()
{
progressmeter(0);
}
/*
* Display a transfer progress bar if progress is non-zero.
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
* SIGALRM is hijacked for use by this function.
* - Before the transfer, set filesize to size of file (or -1 if unknown),
* and call with flag = -1. This starts the once per second timer,
* and a call to updateprogressmeter() upon SIGALRM.
* - During the transfer, updateprogressmeter will call progressmeter
* with flag = 0
* - After the transfer, call with flag = 1
*/
static struct timeval start;
void
progressmeter(flag)
int flag;
{
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
/*
* List of order of magnitude prefixes.
* The last is `P', as 2^64 = 16384 Petabytes
*/
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;
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
char buf[256];
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
if (flag == -1) {
(void) gettimeofday(&start, (struct timezone *)0);
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
lastupdate = start;
lastsize = restart_point;
}
(void) gettimeofday(&now, (struct timezone *)0);
if (!progress || filesize <= 0)
return;
cursize = bytes + restart_point;
ratio = cursize * 100 / filesize;
ratio = MAX(ratio, 0);
ratio = MIN(ratio, 100);
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
snprintf(buf, sizeof(buf), "\r%3d%% ", ratio);
barlength = ttywidth - 30;
if (barlength > 0) {
i = barlength * ratio / 100;
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
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;
}
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
" %5qd %c%c ", abbrevsize, prefixes[i],
prefixes[i] == ' ' ? ' ' : 'B');
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
timersub(&now, &lastupdate, &wait);
if (cursize > lastsize) {
lastupdate = now;
lastsize = cursize;
if (wait.tv_sec >= STALLTIME) { /* fudge out stalled time */
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);
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
if (bytes <= 0 || elapsed <= 0.0) {
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
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 {
remaining = (int)((filesize - restart_point) /
(bytes / elapsed) - elapsed);
i = remaining / 3600;
if (i)
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"%2d:", i);
else
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
" ");
i = remaining % 3600;
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
"%02d:%02d ETA", i / 60, i % 60);
}
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
(void)write(STDOUT_FILENO, buf, strlen(buf));
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
if (flag == -1) {
(void) signal(SIGALRM, updateprogressmeter);
alarmtimer(1); /* set alarm timer for 1 Hz */
} else if (flag == 1) {
alarmtimer(0);
(void) putchar('\n');
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
}
fflush(stdout);
}
/*
* Display transfer statistics.
* Requires start to be initialised by progressmeter(-1),
* direction to be defined by xfer routines, and filesize and bytes
* to be updated by xfer routines
* If siginfo is nonzero, an ETA is displayed, and the output goes to STDERR
* instead of STDOUT.
*/
void
ptransfer(siginfo)
int siginfo;
{
struct timeval now, td;
double elapsed;
off_t bs;
int meg, remaining, hh;
char buf[100];
if (!verbose && !siginfo)
return;
(void) gettimeofday(&now, (struct timezone *)0);
timersub(&now, &start, &td);
elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
bs = bytes / (elapsed == 0.0 ? 1 : elapsed);
meg = 0;
if (bs > (1024 * 1024))
meg = 1;
(void)snprintf(buf, sizeof(buf),
"%qd byte%s %s in %.2f seconds (%.2f %sB/s)\n",
bytes, bytes == 1 ? "" : "s", direction, elapsed,
bs / (1024.0 * (meg ? 1024.0 : 1.0)), meg ? "M" : "K");
if (siginfo && bytes > 0 && elapsed > 0.0) {
remaining = (int)((filesize - restart_point) /
(bytes / elapsed) - elapsed);
hh = remaining / 3600;
remaining %= 3600;
snprintf(buf + strlen(buf) - 1, sizeof(buf) - strlen(buf),
" ETA: %02d:%02d:%02d\n", hh, remaining / 60,
remaining % 60);
}
(void)write(siginfo ? STDERR_FILENO : STDOUT_FILENO, buf, strlen(buf));
}
/*
* List words in stringlist, vertically arranged
*/
void
list_vertical(sl)
StringList *sl;
{
int i, j, w;
int columns, width, lines, items;
char *p;
width = items = 0;
for (i = 0 ; i < sl->sl_cur ; i++) {
w = strlen(sl->sl_str[i]);
if (w > width)
width = w;
}
width = (width + 8) &~ 7;
columns = ttywidth / width;
if (columns == 0)
columns = 1;
lines = (sl->sl_cur + columns - 1) / columns;
for (i = 0; i < lines; i++) {
for (j = 0; j < columns; j++) {
p = sl->sl_str[j * lines + i];
if (p)
printf("%s", p);
if (j * lines + i + lines >= sl->sl_cur) {
printf("\n");
break;
}
w = strlen(p);
while (w < width) {
w = (w + 8) &~ 7;
(void) putchar('\t');
}
}
}
}
[Yet Another Huge Ftp Commit - hopefully the last for a while, barring any more little things people want added ...] New features: * progressmeter is now asynchronous, so "stalled" transfers can be detected. "- stalled -" is displayed instead of the ETA in this case. When the xfer resumes, the time that the xfer was stalled for is factored out of the ETA. It is debatable whether this is better than not factoring it out, but I like it this way (I.e, if it stalls for 8 seconds and the ETA was 30 seconds, when it resumes the ETA will still be 30 seconds). * verbosity can be disabled on the command line (-V), so that in auto-fetch mode the only lines displayed will be a description of the file, and the progress bar (if possible) * if the screen is resized (and detected via the SIGWINCH signal), the progress bar will rescale automatically. Bugs fixed: * progress bar will not use the last character on the line, as this can cause problems on some terminals * screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin * progressmeter() used some vars before initialising them * ^D will quit now. [fixes bin/3162] * use hstrerror() to generate error message for host name lookup failure. * use getcwd instead of getwd (it should have been OK, but why tempt fate?) * auto-fetch transfers will always return a positive exit value upon failure or interruption, relative to the file's position in argv[]. * remote completion of / will work, without putting a leading "///". This is actually a bug in ftpd(1), where "NLST /" prefixes all names with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
/*
* Update the global ttywidth value, using TIOCGWINSZ.
*/
void
setttywidth(a)
int a;
{
struct winsize winsize;
if (ioctl(fileno(stdout), TIOCGWINSZ, &winsize) != -1)
ttywidth = winsize.ws_col;
else
ttywidth = 80;
}
/*
* Set the SIGALRM interval timer for wait seconds, 0 to disable.
*/
void
alarmtimer(wait)
int wait;
{
struct itimerval itv;
itv.it_value.tv_sec = wait;
itv.it_value.tv_usec = 0;
itv.it_interval = itv.it_value;
setitimer(ITIMER_REAL, &itv, NULL);
}