Catch up to current, requested by christos in ticket #1763:
usr.bin/ftp/Makefile up to 1.39 usr.bin/ftp/cmds.c up to 1.141 usr.bin/ftp/complete.c up to 1.47 usr.bin/ftp/domacro.c up to 1.23 usr.bin/ftp/extern.h up to 1.82 usr.bin/ftp/fetch.c up to 1.235 usr.bin/ftp/ftp.1 up to 1.147 usr.bin/ftp/ftp.c up to 1.174 usr.bin/ftp/ftp_var.h up to 1.86 usr.bin/ftp/main.c up to 1.128 usr.bin/ftp/progressbar.c up to 1.24 usr.bin/ftp/progressbar.h up to 1.9 usr.bin/ftp/ssl.c up to 1.12 usr.bin/ftp/ssl.h up to 1.5 usr.bin/ftp/util.c up to 1.164 usr.bin/ftp/version.h up to 1.94 ftp(1): validate address from PASV and LPSV response. ftp(1): use raw write(2) instead of fwrite(3) to avoid stream corruption because of the progress bar interrupts. Fixes for PR 56219 and PR 55857. PR 57003: Support relative redirects.
This commit is contained in:
parent
5579b97d32
commit
71d7fc346c
|
@ -1,4 +1,4 @@
|
|||
# $NetBSD: Makefile,v 1.37.2.2 2022/09/12 15:05:21 martin Exp $
|
||||
# $NetBSD: Makefile,v 1.37.2.3 2022/09/12 17:08:13 martin Exp $
|
||||
# from: @(#)Makefile 8.2 (Berkeley) 4/3/94
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
@ -8,6 +8,7 @@ USE_FORT?= yes # network client
|
|||
PROG= ftp
|
||||
SRCS= cmds.c cmdtab.c complete.c domacro.c fetch.c ftp.c main.c \
|
||||
progressbar.c ruserpass.c util.c
|
||||
SRCS+= ssl.c
|
||||
|
||||
# Uncomment the following to provide defaults for gate-ftp operation
|
||||
#
|
||||
|
@ -19,7 +20,6 @@ CPPFLAGS+=-DNO_EDITCOMPLETE -DNO_ABOUT -DNO_AUTH -DNO_HELP -DNO_STATUS -DNO_DEBU
|
|||
LDADD+= -ledit -lterminfo
|
||||
DPADD+= ${LIBEDIT} ${LIBTERMINFO}
|
||||
CPPFLAGS+= -DWITH_SSL
|
||||
SRCS+=ssl.c
|
||||
LDADD+= -lssl -lcrypto
|
||||
DPADD+= ${LIBSSL} ${LIBCRYPTO}
|
||||
.endif
|
||||
|
@ -31,4 +31,6 @@ CPPFLAGS+= -DINET6
|
|||
cmds.o fetch.o: version.h
|
||||
main.o: ftp_var.h
|
||||
|
||||
CWARNFLAGS.gcc+= ${GCC_NO_FORMAT_OVERFLOW}
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: cmds.c,v 1.137.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: cmds.c,v 1.137.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -96,7 +96,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)cmds.c 8.6 (Berkeley) 10/9/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: cmds.c,v 1.137.8.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: cmds.c,v 1.137.8.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -1131,7 +1131,7 @@ setdebug(int argc, char *argv[])
|
|||
options |= SO_DEBUG;
|
||||
else
|
||||
options &= ~SO_DEBUG;
|
||||
fprintf(ttyout, "Debugging %s (ftp_debug=%d).\n", onoff(ftp_debug), ftp_debug);
|
||||
fprintf(ttyout, "Debugging %s (debug=%d).\n", onoff(ftp_debug), ftp_debug);
|
||||
code = ftp_debug > 0;
|
||||
}
|
||||
|
||||
|
@ -1158,7 +1158,8 @@ cd(int argc, char *argv[])
|
|||
}
|
||||
if (r == COMPLETE) {
|
||||
dirchange = 1;
|
||||
updateremotecwd();
|
||||
remotecwd[0] = '\0';
|
||||
remcwdvalid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1544,9 +1545,9 @@ pwd(int argc, char *argv[])
|
|||
UPRINTF("usage: %s\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
if (! remotecwd[0])
|
||||
if (!remcwdvalid || remotecwd[0] == '\0')
|
||||
updateremotecwd();
|
||||
if (! remotecwd[0])
|
||||
if (remotecwd[0] == '\0')
|
||||
fprintf(ttyout, "Unable to determine remote directory\n");
|
||||
else {
|
||||
fprintf(ttyout, "Remote directory: %s\n", remotecwd);
|
||||
|
@ -1775,6 +1776,18 @@ quit(int argc, char *argv[])
|
|||
exit(0);
|
||||
}
|
||||
|
||||
void __dead
|
||||
justquit(void)
|
||||
{
|
||||
|
||||
quit(0, NULL);
|
||||
/*
|
||||
* quit is not __dead, but for our invocation it never will return,
|
||||
* but some compilers are not smart enough to find this out.
|
||||
*/
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate session, but don't exit.
|
||||
* May be called with 0, NULL.
|
||||
|
@ -2184,7 +2197,7 @@ LOOP:
|
|||
}
|
||||
break;
|
||||
}
|
||||
/* intentional drop through */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
*cp2++ = *cp1;
|
||||
break;
|
||||
|
@ -2359,7 +2372,8 @@ cdup(int argc, char *argv[])
|
|||
}
|
||||
if (r == COMPLETE) {
|
||||
dirchange = 1;
|
||||
updateremotecwd();
|
||||
remotecwd[0] = '\0';
|
||||
remcwdvalid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: complete.c,v 1.46.38.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: complete.c,v 1.46.38.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: complete.c,v 1.46.38.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: complete.c,v 1.46.38.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -99,11 +99,10 @@ complete_ambiguous(char *word, int list, StringList *words)
|
|||
}
|
||||
|
||||
if (!list) {
|
||||
matchlen = 0;
|
||||
lastmatch = words->sl_str[0];
|
||||
matchlen = strlen(lastmatch);
|
||||
for (i = 1 ; i < words->sl_cur ; i++) {
|
||||
for (j = wordlen ; j < strlen(words->sl_str[i]); j++)
|
||||
for (j = wordlen; j < strlen(words->sl_str[i]); j++)
|
||||
if (lastmatch[j] != words->sl_str[i][j])
|
||||
break;
|
||||
if (j < matchlen)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: domacro.c,v 1.22.38.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: domacro.c,v 1.22.38.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985, 1993, 1994
|
||||
|
@ -34,7 +34,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)domacro.c 8.3 (Berkeley) 4/2/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: domacro.c,v 1.22.38.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: domacro.c,v 1.22.38.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -102,7 +102,7 @@ domacro(int argc, char *argv[])
|
|||
}
|
||||
break;
|
||||
}
|
||||
/* intentional drop through */
|
||||
/* FALLTHROUGH */
|
||||
default:
|
||||
*cp2++ = *cp1;
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: extern.h,v 1.80.24.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: extern.h,v 1.80.24.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
|
@ -173,6 +173,7 @@ void pswitch(int);
|
|||
void put(int, char **);
|
||||
void pwd(int, char **);
|
||||
void quit(int, char **);
|
||||
void justquit(void) __dead;
|
||||
void quote(int, char **);
|
||||
void quote1(const char *, int, char **);
|
||||
void recvrequest(const char *, const char *, const char *,
|
||||
|
@ -242,7 +243,14 @@ void user(int, char **);
|
|||
int ftp_connect(int, const struct sockaddr *, socklen_t, int);
|
||||
int ftp_listen(int, int);
|
||||
int ftp_poll(struct pollfd *, int, int);
|
||||
#ifndef SMALL
|
||||
void *ftp_malloc(size_t);
|
||||
StringList *ftp_sl_init(void);
|
||||
void ftp_sl_add(StringList *, char *);
|
||||
char *ftp_strdup(const char *);
|
||||
#else
|
||||
#define ftp_malloc(a) malloc(a);
|
||||
#define ftp_sl_init() sl_init()
|
||||
#define ftp_sl_add(a, b) sl_add((a), (b))
|
||||
#define ftp_strdup(a) strdup(a)
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: fetch.c,v 1.228.4.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: fetch.c,v 1.228.4.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2015 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: fetch.c,v 1.228.4.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: fetch.c,v 1.228.4.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -106,12 +106,13 @@ __dead static void timeouthttp(int);
|
|||
static int auth_url(const char *, char **, const struct authinfo *);
|
||||
static void base64_encode(const unsigned char *, size_t, unsigned char *);
|
||||
#endif
|
||||
static int go_fetch(const char *);
|
||||
static int go_fetch(const char *, struct urlinfo *);
|
||||
static int fetch_ftp(const char *);
|
||||
static int fetch_url(const char *, const char *, char *, char *);
|
||||
static int fetch_url(const char *, const char *, char *, char *,
|
||||
struct urlinfo *);
|
||||
static const char *match_token(const char **, const char *);
|
||||
static int parse_url(const char *, const char *, struct urlinfo *,
|
||||
struct authinfo *);
|
||||
struct authinfo *, struct urlinfo *);
|
||||
static void url_decode(char *);
|
||||
static void freeauthinfo(struct authinfo *);
|
||||
static void freeurlinfo(struct urlinfo *);
|
||||
|
@ -138,6 +139,43 @@ static int redirect_loop;
|
|||
((urltype) == HTTP_URL_T)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* fwrite(3) replacement that just uses write(2). Many stdio implementations
|
||||
* don't handle interrupts properly and corrupt the output. We are taking
|
||||
* alarm interrupts because of the progress bar.
|
||||
*
|
||||
* Assumes `fp' is pristine with no prior I/O calls on it.
|
||||
*/
|
||||
static size_t
|
||||
maxwrite(const void *buf, size_t size, size_t nmemb, FILE *fp)
|
||||
{
|
||||
const char *p = buf;
|
||||
ssize_t nwr = 0;
|
||||
ssize_t n;
|
||||
int fd = fileno(fp);
|
||||
|
||||
size *= nmemb; /* assume no overflow */
|
||||
|
||||
while (size > 0) {
|
||||
if ((n = write(fd, p, size)) == -1) {
|
||||
switch (errno) {
|
||||
case EINTR:
|
||||
case EAGAIN:
|
||||
#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
|
||||
case EWOULDBLOCK:
|
||||
#endif
|
||||
continue;
|
||||
default:
|
||||
return nwr;
|
||||
}
|
||||
}
|
||||
p += n;
|
||||
nwr += n;
|
||||
size -= n;
|
||||
}
|
||||
return nwr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if token is the next word in buf (case insensitive).
|
||||
* If so, advance buf past the token and any trailing LWS, and
|
||||
|
@ -237,7 +275,7 @@ auth_url(const char *challenge, char **response, const struct authinfo *auth)
|
|||
scheme = "Basic"; /* only support Basic authentication */
|
||||
gotpass = NULL;
|
||||
|
||||
DPRINTF("auth_url: challenge `%s'\n", challenge);
|
||||
DPRINTF("%s: challenge `%s'\n", __func__, challenge);
|
||||
|
||||
if (! match_token(&cp, scheme)) {
|
||||
warnx("Unsupported authentication challenge `%s'",
|
||||
|
@ -299,7 +337,7 @@ auth_url(const char *challenge, char **response, const struct authinfo *auth)
|
|||
*response = ftp_malloc(rlen);
|
||||
(void)strlcpy(*response, scheme, rlen);
|
||||
len = strlcat(*response, " ", rlen);
|
||||
/* use `clen - 1' to not encode the trailing NUL */
|
||||
/* use `clen - 1' to not encode the trailing NUL */
|
||||
base64_encode((unsigned char *)clear, clen - 1,
|
||||
(unsigned char *)*response + len);
|
||||
memset(clear, 0, clen);
|
||||
|
@ -330,7 +368,7 @@ base64_encode(const unsigned char *clear, size_t len, unsigned char *encoded)
|
|||
| ((clear[i + 1] >> 4) & 0x0f)];
|
||||
*(cp++) = enc[((clear[i + 1] << 2) & 0x3c)
|
||||
| ((clear[i + 2] >> 6) & 0x03)];
|
||||
*(cp++) = enc[((clear[i + 2] ) & 0x3f)];
|
||||
*(cp++) = enc[((clear[i + 2] ) & 0x3f)];
|
||||
}
|
||||
*cp = '\0';
|
||||
while (i-- > len)
|
||||
|
@ -363,6 +401,42 @@ url_decode(char *url)
|
|||
*q = '\0';
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_port(const struct urlinfo *ui)
|
||||
{
|
||||
|
||||
switch(ui->utype) {
|
||||
case HTTP_URL_T:
|
||||
return httpport;
|
||||
case FTP_URL_T:
|
||||
return ftpport;
|
||||
case FILE_URL_T:
|
||||
return "";
|
||||
#ifdef WITH_SSL
|
||||
case HTTPS_URL_T:
|
||||
return httpsport;
|
||||
#endif
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
use_relative(const struct urlinfo *ui)
|
||||
{
|
||||
if (ui == NULL)
|
||||
return 0;
|
||||
switch (ui->utype) {
|
||||
case HTTP_URL_T:
|
||||
case FILE_URL_T:
|
||||
#ifdef WITH_SSL
|
||||
case HTTPS_URL_T:
|
||||
#endif
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse URL of form (per RFC 3986):
|
||||
|
@ -398,7 +472,7 @@ url_decode(char *url)
|
|||
|
||||
static int
|
||||
parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
||||
struct authinfo *auth)
|
||||
struct authinfo *auth, struct urlinfo *rui)
|
||||
{
|
||||
const char *origurl, *tport;
|
||||
char *cp, *ep, *thost;
|
||||
|
@ -409,29 +483,26 @@ parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
|||
DPRINTF("parse_url: %s `%s'\n", desc, url);
|
||||
|
||||
origurl = url;
|
||||
tport = NULL;
|
||||
|
||||
if (STRNEQUAL(url, HTTP_URL)) {
|
||||
url += sizeof(HTTP_URL) - 1;
|
||||
ui->utype = HTTP_URL_T;
|
||||
ui->portnum = HTTP_PORT;
|
||||
tport = httpport;
|
||||
} else if (STRNEQUAL(url, FTP_URL)) {
|
||||
url += sizeof(FTP_URL) - 1;
|
||||
ui->utype = FTP_URL_T;
|
||||
ui->portnum = FTP_PORT;
|
||||
tport = ftpport;
|
||||
} else if (STRNEQUAL(url, FILE_URL)) {
|
||||
url += sizeof(FILE_URL) - 1;
|
||||
ui->utype = FILE_URL_T;
|
||||
tport = "";
|
||||
#ifdef WITH_SSL
|
||||
} else if (STRNEQUAL(url, HTTPS_URL)) {
|
||||
url += sizeof(HTTPS_URL) - 1;
|
||||
ui->utype = HTTPS_URL_T;
|
||||
ui->portnum = HTTPS_PORT;
|
||||
tport = httpsport;
|
||||
#endif
|
||||
} else if (rui != NULL) {
|
||||
copyurlinfo(ui, rui);
|
||||
} else {
|
||||
warnx("Invalid %s `%s'", desc, url);
|
||||
cleanup_parse_url:
|
||||
|
@ -440,6 +511,7 @@ parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
|||
return (-1);
|
||||
}
|
||||
|
||||
|
||||
if (*url == '\0')
|
||||
return (0);
|
||||
|
||||
|
@ -504,7 +576,8 @@ parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
|||
#endif /* INET6 */
|
||||
if ((cp = strchr(thost, ':')) != NULL)
|
||||
*cp++ = '\0';
|
||||
ui->host = thost;
|
||||
if (*thost != '\0')
|
||||
ui->host = thost;
|
||||
|
||||
/* look for [:port] */
|
||||
if (cp != NULL) {
|
||||
|
@ -519,7 +592,9 @@ parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
|||
}
|
||||
ui->portnum = nport;
|
||||
tport = cp;
|
||||
}
|
||||
} else
|
||||
tport = get_port(ui);
|
||||
|
||||
|
||||
if (tport != NULL)
|
||||
ui->port = ftp_strdup(tport);
|
||||
|
@ -530,8 +605,8 @@ parse_url(const char *url, const char *desc, struct urlinfo *ui,
|
|||
ui->path = ftp_strdup(emptypath);
|
||||
}
|
||||
|
||||
DPRINTF("parse_url: user `%s' pass `%s' host %s port %s(%d) "
|
||||
"path `%s'\n",
|
||||
DPRINTF("%s: user `%s' pass `%s' host %s port %s(%d) "
|
||||
"path `%s'\n", __func__,
|
||||
STRorNULL(auth->user), STRorNULL(auth->pass),
|
||||
STRorNULL(ui->host), STRorNULL(ui->port),
|
||||
ui->portnum ? ui->portnum : -1, STRorNULL(ui->path));
|
||||
|
@ -544,7 +619,7 @@ sigjmp_buf httpabort;
|
|||
static int
|
||||
ftp_socket(const struct urlinfo *ui, void **ssl)
|
||||
{
|
||||
struct addrinfo hints, *res, *res0 = NULL;
|
||||
struct addrinfo hints, *res, *res0 = NULL;
|
||||
int error;
|
||||
int s;
|
||||
const char *host = ui->host;
|
||||
|
@ -649,7 +724,7 @@ handle_noproxy(const char *host, in_port_t portnum)
|
|||
if (*cp == '\0')
|
||||
continue;
|
||||
if ((np = strrchr(cp, ':')) != NULL) {
|
||||
*np++ = '\0';
|
||||
*np++ = '\0';
|
||||
np_port = strtoul(np, &ep, 10);
|
||||
if (*np == '\0' || *ep != '\0')
|
||||
continue;
|
||||
|
@ -681,7 +756,7 @@ handle_proxy(const char *url, const char *penv, struct urlinfo *ui,
|
|||
}
|
||||
|
||||
initurlinfo(&pui);
|
||||
if (parse_url(penv, "proxy URL", &pui, pauth) == -1)
|
||||
if (parse_url(penv, "proxy URL", &pui, pauth, NULL) == -1)
|
||||
return -1;
|
||||
|
||||
if ((!IS_HTTP_TYPE(pui.utype) && pui.utype != FTP_URL_T) ||
|
||||
|
@ -852,9 +927,9 @@ print_connect(FETCH *fin, const struct urlinfo *ui)
|
|||
}
|
||||
#endif
|
||||
|
||||
#define C_OK 0
|
||||
#define C_CLEANUP 1
|
||||
#define C_IMPROPER 2
|
||||
#define C_OK 0
|
||||
#define C_CLEANUP 1
|
||||
#define C_IMPROPER 2
|
||||
|
||||
static int
|
||||
getresponseline(FETCH *fin, char *buf, size_t buflen, int *len)
|
||||
|
@ -953,7 +1028,7 @@ parse_posinfo(const char **cp, struct posinfo *pi)
|
|||
static void
|
||||
do_auth(int hcode, const char *url, const char *penv, struct authinfo *wauth,
|
||||
struct authinfo *pauth, char **auth, const char *message,
|
||||
volatile int *rval)
|
||||
volatile int *rval, struct urlinfo *ui)
|
||||
{
|
||||
struct authinfo aauth;
|
||||
char *response;
|
||||
|
@ -988,7 +1063,8 @@ do_auth(int hcode, const char *url, const char *penv, struct authinfo *wauth,
|
|||
if (auth_url(*auth, &response, &aauth) == 0) {
|
||||
*rval = fetch_url(url, penv,
|
||||
hcode == 401 ? pauth->auth : response,
|
||||
hcode == 401 ? response: wauth->auth);
|
||||
hcode == 401 ? response : wauth->auth,
|
||||
ui);
|
||||
memset(response, 0, strlen(response));
|
||||
FREEPTR(response);
|
||||
}
|
||||
|
@ -999,12 +1075,12 @@ static int
|
|||
negotiate_connection(FETCH *fin, const char *url, const char *penv,
|
||||
struct posinfo *pi, time_t *mtime, struct authinfo *wauth,
|
||||
struct authinfo *pauth, volatile int *rval, volatile int *ischunked,
|
||||
char **auth)
|
||||
char **auth, struct urlinfo *ui)
|
||||
{
|
||||
int len, hcode, rv;
|
||||
char buf[FTPBUFLEN], *ep;
|
||||
const char *cp, *token;
|
||||
char *location, *message;
|
||||
char *location, *message;
|
||||
|
||||
*auth = message = location = NULL;
|
||||
|
||||
|
@ -1119,18 +1195,19 @@ negotiate_connection(FETCH *fin, const char *url, const char *penv,
|
|||
fprintf(ttyout, "Redirected via %s\n",
|
||||
location);
|
||||
*rval = fetch_url(url, location,
|
||||
pauth->auth, wauth->auth);
|
||||
pauth->auth, wauth->auth, ui);
|
||||
} else {
|
||||
if (verbose)
|
||||
fprintf(ttyout, "Redirected to %s\n",
|
||||
location);
|
||||
*rval = go_fetch(location);
|
||||
*rval = go_fetch(location, ui);
|
||||
}
|
||||
goto cleanup_fetch_url;
|
||||
#ifndef NO_AUTH
|
||||
case 401:
|
||||
case 407:
|
||||
do_auth(hcode, url, penv, wauth, pauth, auth, message, rval);
|
||||
do_auth(hcode, url, penv, wauth, pauth, auth, message, rval,
|
||||
ui);
|
||||
goto cleanup_fetch_url;
|
||||
#endif
|
||||
default:
|
||||
|
@ -1195,7 +1272,7 @@ connectmethod(FETCH *fin, const char *url, const char *penv,
|
|||
message = ftp_strdup(ep);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (;;) {
|
||||
int len;
|
||||
if (getresponseline(fin, buf, sizeof(buf), &len) != C_OK)
|
||||
|
@ -1224,7 +1301,8 @@ connectmethod(FETCH *fin, const char *url, const char *penv,
|
|||
break;
|
||||
#ifndef NO_AUTH
|
||||
case 407:
|
||||
do_auth(hcode, url, penv, wauth, pauth, auth, message, rval);
|
||||
do_auth(hcode, url, penv, wauth, pauth, auth, message, rval,
|
||||
ui);
|
||||
goto cleanup_fetch_url;
|
||||
#endif
|
||||
default:
|
||||
|
@ -1262,7 +1340,8 @@ out:
|
|||
* is still open (e.g, ftp xfer with trailing /)
|
||||
*/
|
||||
static int
|
||||
fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
||||
fetch_url(const char *url, const char *proxyenv, char *proxyauth,
|
||||
char *wwwauth, struct urlinfo *rui)
|
||||
{
|
||||
sigfunc volatile oldint;
|
||||
sigfunc volatile oldpipe;
|
||||
|
@ -1271,18 +1350,18 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
int volatile s;
|
||||
struct stat sb;
|
||||
int volatile isproxy;
|
||||
int volatile rval, ischunked;
|
||||
int volatile rval, ischunked;
|
||||
size_t flen;
|
||||
static size_t bufsize;
|
||||
static char *xferbuf;
|
||||
const char *cp;
|
||||
char *ep;
|
||||
char *auth;
|
||||
char *volatile auth;
|
||||
char *volatile savefile;
|
||||
char *volatile location;
|
||||
char *volatile message;
|
||||
char *volatile decodedpath;
|
||||
struct authinfo wauth, pauth;
|
||||
struct authinfo wauth, pauth;
|
||||
struct posinfo pi;
|
||||
off_t hashbytes;
|
||||
int (*volatile closefunc)(FILE *);
|
||||
|
@ -1295,7 +1374,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
|
||||
DPRINTF("%s: `%s' proxyenv `%s'\n", __func__, url, STRorNULL(penv));
|
||||
|
||||
oldquit = oldalrm = oldint = oldpipe = NULL;
|
||||
oldquit = oldalrm = oldint = oldpipe = SIG_ERR;
|
||||
closefunc = NULL;
|
||||
fin = NULL;
|
||||
fout = NULL;
|
||||
|
@ -1315,7 +1394,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
if (sigsetjmp(httpabort, 1))
|
||||
goto cleanup_fetch_url;
|
||||
|
||||
if (parse_url(url, "URL", &ui, &wauth) == -1)
|
||||
if (parse_url(url, "URL", &ui, &wauth, rui) == -1)
|
||||
goto cleanup_fetch_url;
|
||||
|
||||
copyurlinfo(&oui, &ui);
|
||||
|
@ -1331,7 +1410,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
rval = fetch_ftp(url);
|
||||
goto cleanup_fetch_url;
|
||||
}
|
||||
if (!IS_HTTP_TYPE(ui.utype) || outfile == NULL) {
|
||||
if (!IS_HTTP_TYPE(ui.utype) || outfile == NULL) {
|
||||
warnx("Invalid URL (no file after host) `%s'", url);
|
||||
goto cleanup_fetch_url;
|
||||
}
|
||||
|
@ -1386,7 +1465,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
filesize = sb.st_size;
|
||||
}
|
||||
if (restart_point) {
|
||||
if (lseek(fetch_fileno(fin), restart_point, SEEK_SET) < 0) {
|
||||
if (lseek(fetch_fileno(fin), restart_point, SEEK_SET)
|
||||
< 0) {
|
||||
warn("Can't seek to restart `%s'",
|
||||
decodedpath);
|
||||
goto cleanup_fetch_url;
|
||||
|
@ -1460,7 +1540,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
#ifdef WITH_SSL
|
||||
if (isproxy && oui.utype == HTTPS_URL_T) {
|
||||
switch (connectmethod(fin, url, penv, &oui, &ui,
|
||||
&wauth, &pauth, &auth, &hasleading, &rval)) {
|
||||
&wauth, &pauth, __UNVOLATILE(&auth), &hasleading,
|
||||
&rval)) {
|
||||
case C_CLEANUP:
|
||||
goto cleanup_fetch_url;
|
||||
case C_IMPROPER:
|
||||
|
@ -1496,7 +1577,8 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
alarmtimer(0);
|
||||
|
||||
switch (negotiate_connection(fin, url, penv, &pi,
|
||||
&mtime, &wauth, &pauth, &rval, &ischunked, &auth)) {
|
||||
&mtime, &wauth, &pauth, &rval, &ischunked,
|
||||
__UNVOLATILE(&auth), &ui)) {
|
||||
case C_OK:
|
||||
break;
|
||||
case C_CLEANUP:
|
||||
|
@ -1570,9 +1652,9 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
|
||||
bytes = 0;
|
||||
hashbytes = mark;
|
||||
if (oldalrm) {
|
||||
if (oldalrm != SIG_ERR) {
|
||||
(void)xsignal(SIGALRM, oldalrm);
|
||||
oldalrm = NULL;
|
||||
oldalrm = SIG_ERR;
|
||||
}
|
||||
progressmeter(-1);
|
||||
|
||||
|
@ -1603,7 +1685,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
}
|
||||
|
||||
/*
|
||||
* XXX: Work around bug in Apache 1.3.9 and
|
||||
* XXX: Work around bug in Apache 1.3.9 and
|
||||
* 1.3.11, which incorrectly put trailing
|
||||
* space after the chunk-size.
|
||||
*/
|
||||
|
@ -1638,13 +1720,17 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
if (ischunked)
|
||||
bufrem = MIN(chunksize, bufrem);
|
||||
while (bufrem > 0) {
|
||||
size_t nr = MIN((off_t)bufsize, bufrem);
|
||||
flen = fetch_read(xferbuf, sizeof(char),
|
||||
MIN((off_t)bufsize, bufrem), fin);
|
||||
if (flen <= 0)
|
||||
nr, fin);
|
||||
if (flen == 0) {
|
||||
if (fetch_error(fin))
|
||||
goto chunkerror;
|
||||
goto chunkdone;
|
||||
}
|
||||
bytes += flen;
|
||||
bufrem -= flen;
|
||||
if (fwrite(xferbuf, sizeof(char), flen, fout)
|
||||
if (maxwrite(xferbuf, sizeof(char), flen, fout)
|
||||
!= flen) {
|
||||
warn("Writing `%s'", savefile);
|
||||
goto cleanup_fetch_url;
|
||||
|
@ -1692,7 +1778,7 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
} while (ischunked);
|
||||
|
||||
/* XXX: deal with optional trailer & CRLF here? */
|
||||
|
||||
chunkerror:
|
||||
if (hash && !progress && bytes > 0) {
|
||||
if (bytes < mark)
|
||||
(void)putc('#', ttyout);
|
||||
|
@ -1730,14 +1816,14 @@ fetch_url(const char *url, const char *proxyenv, char *proxyauth, char *wwwauth)
|
|||
warnx("Improper response from `%s:%s'", ui.host, ui.port);
|
||||
|
||||
cleanup_fetch_url:
|
||||
if (oldint)
|
||||
if (oldint != SIG_ERR)
|
||||
(void)xsignal(SIGINT, oldint);
|
||||
if (oldpipe)
|
||||
if (oldpipe != SIG_ERR)
|
||||
(void)xsignal(SIGPIPE, oldpipe);
|
||||
if (oldalrm)
|
||||
if (oldalrm != SIG_ERR)
|
||||
(void)xsignal(SIGALRM, oldalrm);
|
||||
if (oldquit)
|
||||
(void)xsignal(SIGQUIT, oldpipe);
|
||||
if (oldquit != SIG_ERR)
|
||||
(void)xsignal(SIGQUIT, oldquit);
|
||||
if (fin != NULL)
|
||||
fetch_close(fin);
|
||||
else if (s != -1)
|
||||
|
@ -1807,10 +1893,10 @@ fetch_ftp(const char *url)
|
|||
char dirbuf[4];
|
||||
int dirhasglob, filehasglob, rval, transtype, xargc;
|
||||
int oanonftp, oautologin;
|
||||
struct authinfo auth;
|
||||
struct authinfo auth;
|
||||
struct urlinfo ui;
|
||||
|
||||
DPRINTF("fetch_ftp: `%s'\n", url);
|
||||
DPRINTF("%s: `%s'\n", __func__, url);
|
||||
dir = file = NULL;
|
||||
rval = 1;
|
||||
transtype = TYPE_I;
|
||||
|
@ -1819,7 +1905,7 @@ fetch_ftp(const char *url)
|
|||
initauthinfo(&auth, NULL);
|
||||
|
||||
if (STRNEQUAL(url, FTP_URL)) {
|
||||
if ((parse_url(url, "URL", &ui, &auth) == -1) ||
|
||||
if ((parse_url(url, "URL", &ui, &auth, NULL) == -1) ||
|
||||
(auth.user != NULL && *auth.user == '\0') ||
|
||||
EMPTYSTRING(ui.host)) {
|
||||
warnx("Invalid URL `%s'", url);
|
||||
|
@ -1831,7 +1917,8 @@ fetch_ftp(const char *url)
|
|||
*/
|
||||
|
||||
/* check for trailing ';type=[aid]' */
|
||||
if (! EMPTYSTRING(ui.path) && (cp = strrchr(ui.path, ';')) != NULL) {
|
||||
if (! EMPTYSTRING(ui.path)
|
||||
&& (cp = strrchr(ui.path, ';')) != NULL) {
|
||||
if (strcasecmp(cp, ";type=a") == 0)
|
||||
transtype = TYPE_A;
|
||||
else if (strcasecmp(cp, ";type=i") == 0)
|
||||
|
@ -1873,12 +1960,12 @@ fetch_ftp(const char *url)
|
|||
* If we are dealing with classic `[user@]host:[path]' syntax,
|
||||
* then a path of the form `/file' (resulting from input of the
|
||||
* form `host:/file') means that we should do "CWD /" before
|
||||
* retrieving the file. So we set dir="/" and file="file".
|
||||
* retrieving the file. So we set dir="/" and file="file".
|
||||
*
|
||||
* But if we are dealing with URLs like `ftp://host/path' then
|
||||
* a path of the form `/file' (resulting from a URL of the form
|
||||
* `ftp://host//file') means that we should do `CWD ' (with an
|
||||
* empty argument) before retrieving the file. So we set
|
||||
* empty argument) before retrieving the file. So we set
|
||||
* dir="" and file="file".
|
||||
*
|
||||
* If the path does not contain / at all, we set dir=NULL.
|
||||
|
@ -1909,8 +1996,8 @@ fetch_ftp(const char *url)
|
|||
url_decode(file);
|
||||
/* but still don't url_decode(dir) */
|
||||
}
|
||||
DPRINTF("fetch_ftp: user `%s' pass `%s' host %s port %s "
|
||||
"path `%s' dir `%s' file `%s'\n",
|
||||
DPRINTF("%s: user `%s' pass `%s' host %s port %s "
|
||||
"path `%s' dir `%s' file `%s'\n", __func__,
|
||||
STRorNULL(auth.user), STRorNULL(auth.pass),
|
||||
STRorNULL(ui.host), STRorNULL(ui.port),
|
||||
STRorNULL(ui.path), STRorNULL(dir), STRorNULL(file));
|
||||
|
@ -1959,7 +2046,7 @@ fetch_ftp(const char *url)
|
|||
setbinary(1, xargv);
|
||||
break;
|
||||
default:
|
||||
errx(1, "fetch_ftp: unknown transfer type %d", transtype);
|
||||
errx(1, "%s: unknown transfer type %d", __func__, transtype);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1981,7 +2068,7 @@ fetch_ftp(const char *url)
|
|||
* (urltype is FTP_URL_T), then RFC 3986 says we need to
|
||||
* send a separate CWD command for each unescaped "/"
|
||||
* in the path, and we have to interpret %hex escaping
|
||||
* *after* we find the slashes. It's possible to get
|
||||
* *after* we find the slashes. It's possible to get
|
||||
* empty components here, (from multiple adjacent
|
||||
* slashes in the path) and RFC 3986 says that we should
|
||||
* still do `CWD ' (with a null argument) in such cases.
|
||||
|
@ -2024,7 +2111,7 @@ fetch_ftp(const char *url)
|
|||
* "CWD /", "CWD foo", "CWD bar", "RETR file"
|
||||
* ftp://host/%2Ffoo/bar/file dir="%2Ffoo/bar"
|
||||
* "CWD /foo", "CWD bar", "RETR file"
|
||||
* ftp://host/%2Ffoo%2Fbar/file dir="%2Ffoo%2Fbar"
|
||||
* ftp://host/%2Ffoo%2Fbar/file dir="%2Ffoo%2Fbar"
|
||||
* "CWD /foo/bar", "RETR file"
|
||||
* ftp://host/%2Ffoo%2Fbar%2Ffile dir=NULL
|
||||
* "RETR /foo/bar/file"
|
||||
|
@ -2041,7 +2128,7 @@ fetch_ftp(const char *url)
|
|||
url_decode(dir);
|
||||
} else
|
||||
nextpart = NULL;
|
||||
DPRINTF("fetch_ftp: dir `%s', nextpart `%s'\n",
|
||||
DPRINTF("%s: dir `%s', nextpart `%s'\n", __func__,
|
||||
STRorNULL(dir), STRorNULL(nextpart));
|
||||
if (ui.utype == FTP_URL_T || *dir != '\0') {
|
||||
(void)strlcpy(cmdbuf, "cd", sizeof(cmdbuf));
|
||||
|
@ -2097,14 +2184,15 @@ fetch_ftp(const char *url)
|
|||
mget(xargc, xargv);
|
||||
interactive = ointeractive;
|
||||
} else {
|
||||
if (outfile == NULL) {
|
||||
char *destfile = outfile;
|
||||
if (destfile == NULL) {
|
||||
cp = strrchr(file, '/'); /* find savefile */
|
||||
if (cp != NULL)
|
||||
outfile = cp + 1;
|
||||
destfile = cp + 1;
|
||||
else
|
||||
outfile = file;
|
||||
destfile = file;
|
||||
}
|
||||
xargv[2] = (char *)outfile;
|
||||
xargv[2] = (char *)destfile;
|
||||
xargv[3] = NULL;
|
||||
xargc++;
|
||||
if (restartautofetch)
|
||||
|
@ -2135,7 +2223,7 @@ fetch_ftp(const char *url)
|
|||
* is still open (e.g, ftp xfer with trailing /)
|
||||
*/
|
||||
static int
|
||||
go_fetch(const char *url)
|
||||
go_fetch(const char *url, struct urlinfo *rui)
|
||||
{
|
||||
char *proxyenv;
|
||||
char *p;
|
||||
|
@ -2184,7 +2272,7 @@ go_fetch(const char *url)
|
|||
|| STRNEQUAL(url, HTTPS_URL)
|
||||
#endif
|
||||
|| STRNEQUAL(url, FILE_URL))
|
||||
return (fetch_url(url, NULL, NULL, NULL));
|
||||
return (fetch_url(url, NULL, NULL, NULL, rui));
|
||||
|
||||
/*
|
||||
* If it contains "://" but does not begin with ftp://
|
||||
|
@ -2198,14 +2286,21 @@ go_fetch(const char *url)
|
|||
if ((p = strstr(url, "://")) != NULL && ! STRNEQUAL(url, FTP_URL))
|
||||
errx(1, "Unsupported URL scheme `%.*s'", (int)(p - url), url);
|
||||
|
||||
/*
|
||||
* Refer to previous urlinfo if provided. This makes relative
|
||||
* redirects work.
|
||||
*/
|
||||
if (use_relative(rui))
|
||||
return fetch_url(url, NULL, NULL, NULL, rui);
|
||||
|
||||
/*
|
||||
* Try FTP URL-style and host:file arguments next.
|
||||
* If ftpproxy is set with an FTP URL, use fetch_url()
|
||||
* Othewise, use fetch_ftp().
|
||||
* Otherwise, use fetch_ftp().
|
||||
*/
|
||||
proxyenv = getoptionvalue("ftp_proxy");
|
||||
if (!EMPTYSTRING(proxyenv) && STRNEQUAL(url, FTP_URL))
|
||||
return (fetch_url(url, NULL, NULL, NULL));
|
||||
return (fetch_url(url, NULL, NULL, NULL, rui));
|
||||
|
||||
return (fetch_ftp(url));
|
||||
}
|
||||
|
@ -2248,10 +2343,11 @@ auto_fetch(int argc, char *argv[])
|
|||
redirect_loop = 0;
|
||||
if (!anonftp)
|
||||
anonftp = 2; /* Handle "automatic" transfers. */
|
||||
rval = go_fetch(argv[argpos]);
|
||||
rval = go_fetch(argv[argpos], NULL);
|
||||
if (outfile != NULL && strcmp(outfile, "-") != 0
|
||||
&& outfile[0] != '|')
|
||||
outfile = NULL;
|
||||
&& outfile[0] != '|') {
|
||||
FREEPTR(outfile);
|
||||
}
|
||||
if (rval > 0)
|
||||
rval = argpos + 1;
|
||||
}
|
||||
|
@ -2286,7 +2382,7 @@ auto_put(int argc, char **argv, const char *uploadserver)
|
|||
pathsep = NULL;
|
||||
rval = 1;
|
||||
|
||||
DPRINTF("auto_put: target `%s'\n", uploadserver);
|
||||
DPRINTF("%s: target `%s'\n", __func__, uploadserver);
|
||||
|
||||
path = ftp_strdup(uploadserver);
|
||||
len = strlen(path);
|
||||
|
@ -2295,7 +2391,7 @@ auto_put(int argc, char **argv, const char *uploadserver)
|
|||
* make sure we always pass a directory to auto_fetch
|
||||
*/
|
||||
if (argc > 1) { /* more than one file to upload */
|
||||
len = strlen(uploadserver) + 2; /* path + "/" + "\0" */
|
||||
len = strlen(uploadserver) + 2; /* path + "/" + "\0" */
|
||||
free(path);
|
||||
path = (char *)ftp_malloc(len);
|
||||
(void)strlcpy(path, uploadserver, len);
|
||||
|
@ -2319,7 +2415,7 @@ auto_put(int argc, char **argv, const char *uploadserver)
|
|||
uargc++;
|
||||
}
|
||||
}
|
||||
DPRINTF("auto_put: URL `%s' argv[2] `%s'\n",
|
||||
DPRINTF("%s: URL `%s' argv[2] `%s'\n", __func__,
|
||||
path, STRorNULL(uargv[2]));
|
||||
|
||||
/* connect and cwd */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" $NetBSD: ftp.1,v 1.135.8.2 2022/09/12 15:05:21 martin Exp $
|
||||
.\" $NetBSD: ftp.1,v 1.135.8.3 2022/09/12 17:08:13 martin Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1996-2015 The NetBSD Foundation, Inc.
|
||||
.\" Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -57,7 +57,7 @@
|
|||
.\"
|
||||
.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94
|
||||
.\"
|
||||
.Dd April 24, 2015
|
||||
.Dd August 29, 2022
|
||||
.Dt FTP 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
|
@ -65,7 +65,7 @@
|
|||
.Nd Internet file transfer program
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl 46AadefginpRtVv
|
||||
.Op Fl 46AadefginpRtVv?
|
||||
.Op Fl N Ar netrc
|
||||
.Op Fl o Ar output
|
||||
.Op Fl P Ar port
|
||||
|
@ -84,12 +84,11 @@
|
|||
.Xc
|
||||
.Oc
|
||||
.Ek
|
||||
.Op Fl x Ar xferbufsize
|
||||
.Op Fl x Ar xfersize
|
||||
.Bk -words
|
||||
.\" [[user@]host [port]]
|
||||
.Oo
|
||||
.Oo Ar user Ns Li \&@ Oc Ns Ar host
|
||||
.Op Ar port
|
||||
.Oo Ar user Ns Li \&@ Oc Ns Ar host Oo Ar port Oc
|
||||
.Oc
|
||||
.Ek
|
||||
.Bk -words
|
||||
|
@ -122,7 +121,7 @@
|
|||
.Ar host Oo Li \&: Ar port Oc
|
||||
.Li / Ar path
|
||||
.Op Li /
|
||||
.Op Li ;type= Ar X
|
||||
.Op Li ;type= Ar type
|
||||
.Oc
|
||||
.Sm on
|
||||
.Ek
|
||||
|
@ -139,12 +138,24 @@
|
|||
.Oc
|
||||
.Sm on
|
||||
.Ek
|
||||
.Op Ar \&.\&.\&.
|
||||
.Bk -words
|
||||
.\" [https://[user[:password]@]host[:port]/path]
|
||||
.Sm off
|
||||
.Oo
|
||||
.Li https://
|
||||
.Oo Ar user
|
||||
.Op Li \&: Ar password
|
||||
.Li \&@ Oc
|
||||
.Ar host Oo Li \&: Ar port Oc
|
||||
.Li / Ar path
|
||||
.Oc
|
||||
.Sm on
|
||||
.Ek
|
||||
.Ar \&...
|
||||
.Nm
|
||||
.Bk -words
|
||||
.Fl u Ar URL Ar file
|
||||
.Fl u Ar url Ar
|
||||
.Ek
|
||||
.Op Ar \&.\&.\&.
|
||||
.Sh DESCRIPTION
|
||||
.Nm
|
||||
is the user interface to the Internet standard File Transfer Protocol.
|
||||
|
@ -173,10 +184,13 @@ Forces
|
|||
.Nm
|
||||
to only use IPv6 addresses.
|
||||
.It Fl A
|
||||
Force active mode ftp.
|
||||
Force active mode
|
||||
.Tn FTP .
|
||||
By default,
|
||||
.Nm
|
||||
will try to use passive mode ftp and fall back to active mode
|
||||
will try to use passive mode
|
||||
.Tn FTP
|
||||
and fall back to active mode
|
||||
if passive is not supported by the server.
|
||||
This option causes
|
||||
.Nm
|
||||
|
@ -284,12 +298,14 @@ bytes/second.
|
|||
Refer to
|
||||
.Ic rate
|
||||
for more information.
|
||||
.It Fl u Ar URL file Op \&.\&.\&.
|
||||
.It Fl u Ar url Ar
|
||||
Upload files on the command line to
|
||||
.Ar URL
|
||||
.Ar url
|
||||
where
|
||||
.Ar URL
|
||||
is one of the ftp URL types as supported by auto-fetch
|
||||
.Ar url
|
||||
is one of the
|
||||
.Sq Li ftp://
|
||||
URL types as supported by auto-fetch
|
||||
(with an optional target filename for single file uploads), and
|
||||
.Ar file
|
||||
is one or more local files to be uploaded.
|
||||
|
@ -312,12 +328,14 @@ Forces
|
|||
.Nm
|
||||
to show all responses from the remote server, as well
|
||||
as report on data transfer statistics.
|
||||
.It Fl x Ar xferbufsize
|
||||
.It Fl x Ar xfersize
|
||||
Set the size of the socket send and receive buffers to
|
||||
.Ar xferbufsize .
|
||||
.Ar xfersize .
|
||||
Refer to
|
||||
.Ic xferbuf
|
||||
for more information.
|
||||
.It Fl ?
|
||||
Display help to stdout, and exit.
|
||||
.El
|
||||
.Pp
|
||||
The client host with which
|
||||
|
@ -334,7 +352,7 @@ from the user.
|
|||
When
|
||||
.Nm
|
||||
is awaiting commands from the user the prompt
|
||||
.Ql ftp\*[Gt]
|
||||
.Ql ftp>
|
||||
is provided to the user.
|
||||
The following commands are recognized
|
||||
by
|
||||
|
@ -442,6 +460,16 @@ when an ascii type transfer is made, these linefeeds may be
|
|||
distinguished from a record delimiter only when
|
||||
.Ic \&cr
|
||||
is off.
|
||||
.It Ic debug Op Ar debug-value
|
||||
Toggle debugging mode.
|
||||
If an optional
|
||||
.Ar debug-value
|
||||
is specified it is used to set the debugging level.
|
||||
When debugging is on,
|
||||
.Nm
|
||||
prints each command sent to the remote machine, preceded
|
||||
by the string
|
||||
.Ql \-\-> .
|
||||
.It Ic delete Ar remote-file
|
||||
Delete the file
|
||||
.Ar remote-file
|
||||
|
@ -477,18 +505,16 @@ Toggle command line editing, and context sensitive command and file
|
|||
completion.
|
||||
This is automatically enabled if input is from a terminal, and
|
||||
disabled otherwise.
|
||||
.It Ic epsv epsv4 epsv6
|
||||
.It Ic epsv , epsv4 , epsv6
|
||||
Toggle the use of the extended
|
||||
.Dv EPSV
|
||||
and
|
||||
.Dv EPRT
|
||||
commands on all IP, IPv4, and IPv6 connections respectively.
|
||||
First try
|
||||
.Dv EPSV /
|
||||
.Dv EPRT ,
|
||||
.Dv EPSV Ns \^/\^ Ns Dv EPRT ,
|
||||
and then
|
||||
.Dv PASV /
|
||||
.Dv PORT .
|
||||
.Dv PASV Ns \^/\^ Ns Dv PORT .
|
||||
This is enabled by default.
|
||||
If an extended command fails then this option will be temporarily
|
||||
disabled for the duration of the current connection, or until
|
||||
|
@ -519,19 +545,11 @@ format is
|
|||
.It Ic ftp Ar host Op Ar port
|
||||
A synonym for
|
||||
.Ic open .
|
||||
.It Ic ftp_debug Op Ar ftp_debug-value
|
||||
Toggle debugging mode.
|
||||
If an optional
|
||||
.Ar ftp_debug-value
|
||||
is specified it is used to set the debugging level.
|
||||
When debugging is on,
|
||||
.Nm
|
||||
prints each command sent to the remote machine, preceded
|
||||
by the string
|
||||
.Ql \-\-\*[Gt] .
|
||||
.It Ic gate Op Ar host Op Ar port
|
||||
Toggle gate-ftp mode, which used to connect through the
|
||||
TIS FWTK and Gauntlet ftp proxies.
|
||||
TIS FWTK and Gauntlet
|
||||
.Tn FTP
|
||||
proxies.
|
||||
This will not be permitted if the gate-ftp server hasn't been set
|
||||
(either explicitly by the user, or from the
|
||||
.Ev FTPSERVER
|
||||
|
@ -589,9 +607,11 @@ each remote file name is expanded
|
|||
separately on the remote machine and the lists are not merged.
|
||||
Expansion of a directory name is likely to be
|
||||
different from expansion of the name of an ordinary file:
|
||||
the exact result depends on the foreign operating system and ftp server,
|
||||
the exact result depends on the foreign operating system and
|
||||
.Tn FTP
|
||||
server,
|
||||
and can be previewed by doing
|
||||
.Ql mls remote-files \-
|
||||
.Sq Li mls remote-files \- .
|
||||
Note:
|
||||
.Ic mget ,
|
||||
.Ic mput
|
||||
|
@ -672,32 +692,32 @@ To invoke a macro, use the
|
|||
command (see above).
|
||||
.Pp
|
||||
The macro processor interprets
|
||||
.Sq $
|
||||
.Ql $
|
||||
and
|
||||
.Sq \e
|
||||
.Ql \e
|
||||
as special characters.
|
||||
A
|
||||
.Sq $
|
||||
.Ql $
|
||||
followed by a number (or numbers) is replaced by the
|
||||
corresponding argument on the macro invocation command line.
|
||||
A
|
||||
.Sq $
|
||||
.Ql $
|
||||
followed by an
|
||||
.Sq i
|
||||
.Ql i
|
||||
signals the macro processor that the executing macro is to be
|
||||
looped.
|
||||
On the first pass
|
||||
.Dq $i
|
||||
.Ql $i
|
||||
is replaced by the first argument on the macro invocation command
|
||||
line, on the second pass it is replaced by the second argument,
|
||||
and so on.
|
||||
A
|
||||
.Sq \e
|
||||
.Ql \e
|
||||
followed by any character is replaced by that character.
|
||||
Use the
|
||||
.Sq \e
|
||||
.Ql \e
|
||||
to prevent special treatment of the
|
||||
.Sq $ .
|
||||
.Ql $ .
|
||||
.It Ic mdelete Op Ar remote-files
|
||||
Delete the
|
||||
.Ar remote-files
|
||||
|
@ -732,7 +752,7 @@ Files are transferred into the local working directory,
|
|||
which can be changed with
|
||||
.Ql lcd directory ;
|
||||
new local directories can be created with
|
||||
.Ql "\&! mkdir directory" .
|
||||
.Sq Li "\&! mkdir directory" .
|
||||
.It Ic mkdir Ar directory-name
|
||||
Make a directory on the remote machine.
|
||||
.It Ic mls Ar remote-files local-file
|
||||
|
@ -755,7 +775,7 @@ Display the contents of
|
|||
in a machine-parsable form, using
|
||||
.Dv MLSD .
|
||||
The format of display can be changed with
|
||||
.Sq "remopts mlst ..." .
|
||||
.Sq Li "remopts mlst ..." .
|
||||
.It Ic mlst Op Ar remote-path
|
||||
Display the details about
|
||||
.Ar remote-path
|
||||
|
@ -763,7 +783,7 @@ Display the details about
|
|||
in a machine-parsable form, using
|
||||
.Dv MLST .
|
||||
The format of display can be changed with
|
||||
.Sq "remopts mlst ..." .
|
||||
.Sq Li "remopts mlst ..." .
|
||||
.It Ic mode Ar mode-name
|
||||
Set the file transfer
|
||||
.Ic mode
|
||||
|
@ -809,7 +829,7 @@ If the file does not
|
|||
exist on the current system, the remote file is considered
|
||||
.Ic newer .
|
||||
Otherwise, this command is identical to
|
||||
.Ar get .
|
||||
.Ic get .
|
||||
.It Ic nlist Op Ar remote-path Op Ar local-file
|
||||
A synonym for
|
||||
.Ic ls .
|
||||
|
@ -834,7 +854,8 @@ The mapping follows the pattern set by
|
|||
.Ar inpattern
|
||||
and
|
||||
.Ar outpattern .
|
||||
.Op Ar Inpattern
|
||||
.Pp
|
||||
.Ar inpattern
|
||||
is a template for incoming filenames (which may have already been
|
||||
processed according to the
|
||||
.Ic ntrans
|
||||
|
@ -843,16 +864,16 @@ and
|
|||
settings).
|
||||
Variable templating is accomplished by including the
|
||||
sequences
|
||||
.Dq $1 ,
|
||||
.Dq $2 ,
|
||||
\&...
|
||||
.Dq $9
|
||||
.Ql $1 ,
|
||||
.Ql $2 ,
|
||||
\&...\|,
|
||||
.Ql $9
|
||||
in
|
||||
.Ar inpattern .
|
||||
Use
|
||||
.Sq \e
|
||||
.Ql \e
|
||||
to prevent this special treatment of the
|
||||
.Sq $
|
||||
.Ql $
|
||||
character.
|
||||
All other characters are treated literally, and are used to determine the
|
||||
.Ic nmap
|
||||
|
@ -860,53 +881,72 @@ All other characters are treated literally, and are used to determine the
|
|||
variable values.
|
||||
For example, given
|
||||
.Ar inpattern
|
||||
$1.$2 and the remote file name "mydata.data", $1 would have the value
|
||||
"mydata", and $2 would have the value "data".
|
||||
.Sq Li $1.$2
|
||||
and the remote file name
|
||||
.Sq Li mydata.data ,
|
||||
.Ql $1
|
||||
would have the value
|
||||
.Sq Li mydata ,
|
||||
and
|
||||
.Ql $2
|
||||
would have the value
|
||||
.Sq Li data .
|
||||
.Pp
|
||||
The
|
||||
.Ar outpattern
|
||||
determines the resulting mapped filename.
|
||||
The sequences
|
||||
.Dq $1 ,
|
||||
.Dq $2 ,
|
||||
\&...
|
||||
.Dq $9
|
||||
.Ql $1 ,
|
||||
.Ql $2 ,
|
||||
\&...\|,
|
||||
.Ql $9
|
||||
are replaced by any value resulting from the
|
||||
.Ar inpattern
|
||||
template.
|
||||
The sequence
|
||||
.Dq $0
|
||||
.Ql $0
|
||||
is replaced by the original filename.
|
||||
Additionally, the sequence
|
||||
.Dq Op Ar seq1 , Ar seq2
|
||||
is replaced by
|
||||
.Op Ar seq1
|
||||
.Ar seq1
|
||||
if
|
||||
.Ar seq1
|
||||
is not a null string; otherwise it is replaced by
|
||||
.Ar seq2 .
|
||||
For example, the command
|
||||
.Pp
|
||||
.Bd -literal -offset indent -compact
|
||||
nmap $1.$2.$3 [$1,$2].[$2,file]
|
||||
.Ed
|
||||
.Dl nmap $1.$2.$3 [$1,$2].[$2,file]
|
||||
.Pp
|
||||
would yield
|
||||
the output filename "myfile.data" for input filenames "myfile.data" and
|
||||
"myfile.data.old", "myfile.file" for the input filename "myfile", and
|
||||
"myfile.myfile" for the input filename ".myfile".
|
||||
the output filename
|
||||
.Sq Li myfile.data
|
||||
for input filenames
|
||||
.Sq Li myfile.data
|
||||
and
|
||||
.Sq Li myfile.data.old ,
|
||||
.Sq Li myfile.file
|
||||
for the input filename
|
||||
.Sq Li myfile ,
|
||||
and
|
||||
.Sq Li myfile.myfile
|
||||
for the input filename
|
||||
.Sq Li "\&.myfile" .
|
||||
Spaces may be included in
|
||||
.Ar outpattern ,
|
||||
as in the example:
|
||||
.Dl nmap $1 sed "s/ *$//" \*[Gt] $1
|
||||
.Pp
|
||||
.Dl nmap $1 sed "s/ *$//" > $1
|
||||
.Pp
|
||||
Use the
|
||||
.Sq \e
|
||||
.Ql \e
|
||||
character to prevent special treatment
|
||||
of the
|
||||
.Sq $ ,
|
||||
.Sq \&[ ,
|
||||
.Sq \&] ,
|
||||
.Ql $ ,
|
||||
.Ql \&[ ,
|
||||
.Ql \&] ,
|
||||
and
|
||||
.Sq \&,
|
||||
.Ql \&,
|
||||
characters.
|
||||
.It Ic ntrans Op Ar inchars Op Ar outchars
|
||||
Set or unset the filename character translation mechanism.
|
||||
|
@ -1027,7 +1067,7 @@ The progress bar will be disabled for a transfer that has
|
|||
as
|
||||
.Sq Fl
|
||||
or a command that starts with
|
||||
.Sq \&| .
|
||||
.Ql \&| .
|
||||
Refer to
|
||||
.Sx FILE NAMING CONVENTIONS
|
||||
for more information.
|
||||
|
@ -1081,7 +1121,9 @@ Any other response will answer
|
|||
.Sq yes
|
||||
to the current file.
|
||||
.It Ic proxy Ar ftp-command
|
||||
Execute an ftp command on a secondary control connection.
|
||||
Execute an
|
||||
.Tn FTP
|
||||
command on a secondary control connection.
|
||||
This command allows simultaneous connection to two remote
|
||||
.Tn FTP
|
||||
servers for transferring files between the two servers.
|
||||
|
@ -1090,11 +1132,13 @@ The first
|
|||
command should be an
|
||||
.Ic open ,
|
||||
to establish the secondary control connection.
|
||||
Enter the command "proxy ?" to see other
|
||||
Enter the command
|
||||
.Sq Li "proxy ?"
|
||||
to see other
|
||||
.Tn FTP
|
||||
commands executable on the secondary connection.
|
||||
The following commands behave differently when prefaced by
|
||||
.Ic proxy :
|
||||
.Ic proxy\^ :
|
||||
.Ic open
|
||||
will not define new macros during the auto-login process,
|
||||
.Ic close
|
||||
|
@ -1139,7 +1183,7 @@ machine.
|
|||
.It Ic quit
|
||||
A synonym for
|
||||
.Ic bye .
|
||||
.It Ic quote Ar arg1 arg2 ...
|
||||
.It Ic quote Op Ar arg ...
|
||||
The arguments specified are sent, verbatim, to the remote
|
||||
.Tn FTP
|
||||
server.
|
||||
|
@ -1153,7 +1197,7 @@ is 0, disable the throttle.
|
|||
.Pp
|
||||
.Ar direction
|
||||
may be one of:
|
||||
.Bl -tag -width "all" -offset indent -compact
|
||||
.Bl -tag -width ".Cm all" -offset indent -compact
|
||||
.It Cm all
|
||||
Both directions.
|
||||
.It Cm get
|
||||
|
@ -1166,7 +1210,7 @@ Outgoing transfers.
|
|||
can be modified on the fly by
|
||||
.Ar increment
|
||||
bytes (default: 1024) each time a given signal is received:
|
||||
.Bl -tag -width "SIGUSR1" -offset indent
|
||||
.Bl -tag -width ".Dv SIGUSR1" -offset indent
|
||||
.It Dv SIGUSR1
|
||||
Increment
|
||||
.Ar maximum
|
||||
|
@ -1224,7 +1268,7 @@ to
|
|||
Remote
|
||||
.Tn FTP
|
||||
commands known to support options include:
|
||||
.Sq MLST
|
||||
.Dv MLST
|
||||
(used for
|
||||
.Dv MLSD
|
||||
and
|
||||
|
@ -1277,10 +1321,16 @@ local filename for a
|
|||
.Ic get
|
||||
or
|
||||
.Ic mget
|
||||
command, a ".1" is appended to the name.
|
||||
command, a
|
||||
.Ql \&.1
|
||||
is appended to the name.
|
||||
If the resulting name matches another existing file,
|
||||
a ".2" is appended to the original name.
|
||||
If this process continues up to ".99", an error
|
||||
a
|
||||
.Ql \&.2
|
||||
is appended to the original name.
|
||||
If this process continues up to
|
||||
.Ql .99 ,
|
||||
an error
|
||||
message is printed, and the transfer does not take place.
|
||||
The generated unique filename will be reported.
|
||||
Note that
|
||||
|
@ -1358,7 +1408,7 @@ Defaults to
|
|||
Defaults to
|
||||
.Ev $FTPRPROMPT .
|
||||
.El
|
||||
.It Ic site Ar arg1 arg2 ...
|
||||
.It Ic site Op Ar arg ...
|
||||
The arguments specified are sent, verbatim, to the remote
|
||||
.Tn FTP
|
||||
server as a
|
||||
|
@ -1479,7 +1529,7 @@ A synonym for
|
|||
.Pp
|
||||
Command arguments which have embedded spaces may be quoted with
|
||||
quote
|
||||
.Sq \&"
|
||||
.Ql \&\(dq
|
||||
marks.
|
||||
.Pp
|
||||
Commands which toggle settings can take an explicit
|
||||
|
@ -1514,7 +1564,7 @@ If
|
|||
receives a
|
||||
.Dv SIGINFO
|
||||
(see the
|
||||
.Dq status
|
||||
.Cm status
|
||||
argument of
|
||||
.Xr stty 1 )
|
||||
or
|
||||
|
@ -1544,7 +1594,7 @@ contains a glob character and globbing is enabled,
|
|||
(see
|
||||
.Ic glob ) ,
|
||||
then the equivalent of
|
||||
.Ql mget path
|
||||
.Sq Li mget path
|
||||
is performed.
|
||||
.Pp
|
||||
If the directory component of
|
||||
|
@ -1557,10 +1607,10 @@ of
|
|||
in the current directory.
|
||||
Otherwise, the full remote name is used as the local name,
|
||||
relative to the local root directory.
|
||||
.\" ftp://[user[:password]@]host[:port]/path[/][;type=X]
|
||||
.\" ftp://[user[:password]@]host[:port]/path[/][;type=type]
|
||||
.It Li ftp:// Ns Oo Ar user Ns Oo Ns Li \&: Ns Ar password Oc Ns Li \&@ Oc \
|
||||
Ns Ar host Ns Oo Li \&: Ns Ar port Oc Ns Li / Ns Ar path Ns Oo Li / Oc \
|
||||
Ns Oo Li ;type= Ns Ar X Oc
|
||||
Ns Oo Li ;type= Ns Ar type Oc
|
||||
An
|
||||
.Tn FTP
|
||||
URL, retrieved using the
|
||||
|
@ -1583,9 +1633,9 @@ In this case, use
|
|||
if supplied, otherwise prompt the user for one.
|
||||
.Pp
|
||||
If a suffix of
|
||||
.Sq ;type=A
|
||||
.Sq Li \&;type=A
|
||||
or
|
||||
.Sq ;type=I
|
||||
.Sq Li \&;type=I
|
||||
is supplied, then the transfer type will take place as
|
||||
ascii or binary (respectively).
|
||||
The default transfer type is binary.
|
||||
|
@ -1596,7 +1646,7 @@ In order to be compliant with
|
|||
interprets the
|
||||
.Ar path
|
||||
part of an
|
||||
.Dq ftp://
|
||||
.Sq Li ftp://
|
||||
auto-fetch URL as follows:
|
||||
.Bl -bullet
|
||||
.It
|
||||
|
@ -1676,20 +1726,20 @@ user.
|
|||
If the
|
||||
.Pa /
|
||||
directory is required, use a leading path of
|
||||
.Dq %2F .
|
||||
.Sq Li \&%2F .
|
||||
If a user's home directory is required (and the remote server supports
|
||||
the syntax), use a leading path of
|
||||
.Dq %7Euser/ .
|
||||
.Sq Li \&%7E Ns Ar user Ns Li / .
|
||||
For example, to retrieve
|
||||
.Pa /etc/motd
|
||||
from
|
||||
.Sq localhost
|
||||
.Sq Li localhost
|
||||
as the user
|
||||
.Sq myname
|
||||
.Sq Li myname
|
||||
with the password
|
||||
.Sq mypass ,
|
||||
.Sq Li mypass ,
|
||||
use
|
||||
.Dq ftp://myname:mypass@localhost/%2fetc/motd
|
||||
.Sq Li ftp://myname:mypass@localhost/%2fetc/motd
|
||||
.It
|
||||
The exact
|
||||
.Ic cd
|
||||
|
@ -1697,11 +1747,11 @@ and
|
|||
.Ic get
|
||||
commands can be controlled by careful choice of
|
||||
where to use
|
||||
.Sq /
|
||||
.Sq Li /
|
||||
and where to use
|
||||
.Sq %2F
|
||||
.Sq Li \&%2F
|
||||
(or
|
||||
.Sq %2f ) .
|
||||
.Sq Li %2f ) .
|
||||
For example, the following URLs correspond to the
|
||||
equivalents of the indicated commands:
|
||||
.Bl -tag -width "ftp://host/%2Fdir1%2Fdir2%2Ffile"
|
||||
|
@ -1748,9 +1798,9 @@ If
|
|||
authorization is required to retrieve
|
||||
.Ar path ,
|
||||
and
|
||||
.Sq user
|
||||
.Ar user
|
||||
(and optionally
|
||||
.Sq password )
|
||||
.Ar password\^ )
|
||||
is in the URL, use them for the first attempt to authenticate.
|
||||
.\" https://[user[:password]@]host[:port]/path
|
||||
.It Li https:// Ns Oo Ar user Ns Oo Li \&: Ns Ar password Oc Ns Li \&@ Oc \
|
||||
|
@ -1770,9 +1820,9 @@ If
|
|||
authorization is required to retrieve
|
||||
.Ar path ,
|
||||
and
|
||||
.Sq user
|
||||
.Ar user
|
||||
(and optionally
|
||||
.Sq password )
|
||||
.Ar password\^ )
|
||||
is in the URL, use them for the first attempt to authenticate.
|
||||
There is currently no certificate validation and verification.
|
||||
.\" file:///path
|
||||
|
@ -1815,7 +1865,7 @@ is recommended, to avoid writing to unexpected file names.
|
|||
If a classic format or an
|
||||
.Tn FTP
|
||||
URL format has a trailing
|
||||
.Sq /
|
||||
.Ql /
|
||||
or an empty
|
||||
.Ar path
|
||||
component, then
|
||||
|
@ -1847,9 +1897,9 @@ proxies will be restarted.
|
|||
For
|
||||
.Tn FTP ,
|
||||
this is implemented by using
|
||||
.Nm reget
|
||||
.Ic reget
|
||||
instead of
|
||||
.Nm get .
|
||||
.Ic get .
|
||||
For
|
||||
.Tn HTTP ,
|
||||
this is implemented by using the
|
||||
|
@ -1863,7 +1913,7 @@ to enter a username and password to authenticate with.
|
|||
When specifying IPv6 numeric addresses in a URL, you need to
|
||||
surround the address in square brackets.
|
||||
E.g.:
|
||||
.Dq ftp://[::1]:21/ .
|
||||
.Sq Li ftp://[::1]:21/ .
|
||||
This is because colons are used in IPv6 numeric address as well as
|
||||
being the separator for the port number.
|
||||
.Sh ABORTING A FILE TRANSFER
|
||||
|
@ -1886,7 +1936,9 @@ sending the requested file.
|
|||
.Pp
|
||||
If the terminal interrupt key sequence is used whilst
|
||||
.Nm
|
||||
is awaiting a reply from the remote server for the ABOR processing,
|
||||
is awaiting a reply from the remote server for the
|
||||
.Dv ABOR
|
||||
processing,
|
||||
then the connection will be closed.
|
||||
This is different from the traditional behaviour (which ignores the
|
||||
terminal interrupt during this phase), but is considered more useful.
|
||||
|
@ -1899,13 +1951,13 @@ commands are processed according to the following rules.
|
|||
If the file name
|
||||
.Sq Fl
|
||||
is specified, the
|
||||
.Ar stdin
|
||||
.Va stdin
|
||||
(for reading) or
|
||||
.Ar stdout
|
||||
.Va stdout
|
||||
(for writing) is used.
|
||||
.It
|
||||
If the first character of the file name is
|
||||
.Sq \&| ,
|
||||
.Ql \&| ,
|
||||
the
|
||||
remainder of the argument is interpreted as a shell command.
|
||||
.Nm
|
||||
|
@ -1915,13 +1967,12 @@ with the argument supplied, and reads (writes) from the stdout
|
|||
(stdin).
|
||||
If the shell command includes spaces, the argument
|
||||
must be quoted; e.g.
|
||||
.Dq Qq Li \&| ls\ \-lt .
|
||||
.Sq Li \(dq|\~ls\~\-lt\(dq .
|
||||
A particularly
|
||||
useful example of this mechanism is:
|
||||
.Dq Li dir \&"\&" \&|more .
|
||||
.Sq Li dir\~\(dq\(dq\~|more .
|
||||
.It
|
||||
Failing the above checks, if
|
||||
.Dq globbing
|
||||
Failing the above checks, if globbing
|
||||
is enabled, local file names are expanded according to the rules
|
||||
used in the
|
||||
.Xr csh 1 ;
|
||||
|
@ -1932,7 +1983,7 @@ If the
|
|||
.Nm
|
||||
command expects a single local file (e.g.
|
||||
.Ic put ) ,
|
||||
only the first filename generated by the "globbing" operation is used.
|
||||
only the first filename generated by the globbing operation is used.
|
||||
.It
|
||||
For
|
||||
.Ic mget
|
||||
|
@ -2133,7 +2184,7 @@ The
|
|||
.Xr editline 3
|
||||
library is configured with a
|
||||
.Pa .editrc
|
||||
file - refer to
|
||||
file \(em refer to
|
||||
.Xr editrc 5
|
||||
for more information.
|
||||
.Pp
|
||||
|
@ -2150,7 +2201,7 @@ By default, this is bound to the TAB key.
|
|||
By default,
|
||||
.Nm
|
||||
displays a command line prompt of
|
||||
.Dq "ftp\*[Gt] "
|
||||
.Sq Li ftp>\~
|
||||
to the user.
|
||||
This can be changed with the
|
||||
.Ic "set prompt"
|
||||
|
@ -2167,42 +2218,42 @@ information:
|
|||
.It Li \&%/
|
||||
The current remote working directory.
|
||||
.\" %c[[0]n], %.[[0]n]
|
||||
.It \&%c Ns Oo Oo Li 0 Oc Ns Ar n Oc , Ns Li \&%. Ns Oo Oo Li 0 Oc Ns Ar n Oc
|
||||
.It Li \&%c Ns Oo Oo Li 0 Oc Ns Ar n Oc , Li \&%. Ns Oo Oo Li 0 Oc Ns Ar n Oc
|
||||
The trailing component of the current remote working directory, or
|
||||
.Em n
|
||||
.Ar n
|
||||
trailing components if a digit
|
||||
.Em n
|
||||
.Ar n
|
||||
is given.
|
||||
If
|
||||
.Em n
|
||||
.Ar n
|
||||
begins with
|
||||
.Sq 0 ,
|
||||
.Ql 0 ,
|
||||
the number of skipped components precede the trailing component(s) in
|
||||
the format
|
||||
.\" ``/<number>trailing''
|
||||
.Do
|
||||
.Sm off
|
||||
.Li / Li \*[Lt] Va number Li \*[Gt]
|
||||
.Va trailing
|
||||
.Li / Li < Ar number Li >
|
||||
.Ar trailing
|
||||
.Sm on
|
||||
.Dc
|
||||
(for
|
||||
.Sq \&%c )
|
||||
.Ql \&%c )
|
||||
or
|
||||
.\" ``...trailing''
|
||||
.Dq Li \&... Ns Va trailing
|
||||
.Dq Li \&... Ns Ar trailing
|
||||
(for
|
||||
.Sq \&%. ) .
|
||||
.Ql \&%. ) .
|
||||
.It Li \&%M
|
||||
The remote host name.
|
||||
.It Li \&%m
|
||||
The remote host name, up to the first
|
||||
.Sq \&. .
|
||||
The remote host name, up to the first dot
|
||||
.Ql \&. .
|
||||
.It Li \&%n
|
||||
The remote user name.
|
||||
.It Li \&%%
|
||||
A single
|
||||
.Sq % .
|
||||
A single percent character
|
||||
.Ql % .
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Nm
|
||||
|
@ -2213,7 +2264,7 @@ Password to send in an anonymous
|
|||
.Tn FTP
|
||||
transfer.
|
||||
Defaults to
|
||||
.Dq Li `whoami`@ .
|
||||
.Dq Li \&\`whoami\`@ .
|
||||
.It Ev FTPMODE
|
||||
Overrides the default operation mode.
|
||||
Support values are:
|
||||
|
@ -2234,14 +2285,13 @@ only
|
|||
.It Ev FTPPROMPT
|
||||
Command-line prompt to use.
|
||||
Defaults to
|
||||
.Dq "ftp\*[Gt] " .
|
||||
.Sq Li ftp>\~ .
|
||||
Refer to
|
||||
.Sx COMMAND LINE PROMPT
|
||||
for more information.
|
||||
.It Ev FTPRPROMPT
|
||||
Command-line right side prompt to use.
|
||||
Defaults to
|
||||
.Dq "" .
|
||||
Defaults to empty string.
|
||||
Refer to
|
||||
.Sx COMMAND LINE PROMPT
|
||||
for more information.
|
||||
|
@ -2254,9 +2304,9 @@ Port to use when connecting to gate-ftp server when
|
|||
.Ic gate
|
||||
is enabled.
|
||||
Default is port returned by a
|
||||
.Fn getservbyname
|
||||
.Xr getservbyname 3
|
||||
lookup of
|
||||
.Dq ftpgate/tcp .
|
||||
.Dq Li ftpgate/tcp .
|
||||
.It Ev FTPUSERAGENT
|
||||
The value to send for the
|
||||
.Tn HTTP
|
||||
|
@ -2270,6 +2320,8 @@ file, if one exists.
|
|||
An alternate location of the
|
||||
.Pa .netrc
|
||||
file.
|
||||
.It Ev NO_CERT_VERIFY
|
||||
Don't verify SSL certificates.
|
||||
.It Ev PAGER
|
||||
Used by various commands to display files.
|
||||
Defaults to
|
||||
|
@ -2304,9 +2356,9 @@ If
|
|||
.Dq unsafe
|
||||
URL characters are required in the username or password
|
||||
(for example
|
||||
.Sq @
|
||||
.Ql @
|
||||
or
|
||||
.Sq / ) ,
|
||||
.Ql / ) ,
|
||||
encode them with
|
||||
.Li RFC 3986
|
||||
.Sq Li \&% Ns Ar XX
|
||||
|
@ -2323,10 +2375,22 @@ may be incompatible with other programs that use it
|
|||
.Em NOTE :
|
||||
this is not used for interactive sessions, only for command-line
|
||||
fetches.
|
||||
.It Ev https_proxy
|
||||
URL of
|
||||
.Tn HTTPS
|
||||
proxy to use when making
|
||||
.Tn HTTPS
|
||||
URL requests.
|
||||
.Pp
|
||||
See
|
||||
.Ev http_proxy
|
||||
for further notes about proxy use.
|
||||
.It Ev no_proxy
|
||||
A space or comma separated list of hosts (or domains) for which
|
||||
proxying is not to be used.
|
||||
Each entry may have an optional trailing ":port", which restricts
|
||||
Each entry may have an optional trailing
|
||||
.Sq Li \&: Ns Ar port ,
|
||||
which restricts
|
||||
the matching to connections to that port.
|
||||
.El
|
||||
.Sh EXTENDED PASSIVE MODE AND FIREWALLS
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: ftp.c,v 1.167.6.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: ftp.c,v 1.167.6.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -92,7 +92,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ftp.c,v 1.167.6.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: ftp.c,v 1.167.6.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -280,6 +280,11 @@ hookup(const char *host, const char *port)
|
|||
goto bad;
|
||||
}
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_KEEPALIVE,
|
||||
(void *)&on, sizeof(on)) == -1) {
|
||||
DWARN("setsockopt %s (ignored)", "SO_KEEPALIVE");
|
||||
}
|
||||
|
||||
if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE,
|
||||
(void *)&on, sizeof(on)) == -1) {
|
||||
DWARN("setsockopt %s (ignored)", "SO_OOBINLINE");
|
||||
|
@ -320,6 +325,17 @@ cmdtimeout(int notused)
|
|||
errno = oerrno;
|
||||
}
|
||||
|
||||
static int
|
||||
issighandler(sigfunc func)
|
||||
{
|
||||
return (func != SIG_IGN &&
|
||||
func != SIG_DFL &&
|
||||
#ifdef SIG_HOLD
|
||||
func != SIG_HOLD &&
|
||||
#endif
|
||||
func != SIG_ERR);
|
||||
}
|
||||
|
||||
/*VARARGS*/
|
||||
int
|
||||
command(const char *fmt, ...)
|
||||
|
@ -359,8 +375,9 @@ command(const char *fmt, ...)
|
|||
(void)fflush(cout);
|
||||
cpend = 1;
|
||||
r = getreply(!strcmp(fmt, "QUIT"));
|
||||
if (abrtflag && oldsigint != SIG_IGN)
|
||||
if (abrtflag && issighandler(oldsigint)) {
|
||||
(*oldsigint)(SIGINT);
|
||||
}
|
||||
(void)xsignal(SIGINT, oldsigint);
|
||||
return (r);
|
||||
}
|
||||
|
@ -510,11 +527,14 @@ getreply(int expecteof)
|
|||
(void)xsignal(SIGALRM, oldsigalrm);
|
||||
if (code == 421 || originalcode == 421)
|
||||
lostpeer(0);
|
||||
if (abrtflag && oldsigint != cmdabort && oldsigint != SIG_IGN)
|
||||
if (abrtflag && oldsigint != cmdabort &&
|
||||
issighandler(oldsigint)) {
|
||||
(*oldsigint)(SIGINT);
|
||||
}
|
||||
if (timeoutflag && oldsigalrm != cmdtimeout &&
|
||||
oldsigalrm != SIG_IGN)
|
||||
issighandler(oldsigalrm)) {
|
||||
(*oldsigalrm)(SIGINT);
|
||||
}
|
||||
return (n - '0');
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +598,7 @@ abortxfer(int notused)
|
|||
|
||||
/*
|
||||
* Read data from infd & write to outfd, using buf/bufsize as the temporary
|
||||
* buffer, dealing with short writes.
|
||||
* buffer, dealing with short reads or writes.
|
||||
* If rate_limit != 0, rate-limit the transfer.
|
||||
* If hash_interval != 0, fputc('c', ttyout) every hash_interval bytes.
|
||||
* Updates global variables: bytes.
|
||||
|
@ -612,15 +632,25 @@ copy_bytes(int infd, int outfd, char *buf, size_t bufsize,
|
|||
bufrem = bufchunk;
|
||||
while (bufrem > 0) {
|
||||
inc = read(infd, buf, MIN((off_t)bufsize, bufrem));
|
||||
if (inc <= 0)
|
||||
if (inc < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
goto copy_done;
|
||||
} else if (inc == 0) {
|
||||
goto copy_done;
|
||||
}
|
||||
bytes += inc;
|
||||
bufrem -= inc;
|
||||
bufp = buf;
|
||||
while (inc > 0) {
|
||||
outc = write(outfd, bufp, inc);
|
||||
if (outc < 0)
|
||||
if (outc < 0) {
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
continue;
|
||||
}
|
||||
goto copy_done;
|
||||
}
|
||||
inc -= outc;
|
||||
bufp += outc;
|
||||
}
|
||||
|
@ -670,7 +700,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
FILE *volatile dout;
|
||||
int (*volatile closefunc)(FILE *);
|
||||
sigfunc volatile oldintr;
|
||||
sigfunc volatile oldintp;
|
||||
sigfunc volatile oldpipe;
|
||||
off_t volatile hashbytes;
|
||||
int hash_interval;
|
||||
const char *lmode;
|
||||
|
@ -697,8 +727,8 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
if (curtype != type)
|
||||
changetype(type, 0);
|
||||
closefunc = NULL;
|
||||
oldintr = NULL;
|
||||
oldintp = NULL;
|
||||
oldintr = SIG_ERR;
|
||||
oldpipe = SIG_ERR;
|
||||
lmode = "w";
|
||||
if (sigsetjmp(xferabort, 1)) {
|
||||
while (cpend)
|
||||
|
@ -712,7 +742,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
fin = stdin;
|
||||
progress = 0;
|
||||
} else if (*local == '|') {
|
||||
oldintp = xsignal(SIGPIPE, SIG_IGN);
|
||||
oldpipe = xsignal(SIGPIPE, SIG_IGN);
|
||||
fin = popen(local + 1, "r");
|
||||
if (fin == NULL) {
|
||||
warn("Can't execute `%s'", local + 1);
|
||||
|
@ -786,7 +816,9 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
}
|
||||
|
||||
progressmeter(-1);
|
||||
oldintp = xsignal(SIGPIPE, SIG_IGN);
|
||||
if (oldpipe == SIG_ERR) {
|
||||
oldpipe = xsignal(SIGPIPE, SIG_IGN);
|
||||
}
|
||||
hash_interval = (hash && (!progress || filesize < 0)) ? mark : 0;
|
||||
|
||||
switch (curtype) {
|
||||
|
@ -855,7 +887,7 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
|
||||
abort:
|
||||
(void)xsignal(SIGINT, oldintr);
|
||||
oldintr = NULL;
|
||||
oldintr = SIG_ERR;
|
||||
if (!cpend) {
|
||||
code = -1;
|
||||
goto cleanupsend;
|
||||
|
@ -874,10 +906,10 @@ sendrequest(const char *cmd, const char *local, const char *remote,
|
|||
ptransfer(0);
|
||||
|
||||
cleanupsend:
|
||||
if (oldintr)
|
||||
if (oldintr != SIG_ERR)
|
||||
(void)xsignal(SIGINT, oldintr);
|
||||
if (oldintp)
|
||||
(void)xsignal(SIGPIPE, oldintp);
|
||||
if (oldpipe != SIG_ERR)
|
||||
(void)xsignal(SIGPIPE, oldpipe);
|
||||
if (data >= 0) {
|
||||
(void)close(data);
|
||||
data = -1;
|
||||
|
@ -899,7 +931,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
|
|||
FILE *volatile din;
|
||||
int (*volatile closefunc)(FILE *);
|
||||
sigfunc volatile oldintr;
|
||||
sigfunc volatile oldintp;
|
||||
sigfunc volatile oldpipe;
|
||||
int c, d;
|
||||
int volatile is_retr;
|
||||
int volatile tcrflag;
|
||||
|
@ -935,8 +967,8 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
|
|||
return;
|
||||
}
|
||||
closefunc = NULL;
|
||||
oldintr = NULL;
|
||||
oldintp = NULL;
|
||||
oldintr = SIG_ERR;
|
||||
oldpipe = SIG_ERR;
|
||||
tcrflag = !crflag && is_retr;
|
||||
if (sigsetjmp(xferabort, 1)) {
|
||||
while (cpend)
|
||||
|
@ -1017,7 +1049,7 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
|
|||
progress = 0;
|
||||
preserve = 0;
|
||||
} else if (!ignorespecial && *local == '|') {
|
||||
oldintp = xsignal(SIGPIPE, SIG_IGN);
|
||||
oldpipe = xsignal(SIGPIPE, SIG_IGN);
|
||||
fout = popen(local + 1, "w");
|
||||
if (fout == NULL) {
|
||||
warn("Can't execute `%s'", local+1);
|
||||
|
@ -1183,10 +1215,10 @@ recvrequest(const char *cmd, const char *volatile local, const char *remote,
|
|||
ptransfer(0);
|
||||
|
||||
cleanuprecv:
|
||||
if (oldintr)
|
||||
if (oldintr != SIG_ERR)
|
||||
(void)xsignal(SIGINT, oldintr);
|
||||
if (oldintp)
|
||||
(void)xsignal(SIGPIPE, oldintp);
|
||||
if (oldpipe != SIG_ERR)
|
||||
(void)xsignal(SIGPIPE, oldpipe);
|
||||
if (data >= 0) {
|
||||
(void)close(data);
|
||||
data = -1;
|
||||
|
@ -1349,13 +1381,11 @@ initconn(void)
|
|||
if (data_addr.su_family != AF_INET) {
|
||||
fputs(
|
||||
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (code / 10 == 22 && code != 227) {
|
||||
fputs("wrong server: return code must be 227\n",
|
||||
ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
error = sscanf(pasv, "%u,%u,%u,%u,%u,%u",
|
||||
|
@ -1364,21 +1394,24 @@ initconn(void)
|
|||
if (error != 6) {
|
||||
fputs(
|
||||
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
error = 0;
|
||||
memset(&data_addr, 0, sizeof(data_addr));
|
||||
data_addr.su_family = AF_INET;
|
||||
data_addr.su_len = sizeof(struct sockaddr_in);
|
||||
data_addr.si_su.su_sin.sin_addr.s_addr =
|
||||
htonl(pack4(addr, 0));
|
||||
data_addr.su_port = htons(pack2(port, 0));
|
||||
if (data_addr.si_su.su_sin.sin_addr.s_addr !=
|
||||
hisctladdr.si_su.su_sin.sin_addr.s_addr) {
|
||||
fputs("Passive mode address mismatch.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
} else if (strcmp(pasvcmd, "LPSV") == 0) {
|
||||
if (code / 10 == 22 && code != 228) {
|
||||
fputs("wrong server: return code must be 228\n",
|
||||
ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
switch (data_addr.su_family) {
|
||||
|
@ -1391,23 +1424,26 @@ initconn(void)
|
|||
if (error != 9) {
|
||||
fputs(
|
||||
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (af != 4 || hal != 4 || pal != 2) {
|
||||
fputs(
|
||||
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
memset(&data_addr, 0, sizeof(data_addr));
|
||||
data_addr.su_family = AF_INET;
|
||||
data_addr.su_len = sizeof(struct sockaddr_in);
|
||||
data_addr.si_su.su_sin.sin_addr.s_addr =
|
||||
htonl(pack4(addr, 0));
|
||||
data_addr.su_port = htons(pack2(port, 0));
|
||||
if (data_addr.si_su.su_sin.sin_addr.s_addr !=
|
||||
hisctladdr.si_su.su_sin.sin_addr.s_addr) {
|
||||
fputs("Passive mode address mismatch.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
|
@ -1423,17 +1459,14 @@ initconn(void)
|
|||
if (error != 21) {
|
||||
fputs(
|
||||
"Passive mode address scan failure. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (af != 6 || hal != 16 || pal != 2) {
|
||||
fputs(
|
||||
"Passive mode AF mismatch. Shouldn't happen!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
|
||||
error = 0;
|
||||
memset(&data_addr, 0, sizeof(data_addr));
|
||||
data_addr.su_family = AF_INET6;
|
||||
data_addr.su_len = sizeof(struct sockaddr_in6);
|
||||
|
@ -1445,10 +1478,19 @@ initconn(void)
|
|||
}
|
||||
}
|
||||
data_addr.su_port = htons(pack2(port, 0));
|
||||
if (memcmp(
|
||||
&data_addr.si_su.su_sin6.sin6_addr,
|
||||
&hisctladdr.si_su.su_sin6.sin6_addr,
|
||||
sizeof(data_addr.si_su.su_sin6.sin6_addr))) {
|
||||
fputs("Passive mode address mismatch.\n",
|
||||
ttyout);
|
||||
goto bad;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
error = 1;
|
||||
fputs("Unknown passive mode AF.\n", ttyout);
|
||||
goto bad;
|
||||
}
|
||||
} else if (strcmp(pasvcmd, "EPSV") == 0) {
|
||||
char delim[4];
|
||||
|
@ -1457,20 +1499,17 @@ initconn(void)
|
|||
if (code / 10 == 22 && code != 229) {
|
||||
fputs("wrong server: return code must be 229\n",
|
||||
ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (sscanf(pasv, "%c%c%c%d%c", &delim[0],
|
||||
&delim[1], &delim[2], &port[1],
|
||||
&delim[3]) != 5) {
|
||||
fputs("parse error!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
if (delim[0] != delim[1] || delim[0] != delim[2]
|
||||
|| delim[0] != delim[3]) {
|
||||
fputs("parse error!\n", ttyout);
|
||||
error = 1;
|
||||
goto bad;
|
||||
}
|
||||
data_addr = hisctladdr;
|
||||
|
@ -1553,8 +1592,8 @@ initconn(void)
|
|||
result = COMPLETE + 1;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
#ifdef INET6
|
||||
/* FALLTHROUGH */
|
||||
case AF_INET6:
|
||||
if (!epsv6 || epsv6bad) {
|
||||
result = COMPLETE + 1;
|
||||
|
@ -1856,7 +1895,7 @@ proxtrans(const char *cmd, const char *local, const char *remote)
|
|||
int volatile secndflag;
|
||||
const char *volatile cmd2;
|
||||
|
||||
oldintr = NULL;
|
||||
oldintr = SIG_ERR;
|
||||
secndflag = 0;
|
||||
if (strcmp(cmd, "RETR"))
|
||||
cmd2 = "RETR";
|
||||
|
@ -2047,7 +2086,7 @@ gunique(const char *local)
|
|||
* needs to get back to a known state.
|
||||
*/
|
||||
static void
|
||||
abort_squared(int dummy)
|
||||
abort_squared(int signo)
|
||||
{
|
||||
char msgbuf[100];
|
||||
size_t len;
|
||||
|
@ -2057,7 +2096,7 @@ abort_squared(int dummy)
|
|||
len = strlcpy(msgbuf, "\nremote abort aborted; closing connection.\n",
|
||||
sizeof(msgbuf));
|
||||
write(fileno(ttyout), msgbuf, len);
|
||||
lostpeer(0);
|
||||
lostpeer(signo);
|
||||
siglongjmp(xferabort, 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ftp_var.h,v 1.84.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: ftp_var.h,v 1.84.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
|
@ -269,6 +269,7 @@ GLOBAL int unix_server; /* server is unix, can use binary for ascii */
|
|||
GLOBAL int unix_proxy; /* proxy is unix, can use binary for ascii */
|
||||
GLOBAL char localcwd[MAXPATHLEN]; /* local dir */
|
||||
GLOBAL char remotecwd[MAXPATHLEN]; /* remote dir */
|
||||
GLOBAL int remcwdvalid; /* remotecwd has been updated */
|
||||
GLOBAL char *username; /* name of user logged in as. (dynamic) */
|
||||
|
||||
GLOBAL sa_family_t family; /* address family to use for connections */
|
||||
|
@ -340,7 +341,7 @@ extern struct option optiontab[];
|
|||
#define DPRINTF(...) (void)0
|
||||
#define DWARN(...) (void)0
|
||||
#else
|
||||
#define DWFTP(a) do a; while (/*CONSTCOND*/0)
|
||||
#define DWFTP(a) do a; while (0)
|
||||
#define DPRINTF(...) DWFTP(if (ftp_debug) (void)fprintf(ttyout, __VA_ARGS__))
|
||||
#define DWARN(...) DWFTP(if (ftp_debug) warn(__VA_ARGS__))
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: main.c,v 1.123.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: main.c,v 1.123.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2015 The NetBSD Foundation, Inc.
|
||||
|
@ -98,7 +98,7 @@ __COPYRIGHT("@(#) Copyright (c) 1985, 1989, 1993, 1994\
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 10/9/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.123.8.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.123.8.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -130,7 +130,8 @@ __RCSID("$NetBSD: main.c,v 1.123.8.2 2022/09/12 15:05:21 martin Exp $");
|
|||
#define NO_PROXY "no_proxy" /* env var with list of non-proxied
|
||||
* hosts, comma or space separated */
|
||||
|
||||
__dead static void usage(void);
|
||||
static int usage(void);
|
||||
static int usage_help(void);
|
||||
static void setupoption(const char *, const char *, const char *);
|
||||
|
||||
int
|
||||
|
@ -266,7 +267,7 @@ main(int volatile argc, char **volatile argv)
|
|||
}
|
||||
}
|
||||
|
||||
while ((ch = getopt(argc, argv, "46AadefginN:o:pP:q:r:Rs:tT:u:vVx:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, ":46AadefginN:o:pP:q:r:Rs:tT:u:vVx:")) != -1) {
|
||||
switch (ch) {
|
||||
case '4':
|
||||
family = AF_INET;
|
||||
|
@ -324,7 +325,7 @@ main(int volatile argc, char **volatile argv)
|
|||
break;
|
||||
|
||||
case 'o':
|
||||
outfile = optarg;
|
||||
outfile = ftp_strdup(optarg);
|
||||
if (strcmp(outfile, "-") == 0)
|
||||
ttyout = stderr;
|
||||
break;
|
||||
|
@ -378,15 +379,15 @@ main(int volatile argc, char **volatile argv)
|
|||
if (*cp == '\0') {
|
||||
warnx("Bad throttle value `%s'",
|
||||
optarg);
|
||||
usage();
|
||||
/* NOTREACHED */
|
||||
return usage();
|
||||
}
|
||||
targv[targc++] = cp;
|
||||
if (targc >= 5)
|
||||
break;
|
||||
}
|
||||
if (parserate(targc, targv, 1) == -1)
|
||||
usage();
|
||||
if (parserate(targc, targv, 1) == -1) {
|
||||
return usage();
|
||||
}
|
||||
free(oac);
|
||||
break;
|
||||
}
|
||||
|
@ -415,8 +416,19 @@ main(int volatile argc, char **volatile argv)
|
|||
rcvbuf_size = sndbuf_size;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
if (optopt == '?') {
|
||||
return usage_help();
|
||||
}
|
||||
warnx("-%c: unknown option", optopt);
|
||||
return usage();
|
||||
|
||||
case ':':
|
||||
warnx("-%c: missing argument", optopt);
|
||||
return usage();
|
||||
|
||||
default:
|
||||
usage();
|
||||
errx(1, "unimplemented option -%c", ch);
|
||||
}
|
||||
}
|
||||
/* set line buffering on ttyout */
|
||||
|
@ -464,7 +476,6 @@ main(int volatile argc, char **volatile argv)
|
|||
if (localhome == NULL && !EMPTYSTRING(pw->pw_dir))
|
||||
localhome = ftp_strdup(pw->pw_dir);
|
||||
localname = ftp_strdup(pw->pw_name);
|
||||
anonuser = localname;
|
||||
}
|
||||
if (netrc[0] == '\0' && localhome != NULL) {
|
||||
if (strlcpy(netrc, localhome, sizeof(netrc)) >= sizeof(netrc) ||
|
||||
|
@ -573,8 +584,9 @@ main(int volatile argc, char **volatile argv)
|
|||
retry_connect = 0; /* connected, stop hiding msgs */
|
||||
}
|
||||
}
|
||||
if (isupload)
|
||||
usage();
|
||||
if (isupload) {
|
||||
return usage();
|
||||
}
|
||||
|
||||
#ifndef NO_EDITCOMPLETE
|
||||
controlediting();
|
||||
|
@ -661,7 +673,7 @@ cmdscanner(void)
|
|||
case -2: /* error */
|
||||
if (fromatty)
|
||||
putc('\n', ttyout);
|
||||
quit(0, NULL);
|
||||
justquit();
|
||||
/* NOTREACHED */
|
||||
case -3: /* too long; try again */
|
||||
fputs("Sorry, input line is too long.\n",
|
||||
|
@ -683,7 +695,7 @@ cmdscanner(void)
|
|||
if (buf == NULL || num == 0) {
|
||||
if (fromatty)
|
||||
putc('\n', ttyout);
|
||||
quit(0, NULL);
|
||||
justquit();
|
||||
}
|
||||
if (num >= sizeof(line)) {
|
||||
fputs("Sorry, input line is too long.\n",
|
||||
|
@ -837,7 +849,6 @@ slurpstring(void)
|
|||
slrflag++;
|
||||
INC_CHKCURSOR(stringbase);
|
||||
return ((*sb == '!') ? bangstr : dollarstr);
|
||||
/* NOTREACHED */
|
||||
case 1:
|
||||
slrflag++;
|
||||
altarg = stringbase;
|
||||
|
@ -966,7 +977,7 @@ help(int argc, char *argv[])
|
|||
cmd = argv[0];
|
||||
isusage = (strcmp(cmd, "usage") == 0);
|
||||
if (argc == 0 || (isusage && argc == 1)) {
|
||||
UPRINTF("usage: %s [command [...]]\n", cmd);
|
||||
UPRINTF("usage: %s [command ...]\n", cmd);
|
||||
return;
|
||||
}
|
||||
if (argc == 1) {
|
||||
|
@ -1045,20 +1056,69 @@ setupoption(const char *name, const char *value, const char *defaultvalue)
|
|||
set_option(name, value ? value : defaultvalue, 0);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
synopsis(FILE * stream)
|
||||
{
|
||||
const char * progname = getprogname();
|
||||
|
||||
fprintf(stream,
|
||||
"usage: %s [-46AadefginpRtVv] [-N NETRC] [-o OUTPUT] [-P PORT] [-q QUITTIME]\n"
|
||||
" [-r RETRY] [-s SRCADDR] [-T DIR,MAX[,INC]] [-x XFERSIZE]\n"
|
||||
" [[USER@]HOST [PORT]]\n"
|
||||
" [[USER@]HOST:[PATH][/]]\n"
|
||||
" [file:///PATH]\n"
|
||||
" [ftp://[USER[:PASSWORD]@]HOST[:PORT]/PATH[/][;type=TYPE]]\n"
|
||||
" [http://[USER[:PASSWORD]@]HOST[:PORT]/PATH]\n"
|
||||
#ifdef WITH_SSL
|
||||
" [https://[USER[:PASSWORD]@]HOST[:PORT]/PATH]\n"
|
||||
#endif
|
||||
" ...\n"
|
||||
" %s -u URL FILE ...\n"
|
||||
" %s -?\n",
|
||||
progname, progname, progname);
|
||||
}
|
||||
|
||||
static int
|
||||
usage_help(void)
|
||||
{
|
||||
synopsis(stdout);
|
||||
#ifndef NO_USAGE
|
||||
printf(
|
||||
" -4 Only use IPv4 addresses\n"
|
||||
" -6 Only use IPv6 addresses\n"
|
||||
" -A Force active mode\n"
|
||||
" -a Use anonymous login\n"
|
||||
" -d Enable debugging\n"
|
||||
" -e Disable command-line editing\n"
|
||||
" -f Force cache reload for FTP or HTTP proxy transfers\n"
|
||||
" -g Disable file name globbing\n"
|
||||
" -i Disable interactive prompt during multiple file transfers\n"
|
||||
" -N NETRC Use NETRC instead of ~/.netrc\n"
|
||||
" -n Disable auto-login\n"
|
||||
" -o OUTPUT Save auto-fetched files to OUTPUT\n"
|
||||
" -P PORT Use port PORT\n"
|
||||
" -p Force passive mode\n"
|
||||
" -q QUITTIME Quit if connection stalls for QUITTIME seconds\n"
|
||||
" -R Restart non-proxy auto-fetch\n"
|
||||
" -r RETRY Retry failed connection attempts after RETRY seconds\n"
|
||||
" -s SRCADDR Use source address SRCADDR\n"
|
||||
" -t Enable packet tracing\n"
|
||||
" -T DIR,MAX[,INC]\n"
|
||||
" Set maximum transfer rate for direction DIR to MAX bytes/s,\n"
|
||||
" with optional increment INC bytes/s\n"
|
||||
" -u URL URL to upload file arguments to\n"
|
||||
" -V Disable verbose and progress\n"
|
||||
" -v Enable verbose and progress\n"
|
||||
" -x XFERSIZE Set socket send and receive size to XFERSIZE\n"
|
||||
" -? Display this help and exit\n"
|
||||
);
|
||||
#endif
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
usage(void)
|
||||
{
|
||||
const char *progname = getprogname();
|
||||
|
||||
(void)fprintf(stderr,
|
||||
"usage: %s [-46AadefginpRtVv] [-N netrc] [-o outfile] [-P port] [-q quittime]\n"
|
||||
" [-r retry] [-s srcaddr] [-T dir,max[,inc]] [-x xferbufsize]\n"
|
||||
" [[user@]host [port]] [host:path[/]] [file:///file]\n"
|
||||
" [ftp://[user[:pass]@]host[:port]/path[/]]\n"
|
||||
" [http://[user[:pass]@]host[:port]/path] [...]\n"
|
||||
#ifdef WITH_SSL
|
||||
" [https://[user[:pass]@]host[:port]/path] [...]\n"
|
||||
#endif
|
||||
" %s -u URL file [...]\n", progname, progname);
|
||||
exit(1);
|
||||
synopsis(stderr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: progressbar.c,v 1.22.24.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: progressbar.c,v 1.22.24.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1997-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: progressbar.c,v 1.22.24.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: progressbar.c,v 1.22.24.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -87,6 +87,7 @@ updateprogressmeter(int dummy)
|
|||
/*
|
||||
* List of order of magnitude suffixes, per IEC 60027-2.
|
||||
*/
|
||||
#if !defined(NO_PROGRESS) || !defined(STANDALONE_PROGRESS)
|
||||
static const char * const suffixes[] = {
|
||||
"", /* 2^0 (byte) */
|
||||
"KiB", /* 2^10 Kibibyte */
|
||||
|
@ -102,6 +103,7 @@ static const char * const suffixes[] = {
|
|||
#endif
|
||||
};
|
||||
#define NSUFFIXES (int)(sizeof(suffixes) / sizeof(suffixes[0]))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Display a transfer progress bar if progress is non-zero.
|
||||
|
@ -139,8 +141,10 @@ progressmeter(int flag)
|
|||
* these appropriately.
|
||||
*/
|
||||
#endif
|
||||
#if !defined(NO_PROGRESS) || !defined(STANDALONE_PROGRESS)
|
||||
size_t len;
|
||||
char buf[256]; /* workspace for progress bar */
|
||||
#endif
|
||||
#ifndef NO_PROGRESS
|
||||
#define BAROVERHEAD 45 /* non `*' portion of progress bar */
|
||||
/*
|
||||
|
@ -189,7 +193,7 @@ progressmeter(int flag)
|
|||
if (quit_time > 0 || progress) {
|
||||
#endif /* !STANDALONE_PROGRESS */
|
||||
if (flag == -1) {
|
||||
(void)xsignal_restart(SIGALRM, updateprogressmeter, 1);
|
||||
(void)xsignal(SIGALRM, updateprogressmeter);
|
||||
alarmtimer(1); /* set alarm timer for 1 Hz */
|
||||
} else if (flag == 1) {
|
||||
alarmtimer(0);
|
||||
|
@ -400,73 +404,21 @@ alarmtimer(int wait)
|
|||
setitimer(ITIMER_REAL, &itv, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Install a POSIX signal handler, allowing the invoker to set whether
|
||||
* the signal should be restartable or not
|
||||
* Install a non-restartable POSIX signal handler.
|
||||
*/
|
||||
sigfunc
|
||||
xsignal_restart(int sig, sigfunc func, int restartable)
|
||||
xsignal(int sig, sigfunc func)
|
||||
{
|
||||
struct sigaction act, oact;
|
||||
act.sa_handler = func;
|
||||
|
||||
sigemptyset(&act.sa_mask);
|
||||
#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */
|
||||
act.sa_flags = restartable ? SA_RESTART : 0;
|
||||
#elif defined(SA_INTERRUPT) /* SunOS 4.x */
|
||||
act.sa_flags = restartable ? 0 : SA_INTERRUPT;
|
||||
#else
|
||||
#error "system must have SA_RESTART or SA_INTERRUPT"
|
||||
act.sa_flags = 0;
|
||||
#if defined(SA_INTERRUPT) /* SunOS 4.x */
|
||||
act.sa_flags = SA_INTERRUPT;
|
||||
#endif
|
||||
if (sigaction(sig, &act, &oact) < 0)
|
||||
return (SIG_ERR);
|
||||
return (oact.sa_handler);
|
||||
}
|
||||
|
||||
/*
|
||||
* Install a signal handler with the `restartable' flag set dependent upon
|
||||
* which signal is being set. (This is a wrapper to xsignal_restart())
|
||||
*/
|
||||
sigfunc
|
||||
xsignal(int sig, sigfunc func)
|
||||
{
|
||||
int restartable;
|
||||
|
||||
/*
|
||||
* Some signals print output or change the state of the process.
|
||||
* There should be restartable, so that reads and writes are
|
||||
* not affected. Some signals should cause program flow to change;
|
||||
* these signals should not be restartable, so that the system call
|
||||
* will return with EINTR, and the program will go do something
|
||||
* different. If the signal handler calls longjmp() or siglongjmp(),
|
||||
* it doesn't matter if it's restartable.
|
||||
*/
|
||||
|
||||
switch(sig) {
|
||||
#ifdef SIGINFO
|
||||
case SIGINFO:
|
||||
#endif
|
||||
case SIGQUIT:
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:
|
||||
case SIGWINCH:
|
||||
restartable = 1;
|
||||
break;
|
||||
|
||||
case SIGALRM:
|
||||
case SIGINT:
|
||||
case SIGPIPE:
|
||||
restartable = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* This is unpleasant, but I don't know what would be better.
|
||||
* Right now, this "can't happen"
|
||||
*/
|
||||
errx(1, "xsignal_restart: called with signal %d", sig);
|
||||
}
|
||||
|
||||
return(xsignal_restart(sig, func, restartable));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: progressbar.h,v 1.8.38.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: progressbar.h,v 1.8.38.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996-2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1996-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -68,7 +68,6 @@ int foregroundproc(void);
|
|||
void alarmtimer(int);
|
||||
void progressmeter(int);
|
||||
sigfunc xsignal(int, sigfunc);
|
||||
sigfunc xsignal_restart(int, sigfunc, int);
|
||||
|
||||
#ifndef STANDALONE_PROGRESS
|
||||
void psummary(int);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ssl.c,v 1.5.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: ssl.c,v 1.5.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
|
||||
|
@ -34,12 +34,17 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: ssl.c,v 1.5.8.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: ssl.c,v 1.5.8.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/select.h>
|
||||
|
@ -47,11 +52,14 @@ __RCSID("$NetBSD: ssl.c,v 1.5.8.2 2022/09/12 15:05:21 martin Exp $");
|
|||
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#ifdef WITH_SSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
#include "ssl.h"
|
||||
|
||||
|
@ -74,7 +82,9 @@ struct fetch_connect {
|
|||
int issock;
|
||||
int iserr;
|
||||
int iseof;
|
||||
#ifdef WITH_SSL
|
||||
SSL *ssl; /* SSL handle */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -87,6 +97,7 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
struct timeval now, timeout, delta;
|
||||
fd_set writefds;
|
||||
ssize_t len, total;
|
||||
int fd = conn->sd;
|
||||
int r;
|
||||
|
||||
if (quit_time > 0) {
|
||||
|
@ -97,8 +108,8 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
|
||||
total = 0;
|
||||
while (iovcnt > 0) {
|
||||
while (quit_time > 0 && !FD_ISSET(conn->sd, &writefds)) {
|
||||
FD_SET(conn->sd, &writefds);
|
||||
while (quit_time > 0 && !FD_ISSET(fd, &writefds)) {
|
||||
FD_SET(fd, &writefds);
|
||||
gettimeofday(&now, NULL);
|
||||
delta.tv_sec = timeout.tv_sec - now.tv_sec;
|
||||
delta.tv_usec = timeout.tv_usec - now.tv_usec;
|
||||
|
@ -111,7 +122,7 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
return -1;
|
||||
}
|
||||
errno = 0;
|
||||
r = select(conn->sd + 1, NULL, &writefds, NULL, &delta);
|
||||
r = select(fd + 1, NULL, &writefds, NULL, &delta);
|
||||
if (r == -1) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
@ -119,10 +130,12 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
}
|
||||
}
|
||||
errno = 0;
|
||||
#ifdef WITH_SSL
|
||||
if (conn->ssl != NULL)
|
||||
len = SSL_write(conn->ssl, iov->iov_base, iov->iov_len);
|
||||
else
|
||||
len = writev(conn->sd, iov, iovcnt);
|
||||
#endif
|
||||
len = writev(fd, iov, iovcnt);
|
||||
if (len == 0) {
|
||||
/* we consider a short write a failure */
|
||||
/* XXX perhaps we shouldn't in the SSL case */
|
||||
|
@ -130,7 +143,7 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
if (errno == EINTR)
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
|
@ -148,11 +161,8 @@ fetch_writev(struct fetch_connect *conn, struct iovec *iov, int iovcnt)
|
|||
return total;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write to a connection w/ timeout
|
||||
*/
|
||||
static int
|
||||
fetch_write(struct fetch_connect *conn, const char *str, size_t len)
|
||||
static ssize_t
|
||||
fetch_write(const void *str, size_t len, struct fetch_connect *conn)
|
||||
{
|
||||
struct iovec iov[1];
|
||||
|
||||
|
@ -181,7 +191,7 @@ fetch_printf(struct fetch_connect *conn, const char *fmt, ...)
|
|||
return -1;
|
||||
}
|
||||
|
||||
r = fetch_write(conn, msg, len);
|
||||
r = fetch_write(msg, len, conn);
|
||||
free(msg);
|
||||
return r;
|
||||
}
|
||||
|
@ -210,15 +220,16 @@ fetch_clearerr(struct fetch_connect *conn)
|
|||
int
|
||||
fetch_flush(struct fetch_connect *conn)
|
||||
{
|
||||
int v;
|
||||
|
||||
if (conn->issock) {
|
||||
int fd = conn->sd;
|
||||
int v;
|
||||
#ifdef TCP_NOPUSH
|
||||
v = 0;
|
||||
setsockopt(conn->sd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NOPUSH, &v, sizeof(v));
|
||||
#endif
|
||||
v = 1;
|
||||
setsockopt(conn->sd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &v, sizeof(v));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -271,44 +282,44 @@ fetch_fdopen(int sd, const char *fmode)
|
|||
int
|
||||
fetch_close(struct fetch_connect *conn)
|
||||
{
|
||||
int rv = 0;
|
||||
if (conn == NULL)
|
||||
return 0;
|
||||
|
||||
if (conn != NULL) {
|
||||
fetch_flush(conn);
|
||||
SSL_free(conn->ssl);
|
||||
rv = close(conn->sd);
|
||||
if (rv < 0) {
|
||||
errno = rv;
|
||||
rv = EOF;
|
||||
}
|
||||
free(conn->cache.buf);
|
||||
free(conn->buf);
|
||||
free(conn);
|
||||
}
|
||||
return rv;
|
||||
fetch_flush(conn);
|
||||
#ifdef WITH_SSL
|
||||
SSL_free(conn->ssl);
|
||||
#endif
|
||||
close(conn->sd);
|
||||
free(conn->cache.buf);
|
||||
free(conn->buf);
|
||||
free(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FETCH_WRITE_WAIT -3
|
||||
#define FETCH_READ_WAIT -2
|
||||
#define FETCH_READ_ERROR -1
|
||||
|
||||
#ifdef WITH_SSL
|
||||
static ssize_t
|
||||
fetch_ssl_read(SSL *ssl, void *buf, size_t len)
|
||||
{
|
||||
ssize_t rlen;
|
||||
int ssl_err;
|
||||
|
||||
rlen = SSL_read(ssl, buf, len);
|
||||
if (rlen < 0) {
|
||||
ssl_err = SSL_get_error(ssl, rlen);
|
||||
if (ssl_err == SSL_ERROR_WANT_READ ||
|
||||
ssl_err == SSL_ERROR_WANT_WRITE) {
|
||||
return FETCH_READ_WAIT;
|
||||
}
|
||||
if (rlen >= 0)
|
||||
return rlen;
|
||||
|
||||
switch (SSL_get_error(ssl, rlen)) {
|
||||
case SSL_ERROR_WANT_READ:
|
||||
return FETCH_READ_WAIT;
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
return FETCH_WRITE_WAIT;
|
||||
default:
|
||||
ERR_print_errors_fp(ttyout);
|
||||
return FETCH_READ_ERROR;
|
||||
}
|
||||
return rlen;
|
||||
}
|
||||
#endif /* WITH_SSL */
|
||||
|
||||
static ssize_t
|
||||
fetch_nonssl_read(int sd, void *buf, size_t len)
|
||||
|
@ -316,7 +327,7 @@ fetch_nonssl_read(int sd, void *buf, size_t len)
|
|||
ssize_t rlen;
|
||||
|
||||
rlen = read(sd, buf, len);
|
||||
if (rlen < 0) {
|
||||
if (rlen == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return FETCH_READ_WAIT;
|
||||
return FETCH_READ_ERROR;
|
||||
|
@ -347,14 +358,49 @@ fetch_cache_data(struct fetch_connect *conn, char *src, size_t nbytes)
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
static int
|
||||
fetch_wait(struct fetch_connect *conn, ssize_t rlen, struct timeval *timeout)
|
||||
{
|
||||
struct timeval now, delta;
|
||||
int fd = conn->sd;
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
while (!FD_ISSET(fd, &fds)) {
|
||||
FD_SET(fd, &fds);
|
||||
if (quit_time > 0) {
|
||||
gettimeofday(&now, NULL);
|
||||
if (!timercmp(timeout, &now, >)) {
|
||||
fprintf(ttyout, "\r\n%s: transfer aborted"
|
||||
" because stalled for %lu sec.\r\n",
|
||||
getprogname(), (unsigned long)quit_time);
|
||||
errno = ETIMEDOUT;
|
||||
conn->iserr = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
timersub(timeout, &now, &delta);
|
||||
}
|
||||
errno = 0;
|
||||
if (select(fd + 1,
|
||||
rlen == FETCH_READ_WAIT ? &fds : NULL,
|
||||
rlen == FETCH_WRITE_WAIT ? &fds : NULL,
|
||||
NULL, quit_time > 0 ? &delta : NULL) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
conn->iserr = errno;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
|
||||
{
|
||||
struct timeval now, timeout, delta;
|
||||
fd_set readfds;
|
||||
ssize_t rlen, total;
|
||||
size_t len;
|
||||
char *start, *buf;
|
||||
struct timeval timeout;
|
||||
|
||||
if (quit_time > 0) {
|
||||
gettimeofday(&timeout, NULL);
|
||||
|
@ -402,40 +448,31 @@ fetch_read(void *ptr, size_t size, size_t nmemb, struct fetch_connect *conn)
|
|||
* In the non-SSL case, it may improve performance (very
|
||||
* slightly) when reading small amounts of data.
|
||||
*/
|
||||
#ifdef WITH_SSL
|
||||
if (conn->ssl != NULL)
|
||||
rlen = fetch_ssl_read(conn->ssl, buf, len);
|
||||
else
|
||||
#endif
|
||||
rlen = fetch_nonssl_read(conn->sd, buf, len);
|
||||
if (rlen == 0) {
|
||||
switch (rlen) {
|
||||
case 0:
|
||||
conn->iseof = 1;
|
||||
return total;
|
||||
case FETCH_READ_ERROR:
|
||||
conn->iserr = errno;
|
||||
if (errno == EINTR)
|
||||
fetch_cache_data(conn, start, total);
|
||||
return 0;
|
||||
case FETCH_READ_WAIT:
|
||||
case FETCH_WRITE_WAIT:
|
||||
if (fetch_wait(conn, rlen, &timeout) == -1)
|
||||
return 0;
|
||||
break;
|
||||
} else if (rlen > 0) {
|
||||
default:
|
||||
len -= rlen;
|
||||
buf += rlen;
|
||||
total += rlen;
|
||||
continue;
|
||||
} else if (rlen == FETCH_READ_ERROR) {
|
||||
if (errno == EINTR)
|
||||
fetch_cache_data(conn, start, total);
|
||||
return -1;
|
||||
}
|
||||
FD_ZERO(&readfds);
|
||||
while (!FD_ISSET(conn->sd, &readfds)) {
|
||||
FD_SET(conn->sd, &readfds);
|
||||
if (quit_time > 0) {
|
||||
gettimeofday(&now, NULL);
|
||||
if (!timercmp(&timeout, &now, >)) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
timersub(&timeout, &now, &delta);
|
||||
}
|
||||
errno = 0;
|
||||
if (select(conn->sd + 1, &readfds, NULL, NULL,
|
||||
quit_time > 0 ? &delta : NULL) < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
|
@ -450,7 +487,7 @@ char *
|
|||
fetch_getln(char *str, int size, struct fetch_connect *conn)
|
||||
{
|
||||
size_t tmpsize;
|
||||
ssize_t len;
|
||||
size_t len;
|
||||
char c;
|
||||
|
||||
if (conn->buf == NULL) {
|
||||
|
@ -473,13 +510,12 @@ fetch_getln(char *str, int size, struct fetch_connect *conn)
|
|||
conn->buflen = 0;
|
||||
do {
|
||||
len = fetch_read(&c, sizeof(c), 1, conn);
|
||||
if (len == -1) {
|
||||
conn->iserr = 1;
|
||||
return NULL;
|
||||
}
|
||||
if (len == 0) {
|
||||
conn->iseof = 1;
|
||||
break;
|
||||
if (conn->iserr)
|
||||
return NULL;
|
||||
if (conn->iseof)
|
||||
break;
|
||||
abort();
|
||||
}
|
||||
conn->buf[conn->buflen++] = c;
|
||||
if (conn->buflen == conn->bufsize) {
|
||||
|
@ -531,8 +567,8 @@ fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
|
|||
} else if (len == buflen - 1) { /* line too long */
|
||||
while (1) {
|
||||
char c;
|
||||
ssize_t rlen = fetch_read(&c, sizeof(c), 1, conn);
|
||||
if (rlen <= 0 || c == '\n')
|
||||
size_t rlen = fetch_read(&c, sizeof(c), 1, conn);
|
||||
if (rlen == 0 || c == '\n')
|
||||
break;
|
||||
}
|
||||
if (errormsg)
|
||||
|
@ -545,12 +581,15 @@ fetch_getline(struct fetch_connect *conn, char *buf, size_t buflen,
|
|||
return len;
|
||||
}
|
||||
|
||||
#ifdef WITH_SSL
|
||||
void *
|
||||
fetch_start_ssl(int sock, const char *servername)
|
||||
{
|
||||
SSL *ssl;
|
||||
SSL_CTX *ctx;
|
||||
X509_VERIFY_PARAM *param;
|
||||
int ret, ssl_err;
|
||||
int verify = 0; // getenv("NO_CERT_VERIFY") == NULL;
|
||||
|
||||
/* Init the SSL library and context */
|
||||
if (!SSL_library_init()){
|
||||
|
@ -562,6 +601,10 @@ fetch_start_ssl(int sock, const char *servername)
|
|||
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||
if (verify) {
|
||||
SSL_CTX_set_default_verify_paths(ctx);
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
}
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
if (ssl == NULL){
|
||||
|
@ -569,6 +612,19 @@ fetch_start_ssl(int sock, const char *servername)
|
|||
SSL_CTX_free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (verify) {
|
||||
param = SSL_get0_param(ssl);
|
||||
if (!X509_VERIFY_PARAM_set1_host(param, servername,
|
||||
strlen(servername))) {
|
||||
fprintf(ttyout, "SSL verification setup failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Enable peer verification, (using the default callback) */
|
||||
SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
|
||||
}
|
||||
|
||||
SSL_set_fd(ssl, sock);
|
||||
if (!SSL_set_tlsext_host_name(ssl, __UNCONST(servername))) {
|
||||
fprintf(ttyout, "SSL hostname setting failed\n");
|
||||
|
@ -605,10 +661,13 @@ fetch_start_ssl(int sock, const char *servername)
|
|||
|
||||
return ssl;
|
||||
}
|
||||
#endif /* WITH_SSL */
|
||||
|
||||
|
||||
void
|
||||
fetch_set_ssl(struct fetch_connect *conn, void *ssl)
|
||||
{
|
||||
#ifdef WITH_SSL
|
||||
conn->ssl = ssl;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: ssl.h,v 1.3.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: ssl.h,v 1.3.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2012 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 2012-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -25,7 +25,6 @@
|
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifdef WITH_SSL
|
||||
|
||||
#define FETCH struct fetch_connect
|
||||
struct fetch_connect;
|
||||
|
@ -38,26 +37,8 @@ int fetch_flush(struct fetch_connect *);
|
|||
struct fetch_connect *fetch_open(const char *, const char *);
|
||||
struct fetch_connect *fetch_fdopen(int, const char *);
|
||||
int fetch_close(struct fetch_connect *);
|
||||
ssize_t fetch_read(void *, size_t, size_t, struct fetch_connect *);
|
||||
size_t fetch_read(void *, size_t, size_t, struct fetch_connect *);
|
||||
char *fetch_getln(char *, int, struct fetch_connect *);
|
||||
int fetch_getline(struct fetch_connect *, char *, size_t, const char **);
|
||||
void fetch_set_ssl(struct fetch_connect *, void *);
|
||||
void *fetch_start_ssl(int, const char *);
|
||||
|
||||
#else /* !WITH_SSL */
|
||||
|
||||
#define FETCH FILE
|
||||
|
||||
#define fetch_printf fprintf
|
||||
#define fetch_fileno fileno
|
||||
#define fetch_error ferror
|
||||
#define fetch_flush fflush
|
||||
#define fetch_open fopen
|
||||
#define fetch_fdopen fdopen
|
||||
#define fetch_close fclose
|
||||
#define fetch_read fread
|
||||
#define fetch_getln fgets
|
||||
#define fetch_getline get_line
|
||||
#define fetch_set_ssl(a, b)
|
||||
|
||||
#endif /* !WITH_SSL */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: util.c,v 1.158.22.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: util.c,v 1.158.22.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1997-2020 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: util.c,v 1.158.22.2 2022/09/12 15:05:21 martin Exp $");
|
||||
__RCSID("$NetBSD: util.c,v 1.158.22.3 2022/09/12 17:08:13 martin Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
|
@ -171,7 +171,7 @@ parse_feat(const char *fline)
|
|||
* work-around broken ProFTPd servers that can't
|
||||
* even obey RFC 2389.
|
||||
*/
|
||||
while (*fline && isspace((int)*fline))
|
||||
while (*fline && isspace((unsigned char)*fline))
|
||||
fline++;
|
||||
|
||||
if (strcasecmp(fline, "MDTM") == 0)
|
||||
|
@ -324,9 +324,10 @@ intr(int signo)
|
|||
/*
|
||||
* Signal handler for lost connections; cleanup various elements of
|
||||
* the connection state, and call cleanuppeer() to finish it off.
|
||||
* This function is not signal safe, so exit if called by a signal.
|
||||
*/
|
||||
void
|
||||
lostpeer(int dummy)
|
||||
lostpeer(int signo)
|
||||
{
|
||||
int oerrno = errno;
|
||||
|
||||
|
@ -356,6 +357,9 @@ lostpeer(int dummy)
|
|||
proxflag = 0;
|
||||
pswitch(0);
|
||||
cleanuppeer();
|
||||
if (signo) {
|
||||
errx(1, "lostpeer due to signal %d", signo);
|
||||
}
|
||||
errno = oerrno;
|
||||
}
|
||||
|
||||
|
@ -478,7 +482,8 @@ ftp_login(const char *host, const char *luser, const char *lpass)
|
|||
}
|
||||
}
|
||||
updatelocalcwd();
|
||||
updateremotecwd();
|
||||
remotecwd[0] = '\0';
|
||||
remcwdvalid = 0;
|
||||
|
||||
cleanup_ftp_login:
|
||||
FREEPTR(fuser);
|
||||
|
@ -615,7 +620,7 @@ remglob(char *argv[], int doswitch, const char **errbuf)
|
|||
* return value. Can't control multiple values being expanded from the
|
||||
* expression, we return only the first.
|
||||
* Returns NULL on error, or a pointer to a buffer containing the filename
|
||||
* that's the caller's responsiblity to free(3) when finished with.
|
||||
* that's the caller's responsibility to free(3) when finished with.
|
||||
*/
|
||||
char *
|
||||
globulize(const char *pattern)
|
||||
|
@ -726,7 +731,7 @@ remotemodtime(const char *file, int noisy)
|
|||
*frac++ = '\0';
|
||||
if (strlen(timestr) == 15 && strncmp(timestr, "191", 3) == 0) {
|
||||
/*
|
||||
* XXX: Workaround for lame ftpd's that return
|
||||
* XXX: Workaround for buggy ftp servers that return
|
||||
* `19100' instead of `2000'
|
||||
*/
|
||||
fprintf(ttyout,
|
||||
|
@ -835,6 +840,7 @@ updateremotecwd(void)
|
|||
size_t i;
|
||||
char *cp;
|
||||
|
||||
remcwdvalid = 1; /* whether it works or not, we are done */
|
||||
overbose = verbose;
|
||||
ocode = code;
|
||||
if (ftp_debug == 0)
|
||||
|
@ -1174,6 +1180,8 @@ formatbuf(char *buf, size_t len, const char *src)
|
|||
case '/':
|
||||
case '.':
|
||||
case 'c':
|
||||
if (connected && !remcwdvalid)
|
||||
updateremotecwd();
|
||||
p2 = connected ? remotecwd : "";
|
||||
updirs = pdirs = 0;
|
||||
|
||||
|
@ -1487,6 +1495,7 @@ ftp_poll(struct pollfd *fds, int nfds, int timeout)
|
|||
return poll(fds, nfds, timeout);
|
||||
}
|
||||
|
||||
#ifndef SMALL
|
||||
/*
|
||||
* malloc() with inbuilt error checking
|
||||
*/
|
||||
|
@ -1541,3 +1550,4 @@ ftp_strdup(const char *str)
|
|||
err(1, "Unable to allocate memory for string copy");
|
||||
return (s);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* $NetBSD: version.h,v 1.87.8.2 2022/09/12 15:05:21 martin Exp $ */
|
||||
/* $NetBSD: version.h,v 1.87.8.3 2022/09/12 17:08:13 martin Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999-2015 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1999-2021 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
|
@ -34,5 +34,5 @@
|
|||
#endif
|
||||
|
||||
#ifndef FTP_VERSION
|
||||
#define FTP_VERSION "20150912"
|
||||
#define FTP_VERSION "20210826"
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue