[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:
parent
516292d398
commit
e25749a582
|
@ -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;
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue