1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2024-05-13 19:16:15 +02:00

19674, modified: support for non-standard ports in zftp.

This commit is contained in:
Peter Stephenson 2004-03-24 11:31:30 +00:00
parent dda348832d
commit 8de7436fc0
6 changed files with 214 additions and 57 deletions

View File

@ -1,3 +1,11 @@
2004-03-24 Peter Stephenson <pws@csr.com>
* 19674 plus unposted changes suggested in 19676:
configure.ac, Doc/Zsh/mod_zftp.yo, Src/Modules/zftp.c,
Etc/NEWS, Functions/Zftp/zfstat: Add support for non-standard
ports to core zftp. Not yet handled by the function system
(except zfstat reports port): needed in lastloc and bookmarks.
2004-03-23 Peter Stephenson <pws@csr.com>
* 19661: Danek Duvall: Completion/Unix/Type/_diff_options:

View File

@ -1,17 +1,21 @@
texinode(The zftp Module)(The zle Module)(The stat Module)(Zsh Modules)
sect(The zftp Module)
The tt(zftp) module makes available one builtin command:
COMMENT(!MOD!zsh/zftp
A builtin FTP client.
!MOD!)
The tt(zsh/zftp) module makes available one builtin command:
startitem()
findex(zftp)
cindex(FTP)
cindex(files, transferring)
item(tt(zftp) var(subcommand) [ var(args) ])(
The tt(zftp) module is a client for FTP (file transfer protocol). It
The tt(zsh/zftp) module is a client for FTP (file transfer protocol). It
is implemented as a builtin to allow full use of shell command line
editing, file I/O, and job control mechanisms. Often, users will
access it via shell functions providing higher level abilities such as
username and password lookup. However, it is entirely usable in its
access it via shell functions providing a more powerful interface; a set is
provided with the tt(zsh) distribution and is described in
ifzman(zmanref(zshzftpsys))\
ifnzman(noderef(Zftp Function System))\
. However, the tt(zftp) command is entirely usable in its
own right.
All commands consist of the command name tt(zftp) followed by the name
@ -27,15 +31,25 @@ cindex(zftp, subcommands)
startitem()
cindex(FTP, starting a session)
item(tt(open) var(host) [ var(user) [ var(password) [ var(account) ] ] ])(
item(tt(open) var(host)[tt(:)var(port)] [ var(user) [ var(password) [ var(account) ] ] ])(
Open a new FTP session to var(host), which may be the name of a TCP/IP
connected host or an IP number in the standard dot notation.
connected host or an IP number in the standard dot notation. If the
argument is in the form var(host)tt(:)var(port), open a connection to
TCP port var(port) instead of the standard FTP port 21. This may be
the name of a TCP service or a number: see the description of
tt(ZFTP_PORT) below for more information.
If IPv6 addresses in colon format are used, the var(host) should be
surrounded by quoted square brackets to distinguish it from the var(port),
for example tt('[fe80::203:baff:fe02:8b56]'). For consistency this is
allowed with all forms of var(host).
Remaining arguments are passed to the tt(login) subcommand. Note that
if no arguments beyond var(host) are supplied, tt(open) will em(not)
automatically call tt(login). If no arguments at all are supplied,
tt(open) will use the parameters set by the tt(params) subcommand.
After a successful open, the shell variables tt(ZFTP_HOST),
After a successful open, the shell variables tt(ZFTP_HOST), tt(ZFTP_PORT),
tt(ZFTP_IP) and tt(ZFTP_SYSTEM) are available; see `Variables'
below.
)
@ -60,37 +74,50 @@ xitem(tt(params) [ var(host) [ var(user) [ var(password) \
item(tt(params) tt(-))(
Store the given parameters for a later tt(open) command with no
arguments. Only those given on the command line will be remembered.
Any of the parameters may, however, be specified as a `tt(?)', which
may need to be quoted to protect it from shell expansion: in this case,
the appropriate parameter will be read from stdin as with the
tt(login) subcommand, including special handling of var(password).
If no arguments are given, the parameters currently set are printed,
although the password will appear as a line of stars.
although the password will appear as a line of stars; the return value is
one if no parameters were set, zero otherwise.
Any of the parameters may be specified as a `tt(?)', which
may need to be quoted to protect it from shell expansion. In this case,
the appropriate parameter will be read from stdin as with the
tt(login) subcommand, including special handling of var(password). If the
`tt(?)' is followed by a string, that is used as the prompt for reading the
parameter instead of the default message (any necessary punctuation and
whitespace should be included at the end of the prompt). The first letter
of the parameter (only) may be quoted with a `tt(\)'; hence an argument
tt("\\$word") guarantees that the string from the shell parameter tt($word)
will be treated literally, whether or not it begins with a `tt(?)'.
If instead a single `tt(-)' is given, the existing parameters, if any,
are deleted. In that case, calling tt(open) with no arguments will
cause an error.
The list of parameters is not deleted after a tt(close), however it
will be deleted if the tt(zftp) module is unloaded.
will be deleted if the tt(zsh/zftp) module is unloaded.
For example,
nofill(tt(zftp params ftp.elsewhere.xx juser '?'))
example(zftp params ftp.elsewhere.xx juser '?Password for juser: ')
will store the host tt(ftp.elsewhere.xx) and the user tt(juser) and
then prompt the user for the corresponding password.
then prompt the user for the corresponding password with the given prompt.
)
item(tt(test))(
Test the connection; if the server has reported
that it has closed the connection (maybe due to a timeout), return
status 2; if no connection was open anyway, return status 1; else
return status 0. The tt(test) subcommand is
silent, apart from messages printed by the tt($ZFTP_VERBOSE)
mechanism, or error messages if the connection closes. There is no
network overhead for this test.
This command may also be used to set up a transfer which then takes
place completely in the background, freeing tt(zftp) for concurrent
foreground use. For example,
The test is only supported on systems with either the tt(select(2)) or
tt(poll(2)) system calls; otherwise the message `tt(not
supported on this system)' is printed instead.
nofill(tt(zftp params ftp.soreeyes.ca bubble squeak))
nofill(tt(LPAR()zftp open; zftp get foo >bar; zftp close)tt(RPAR() &))
--- here, the connection is restricted to a background subshell and
you are free to open a simultaneous connection in the foreground.
The tt(test) subcommand will automatically be called at the start of any
other subcommand for the current session when a connection is open.
)
item(tt(cd) var(directory))(
Change the remote directory to var(directory). Also alters the shell
@ -114,7 +141,7 @@ Otherwise, up to vagaries of the server implementation, behaves
similar to tt(dir).
)
item(tt(type) [ var(type) ])(
Change the type for transfer to var(type), or print the current type
Change the type for the transfer to var(type), or print the current type
if var(type) is absent. The allowed values are `tt(A)' (ASCII),
`tt(I)' (Image, i.e. binary), or `tt(B)' (a synonym for `tt(I)').
@ -185,7 +212,7 @@ item(tt(mkdir) var(directory))(
Create a new directory var(directory) on the server.
)
item(tt(rmdir) var(directory))(
Delete the diretory var(directory) on the server.
Delete the directory var(directory) on the server.
)
item(tt(rename) var(old-name) var(new-name))(
Rename file var(old-name) to var(new-name) on the server.
@ -197,7 +224,7 @@ only need this if instructed by the server to use it.
item(tt(quote) var(args...))(
Send the raw FTP command sequence to the server. You should be
familiar with the FTP command set as defined in RFC959 before doing
this. Useful comands may include tt(STAT) and tt(HELP). Note also
this. Useful commands may include tt(STAT) and tt(HELP). Note also
the mechanism for returning messages as described for the variable
tt(ZFTP_VERBOSE) below, in particular that all messages from the
control connection are sent to standard error.
@ -205,8 +232,33 @@ control connection are sent to standard error.
xitem(tt(close))
item(tt(quit))(
Close the current data connection. This unsets the shell parameters
tt(ZFTP_HOST), tt(ZFTP_IP), tt(ZFTP_SYSTEM), tt(ZFTP_USER),
tt(ZFTP_ACCOUNT) and tt(ZFTP_PWD).
tt(ZFTP_HOST), tt(ZFTP_PORT), tt(ZFTP_IP), tt(ZFTP_SYSTEM), tt(ZFTP_USER),
tt(ZFTP_ACCOUNT), tt(ZFTP_PWD), tt(ZFTP_TYPE) and tt(ZFTP_MODE).
)
item(tt(session) [ var(sessname) ])(
Allows multiple FTP sessions to be used at once. The name of the session
is an arbitrary string of characters; the default session is called
`tt(default)'. If this command is called without an argument, it will list
all the current sessions; with an argument, it will either switch to the
existing session called var(sessname), or create a new session of that name.
Each session remembers the status of the connection, the set of
connection-specific shell parameters (the same set as are unset when a
connection closes, as given in the description of tt(close)), and any user
parameters specified with the tt(params) subcommand. Changing to a
previous session restores those values; changing to a new session
initialises them in the same way as if tt(zftp) had just been loaded. The
name of the current session is given by the parameter tt(ZFTP_SESSION).
)
item(tt(rmsession) [ var(sessname) ])(
Delete a session; if a name is not given, the current session is deleted.
If the current session is deleted, the earliest existing session becomes
the new current session, otherwise the current session is not changed.
If the session being deleted is the only one, a new session called
`tt(default)' is created and becomes the current session; note that this is
a new session even if the session being deleted is also called
`tt(default)'. It is recommended that sessions not be deleted while
background commands which use tt(zftp) are still active.
)
enditem()
@ -216,6 +268,7 @@ The following shell parameters are used by tt(zftp). Currently none
of them are special.
startitem()
vindex(ZFTP_TMOUT)
item(tt(ZFTP_TMOUT))(
Integer. The time in seconds to wait for a network operation to
complete before returning an error. If this is not set when the
@ -235,6 +288,18 @@ opened as an IP number, tt(ZFTP_HOST) contains that instead; this
saves the overhead for a name lookup, as IP numbers are most commonly
used when a nameserver is unavailable.
)
vindex(ZFTP_PORT)
item(tt(ZFTP_PORT))(
Readonly. The number of the remote TCP port to which the connection is
open (even if the port was originally specified as a named service).
Usually this is the standard FTP port, 21.
In the unlikely event that your system does not have the appropriate
conversion functions, this appears in network byte order. If your
system is little-endian, the port then consists of two swapped bytes and the
standard port will be reported as 5376. In that case, numeric ports passed
to tt(zftp open) will also need to be in this format.
)
vindex(ZFTP_SYSTEM)
item(tt(ZFTP_SYSTEM))(
Readonly. The system type string returned by the server in response
@ -251,8 +316,8 @@ vindex(ZFTP_USER)
item(tt(ZFTP_USER))(
Readonly. The username currently logged in, if any.
)
vindex(ZFTP_ACCT)
item(tt(ZFTP_ACCT))(
vindex(ZFTP_ACCOUNT)
item(tt(ZFTP_ACCOUNT))(
Readonly. The account name of the current user, if any. Most servers
do not require an account name.
)
@ -263,12 +328,19 @@ Readonly. The current directory on the server.
vindex(ZFTP_CODE)
item(tt(ZFTP_CODE))(
Readonly. The three digit code of the last FTP reply from the server
as a string. This can still be read after the connection is closed.
as a string. This can still be read after the connection is closed, and
is not changed when the current session changes.
)
vindex(ZFTP_REPLY)
item(tt(ZFTP_REPLY))(
Readonly. The last line of the last reply sent by the server. This
can still be read after the connection is closed.
can still be read after the connection is closed, and is not changed when
the current session changes.
)
vindex(ZFTP_SESSION)
item(tt(ZFTP_SESSION))(
Readonly. The name of the current FTP session; see the description of the
tt(session) subcommand.
)
vindex(ZFTP_PREFS)
item(tt(ZFTP_PREFS))(
@ -311,7 +383,7 @@ digit reply code is defined by RFC959 to correspond to:
startitem()
item(1.)(
A positive prelimnary reply.
A positive preliminary reply.
)
item(2.)(
A positive completion reply.
@ -350,14 +422,14 @@ subsect(Functions)
cindex(zftp, functions)
startitem()
findex(zftp_chpwd)
findex(zftp_chpwd, specification)
item(tt(zftp_chpwd))(
If this function is set by the user, it is called every time the
directory changes on the server, including when a user is logged
in, or when a connection is closed. In the last case, tt($ZFTP_PWD)
will be unset; otherwise it will reflect the new directory.
)
findex(zftp_progress)
findex(zftp_progress, specification)
item(tt(zftp_progress))(
If this function is set by the user, it will be called during
a tt(get), tt(put) or tt(append) operation each time sufficient data
@ -405,17 +477,25 @@ Sometimes the progress meter may cause disruption. It is up to the
user to decide whether the function should be defined and to use
tt(unfunction) when necessary.
)
enditem()
subsect(Problems)
cindex(zftp, problems)
With the exception noted for the tt(params) subcommand, a connection
may not be opened in the left hand side of a pipe as this occurs in a
subshell and the file information is not updated in the main shell.
In the case of type or mode changes or closing the connection in a
subshell, the information is returned but variables are not updated
until the next call to tt(zftp). Other status changes in subshells
will not be reflected by changes to the variables (but should
be otherwise harmless).
A connection may not be opened in the left hand side of a pipe as this
occurs in a subshell and the file information is not updated in the main
shell. In the case of type or mode changes or closing the connection in a
subshell, the information is returned but variables are not updated until
the next call to tt(zftp). Other status changes in subshells will not be
reflected by changes to the variables (but should be otherwise harmless).
enditem()
Deleting sessions while a tt(zftp) command is active in the background can
have unexpected effects, even if it does not use the session being deleted.
This is because all shell subprocesses share information on the state of
all connections, and deleting a session changes the ordering of that
information.
On some operating systems, the control connection is not valid after a
fork(), so that operations in subshells, on the left hand side of a
pipeline, or in the background are not possible, as they should be. This
is presumably a bug in the operating system.

View File

@ -2,6 +2,19 @@
CHANGES FROM PREVIOUS VERSIONS OF ZSH
-------------------------------------
Changes since zsh version 4.2.0
-------------------------------
The zftp module supports ports following the hostname in the normal suffix
notation, `host:port'. This requires IPv6 colon-style addresses to be
specified in suitably quoted square brackets, for example:
zftp open '[f000::baaa]'
zftp open '[f000::baaa]:ftp'
(the two are equivalent).
New features between zsh versions 4.0 and 4.2
---------------------------------------------

View File

@ -19,6 +19,7 @@ done
if [[ -n $ZFTP_HOST ]]; then
print "Host:\t\t$ZFTP_HOST"
print "Port:\t\t$ZFTP_PORT"
print "IP:\t\t$ZFTP_IP"
[[ -n $ZFTP_SYSTEM ]] && print "System type:\t$ZFTP_SYSTEM"
if [[ -n $ZFTP_USER ]]; then

View File

@ -195,7 +195,7 @@ static struct builtin bintab[] = {
* currently there aren't any, which is the way I like it.
*/
static char *zfparams[] = {
"ZFTP_HOST", "ZFTP_IP", "ZFTP_SYSTEM", "ZFTP_USER",
"ZFTP_HOST", "ZFTP_PORT", "ZFTP_IP", "ZFTP_SYSTEM", "ZFTP_USER",
"ZFTP_ACCOUNT", "ZFTP_PWD", "ZFTP_TYPE", "ZFTP_MODE", NULL
};
@ -1699,8 +1699,9 @@ zftp_open(char *name, char **args, int flags)
struct protoent *zprotop;
struct servent *zservp;
struct hostent *zhostp = NULL;
char **addrp, *fname;
int err, tmout;
char **addrp, *fname, *tmpptr, *portnam = "ftp";
char *hostnam, *hostsuffix;
int err, tmout, port = -1;
SOCKLEN_T len;
int herrno, af, hlen;
@ -1721,12 +1722,56 @@ zftp_open(char *name, char **args, int flags)
if (zfsess->control)
zfclose(0);
hostnam = dupstring(args[0]);
/*
* Check for IPv6 address in square brackets (RFC2732).
* We are more lenient and allow any form for the host here.
*/
if (hostnam[0] == '[') {
hostnam++;
hostsuffix = strchr(hostnam, ']');
if (!hostsuffix || (hostsuffix[1] && hostsuffix[1] != ':')) {
zwarnnam(name, "Invalid host format: %s", hostnam, 0);
return 1;
}
*hostsuffix++ = '\0';
}
else
hostsuffix = hostnam;
if ((tmpptr = strchr(hostsuffix, ':'))) {
char *endptr;
*tmpptr++ = '\0';
port = (int)zstrtol(tmpptr, &endptr, 10);
/*
* If the port is not numeric, look it up by name below.
*/
if (*endptr) {
portnam = tmpptr;
port = -1;
}
#if defined(HAVE_NTOHS) && defined(HAVE_HTONS)
else {
port = (int)htons((unsigned short)port);
}
#endif
}
/* this is going to give 0. why bother? */
zprotop = getprotobyname("tcp");
zservp = getservbyname("ftp", "tcp");
if (!zprotop) {
zwarnnam(name, "Can't find protocol TCP (is your network functional)?",
NULL, 0);
return 1;
}
if (port < 0)
zservp = getservbyname(portnam, "tcp");
else
zservp = getservbyport(port, "tcp");
if (!zprotop || !zservp) {
zwarnnam(name, "Somebody stole FTP!", NULL, 0);
zwarnnam(name, "Can't find port for service `%s'", portnam, 0);
return 1;
}
@ -1762,7 +1807,9 @@ zftp_open(char *name, char **args, int flags)
# define FAILED() do { } while(0)
#endif
{
zhostp = zsh_getipnodebyname(args[0], af, 0, &herrno);
off_t tcp_port;
zhostp = zsh_getipnodebyname(hostnam, af, 0, &herrno);
if (!zhostp || errflag) {
/* should use herror() here if available, but maybe
* needs configure test. on AIX it's present but not
@ -1771,11 +1818,18 @@ zftp_open(char *name, char **args, int flags)
* on the other hand, herror() is obsolete
*/
FAILED();
zwarnnam(name, "host not found: %s", args[0], 0);
zwarnnam(name, "host not found: %s", hostnam, 0);
alarm(0);
return 1;
}
zfsetparam("ZFTP_HOST", ztrdup(zhostp->h_name), ZFPM_READONLY);
/* careful with pointer types */
#if defined(HAVE_NTOHS) && defined(HAVE_HTONS)
tcp_port = (off_t)ntohs((unsigned short)zservp->s_port);
#else
tcp_port = (off_t)zservp->s_port;
#endif
zfsetparam("ZFTP_PORT", &tcp_port, ZFPM_READONLY|ZFPM_INTEGER);
#ifdef SUPPORT_IPV6
if(af == AF_INET6) {
@ -1795,6 +1849,7 @@ zftp_open(char *name, char **args, int flags)
}
freehostent(zhostp);
zfunsetparam("ZFTP_HOST");
zfunsetparam("ZFTP_PORT");
FAILED();
zwarnnam(name, "socket failed: %e", NULL, errno);
alarm(0);
@ -1815,8 +1870,7 @@ zftp_open(char *name, char **args, int flags)
if(hlen != zhostp->h_length)
zwarnnam(name, "address length mismatch", NULL, 0);
do {
err = tcp_connect(zfsess->control, *addrp, zhostp, zservp->s_port);
} while (err && errno == EINTR && !errflag);
err = tcp_connect(zfsess->control, *addrp, zhostp, zservp->s_port); } while (err && errno == EINTR && !errflag);
/* you can check whether it's worth retrying here */
}

View File

@ -1053,7 +1053,8 @@ AC_CHECK_FUNCS(strftime difftime gettimeofday \
nl_langinfo \
erand48 open_memstream \
wctomb iconv \
grantpt unlockpt ptsname)
grantpt unlockpt ptsname \
htons ntohs)
AC_FUNC_STRCOLL
if test x$enable_cap = xyes; then