[fear this; more ftp hacking from lukem :-]

features:
---------
* transfer rate throttling with the new `rate' command. syntax:
	rate direction [max [incr]]
  where direction is `all', `get' or `put'.
  if max is not supplied, the current settings are displayed.
  if max is supplied, then transfers in the given direction will
  be throttled to this value.
  if incr is supplied, the increment for the `on-the-fly' scaling
  will be set to that, otherwise `1024' is used.
  currently implemented for binary get, binary put, and url fetches.
  not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
    - SIGUSR1 raises the throttle rate by the increment for that direction
    - SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
  `rcvbuf' and `sndbuf' commands)

bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
  command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
  suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
  it doesn't hurt)

notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
This commit is contained in:
lukem 1999-06-29 10:43:16 +00:00
parent 516292d398
commit e25749a582
9 changed files with 451 additions and 88 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmds.c,v 1.51 1999/06/20 22:07:28 cgd Exp $ */
/* $NetBSD: cmds.c,v 1.52 1999/06/29 10:43:16 lukem Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@ -78,7 +78,7 @@
#if 0
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
#else
__RCSID("$NetBSD: cmds.c,v 1.51 1999/06/20 22:07:28 cgd Exp $");
__RCSID("$NetBSD: cmds.c,v 1.52 1999/06/29 10:43:16 lukem Exp $");
#endif
#endif /* not lint */
@ -727,6 +727,12 @@ status(argc, argv)
fprintf(ttyout,
"Hash mark printing: %s; Mark count: %d; Progress bar: %s.\n",
onoff(hash), mark, onoff(progress));
fprintf(ttyout,
"Get transfer rate throttle: %s; maximum: %d; increment %d.\n",
onoff(rate_get), rate_get, rate_get_incr);
fprintf(ttyout,
"Put transfer rate throttle: %s; maximum: %d; increment %d.\n",
onoff(rate_put), rate_put, rate_put_incr);
fprintf(ttyout, "Use of PORT cmds: %s.\n", onoff(sendport));
#ifndef NO_EDITCOMPLETE
fprintf(ttyout, "Command line editing: %s.\n", onoff(editing));
@ -829,10 +835,9 @@ sethash(argc, argv)
hash = 0;
else {
int nmark;
char *ep;
nmark = strtol(argv[1], &ep, 10);
if (nmark < 1 || *ep != '\0') {
nmark = strsuftoi(argv[1]);
if (nmark < 1) {
fprintf(ttyout, "mark: bad bytecount value `%s'.\n",
argv[1]);
code = -1;
@ -1007,17 +1012,16 @@ setdebug(argc, argv)
else if (strcasecmp(argv[1], "off") == 0)
debug = 0;
else {
char *ep;
long val;
int val;
val = strtol(argv[1], &ep, 10);
if (val < 0 || val > INT_MAX || *ep != '\0') {
val = strsuftoi(argv[1]);
if (val < 0) {
fprintf(ttyout, "%s: bad debugging value.\n",
argv[1]);
code = -1;
return;
}
debug = (int)val;
debug = val;
}
} else
debug = !debug;
@ -2039,6 +2043,89 @@ setrunique(argc, argv)
code = togglevar(argc, argv, &runique, "Receive unique");
}
int
parserate(argc, argv, cmdlineopt)
int argc;
char *argv[];
int cmdlineopt;
{
int dir, max, incr, showonly;
sig_t oldusr1, oldusr2;
if (argc > 4 || (argc < (cmdlineopt ? 3 : 2))) {
usage:
if (cmdlineopt)
fprintf(ttyout,
"usage: %s (all|get|put),maximum[,increment]]\n",
argv[0]);
else
fprintf(ttyout,
"usage: %s (all|get|put) [maximum [increment]]\n",
argv[0]);
return -1;
}
dir = max = incr = showonly = 0;
#define RATE_GET 1
#define RATE_PUT 2
#define RATE_ALL (RATE_GET | RATE_PUT)
if (strcasecmp(argv[1], "all") == 0)
dir = RATE_ALL;
else if (strcasecmp(argv[1], "get") == 0)
dir = RATE_GET;
else if (strcasecmp(argv[1], "put") == 0)
dir = RATE_PUT;
else
goto usage;
if (argc >= 3) {
if ((max = strsuftoi(argv[2])) < 0)
goto usage;
} else
showonly = 1;
if (argc == 4) {
if ((incr = strsuftoi(argv[3])) <= 0)
goto usage;
} else
incr = DEFAULTINCR;
oldusr1 = signal(SIGUSR1, SIG_IGN);
oldusr2 = signal(SIGUSR2, SIG_IGN);
if (dir & RATE_GET) {
if (!showonly) {
rate_get = max;
rate_get_incr = incr;
}
if (!cmdlineopt || verbose)
fprintf(ttyout,
"Get xfer rate throttle: %s; maximum: %d; increment %d.\n",
onoff(rate_get), rate_get, rate_get_incr);
}
if (dir & RATE_PUT) {
if (!showonly) {
rate_put = max;
rate_put_incr = incr;
}
if (!cmdlineopt || verbose)
fprintf(ttyout,
"Put xfer rate throttle: %s; maximum: %d; increment %d.\n",
onoff(rate_put), rate_put, rate_put_incr);
}
(void)signal(SIGUSR1, oldusr1);
(void)signal(SIGUSR2, oldusr2);
return 0;
}
void
setrate(argc, argv)
int argc;
char *argv[];
{
code = parserate(argc, argv, 0);
}
/* change directory to parent directory */
void
cdup(argc, argv)
@ -2311,7 +2398,7 @@ sndbuf(argc, argv)
return;
}
if ((size = getsockbufsize(argv[1])) == -1) {
if ((size = strsuftoi(argv[1])) == -1) {
printf("invalid socket buffer size: %s\n", argv[1]);
code = -1;
return;
@ -2340,7 +2427,7 @@ rcvbuf(argc, argv)
return;
}
if ((size = getsockbufsize(argv[1])) == -1) {
if ((size = strsuftoi(argv[1])) == -1) {
printf("invalid socket buffer size: %s\n", argv[1]);
code = -1;
return;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmdtab.c,v 1.22 1999/06/24 14:54:28 christos Exp $ */
/* $NetBSD: cmdtab.c,v 1.23 1999/06/29 10:43:17 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94";
#else
__RCSID("$NetBSD: cmdtab.c,v 1.22 1999/06/24 14:54:28 christos Exp $");
__RCSID("$NetBSD: cmdtab.c,v 1.23 1999/06/29 10:43:17 lukem Exp $");
#endif
#endif /* not lint */
@ -102,6 +102,7 @@ char proxyhelp[] = "issue command on alternate connection";
char pwdhelp[] = "print working directory on remote machine";
char quithelp[] = "terminate ftp session and exit";
char quotehelp[] = "send arbitrary ftp command";
char ratehelp[] = "set transfer rate limit";
char rcvbufhelp[] = "set socket receive buffer size";
char receivehelp[] = "receive file";
char regethelp[] = "get file restarting at end of local file";
@ -200,6 +201,7 @@ struct cmd cmdtab[] = {
{ "pwd", pwdhelp, 0, 1, 1, CMPL0 pwd },
{ "quit", quithelp, 0, 0, 0, CMPL0 quit },
{ "quote", quotehelp, 1, 1, 1, CMPL0 quote },
{ "rate", ratehelp, 0, 0, 0, CMPL0 setrate },
{ "rcvbuf", rcvbufhelp, 0, 0, 0, CMPL0 rcvbuf },
{ "recv", receivehelp, 1, 1, 1, CMPL(rl) get },
{ "reget", regethelp, 1, 1, 1, CMPL(rl) reget },
@ -220,6 +222,7 @@ struct cmd cmdtab[] = {
{ "sunique", suniquehelp, 0, 0, 1, CMPL0 setsunique },
{ "system", systemhelp, 0, 1, 1, CMPL0 syst },
{ "tenex", tenexhelp, 0, 1, 1, CMPL0 settenex },
{ "throttle", ratehelp, 0, 0, 0, CMPL0 setrate },
{ "trace", tracehelp, 0, 0, 0, CMPL0 settrace },
{ "type", typehelp, 0, 1, 1, CMPL0 settype },
{ "umask", umaskhelp, 0, 1, 1, CMPL0 do_umask },

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.30 1999/06/24 14:46:59 christos Exp $ */
/* $NetBSD: extern.h,v 1.31 1999/06/29 10:43:17 lukem Exp $ */
/*-
* Copyright (c) 1994 The Regents of the University of California.
@ -52,6 +52,7 @@ void cdup __P((int, char **));
void changetype __P((int, int));
void cmdabort __P((int));
void cmdscanner __P((int));
void crankrate __P((int));
int command __P((const char *, ...));
#ifndef NO_EDITCOMPLETE
unsigned char complete __P((EditLine *, int));
@ -74,7 +75,6 @@ void get __P((int, char **));
struct cmd *getcmd __P((const char *));
int getit __P((int, char **, int, const char *));
int getreply __P((int));
int getsockbufsize __P((const char *));
int globulize __P((char **));
char *gunique __P((const char *));
void help __P((int, char **));
@ -100,6 +100,7 @@ void mput __P((int, char **));
char *onoff __P((int));
void newer __P((int, char **));
void page __P((int, char **));
int parserate __P((int, char **, int));
void progressmeter __P((int));
char *prompt __P((void));
void proxabort __P((int));
@ -150,6 +151,7 @@ void setport __P((int, char **));
void setpreserve __P((int, char **));
void setprogress __P((int, char **));
void setprompt __P((int, char **));
void setrate __P((int, char **));
void setrunique __P((int, char **));
void setstruct __P((int, char **));
void setsunique __P((int, char **));
@ -165,6 +167,7 @@ void sizecmd __P((int, char **));
char *slurpstring __P((void));
void sndbuf __P((int, char **));
void status __P((int, char **));
int strsuftoi __P((const char *));
void syst __P((int, char **));
int togglevar __P((int, char **, int *, const char *));
void usage __P((void));

View File

@ -1,4 +1,4 @@
/* $NetBSD: fetch.c,v 1.58 1999/06/27 01:17:19 lukem Exp $ */
/* $NetBSD: fetch.c,v 1.59 1999/06/29 10:43:17 lukem Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: fetch.c,v 1.58 1999/06/27 01:17:19 lukem Exp $");
__RCSID("$NetBSD: fetch.c,v 1.59 1999/06/29 10:43:17 lukem Exp $");
#endif /* not lint */
/*
@ -947,17 +947,37 @@ fetch_url(url, proxyenv, proxyauth, wwwauth)
goto cleanup_fetch_url;
}
if (debug)
fprintf(ttyout, "got chunksize of %qd\n",
fprintf(ttyout,
#ifndef NO_QUAD
"got chunksize of %qd\n",
(long long)chunksize);
#else
"got chunksize of %ld\n",
(long)chunksize);
#endif
if (chunksize == 0)
break;
}
while ((len = fread(buf, sizeof(char),
ischunked ? MIN(chunksize, BUFSIZ) : BUFSIZ, fin)) > 0) {
bytes += len;
if (fwrite(buf, sizeof(char), len, fout) != len) {
warn("Writing `%s'", savefile);
goto cleanup_fetch_url;
/* transfer file or chunk */
while (1) {
struct timeval then, now, td;
off_t bufrem;
(void)gettimeofday(&then, NULL);
bufrem = rate_get ? rate_get : BUFSIZ;
while (bufrem > 0) {
len = fread(buf, sizeof(char),
ischunked ? MIN(chunksize, bufrem) : BUFSIZ,
fin);
if (len <= 0)
goto chunkdone;
bytes += len;
bufrem -= len;
if (fwrite(buf, sizeof(char), len, fout)
!= len) {
warn("Writing `%s'", savefile);
goto cleanup_fetch_url;
}
}
if (hash && !progress) {
while (bytes >= hashbytes) {
@ -966,10 +986,23 @@ fetch_url(url, proxyenv, proxyauth, wwwauth)
}
(void)fflush(ttyout);
}
if (ischunked)
if (ischunked) {
chunksize -= len;
if (chunksize <= 0)
goto chunkdone;
}
if (rate_get) {
while (1) {
(void)gettimeofday(&now, NULL);
timersub(&now, &then, &td);
if (td.tv_sec > 0)
break;
usleep(1000000 - td.tv_usec);
}
}
}
/* read CRLF after chunk*/
chunkdone:
if (ischunked) {
if (fgets(buf, BUFSIZ, fin) == NULL)
break;

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ftp.1,v 1.41 1999/06/13 20:00:03 kleink Exp $
.\" $NetBSD: ftp.1,v 1.42 1999/06/29 10:43:18 lukem Exp $
.\"
.\" Copyright (c) 1985, 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -35,7 +35,7 @@
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
.Dd June 2, 1999
.Dd June 29, 1999
.Dt FTP 1
.Os
.Sh NAME
@ -60,6 +60,18 @@ file transfer program
.Op Fl r Ar seconds
.Ek
.Op Fl t
.Bk -words
.Oo
.Fl T
.Sm off
.Xo
.Ar direction ,
.Ar maximum
.Op , Ar increment
.Xc
.Sm on
.Oc
.Ek
.Op Fl v
.Op Fl V
.Bk -words
@ -190,6 +202,23 @@ seconds.
Restart all non-proxied ftp auto-fetches.
.It Fl t
Enables packet tracing.
.It Xo
.Fl T
.Sm off
.Ar direction ,
.Ar maximum
.Op , Ar increment
.Sm on
.Xc
Set the maximum transfer rate for
.Ar direction
to
.Ar maximum ,
and if specified, the increment to
.Ar increment .
Refer to
.Ic rate
for more information.
.It Fl v
Enable
.Ic verbose
@ -883,11 +912,64 @@ A synonym for
The arguments specified are sent, verbatim, to the remote
.Tn FTP
server.
.It Xo
.Ic rate Ar direction
.Op Ar maximum Op Ar increment
.Xc
Throttle the maximum transfer rate to
.Ar maximum
bytes/second.
If
.Ar maximum
is 0, disable the throttle.
.Pp
.Ar direction
may be one of:
.Bl -tag -width "all" -offset indent -compact
.It Ic all
Both directions.
.It Ic get
Incoming transfers.
.It Ic put
Outgoing transfers.
.El
.Pp
.Ar maximum
can by modified on the fly by
.Ar increment
bytes (default: 1024) each time a given signal is received:
.B
.Bl -tag -width "SIGUSR1" -offset indent
.It Dv SIGUSR1
Increment
.Ar maximum
by
.Ar increment
bytes.
.It Dv SIGUSR2
Decrement
.Ar maximum
by
.Ar increment
bytes.
The result must be a positive number.
.El
.Pp
If
.Ar maximum
is not supplied, the current throttle rates are displayed.
.Pp
Note:
.Ic rate
is not yet implemented for ascii mode transfers.
.It Ic recv Ar remote-file Op Ar local-file
A synonym for
.Ic get .
.It Ic reget Ar remote-file Op Ar local-file
Reget acts like get, except that if
.Ic reget
acts like
.Ic get ,
except that if
.Ar local-file
exists and is
smaller than
@ -1027,6 +1109,9 @@ Set the file transfer type to that needed to
talk to
.Tn TENEX
machines.
.It Ic throttle
A synonym for
.Ic rate .
.It Ic trace
Toggle packet tracing.
.It Ic type Op Ar type-name
@ -1100,6 +1185,25 @@ or
.Ic off
argument to force the setting appropriately.
.Pp
Commands which take a byte count as an argument
(e.g.,
.Ic hash
and
.Ic rate )
support an optional suffix on the argument which changes the
interpretation of the argument.
Supported suffixes are:
.Bl -tag -width 3n -offset indent -compact
.It b
Causes no modification. (Optional)
.It k
Kilo; multiply the argument by 1024
.It m
Mega; multiply the argument by 1048576
.It g
Giga; multiply the argument by 1073741824
.El
.Pp
If
.Nm
receives a
@ -1576,8 +1680,9 @@ command appeared in
.Pp
Various features such as command line editing, context sensitive
command and file completion, dynamic progress bar, automatic
fetching of files and URLs, and modification time
preservation were implemented in
fetching of files and URLs, modification time preservation,
and transfer rate throttling
were implemented in
.Nx 1.3
(and later releases)
by Luke Mewburn,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp.c,v 1.45 1999/06/24 14:50:56 christos Exp $ */
/* $NetBSD: ftp.c,v 1.46 1999/06/29 10:43:18 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
#else
__RCSID("$NetBSD: ftp.c,v 1.45 1999/06/24 14:50:56 christos Exp $");
__RCSID("$NetBSD: ftp.c,v 1.46 1999/06/29 10:43:18 lukem Exp $");
#endif
#endif /* not lint */
@ -640,20 +640,45 @@ sendrequest(cmd, local, remote, printnames)
case TYPE_I:
case TYPE_L:
errno = d = 0;
while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
bytes += c;
for (bufp = buf; c > 0; c -= d, bufp += d)
if ((d = write(fileno(dout), bufp, c)) <= 0)
break;
if (hash && (!progress || filesize < 0) ) {
while (bytes >= hashbytes) {
(void)putc('#', ttyout);
hashbytes += mark;
while (1) {
struct timeval then, now, td;
off_t bufrem, bufsize;
bufsize = sizeof(buf);
(void)gettimeofday(&then, NULL);
errno = c = d = 0;
bufrem = rate_put ? rate_put : bufsize;
while (bufrem > 0) {
if ((c = read(fileno(fin), buf,
MIN(bufsize, bufrem))) <= 0)
goto senddone;
bytes += c;
bufrem -= c;
for (bufp = buf; c > 0; c -= d, bufp += d)
if ((d = write(fileno(dout), bufp, c))
<= 0)
break;
if (d < 0)
goto senddone;
if (hash && (!progress || filesize < 0) ) {
while (bytes >= hashbytes) {
(void)putc('#', ttyout);
hashbytes += mark;
}
(void)fflush(ttyout);
}
}
if (rate_put) {
while (1) {
(void)gettimeofday(&now, NULL);
timersub(&now, &then, &td);
if (td.tv_sec > 0)
break;
usleep(1000000 - td.tv_usec);
}
(void)fflush(ttyout);
}
}
senddone:
if (hash && (!progress || filesize < 0) && bytes > 0) {
if (bytes < mark)
(void)putc('#', ttyout);
@ -768,8 +793,8 @@ recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
sig_t oldinti, oldintr, oldintp;
int c, d;
volatile int is_retr, tcrflag, bare_lfs;
static size_t bufsize;
static char *buf;
size_t bufsize;
char *buf;
volatile off_t hashbytes;
struct stat st;
time_t mtime;
@ -844,7 +869,8 @@ recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
}
if (dir != NULL)
*dir = 0;
d = access(dir == local ? "/" : dir ? local : ".", W_OK);
d = access(dir == local ? "/" :
dir ? local : ".", W_OK);
if (dir != NULL)
*dir = '/';
if (d < 0) {
@ -938,6 +964,12 @@ recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
}
closefunc = fclose;
}
/*
* XXX: look at punting and just using sndbuf_* for
* the buffer size, since st.st_blksize ~= 512
* and BUFSIZ ~= 4K
*/
if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
st.st_blksize = BUFSIZ;
if (st.st_blksize > bufsize) {
@ -964,19 +996,40 @@ recvrequest(cmd, local, remote, lmode, printnames, ignorespecial)
(*closefunc)(fout);
return;
}
errno = d = 0;
while ((c = read(fileno(din), buf, bufsize)) > 0) {
if ((d = write(fileno(fout), buf, c)) != c)
break;
bytes += c;
if (hash && (!progress || filesize < 0)) {
while (bytes >= hashbytes) {
(void)putc('#', ttyout);
hashbytes += mark;
while (1) {
struct timeval then, now, td;
off_t bufrem;
(void)gettimeofday(&then, NULL);
errno = c = d = 0;
bufrem = rate_get ? rate_get : bufsize;
while (bufrem > 0) {
if ((c = read(fileno(din), buf,
MIN(bufsize, bufrem))) <= 0)
goto recvdone;
bytes += c;
bufrem -=c;
if ((d = write(fileno(fout), buf, c)) != c)
goto recvdone;
if (hash && (!progress || filesize < 0)) {
while (bytes >= hashbytes) {
(void)putc('#', ttyout);
hashbytes += mark;
}
(void)fflush(ttyout);
}
}
if (rate_get) {
while (1) {
(void)gettimeofday(&now, NULL);
timersub(&now, &then, &td);
if (td.tv_sec > 0)
break;
usleep(1000000 - td.tv_usec);
}
(void)fflush(ttyout);
}
}
recvdone:
if (hash && (!progress || filesize < 0) && bytes > 0) {
if (bytes < mark)
(void)putc('#', ttyout);
@ -1310,9 +1363,12 @@ void
psummary(notused)
int notused;
{
int oerrno;
oerrno = errno;
if (bytes > 0)
ptransfer(1);
errno = oerrno;
}
void

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp_var.h,v 1.32 1999/06/20 22:07:29 cgd Exp $ */
/* $NetBSD: ftp_var.h,v 1.33 1999/06/29 10:43:18 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -62,10 +62,11 @@
#include "extern.h"
#define HASHBYTES 1024
#define FTPBUFLEN MAXPATHLEN + 200
#define MAX_IN_PORT_T 0xffffU
#define HASHBYTES 1024 /* default mark for `hash' command */
#define DEFAULTINCR 1024 /* default increment for `rate' command */
#define STALLTIME 5 /* # of seconds of no xfer before "stalling" */
#define FTP_PORT 21 /* default if ! getservbyname("ftp/tcp") */
@ -130,6 +131,10 @@ int bytesize; /* local byte size in binary */
int anonftp; /* automatic anonymous login */
int dirchange; /* remote directory changed by cd command */
int flushcache; /* set HTTP cache flush headers with request */
int rate_get; /* maximum get xfer rate */
int rate_get_incr; /* increment for get xfer rate */
int rate_put; /* maximum put xfer rate */
int rate_put_incr; /* increment for put xfer rate */
int retry_connect; /* seconds between retrying connection */
int ttywidth; /* width of tty */
char *tmpdir; /* temporary directory */

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.43 1999/06/20 22:07:29 cgd Exp $ */
/* $NetBSD: main.c,v 1.44 1999/06/29 10:43:19 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\n\
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94";
#else
__RCSID("$NetBSD: main.c,v 1.43 1999/06/20 22:07:29 cgd Exp $");
__RCSID("$NetBSD: main.c,v 1.44 1999/06/29 10:43:19 lukem Exp $");
#endif
#endif /* not lint */
@ -131,6 +131,11 @@ main(argc, argv)
hist = NULL;
#endif
mark = HASHBYTES;
rate_get = 0;
rate_get_incr = DEFAULTINCR;
rate_put = 0;
rate_put_incr = DEFAULTINCR;
marg_sl = sl_init();
if ((tmpdir = getenv("TMPDIR")) == NULL)
tmpdir = _PATH_TMP;
@ -190,7 +195,7 @@ main(argc, argv)
}
}
while ((ch = getopt(argc, argv, "Aadefgino:pP:r:RtvV")) != -1) {
while ((ch = getopt(argc, argv, "Aadefgino:pP:r:RtT:vV")) != -1) {
switch (ch) {
case 'A':
activefallback = 0;
@ -261,6 +266,32 @@ main(argc, argv)
trace = 1;
break;
case 'T':
{
int targc;
char *targv[6], *oac;
/* look for `dir,max[,incr]' */
targc = 0;
targv[targc++] = "-T";
oac = xstrdup(optarg);
while ((cp = strsep(&oac, ",")) != NULL) {
if (*cp == '\0') {
warnx("bad throttle value: %s", optarg);
usage();
/* NOTREACHED */
}
targv[targc++] = cp;
if (targc >= 5)
break;
}
if (parserate(targc, targv, 1) == -1)
usage();
free(oac);
break;
}
case 'v':
progress = verbose = 1;
break;
@ -298,6 +329,8 @@ main(argc, argv)
setttywidth(0);
(void)xsignal(SIGWINCH, setttywidth);
(void)xsignal(SIGUSR1, crankrate);
(void)xsignal(SIGUSR2, crankrate);
#ifdef __GNUC__ /* to shut up gcc warnings */
(void)&argc;
@ -752,11 +785,8 @@ void
usage()
{
(void)fprintf(stderr,
"usage: %s [-AadeginptvV] [-r retry] [-P port] [host [port]]\n"
" %s [-f] [-o outfile] file:///file\n"
" %s [-fR] [-o outfile] ftp://[user[:pass]@]host[:port]/path[/]\n"
" %s [-f] [-o outfile] http://host[:port]/path\n"
" %s [-fR] [-o outfile] host:path[/]\n",
__progname, __progname, __progname, __progname, __progname);
"usage: %s [-AadefginpRtvV] [-r retry] [-o outfile] [-P port] [-T dir,max[,inc]\n"
" [host [port]] [file:///file] [ftp://[user[:pass]@]host[:port]/path[/]]\n"
" [http://[user[:pass]@]host[:port]/path] [host:path[/]]\n", __progname);
exit(1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: util.c,v 1.52 1999/06/26 00:17:02 lukem Exp $ */
/* $NetBSD: util.c,v 1.53 1999/06/29 10:43:19 lukem Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@ -75,7 +75,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: util.c,v 1.52 1999/06/26 00:17:02 lukem Exp $");
__RCSID("$NetBSD: util.c,v 1.53 1999/06/29 10:43:19 lukem Exp $");
#endif /* not lint */
/*
@ -89,6 +89,7 @@ __RCSID("$NetBSD: util.c,v 1.52 1999/06/26 00:17:02 lukem Exp $");
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <termios.h>
@ -285,15 +286,14 @@ ftp_login(host, user, pass)
user = "anonymous"; /* as per RFC 1635 */
}
if (user == NULL) {
if (user == NULL)
freeuser = 1;
if (pass == NULL)
freepass = 1;
freeacct = 1;
if (ruserpass(host, &user, &pass, &acct) < 0) {
code = -1;
goto cleanup_ftp_login;
}
if (pass == NULL)
freepass = 1;
freeacct = 1;
if (ruserpass(host, &user, &pass, &acct) < 0) {
code = -1;
goto cleanup_ftp_login;
}
while (user == NULL) {
@ -787,8 +787,11 @@ static void
updateprogressmeter(dummy)
int dummy;
{
int oerrno;
oerrno = errno;
progressmeter(0);
errno = oerrno;
}
#endif /* NO_PROGRESS */
@ -1076,14 +1079,40 @@ setttywidth(a)
int a;
{
struct winsize winsize;
int oerrno;
oerrno = errno;
if (ioctl(fileno(ttyout), TIOCGWINSZ, &winsize) != -1 &&
winsize.ws_col != 0)
ttywidth = winsize.ws_col;
else
ttywidth = 80;
errno = oerrno;
}
void
crankrate(int sig)
{
switch (sig) {
case SIGUSR1:
if (rate_get)
rate_get += rate_get_incr;
if (rate_put)
rate_put += rate_put_incr;
break;
case SIGUSR2:
if (rate_get && rate_get > rate_get_incr)
rate_get -= rate_get_incr;
if (rate_put && rate_put > rate_put_incr)
rate_put -= rate_put_incr;
break;
default:
err(1, "crankrate invoked with unknown signal: %d", sig);
}
}
/*
* Set the SIGALRM interval timer for wait seconds, 0 to disable.
*/
@ -1146,29 +1175,41 @@ controlediting()
#endif /* !NO_EDITCOMPLETE */
/*
* Parse the specified socket buffer size.
* Convert the string `arg' to an int, which may have an optional SI suffix
* (`b', `k', `m', `g'). Returns the number for success, -1 otherwise.
*/
int
getsockbufsize(arg)
strsuftoi(arg)
const char *arg;
{
char *cp;
int val;
long val;
if (!isdigit((unsigned char)arg[0]))
return (-1);
val = strtol(arg, &cp, 10);
if (cp != NULL) {
if (cp[1] != '\0')
if (cp[0] != '\0' && cp[1] != '\0')
return (-1);
if (cp[0] == 'k')
val *= 1024;
if (cp[0] == 'm')
val *= 1024 * 1024;
switch (tolower((unsigned char)cp[0])) {
case '\0':
case 'b':
break;
case 'k':
val <<= 10;
break;
case 'm':
val <<= 20;
break;
case 'g':
val <<= 30;
break;
default:
return (-1);
}
}
if (val < 0)
if (val < 0 || val > INT_MAX)
return (-1);
return (val);