cleanups/bugfixes:

- don't echo 'ACCT' parameter when debugging (a la 'PASS')
- Fix checking of directory access for "/foo", the parent
  directory is "/", not "" (from FreeBSD)
- remove trailing whitespace on lines
- add any missing NetBSD tags
- cleanups to man page, includinging sorting options description

feature additions:
- variable sized hash marks (from [bin/683], but done in the hash command
  as an optional arg)
- more user-friendly transfer time printing (from FreeBSD, with mods)
- '-p' command line option to jump into PASV mode (closes [bin/2857],
  but with an option rather than checking argv[0])
- SIGINFO support for printing xfer stats when sending/receiving requests
- '-P port' for changing the port to connect to (from thorpej@netbsd.org)
- '-a': bypass normal login, and try anonymous login (from OpenBSD
  via thorpej)
- autofetch files via url (ftp://...) or "classic" (host:/file)
  (from OpenBSD via thorpej)
- 'ftp' synonymous with 'open' (from FreeBSD)
This commit is contained in:
lukem 1996-11-25 05:13:18 +00:00
parent acf2644128
commit 36d3d1fd0f
8 changed files with 435 additions and 140 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmds.c,v 1.8 1995/09/08 01:06:05 tls Exp $ */
/* $NetBSD: cmds.c,v 1.9 1996/11/25 05:13:18 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
#else
static char rcsid[] = "$NetBSD: cmds.c,v 1.8 1995/09/08 01:06:05 tls Exp $";
static char rcsid[] = "$NetBSD: cmds.c,v 1.9 1996/11/25 05:13:18 lukem Exp $";
#endif
#endif /* not lint */
@ -164,6 +164,7 @@ setpeer(argc, argv)
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');
@ -200,7 +201,7 @@ setpeer(argc, argv)
unix_proxy = 0;
else
unix_server = 0;
if (overbose &&
if (overbose &&
!strncmp(reply_string, "215 TOPS20", 10))
printf(
"Remember to set tenex mode when transfering binary files from this machine.\n");
@ -416,7 +417,7 @@ put(argc, argv)
goto usage;
if (argc < 3 && !another(&argc, &argv, "remote-file")) {
usage:
printf("usage: %s local-file remote-file\n", argv[0]);
printf("usage: %s local-file [ remote-file ]\n", argv[0]);
code = -1;
return;
}
@ -516,7 +517,7 @@ mput(argc, argv)
return;
}
for (i = 1; i < argc; i++) {
char **cpp, **gargs;
char **cpp;
glob_t gl;
int flags;
@ -669,15 +670,15 @@ usage:
tm->tm_mon++;
if (tm->tm_year > yy%100)
return (1);
if ((tm->tm_year == yy%100 &&
if ((tm->tm_year == yy%100 &&
tm->tm_mon > mo) ||
(tm->tm_mon == mo &&
(tm->tm_mon == mo &&
tm->tm_mday > day) ||
(tm->tm_mday == day &&
(tm->tm_mday == day &&
tm->tm_hour > hour) ||
(tm->tm_hour == hour &&
(tm->tm_hour == hour &&
tm->tm_min > min) ||
(tm->tm_min == min &&
(tm->tm_min == min &&
tm->tm_sec > sec))
return (1);
} else {
@ -746,7 +747,7 @@ mget(argc, argv)
if (mflag && confirm(argv[0], cp)) {
tp = cp;
if (mcase) {
for (tp2 = tmpbuf; ch = *tp++;)
for (tp2 = tmpbuf; (ch = *tp++) != NULL; )
*tp2++ = isupper(ch) ? tolower(ch) : ch;
*tp2 = '\0';
tp = tmpbuf;
@ -869,7 +870,7 @@ status(argc, argv)
}
printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n",
modename, typename, formname, structname);
printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n",
onoff(verbose), onoff(bell), onoff(interactive),
onoff(doglob));
printf("Store unique: %s; Receive unique: %s\n", onoff(sunique),
@ -887,8 +888,8 @@ status(argc, argv)
else {
printf("Nmap: off\n");
}
printf("Hash mark printing: %s; Use of PORT cmds: %s\n",
onoff(hash), onoff(sendport));
printf("Hash mark printing: %s; Mark count: %d\n", onoff(hash), mark);
printf("Use of PORT cmds: %s\n", onoff(sendport));
if (macnum > 0) {
printf("Macros:\n");
for (i=0; i<macnum; i++) {
@ -929,7 +930,7 @@ settrace(argc, argv)
}
/*
* Toggle hash mark printing during transfers.
* Toggle hash mark printing during transfers, or set hash mark bytecount.
*/
/*VARARGS*/
void
@ -937,13 +938,25 @@ sethash(argc, argv)
int argc;
char *argv[];
{
hash = !hash;
printf("Hash mark printing %s", onoff(hash));
code = hash;
if (hash)
printf(" (%d bytes/hash mark)", 1024);
printf(".\n");
if (argc == 1) {
hash = !hash;
printf("Hash mark printing %s", onoff(hash));
code = hash;
if (hash)
printf(" (%d bytes/hash mark)", mark);
printf(".\n");
} else if (argc != 2) {
printf("usage: %s [number of bytes].\n", argv[0]);
} else {
int nmark = atol(argv[1]);
if (nmark < 1)
printf( "A hash mark bytecount of %d"
" is rather pointless...\n", nmark);
else {
mark = nmark;
printf("Hash mark set to %d bytes/hash mark\n", mark);
}
}
}
/*
@ -1002,7 +1015,7 @@ setglob(argc, argv)
int argc;
char *argv[];
{
doglob = !doglob;
printf("Globbing %s.\n", onoff(doglob));
code = doglob;
@ -1205,6 +1218,9 @@ ls(argc, argv)
return;
}
recvrequest(cmd, argv[2], argv[1], "w", 0);
/* flush results in case commands are coming from a pipe */
fflush(stdout);
}
/*
@ -1268,7 +1284,7 @@ shell(argc, argv)
{
pid_t pid;
sig_t old1, old2;
char shellnam[40], *shell, *namep;
char shellnam[40], *shell, *namep;
union wait status;
old1 = signal (SIGINT, SIG_IGN);
@ -1908,7 +1924,7 @@ domap(name)
break;
case '[':
LOOP:
if (*++cp2 == '$' && isdigit(*(cp2+1))) {
if (*++cp2 == '$' && isdigit(*(cp2+1))) {
if (*++cp2 == '0') {
char *cp3 = name;
@ -1927,7 +1943,7 @@ LOOP:
}
}
else {
while (*cp2 && *cp2 != ',' &&
while (*cp2 && *cp2 != ',' &&
*cp2 != ']') {
if (*cp2 == '\\') {
cp2++;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cmdtab.c,v 1.6 1995/09/08 01:06:10 tls Exp $ */
/* $NetBSD: cmdtab.c,v 1.7 1996/11/25 05:13:20 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)cmdtab.c 8.4 (Berkeley) 10/9/94";
#else
static char rcsid[] = "$NetBSD: cmdtab.c,v 1.6 1995/09/08 01:06:10 tls Exp $";
static char rcsid[] = "$NetBSD: cmdtab.c,v 1.7 1996/11/25 05:13:20 lukem Exp $";
#endif
#endif /* not lint */
@ -66,7 +66,7 @@ char disconhelp[] = "terminate ftp session";
char domachelp[] = "execute macro";
char formhelp[] = "set file transfer format";
char globhelp[] = "toggle metacharacter expansion of local file names";
char hashhelp[] = "toggle printing `#' for each buffer transferred";
char hashhelp[] = "toggle printing `#' marks; specify number to set size";
char helphelp[] = "print local help information";
char idlehelp[] = "get (set) idle timer on remote side";
char lcdhelp[] = "change local working directory";
@ -135,6 +135,7 @@ struct cmd cmdtab[] = {
{ "dir", dirhelp, 1, 1, 1, ls },
{ "disconnect", disconhelp, 0, 1, 1, disconnect },
{ "form", formhelp, 0, 1, 1, setform },
{ "ftp", connecthelp, 0, 0, 1, setpeer },
{ "get", receivehelp, 1, 1, 1, get },
{ "glob", globhelp, 0, 0, 0, setglob },
{ "hash", hashhelp, 0, 0, 0, sethash },

View File

@ -1,4 +1,4 @@
/* $NetBSD: extern.h,v 1.4 1995/09/08 01:06:19 tls Exp $ */
/* $NetBSD: extern.h,v 1.5 1996/11/25 05:13:21 lukem Exp $ */
/*-
* Copyright (c) 1994 The Regents of the University of California.
@ -92,8 +92,9 @@ void newer __P((int, char **));
void proxabort __P(());
void proxtrans __P((char *, char *, char *));
void psabort __P(());
void psummary __P((int));
void pswitch __P((int));
void ptransfer __P((char *, long, struct timeval *, struct timeval *));
void ptransfer __P((char *, long, struct timeval *, struct timeval *, int));
void put __P((int, char **));
void pwd __P((int, char **));
void quit __P((int, char **));

View File

@ -1,4 +1,4 @@
.\" $NetBSD: ftp.1,v 1.11 1995/09/08 01:06:24 tls Exp $
.\" $NetBSD: ftp.1,v 1.12 1996/11/25 05:13:22 lukem Exp $
.\"
.\" Copyright (c) 1985, 1989, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -33,7 +33,7 @@
.\"
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
.\"
.Dd October 9, 1994
.Dd November 25, 1996
.Dt FTP 1
.Os BSD 4.2
.Sh NAME
@ -43,15 +43,24 @@
file transfer program
.Sh SYNOPSIS
.Nm ftp
.Op Fl t
.Op Fl v
.Op Fl a
.Op Fl d
.Op Fl g
.Op Fl i
.Op Fl n
.Op Fl g
.Op Ar host
.Op Fl p
.Op Fl P Ar port
.Op Fl t
.Op Fl v
.Op Ar host Op Ar port
.Nm ftp
ftp://\fIhost\fR/\fIfile\fR
.Nm ftp
ftp://\fIhost\fR:\fIport\fR/\fIfile\fR
.Nm ftp
\fIhost\fR:/\fIfile\fR
.Sh DESCRIPTION
.Nm Ftp
.Nm
is the user interface to the
.Tn ARPANET
standard File Transfer Protocol.
@ -60,51 +69,71 @@ remote network site.
.Pp
Options may be specified at the command line, or to the
command interpreter.
.Bl -tag -width flag
.It Fl t
Enables packet tracing.
.It Fl v
Verbose option forces
.Nm ftp
to show all responses from the remote server, as well
as report on data transfer statistics.
.Bl -tag -width "port "
.It Fl a
Causes
.Nm
to bypass normal login procedure, and use an anonymous login instead.
.It Fl d
Enables debugging.
.It Fl g
Disables file name globbing.
.It Fl i
Turns off interactive prompting during
multiple file transfers.
.It Fl n
Restrains
.Nm ftp
.Nm
from attempting \*(Lqauto-login\*(Rq upon initial connection.
If auto-login is enabled,
.Nm ftp
.Nm
will check the
.Pa .netrc
(see below) file in the user's home directory for an entry describing
an account on the remote machine.
If no entry exists,
.Nm ftp
.Nm
will prompt for the remote machine login name (default is the user
identity on the local machine), and, if necessary, prompt for a password
and an account with which to login.
.It Fl i
Turns off interactive prompting during
multiple file transfers.
.It Fl d
Enables debugging.
.It Fl g
Disables file name globbing.
.It Fl p
Enable passive mode operation for use behind connection filtering firewalls.
.It Fl P Ar port
Sets the port number to
.Ar port .
This option only has meaning if using the auto-fetch feature of
.Nm ftp .
.It Fl t
Enables packet tracing.
.It Fl v
Verbose option forces
.Nm
to show all responses from the remote server, as well
as report on data transfer statistics.
.El
.Pp
In addition to standard commands, this version of
.Nm
supports an auto-fetch feature.
To enable auto-fetch, simply pass the list of hostnames/files
on the command line.
The hostnames/files may be specified in URL-style format
(ftp://ftp.NetBSD.ORG/pub/NetBSD/README) or in the format
ftp.NetBSD.ORG:/pub/NetBSD/README.
.Pp
The client host with which
.Nm ftp
.Nm
is to communicate may be specified on the command line.
If this is done,
.Nm ftp
.Nm
will immediately attempt to establish a connection to an
.Tn FTP
server on that host; otherwise,
.Nm ftp
.Nm
will enter its command interpreter and await instructions
from the user.
When
.Nm ftp
.Nm
is awaiting commands from the user the prompt
.Ql ftp>
is provided to the user.
@ -184,7 +213,7 @@ current remote machine working directory.
Change the permission modes of the file
.Ar file-name
on the remote
sytem to
system to
.Ar mode .
.It Ic close
Terminate the
@ -221,7 +250,7 @@ If an optional
.Ar debug-value
is specified it is used to set the debugging level.
When debugging is on,
.Nm ftp
.Nm
prints each command sent to the remote machine, preceded
by the string
.Ql \-\->
@ -236,7 +265,7 @@ directory,
and, optionally, placing the output in
.Ar local-file .
If interactive prompting is on,
.Nm ftp
.Nm
will prompt the user to verify that the last argument is indeed the
target local file for receiving
.Ic dir
@ -252,6 +281,9 @@ output comes to the terminal.
.It Ic disconnect
A synonym for
.Ar close .
.It Ic ftp Ar host Op Ar port
Synonymous with
.Ic open Ar host Op Ar port
.It Ic form Ar format
Set the file transfer
.Ic form
@ -313,15 +345,18 @@ That can be done by
transferring a
.Xr tar 1
archive of the subtree (in binary mode).
.It Ic hash
.It Ic hash Op Ar size
Toggle hash-sign (``#'') printing for each data block
transferred.
The size of a data block is 1024 bytes.
The size of a data block defaults to 1024 bytes.
This can be changed by specifying
.Ar size
in bytes.
.It Ic help Op Ar command
Print an informative message about the meaning of
.Ar command .
If no argument is given,
.Nm ftp
.Nm
prints a list of the known commands.
.It Ic idle Op Ar seconds
Set the inactivity timer on the remote server to
@ -355,7 +390,7 @@ If
.Ar remote-directory
is left unspecified, the current working directory is used.
If interactive prompting is on,
.Nm ftp
.Nm
will prompt the user to verify that the last argument is indeed the
target local file for receiving
.Ic \&ls
@ -396,7 +431,7 @@ Like
.Ic dir ,
except multiple remote files may be specified.
If interactive prompting is on,
.Nm ftp
.Nm
will prompt the user to verify that the last argument is indeed the
target local file for receiving
.Ic mdir
@ -432,7 +467,7 @@ and the
.Ar local-file
must be specified.
If interactive prompting is on,
.Nm ftp
.Nm
will prompt the user to verify that the last argument is indeed the
target local file for receiving
.Ic mls
@ -477,7 +512,7 @@ If
.Ar remote-directory
is left unspecified, the current working directory is used.
If interactive prompting is on,
.Nm ftp
.Nm
will prompt the user to verify that the last argument is indeed the
target local file for receiving
.Ic nlist
@ -594,14 +629,14 @@ Establish a connection to the specified
server.
An optional port number may be supplied,
in which case,
.Nm ftp
.Nm
will attempt to contact an
.Tn FTP
server at that port.
If the
.Ic auto-login
option is on (default),
.Nm ftp
.Nm
will also attempt to automatically log the user in to
the
.Tn FTP
@ -621,7 +656,7 @@ port and the client connects to it. When using the more traditional
.Dv PORT
command, the client listens on a port and sends that address to the remote
server, who connects back to it. Passive mode is useful when using
.Nm ftp
.Nm
through a gateway router or host that controls the directionality of
traffic.
(Note that though ftp servers are required to support the
@ -783,7 +818,7 @@ Toggle the use of
.Dv PORT
commands.
By default,
.Nm ftp
.Nm
will attempt to use a
.Dv PORT
command when establishing
@ -795,7 +830,7 @@ when performing multiple file transfers.
If the
.Dv PORT
command fails,
.Nm ftp
.Nm
will use the default data port.
When the use of
.Dv PORT
@ -870,7 +905,7 @@ server.
If the
.Ar password
is not specified and the server requires it,
.Nm ftp
.Nm
will prompt the user for it (after disabling local echo).
If an
.Ar account
@ -885,7 +920,7 @@ be relayed to the remote server after the login sequence
is completed if the remote server did not require it
for logging in.
Unless
.Nm ftp
.Nm
is invoked with \*(Lqauto-login\*(Rq disabled, this
process is done automatically on initial connection to
the
@ -908,6 +943,18 @@ A synonym for help.
.Pp
Command arguments which have embedded spaces may be quoted with
quote `"' marks.
.Pp
If
.Nm
receives a
.Dv SIGINFO
(see the
.Dq status
arguments of
.Xr stty 1 )
signal whilst a transfer is in progress, the current transfer rate
statistics will be written to the standard error output, in the
same format as the standard completion message.
.Sh ABORTING A FILE TRANSFER
To abort a file transfer, use the terminal interrupt key
(usually Ctrl-C).
@ -927,18 +974,18 @@ prompt will not appear until the remote server has completed
sending the requested file.
.Pp
The terminal interrupt key sequence will be ignored when
.Nm ftp
.Nm
has completed any local processing and is awaiting a reply
from the remote server.
A long delay in this mode may result from the ABOR processing described
above, or from unexpected behavior by the remote server, including
violations of the ftp protocol.
If the delay results from unexpected remote server behavior, the local
.Nm ftp
.Nm
program must be killed by hand.
.Sh FILE NAMING CONVENTIONS
Files specified as arguments to
.Nm ftp
.Nm
commands are processed according to the following rules.
.Bl -enum
.It
@ -954,7 +1001,7 @@ If the first character of the file name is
.Sq \&| ,
the
remainder of the argument is interpreted as a shell command.
.Nm Ftp
.Nm
then forks a shell, using
.Xr popen 3
with the argument supplied, and reads (writes) from the stdout
@ -973,7 +1020,7 @@ c.f. the
.Ic glob
command.
If the
.Nm ftp
.Nm
command expects a single local file (.e.g.
.Ic put ) ,
only the first filename generated by the "globbing" operation is used.
@ -1018,13 +1065,13 @@ may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary),
and
.Tn PDP Ns -20's
mostly).
.Nm Ftp
.Nm
supports the ascii and image types of file transfer,
plus local byte size 8 for
.Ic tenex
mode transfers.
.Pp
.Nm Ftp
.Nm
supports only the default values for the remaining
file transfer parameters:
.Ic mode ,
@ -1048,7 +1095,7 @@ The auto-login process searches the
file for a
.Ic machine
token that matches the remote machine specified on the
.Nm ftp
.Nm
command line or as an
.Ic open
command argument.
@ -1100,7 +1147,7 @@ Note that if this token is present in the
file for any user other
than
.Ar anonymous ,
.Nm ftp
.Nm
will abort the auto-login process if the
.Pa .netrc
is readable by
@ -1115,7 +1162,7 @@ command if it does not.
.It Ic macdef Ar name
Define a macro.
This token functions like the
.Nm ftp
.Nm
.Ic macdef
command functions.
A macro is defined with the specified name; its contents begin with the
@ -1129,7 +1176,7 @@ is defined, it is automatically executed as the last step in the
auto-login process.
.El
.Sh ENVIRONMENT
.Nm Ftp
.Nm
utilizes the following environment variables.
.Bl -tag -width Fl
.It Ev HOME
@ -1143,7 +1190,7 @@ For default shell.
.Xr ftpd 8
.Sh HISTORY
The
.Nm ftp
.Nm
command appeared in
.Bx 4.2 .
.Sh BUGS

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp.c,v 1.13 1995/09/16 22:32:59 pk Exp $ */
/* $NetBSD: ftp.c,v 1.14 1996/11/25 05:13:23 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
#else
static char rcsid[] = "$NetBSD: ftp.c,v 1.13 1995/09/16 22:32:59 pk Exp $";
static char rcsid[] = "$NetBSD: ftp.c,v 1.14 1996/11/25 05:13:23 lukem Exp $";
#endif
#endif /* not lint */
@ -81,6 +81,9 @@ int ptabflg;
int ptflag = 0;
struct sockaddr_in myctladdr;
off_t restart_point = 0;
char *direction;
struct timeval start, stop;
int bytes;
FILE *cin, *cout;
@ -92,7 +95,7 @@ hookup(host, port)
{
struct hostent *hp = 0;
int s, len, tos;
static char hostnamebuf[80];
static char hostnamebuf[MAXHOSTNAMELEN];
memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
if (inet_aton(host, &hisctladdr.sin_addr) != 0) {
@ -200,13 +203,46 @@ login(host)
{
char tmp[80];
char *user, *pass, *acct;
char anonpass[MAXLOGNAME + MAXHOSTNAMELEN + 2]; /* "user@hostname\0" */
char hostname[MAXHOSTNAMELEN + 1];
int n, aflag = 0;
user = pass = acct = 0;
user = pass = acct = NULL;
if (ruserpass(host, &user, &pass, &acct) < 0) {
code = -1;
return (0);
}
/*
* Set up arguments for an anonymous FTP session, if necessary.
*/
if ((user == NULL || pass == NULL) && anonftp) {
memset(anonpass, 0, sizeof(anonpass));
memset(hostname, 0, sizeof(hostname));
/*
* Set up anonymous login password.
*/
user = getlogin();
gethostname(hostname, MAXHOSTNAMELEN);
#ifndef DONT_CHEAT_ANONPASS
/*
* Every anonymous FTP server I've encountered
* will accept the string "username@", and will
* append the hostname itself. We do this by default
* since many servers are picky about not having
* a FQDN in the anonymous password.
*/
snprintf(anonpass, sizeof(anonpass) - 1, "%s@",
user);
#else
snprintf(anonpass, sizeof(anonpass) - 1, "%s@%s",
user, hp->h_name);
#endif
pass = anonpass;
user = "anonymous";
}
while (user == NULL) {
char *myname = getlogin();
@ -285,7 +321,9 @@ va_dcl
fmt = va_arg(ap, char *);
if (strncmp("PASS ", fmt, 5) == 0)
printf("PASS XXXX");
else
else if (strncmp("ACCT ", fmt, 5) == 0)
printf("ACCT XXXX");
else
vfprintf(stdout, fmt, ap);
va_end(ap);
printf("\n");
@ -440,22 +478,21 @@ abortsend()
longjmp(sendabort, 1);
}
#define HASHBYTES 1024
void
sendrequest(cmd, local, remote, printnames)
char *cmd, *local, *remote;
int printnames;
{
struct stat st;
struct timeval start, stop;
int c, d;
FILE *fin, *dout = 0, *popen();
int (*closefunc) __P((FILE *));
sig_t oldintr, oldintp;
long bytes = 0, hashbytes = HASHBYTES;
sig_t oldinti, oldintr, oldintp;
long hashbytes = mark;
char *lmode, buf[BUFSIZ], *bufp;
direction = "sent";
bytes = 0;
if (verbose && printnames) {
if (local && *local != '-')
printf("local: %s ", local);
@ -471,6 +508,7 @@ sendrequest(cmd, local, remote, printnames)
closefunc = NULL;
oldintr = NULL;
oldintp = NULL;
oldinti = NULL;
lmode = "w";
if (setjmp(sendabort)) {
while (cpend) {
@ -484,10 +522,13 @@ sendrequest(cmd, local, remote, printnames)
(void) signal(SIGINT,oldintr);
if (oldintp)
(void) signal(SIGPIPE,oldintp);
if (oldinti)
(void) signal(SIGINFO,oldinti);
code = -1;
return;
}
oldintr = signal(SIGINT, abortsend);
oldinti = signal(SIGINFO, psummary);
if (strcmp(local, "-") == 0)
fin = stdin;
else if (*local == '|') {
@ -497,6 +538,7 @@ sendrequest(cmd, local, remote, printnames)
warn("%s", local + 1);
(void) signal(SIGINT, oldintr);
(void) signal(SIGPIPE, oldintp);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
@ -506,6 +548,7 @@ sendrequest(cmd, local, remote, printnames)
if (fin == NULL) {
warn("local: %s", local);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
@ -514,6 +557,7 @@ sendrequest(cmd, local, remote, printnames)
(st.st_mode&S_IFMT) != S_IFREG) {
fprintf(stdout, "%s: not a plain file.\n", local);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
fclose(fin);
code = -1;
return;
@ -521,6 +565,7 @@ sendrequest(cmd, local, remote, printnames)
}
if (initconn()) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
code = -1;
@ -564,6 +609,7 @@ sendrequest(cmd, local, remote, printnames)
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
if (closefunc != NULL)
@ -573,6 +619,7 @@ sendrequest(cmd, local, remote, printnames)
} else
if (command("%s", cmd) != PRELIM) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
if (closefunc != NULL)
@ -597,13 +644,13 @@ sendrequest(cmd, local, remote, printnames)
if (hash) {
while (bytes >= hashbytes) {
(void) putchar('#');
hashbytes += HASHBYTES;
hashbytes += mark;
}
(void) fflush(stdout);
}
}
if (hash && bytes > 0) {
if (bytes < HASHBYTES)
if (bytes < mark)
(void) putchar('#');
(void) putchar('\n');
(void) fflush(stdout);
@ -611,7 +658,7 @@ sendrequest(cmd, local, remote, printnames)
if (c < 0)
warn("local: %s", local);
if (d < 0) {
if (errno != EPIPE)
if (errno != EPIPE)
warn("netout");
bytes = -1;
}
@ -623,7 +670,7 @@ sendrequest(cmd, local, remote, printnames)
while (hash && (bytes >= hashbytes)) {
(void) putchar('#');
(void) fflush(stdout);
hashbytes += HASHBYTES;
hashbytes += mark;
}
if (ferror(dout))
break;
@ -635,7 +682,7 @@ sendrequest(cmd, local, remote, printnames)
/* if (c == '\r') { */
/* (void) putc('\0', dout); // this violates rfc */
/* bytes++; */
/* } */
/* } */
}
if (hash) {
if (bytes < hashbytes)
@ -658,13 +705,15 @@ sendrequest(cmd, local, remote, printnames)
(void) gettimeofday(&stop, (struct timezone *)0);
(void) getreply(0);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
if (bytes > 0)
ptransfer("sent", bytes, &start, &stop);
ptransfer(direction, bytes, &start, &stop, 0);
return;
abort:
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
if (!cpend) {
@ -683,7 +732,7 @@ abort:
(*closefunc)(fin);
(void) gettimeofday(&stop, (struct timezone *)0);
if (bytes > 0)
ptransfer("sent", bytes, &start, &stop);
ptransfer(direction, bytes, &start, &stop, 0);
}
jmp_buf recvabort;
@ -706,14 +755,16 @@ recvrequest(cmd, local, remote, lmode, printnames)
{
FILE *fout, *din = 0;
int (*closefunc) __P((FILE *));
sig_t oldintr, oldintp;
sig_t oldinti, oldintr, oldintp;
int c, d, is_retr, tcrflag, bare_lfs = 0;
static int bufsize;
static char *buf;
long bytes = 0, hashbytes = HASHBYTES;
struct timeval start, stop;
long hashbytes = mark;
struct timeval stop;
struct stat st;
direction = "received";
bytes = 0;
is_retr = strcmp(cmd, "RETR") == 0;
if (is_retr && verbose && printnames) {
if (local && *local != '-')
@ -739,10 +790,13 @@ recvrequest(cmd, local, remote, lmode, printnames)
}
if (oldintr)
(void) signal(SIGINT, oldintr);
if (oldinti)
(void) signal(SIGINFO,oldinti);
code = -1;
return;
}
oldintr = signal(SIGINT, abortrecv);
oldinti = signal(SIGINFO, psummary);
if (strcmp(local, "-") && *local != '|') {
if (access(local, 2) < 0) {
char *dir = strrchr(local, '/');
@ -750,17 +804,19 @@ recvrequest(cmd, local, remote, lmode, printnames)
if (errno != ENOENT && errno != EACCES) {
warn("local: %s", local);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
if (dir != NULL)
*dir = 0;
d = access(dir ? local : ".", 2);
d = access(dir == local ? "/" : dir ? local : ".", 2);
if (dir != NULL)
*dir = '/';
if (d < 0) {
warn("local: %s", local);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
@ -768,19 +824,21 @@ recvrequest(cmd, local, remote, lmode, printnames)
chmod(local, 0600) < 0) {
warn("local: %s", local);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
if (runique && errno == EACCES &&
(local = gunique(local)) == NULL) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
}
else if (runique && (local = gunique(local)) == NULL) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
@ -792,6 +850,7 @@ recvrequest(cmd, local, remote, lmode, printnames)
changetype(type, 0);
if (initconn()) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
code = -1;
return;
}
@ -803,11 +862,13 @@ recvrequest(cmd, local, remote, lmode, printnames)
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
return;
}
} else {
if (command("%s", cmd) != PRELIM) {
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
return;
}
}
@ -865,13 +926,13 @@ recvrequest(cmd, local, remote, lmode, printnames)
if (hash) {
while (bytes >= hashbytes) {
(void) putchar('#');
hashbytes += HASHBYTES;
hashbytes += mark;
}
(void) fflush(stdout);
}
}
if (hash && bytes > 0) {
if (bytes < HASHBYTES)
if (bytes < mark)
(void) putchar('#');
(void) putchar('\n');
(void) fflush(stdout);
@ -917,7 +978,7 @@ done:
while (hash && (bytes >= hashbytes)) {
(void) putchar('#');
(void) fflush(stdout);
hashbytes += HASHBYTES;
hashbytes += mark;
}
bytes++;
if ((c = getc(din)) != '\n' || tcrflag) {
@ -959,24 +1020,26 @@ break2:
if (closefunc != NULL)
(*closefunc)(fout);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
(void) fclose(din);
(void) gettimeofday(&stop, (struct timezone *)0);
(void) getreply(0);
if (bytes > 0 && is_retr)
ptransfer("received", bytes, &start, &stop);
ptransfer(direction, bytes, &start, &stop, 0);
return;
abort:
/* abort using RFC959 recommended IP,SYNC sequence */
if (oldintp)
(void) signal(SIGPIPE, oldintr);
(void) signal(SIGPIPE, oldintp);
(void) signal(SIGINT, SIG_IGN);
if (!cpend) {
code = -1;
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
return;
}
@ -992,8 +1055,9 @@ abort:
(void) fclose(din);
(void) gettimeofday(&stop, (struct timezone *)0);
if (bytes > 0)
ptransfer("received", bytes, &start, &stop);
ptransfer(direction, bytes, &start, &stop, 0);
(void) signal(SIGINT, oldintr);
(void) signal(SIGINFO, oldinti);
}
/*
@ -1066,7 +1130,7 @@ initconn()
noport:
data_addr = myctladdr;
if (sendport)
data_addr.sin_port = 0; /* let system pick one */
data_addr.sin_port = 0; /* let system pick one */
if (data != -1)
(void) close(data);
data = socket(AF_INET, SOCK_STREAM, 0);
@ -1152,25 +1216,43 @@ dataconn(lmode)
}
void
ptransfer(direction, bytes, t0, t1)
ptransfer(direction, bytes, t0, t1, siginfo)
char *direction;
long bytes;
struct timeval *t0, *t1;
int siginfo;
{
struct timeval td;
float s;
double s;
long bs;
int meg;
char buf[100];
if (verbose) {
if (verbose || siginfo) {
timersub(t1, t0, &td);
s = td.tv_sec + (td.tv_usec / 1000000.);
#define nz(x) ((x) == 0 ? 1 : (x))
bs = bytes / nz(s);
printf("%ld bytes %s in %.3g seconds (%ld bytes/s)\n",
bytes, direction, s, bs);
s = td.tv_sec + (td.tv_usec / 1000000.0);
bs = bytes / (s == 0 ? 1 : s);
meg = 0;
if (bs > (1024 * 1024))
meg = 1;
(void)snprintf(buf, sizeof(buf),
"%ld byte%s %s in %.2f seconds (%.2f %sB/s)\n",
bytes, bytes == 1 ? "" : "s", direction, s,
bs / (1024.0 * (meg ? 1024.0 : 1.0)), meg ? "M" : "K");
(void)write(siginfo ? STDERR_FILENO : STDOUT_FILENO,
buf, strlen(buf));
}
}
void
psummary(notused)
int notused;
{
(void) gettimeofday(&stop, (struct timezone *)0);
if (bytes > 0)
ptransfer(direction, bytes, &start, &stop, 1);
}
void
psabort()
{
@ -1435,7 +1517,7 @@ gunique(local)
if (cp)
*cp = '\0';
d = access(cp ? local : ".", 2);
d = access(cp == local ? "/" : cp ? local : ".", 2);
if (cp)
*cp = '/';
if (d < 0) {
@ -1489,7 +1571,7 @@ abort_remote(din)
(void) fflush(cout);
FD_ZERO(&mask);
FD_SET(fileno(cin), &mask);
if (din) {
if (din) {
FD_SET(fileno(din), &mask);
}
if ((nfnd = empty(&mask, 10)) <= 0) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ftp_var.h,v 1.7 1995/09/15 00:32:35 pk Exp $ */
/* $NetBSD: ftp_var.h,v 1.8 1996/11/25 05:13:25 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
@ -44,11 +44,15 @@
#include "extern.h"
#define HASHBYTES 1024
/*
* Options and other state info.
*/
int trace; /* trace packets exchanged */
int hash; /* print # for each buffer transferred */
int mark; /* number of bytes between hashes */
int sendport; /* use PORT cmd for each data connection */
int verbose; /* print messages coming back from server */
int connected; /* connected to server */
@ -85,6 +89,7 @@ char modename[32]; /* name of file transfer mode */
int mode; /* file transfer mode */
char bytename[32]; /* local byte size in ascii */
int bytesize; /* local byte size in binary */
int anonftp; /* automatic anonymous login */
char *hostname; /* name of host connected to */
int unix_server; /* server is unix, can use binary for ascii */
@ -127,3 +132,8 @@ struct macel {
int macnum; /* number of defined macros */
struct macel macros[16];
char macbuf[4096];
/*
* The URL prefix for an FTP connection.
*/
#define FTPURL "ftp://"

View File

@ -1,3 +1,5 @@
/* $NetBSD: main.c,v 1.12 1996/11/25 05:13:26 lukem Exp $ */
/*
* Copyright (c) 1985, 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
@ -41,7 +43,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94";
#else
static char rcsid[] = "$NetBSD: main.c,v 1.11 1996/05/07 00:16:55 pk Exp $";
static char rcsid[] = "$NetBSD: main.c,v 1.12 1996/11/25 05:13:26 lukem Exp $";
#endif
#endif /* not lint */
@ -66,6 +68,12 @@ static char rcsid[] = "$NetBSD: main.c,v 1.11 1996/05/07 00:16:55 pk Exp $";
#include "ftp_var.h"
extern char *__progname; /* from crt0.o */
char *portnum; /* alternate port number */
int auto_fetch __P((int, char **));
int
main(argc, argv)
int argc;
@ -81,14 +89,20 @@ main(argc, argv)
doglob = 1;
interactive = 1;
autologin = 1;
passivemode = 0;
mark = HASHBYTES;
while ((ch = getopt(argc, argv, "dgintv")) != EOF) {
while ((ch = getopt(argc, argv, "adginpP:tv")) != EOF) {
switch (ch) {
case 'a':
anonftp = 1;
break;
case 'd':
options |= SO_DEBUG;
debug++;
break;
case 'g':
doglob = 0;
break;
@ -101,6 +115,14 @@ main(argc, argv)
autologin = 0;
break;
case 'p':
passivemode = 1;
break;
case 'P':
portnum = optarg;
break;
case 't':
trace++;
break;
@ -111,7 +133,10 @@ main(argc, argv)
default:
(void)fprintf(stderr,
"usage: ftp [-dgintv] [host [port]]\n");
"usage: %s [-adginptv] [-P port] [host [port]]\n"
" %s ftp://host[:port]/file\n"
" %s host:file\n",
__progname, __progname, __progname);
exit(1);
}
}
@ -123,7 +148,6 @@ main(argc, argv)
verbose++;
cpend = 0; /* no pending replies */
proxy = 0; /* proxy not active */
passivemode = 0; /* passive mode not active */
crflag = 1; /* strip c.r. on ascii gets */
sendport = -1; /* not using ports */
/*
@ -139,9 +163,15 @@ main(argc, argv)
home = homedir;
(void) strcpy(home, pw->pw_dir);
}
/* Handle "automatic" transfers. */
if (argc > 0 && strchr(argv[0], ':') != NULL) {
anonftp = 1;
exit(auto_fetch(argc, argv));
}
if (argc > 0) {
char *xargv[5];
extern char *__progname;
if (setjmp(toplevel))
exit(0);
@ -208,13 +238,15 @@ tail(filename)
char *filename;
{
char *s;
while (*filename) {
s = strrchr(filename, '/');
if (s == NULL)
break;
if (s[1])
return (s + 1);
if (s == filename)
break; XXX
*s = '\0';
}
return (filename);
@ -294,7 +326,7 @@ getcmd(name)
longest = 0;
nmatches = 0;
found = 0;
for (c = cmdtab; p = c->c_name; c++) {
for (c = cmdtab; (p = c->c_name) != NULL; c++) {
for (q = name; *q == *p++; q++)
if (*q == 0) /* exact match? */
return (c);
@ -535,3 +567,109 @@ help(argc, argv)
c->c_name, c->c_help);
}
}
int
auto_fetch(argc, argv)
int argc;
char **argv;
{
char *xargv[5];
char *cp, *host, *dir, *file;
int rval, xargc;
size_t urllen;
urllen = strlen(FTPURL);
rval = 0;
if (setjmp(toplevel))
exit(0);
(void) signal(SIGINT, intr);
(void) signal(SIGPIPE, lostpeer);
/*
* Loop through as long as there's files to fetch.
*/
while (argc > 0 && strchr(argv[0], ':') != NULL) {
host = dir = file = portnum = NULL;
/*
* We muck with the string, so we make a copy.
*/
host = strdup(argv[0]);
if (host == NULL)
errx(1, "Can't allocate memory for auto-fetch.");
/*
* Try URL-style arguments first, then host:file.
*/
if (strncmp(host, FTPURL, urllen) == 0) {
host += urllen;
cp = strchr(host, '/');
/* Look for a port number after the nost name. */
portnum = strchr(host, ':');
if (portnum != NULL)
*portnum++ = '\0';
} else
cp = strchr(host, ':');
/*
* Extract the file and (if present) directory name.
*/
*cp++ = '\0';
dir = cp;
cp = strrchr(cp, '/');
if (cp != NULL) {
*cp++ = '\0';
file = cp;
} else {
file = dir;
dir = NULL;
}
/*
* Set up the connection.
*/
xargv[0] = __progname;
xargv[1] = host;
xargv[2] = NULL;
xargc = 2;
if (portnum != NULL) {
xargv[2] = portnum;
xargv[3] = NULL;
xargc = 3;
}
setpeer(xargc, xargv);
if (connected == 0) {
warnx("Can't connect to host `%s'.", host);
rval = 1;
free(host);
continue;
}
/* Always use binary transfers. */
setbinary(0, NULL);
/* Change directories, if necessary. */
if (dir != NULL) {
xargv[0] = "cd";
xargv[1] = dir;
xargv[2] = NULL;
cd(2, xargv);
/* XXX SHOULD CHECK FOR ERROR CONDITION! */
}
/* Fetch the file. */
xargv[0] = "get";
xargv[1] = file;
xargv[2] = NULL;
get(2, xargv);
disconnect(0, NULL);
free(host);
--argc, ++argv;
}
return (rval);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ruserpass.c,v 1.6 1995/09/08 01:06:43 tls Exp $ */
/* $NetBSD: ruserpass.c,v 1.7 1996/11/25 05:13:27 lukem Exp $ */
/*
* Copyright (c) 1985, 1993, 1994
@ -113,7 +113,7 @@ next:
continue;
/*
* Allow match either for user's input host name
* or official hostname. Also allow match of
* or official hostname. Also allow match of
* incompletely-specified host in local domain.
*/
if (strcasecmp(host, tokval) == 0)
@ -137,7 +137,7 @@ next:
case LOGIN:
if (token())
if (*aname == 0) {
if (*aname == 0) {
*aname = malloc((unsigned) strlen(tokval) + 1);
(void) strcpy(*aname, tokval);
} else {