2020-06-08 04:33:27 +03:00
|
|
|
/* $NetBSD: util.c,v 1.161 2020/06/08 01:33:27 lukem Exp $ */
|
1998-07-10 08:39:03 +04:00
|
|
|
|
|
|
|
/*-
|
2020-06-08 04:33:27 +03:00
|
|
|
* Copyright (c) 1997-2020 The NetBSD Foundation, Inc.
|
1998-07-10 08:39:03 +04:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
1999-10-05 05:16:11 +04:00
|
|
|
* by Luke Mewburn.
|
1998-07-10 08:39:03 +04:00
|
|
|
*
|
1999-01-24 05:39:29 +03:00
|
|
|
* This code is derived from software contributed to The NetBSD Foundation
|
1999-10-05 05:16:11 +04:00
|
|
|
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
|
|
|
* NASA Ames Research Center.
|
1999-01-24 05:39:29 +03:00
|
|
|
*
|
1998-07-10 08:39:03 +04:00
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
|
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 1985, 1989, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
2003-08-07 15:13:06 +04:00
|
|
|
* 3. Neither the name of the University nor the names of its contributors
|
1997-01-19 17:19:02 +03:00
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <sys/cdefs.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#ifndef lint
|
2020-06-08 04:33:27 +03:00
|
|
|
__RCSID("$NetBSD: util.c,v 1.161 2020/06/08 01:33:27 lukem Exp $");
|
1997-01-19 17:19:02 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FTP User Program -- Misc support routines
|
|
|
|
*/
|
2005-01-03 12:50:09 +03:00
|
|
|
#include <sys/param.h>
|
1998-07-10 08:39:03 +04:00
|
|
|
#include <sys/socket.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/time.h>
|
1999-10-13 06:47:54 +04:00
|
|
|
#include <netinet/in.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <arpa/ftp.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <err.h>
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
#include <errno.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <glob.h>
|
1998-05-20 04:55:52 +04:00
|
|
|
#include <signal.h>
|
2005-05-26 06:59:34 +04:00
|
|
|
#include <libgen.h>
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <limits.h>
|
2010-03-05 00:40:53 +03:00
|
|
|
#include <locale.h>
|
2000-09-08 15:54:53 +04:00
|
|
|
#include <netdb.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <stdio.h>
|
1997-07-20 13:45:35 +04:00
|
|
|
#include <stdlib.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <string.h>
|
1999-09-29 04:44:01 +04:00
|
|
|
#include <termios.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <time.h>
|
1997-11-01 17:36:49 +03:00
|
|
|
#include <tzfile.h>
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "ftp_var.h"
|
|
|
|
|
|
|
|
/*
|
2000-06-15 17:08:23 +04:00
|
|
|
* Connect to peer server and auto-login, if possible.
|
1997-01-19 17:19:02 +03:00
|
|
|
*/
|
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
setpeer(int argc, char *argv[])
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
|
|
|
char *host;
|
2009-04-12 14:18:52 +04:00
|
|
|
const char *port;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
1999-10-24 16:31:36 +04:00
|
|
|
if (argc == 0)
|
|
|
|
goto usage;
|
1997-01-19 17:19:02 +03:00
|
|
|
if (connected) {
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Already connected to %s, use close first.\n",
|
1997-03-13 09:23:11 +03:00
|
|
|
hostname);
|
1997-01-19 17:19:02 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (argc < 2)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)another(&argc, &argv, "to");
|
1997-01-19 17:19:02 +03:00
|
|
|
if (argc < 2 || argc > 3) {
|
1999-10-24 16:31:36 +04:00
|
|
|
usage:
|
2005-06-29 06:31:19 +04:00
|
|
|
UPRINTF("usage: %s host-name [port]\n", argv[0]);
|
1997-01-19 17:19:02 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1997-08-18 14:20:13 +04:00
|
|
|
if (gatemode)
|
|
|
|
port = gateport;
|
|
|
|
else
|
|
|
|
port = ftpport;
|
1999-07-02 12:07:40 +04:00
|
|
|
if (argc > 2)
|
1999-11-09 10:26:50 +03:00
|
|
|
port = argv[2];
|
1997-08-18 14:20:13 +04:00
|
|
|
|
|
|
|
if (gatemode) {
|
|
|
|
if (gateserver == NULL || *gateserver == '\0')
|
2007-04-17 09:52:03 +04:00
|
|
|
errx(1, "main: gateserver not defined");
|
1997-08-18 14:20:13 +04:00
|
|
|
host = hookup(gateserver, port);
|
|
|
|
} else
|
|
|
|
host = hookup(argv[1], port);
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
if (host) {
|
1999-06-02 06:03:57 +04:00
|
|
|
if (gatemode && verbose) {
|
|
|
|
fprintf(ttyout,
|
|
|
|
"Connecting via pass-through server %s\n",
|
|
|
|
gateserver);
|
1997-08-18 14:20:13 +04:00
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
connected = 1;
|
|
|
|
/*
|
|
|
|
* Set up defaults for FTP.
|
|
|
|
*/
|
1999-09-28 10:47:38 +04:00
|
|
|
(void)strlcpy(typename, "ascii", sizeof(typename));
|
|
|
|
type = TYPE_A;
|
1997-01-19 17:19:02 +03:00
|
|
|
curtype = TYPE_A;
|
1999-09-28 10:47:38 +04:00
|
|
|
(void)strlcpy(formname, "non-print", sizeof(formname));
|
|
|
|
form = FORM_N;
|
|
|
|
(void)strlcpy(modename, "stream", sizeof(modename));
|
|
|
|
mode = MODE_S;
|
|
|
|
(void)strlcpy(structname, "file", sizeof(structname));
|
|
|
|
stru = STRU_F;
|
|
|
|
(void)strlcpy(bytename, "8", sizeof(bytename));
|
|
|
|
bytesize = 8;
|
1997-01-19 17:19:02 +03:00
|
|
|
if (autologin)
|
1998-07-22 20:06:27 +04:00
|
|
|
(void)ftp_login(argv[1], NULL, NULL);
|
2000-06-15 17:08:23 +04:00
|
|
|
}
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
static void
|
2009-04-12 11:07:41 +04:00
|
|
|
parse_feat(const char *fline)
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
{
|
|
|
|
|
2003-07-31 10:57:07 +04:00
|
|
|
/*
|
|
|
|
* work-around broken ProFTPd servers that can't
|
2010-03-05 10:41:10 +03:00
|
|
|
* even obey RFC 2389.
|
2003-07-31 10:57:07 +04:00
|
|
|
*/
|
2009-04-12 11:07:41 +04:00
|
|
|
while (*fline && isspace((int)*fline))
|
|
|
|
fline++;
|
2003-07-31 10:57:07 +04:00
|
|
|
|
2009-04-12 11:07:41 +04:00
|
|
|
if (strcasecmp(fline, "MDTM") == 0)
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
features[FEAT_MDTM] = 1;
|
2009-04-12 11:07:41 +04:00
|
|
|
else if (strncasecmp(fline, "MLST", sizeof("MLST") - 1) == 0) {
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
features[FEAT_MLST] = 1;
|
2009-04-12 11:07:41 +04:00
|
|
|
} else if (strcasecmp(fline, "REST STREAM") == 0)
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
features[FEAT_REST_STREAM] = 1;
|
2009-04-12 11:07:41 +04:00
|
|
|
else if (strcasecmp(fline, "SIZE") == 0)
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
features[FEAT_SIZE] = 1;
|
2009-04-12 11:07:41 +04:00
|
|
|
else if (strcasecmp(fline, "TVFS") == 0)
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
features[FEAT_TVFS] = 1;
|
|
|
|
}
|
|
|
|
|
2000-06-15 17:08:23 +04:00
|
|
|
/*
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
* Determine the remote system type (SYST) and features (FEAT).
|
2000-06-15 17:08:23 +04:00
|
|
|
* Call after a successful login (i.e, connected = -1)
|
|
|
|
*/
|
|
|
|
void
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
getremoteinfo(void)
|
2000-06-15 17:08:23 +04:00
|
|
|
{
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
int overbose, i;
|
2000-06-15 17:08:23 +04:00
|
|
|
|
|
|
|
overbose = verbose;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (ftp_debug == 0)
|
2000-06-15 17:08:23 +04:00
|
|
|
verbose = -1;
|
|
|
|
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
/* determine remote system type */
|
|
|
|
if (command("SYST") == COMPLETE) {
|
|
|
|
if (overbose) {
|
2013-02-20 03:29:15 +04:00
|
|
|
int os_len = strcspn(reply_string + 4, " \r\n\t");
|
|
|
|
if (os_len > 1 && reply_string[4 + os_len - 1] == '.')
|
|
|
|
os_len--;
|
|
|
|
fprintf(ttyout, "Remote system type is %.*s.\n",
|
|
|
|
os_len, reply_string + 4);
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
}
|
2013-02-20 03:29:15 +04:00
|
|
|
/*
|
|
|
|
* Decide whether we should default to bninary.
|
|
|
|
* Traditionally checked for "215 UNIX Type: L8", but
|
|
|
|
* some printers report "Linux" ! so be more forgiving.
|
|
|
|
* In reality we probably almost never want text any more.
|
|
|
|
*/
|
|
|
|
if (!strncasecmp(reply_string + 4, "unix", 4) ||
|
|
|
|
!strncasecmp(reply_string + 4, "linux", 5)) {
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
if (proxy)
|
|
|
|
unix_proxy = 1;
|
|
|
|
else
|
|
|
|
unix_server = 1;
|
|
|
|
/*
|
|
|
|
* Set type to 0 (not specified by user),
|
|
|
|
* meaning binary by default, but don't bother
|
|
|
|
* telling server. We can use binary
|
|
|
|
* for text files unless changed by the user.
|
|
|
|
*/
|
|
|
|
type = 0;
|
|
|
|
(void)strlcpy(typename, "binary", sizeof(typename));
|
|
|
|
if (overbose)
|
|
|
|
fprintf(ttyout,
|
|
|
|
"Using %s mode to transfer files.\n",
|
|
|
|
typename);
|
|
|
|
} else {
|
|
|
|
if (proxy)
|
|
|
|
unix_proxy = 0;
|
|
|
|
else
|
|
|
|
unix_server = 0;
|
|
|
|
if (overbose &&
|
|
|
|
!strncmp(reply_string, "215 TOPS20", 10))
|
|
|
|
fputs(
|
1998-06-04 12:28:35 +04:00
|
|
|
"Remember to set tenex mode when transferring binary files from this machine.\n",
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
ttyout);
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
|
|
|
|
/* determine features (if any) */
|
|
|
|
for (i = 0; i < FEAT_max; i++)
|
|
|
|
features[i] = -1;
|
|
|
|
reply_callback = parse_feat;
|
|
|
|
if (command("FEAT") == COMPLETE) {
|
|
|
|
for (i = 0; i < FEAT_max; i++) {
|
|
|
|
if (features[i] == -1)
|
|
|
|
features[i] = 0;
|
|
|
|
}
|
|
|
|
features[FEAT_FEAT] = 1;
|
|
|
|
} else
|
|
|
|
features[FEAT_FEAT] = 0;
|
2005-06-29 06:31:19 +04:00
|
|
|
#ifndef NO_DEBUG
|
2006-01-31 23:05:35 +03:00
|
|
|
if (ftp_debug) {
|
2003-07-31 10:57:07 +04:00
|
|
|
#define DEBUG_FEAT(x) fprintf(ttyout, "features[" #x "] = %d\n", features[(x)])
|
|
|
|
DEBUG_FEAT(FEAT_FEAT);
|
|
|
|
DEBUG_FEAT(FEAT_MDTM);
|
|
|
|
DEBUG_FEAT(FEAT_MLST);
|
|
|
|
DEBUG_FEAT(FEAT_REST_STREAM);
|
|
|
|
DEBUG_FEAT(FEAT_SIZE);
|
|
|
|
DEBUG_FEAT(FEAT_TVFS);
|
|
|
|
#undef DEBUG_FEAT
|
|
|
|
}
|
2005-06-29 06:31:19 +04:00
|
|
|
#endif
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
reply_callback = NULL;
|
|
|
|
|
2000-06-15 17:08:23 +04:00
|
|
|
verbose = overbose;
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
|
1999-10-24 16:31:36 +04:00
|
|
|
/*
|
|
|
|
* Reset the various variables that indicate connection state back to
|
|
|
|
* disconnected settings.
|
|
|
|
* The caller is responsible for issuing any commands to the remote server
|
|
|
|
* to perform a clean shutdown before this is invoked.
|
|
|
|
*/
|
|
|
|
void
|
2000-06-15 17:08:23 +04:00
|
|
|
cleanuppeer(void)
|
1999-10-24 16:31:36 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
if (cout)
|
|
|
|
(void)fclose(cout);
|
|
|
|
cout = NULL;
|
|
|
|
connected = 0;
|
2000-06-15 17:08:23 +04:00
|
|
|
unix_server = 0;
|
|
|
|
unix_proxy = 0;
|
1999-10-24 16:31:36 +04:00
|
|
|
/*
|
|
|
|
* determine if anonftp was specifically set with -a
|
|
|
|
* (1), or implicitly set by auto_fetch() (2). in the
|
|
|
|
* latter case, disable after the current xfer
|
|
|
|
*/
|
|
|
|
if (anonftp == 2)
|
|
|
|
anonftp = 0;
|
|
|
|
data = -1;
|
|
|
|
epsv4bad = 0;
|
2008-05-10 04:05:31 +04:00
|
|
|
epsv6bad = 0;
|
1999-11-11 05:53:02 +03:00
|
|
|
if (username)
|
|
|
|
free(username);
|
1999-11-27 04:00:06 +03:00
|
|
|
username = NULL;
|
1999-10-24 16:31:36 +04:00
|
|
|
if (!proxy)
|
|
|
|
macnum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Top-level signal handler for interrupted commands.
|
|
|
|
*/
|
|
|
|
void
|
2004-07-20 14:40:21 +04:00
|
|
|
intr(int signo)
|
1999-10-24 16:31:36 +04:00
|
|
|
{
|
|
|
|
|
2004-07-20 14:40:21 +04:00
|
|
|
sigint_raised = 1;
|
1999-10-24 16:31:36 +04:00
|
|
|
alarmtimer(0);
|
|
|
|
if (fromatty)
|
|
|
|
write(fileno(ttyout), "\n", 1);
|
|
|
|
siglongjmp(toplevel, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Signal handler for lost connections; cleanup various elements of
|
|
|
|
* the connection state, and call cleanuppeer() to finish it off.
|
2020-06-08 04:33:27 +03:00
|
|
|
* This function is not signal safe, so exit if called by a signal.
|
1999-10-24 16:31:36 +04:00
|
|
|
*/
|
|
|
|
void
|
2020-06-08 04:33:27 +03:00
|
|
|
lostpeer(int signo)
|
1999-10-24 16:31:36 +04:00
|
|
|
{
|
|
|
|
int oerrno = errno;
|
|
|
|
|
|
|
|
alarmtimer(0);
|
|
|
|
if (connected) {
|
|
|
|
if (cout != NULL) {
|
|
|
|
(void)shutdown(fileno(cout), 1+1);
|
|
|
|
(void)fclose(cout);
|
|
|
|
cout = NULL;
|
|
|
|
}
|
|
|
|
if (data >= 0) {
|
|
|
|
(void)shutdown(data, 1+1);
|
|
|
|
(void)close(data);
|
|
|
|
data = -1;
|
|
|
|
}
|
|
|
|
connected = 0;
|
|
|
|
}
|
|
|
|
pswitch(1);
|
|
|
|
if (connected) {
|
|
|
|
if (cout != NULL) {
|
|
|
|
(void)shutdown(fileno(cout), 1+1);
|
|
|
|
(void)fclose(cout);
|
|
|
|
cout = NULL;
|
|
|
|
}
|
|
|
|
connected = 0;
|
|
|
|
}
|
|
|
|
proxflag = 0;
|
|
|
|
pswitch(0);
|
|
|
|
cleanuppeer();
|
2020-06-08 04:33:27 +03:00
|
|
|
if (signo) {
|
|
|
|
errx(1, "lostpeer due to signal %d", signo);
|
|
|
|
}
|
1999-10-24 16:31:36 +04:00
|
|
|
errno = oerrno;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-04-14 13:09:15 +04:00
|
|
|
/*
|
2000-06-15 17:08:23 +04:00
|
|
|
* Login to remote host, using given username & password if supplied.
|
|
|
|
* Return non-zero if successful.
|
1997-04-14 13:09:15 +04:00
|
|
|
*/
|
|
|
|
int
|
2005-06-10 04:18:46 +04:00
|
|
|
ftp_login(const char *host, const char *luser, const char *lpass)
|
1997-04-14 13:09:15 +04:00
|
|
|
{
|
|
|
|
char tmp[80];
|
2009-04-12 11:07:41 +04:00
|
|
|
char *fuser, *pass, *facct, *p;
|
2007-04-11 04:52:38 +04:00
|
|
|
char emptypass[] = "";
|
2005-06-10 04:18:46 +04:00
|
|
|
const char *errormsg;
|
|
|
|
int n, aflag, rval, nlen;
|
1997-04-14 13:09:15 +04:00
|
|
|
|
2005-06-10 04:18:46 +04:00
|
|
|
aflag = rval = 0;
|
2009-04-12 11:07:41 +04:00
|
|
|
fuser = pass = facct = NULL;
|
2005-06-10 04:18:46 +04:00
|
|
|
if (luser)
|
2009-04-12 11:07:41 +04:00
|
|
|
fuser = ftp_strdup(luser);
|
2005-06-10 04:18:46 +04:00
|
|
|
if (lpass)
|
2006-01-31 23:01:23 +03:00
|
|
|
pass = ftp_strdup(lpass);
|
1997-04-14 13:09:15 +04:00
|
|
|
|
2005-06-29 06:31:19 +04:00
|
|
|
DPRINTF("ftp_login: user `%s' pass `%s' host `%s'\n",
|
2009-04-12 11:07:41 +04:00
|
|
|
STRorNULL(fuser), STRorNULL(pass), STRorNULL(host));
|
1999-11-27 00:41:55 +03:00
|
|
|
|
1997-04-14 13:09:15 +04:00
|
|
|
/*
|
|
|
|
* Set up arguments for an anonymous FTP session, if necessary.
|
|
|
|
*/
|
1999-05-05 20:04:58 +04:00
|
|
|
if (anonftp) {
|
2009-04-12 11:07:41 +04:00
|
|
|
FREEPTR(fuser);
|
2010-03-05 10:41:10 +03:00
|
|
|
fuser = ftp_strdup("anonymous"); /* as per RFC 1635 */
|
2005-06-10 04:18:46 +04:00
|
|
|
FREEPTR(pass);
|
2006-01-31 23:01:23 +03:00
|
|
|
pass = ftp_strdup(getoptionvalue("anonpass"));
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
|
|
|
|
2009-04-12 11:07:41 +04:00
|
|
|
if (ruserpass(host, &fuser, &pass, &facct) < 0) {
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
code = -1;
|
|
|
|
goto cleanup_ftp_login;
|
1999-05-05 20:04:58 +04:00
|
|
|
}
|
|
|
|
|
2009-04-12 11:07:41 +04:00
|
|
|
while (fuser == NULL) {
|
2000-11-15 03:10:59 +03:00
|
|
|
if (localname)
|
|
|
|
fprintf(ttyout, "Name (%s:%s): ", host, localname);
|
1997-04-14 13:09:15 +04:00
|
|
|
else
|
1998-06-04 12:28:35 +04:00
|
|
|
fprintf(ttyout, "Name (%s): ", host);
|
2005-06-10 04:18:46 +04:00
|
|
|
errormsg = NULL;
|
2009-07-13 23:05:39 +04:00
|
|
|
nlen = get_line(stdin, tmp, sizeof(tmp), &errormsg);
|
2005-06-10 04:18:46 +04:00
|
|
|
if (nlen < 0) {
|
|
|
|
fprintf(ttyout, "%s; %s aborted.\n", errormsg, "login");
|
1999-06-02 06:03:57 +04:00
|
|
|
code = -1;
|
|
|
|
goto cleanup_ftp_login;
|
2005-06-10 04:18:46 +04:00
|
|
|
} else if (nlen == 0) {
|
2009-04-12 11:07:41 +04:00
|
|
|
fuser = ftp_strdup(localname);
|
2005-06-10 04:18:46 +04:00
|
|
|
} else {
|
2009-04-12 11:07:41 +04:00
|
|
|
fuser = ftp_strdup(tmp);
|
1999-06-02 06:03:57 +04:00
|
|
|
}
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
1999-06-02 06:03:57 +04:00
|
|
|
|
|
|
|
if (gatemode) {
|
|
|
|
char *nuser;
|
2005-05-19 07:05:04 +04:00
|
|
|
size_t len;
|
1999-06-02 06:03:57 +04:00
|
|
|
|
2009-04-12 11:07:41 +04:00
|
|
|
len = strlen(fuser) + 1 + strlen(host) + 1;
|
2006-01-31 23:01:23 +03:00
|
|
|
nuser = ftp_malloc(len);
|
2009-04-12 11:07:41 +04:00
|
|
|
(void)strlcpy(nuser, fuser, len);
|
1999-09-28 10:47:38 +04:00
|
|
|
(void)strlcat(nuser, "@", len);
|
|
|
|
(void)strlcat(nuser, host, len);
|
2009-04-12 11:07:41 +04:00
|
|
|
FREEPTR(fuser);
|
|
|
|
fuser = nuser;
|
1999-06-02 06:03:57 +04:00
|
|
|
}
|
|
|
|
|
2009-04-12 11:07:41 +04:00
|
|
|
n = command("USER %s", fuser);
|
1997-04-14 13:09:15 +04:00
|
|
|
if (n == CONTINUE) {
|
1999-06-25 03:21:02 +04:00
|
|
|
if (pass == NULL) {
|
2005-06-10 04:18:46 +04:00
|
|
|
p = getpass("Password: ");
|
2007-04-11 04:52:38 +04:00
|
|
|
if (p == NULL)
|
|
|
|
p = emptypass;
|
2006-01-31 23:01:23 +03:00
|
|
|
pass = ftp_strdup(p);
|
2005-06-10 04:18:46 +04:00
|
|
|
memset(p, 0, strlen(p));
|
1999-06-25 03:21:02 +04:00
|
|
|
}
|
1997-04-14 13:09:15 +04:00
|
|
|
n = command("PASS %s", pass);
|
2005-06-10 04:18:46 +04:00
|
|
|
memset(pass, 0, strlen(pass));
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
aflag++;
|
2009-04-12 11:07:41 +04:00
|
|
|
if (facct == NULL) {
|
2005-06-10 04:18:46 +04:00
|
|
|
p = getpass("Account: ");
|
2007-04-11 04:52:38 +04:00
|
|
|
if (p == NULL)
|
|
|
|
p = emptypass;
|
2009-04-12 11:07:41 +04:00
|
|
|
facct = ftp_strdup(p);
|
2005-06-10 04:18:46 +04:00
|
|
|
memset(p, 0, strlen(p));
|
1999-05-05 20:04:58 +04:00
|
|
|
}
|
2009-04-12 11:07:41 +04:00
|
|
|
if (facct[0] == '\0') {
|
2007-04-17 09:52:03 +04:00
|
|
|
warnx("Login failed");
|
1999-06-02 06:03:57 +04:00
|
|
|
goto cleanup_ftp_login;
|
|
|
|
}
|
2009-04-12 11:07:41 +04:00
|
|
|
n = command("ACCT %s", facct);
|
|
|
|
memset(facct, 0, strlen(facct));
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
|
|
|
if ((n != COMPLETE) ||
|
2009-04-12 11:07:41 +04:00
|
|
|
(!aflag && facct != NULL && command("ACCT %s", facct) != COMPLETE)) {
|
2007-04-17 09:52:03 +04:00
|
|
|
warnx("Login failed");
|
1999-05-05 20:04:58 +04:00
|
|
|
goto cleanup_ftp_login;
|
|
|
|
}
|
1999-05-20 18:08:12 +04:00
|
|
|
rval = 1;
|
2009-04-12 11:07:41 +04:00
|
|
|
username = ftp_strdup(fuser);
|
1999-05-20 18:08:12 +04:00
|
|
|
if (proxy)
|
1999-05-05 20:04:58 +04:00
|
|
|
goto cleanup_ftp_login;
|
1999-05-20 18:08:12 +04:00
|
|
|
|
1997-04-14 13:09:15 +04:00
|
|
|
connected = -1;
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
getremoteinfo();
|
1997-04-14 13:09:15 +04:00
|
|
|
for (n = 0; n < macnum; ++n) {
|
|
|
|
if (!strcmp("init", macros[n].mac_name)) {
|
1999-09-28 10:47:38 +04:00
|
|
|
(void)strlcpy(line, "$init", sizeof(line));
|
1997-04-14 13:09:15 +04:00
|
|
|
makeargv();
|
|
|
|
domacro(margc, margv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-01-03 12:50:09 +03:00
|
|
|
updatelocalcwd();
|
2017-11-21 00:11:36 +03:00
|
|
|
remotecwd[0] = '\0';
|
|
|
|
remcwdvalid = 0;
|
1999-11-27 00:41:55 +03:00
|
|
|
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
cleanup_ftp_login:
|
2009-04-12 11:07:41 +04:00
|
|
|
FREEPTR(fuser);
|
2005-06-10 04:18:46 +04:00
|
|
|
if (pass != NULL)
|
|
|
|
memset(pass, 0, strlen(pass));
|
|
|
|
FREEPTR(pass);
|
2009-04-12 11:07:41 +04:00
|
|
|
if (facct != NULL)
|
|
|
|
memset(facct, 0, strlen(facct));
|
|
|
|
FREEPTR(facct);
|
1999-05-05 20:04:58 +04:00
|
|
|
return (rval);
|
1997-04-14 13:09:15 +04:00
|
|
|
}
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/*
|
1997-03-13 09:23:11 +03:00
|
|
|
* `another' gets another argument, and stores the new argc and argv.
|
1999-10-24 16:31:36 +04:00
|
|
|
* It reverts to the top level (via intr()) on EOF/error.
|
1997-01-19 17:19:02 +03:00
|
|
|
*
|
|
|
|
* Returns false if no new arguments have been added.
|
|
|
|
*/
|
|
|
|
int
|
2009-04-12 11:07:41 +04:00
|
|
|
another(int *pargc, char ***pargv, const char *aprompt)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
2005-06-10 04:18:46 +04:00
|
|
|
const char *errormsg;
|
|
|
|
int ret, nlen;
|
|
|
|
size_t len;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
2005-05-19 07:05:04 +04:00
|
|
|
len = strlen(line);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (len >= sizeof(line) - 3) {
|
2005-06-10 04:18:46 +04:00
|
|
|
fputs("Sorry, arguments too long.\n", ttyout);
|
1999-10-09 07:00:55 +04:00
|
|
|
intr(0);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
2009-04-12 11:07:41 +04:00
|
|
|
fprintf(ttyout, "(%s) ", aprompt);
|
1997-01-19 17:19:02 +03:00
|
|
|
line[len++] = ' ';
|
2005-06-10 04:18:46 +04:00
|
|
|
errormsg = NULL;
|
2009-07-13 23:05:39 +04:00
|
|
|
nlen = get_line(stdin, line + len, sizeof(line)-len, &errormsg);
|
2005-06-10 04:18:46 +04:00
|
|
|
if (nlen < 0) {
|
|
|
|
fprintf(ttyout, "%s; %s aborted.\n", errormsg, "operation");
|
1999-10-09 07:00:55 +04:00
|
|
|
intr(0);
|
1999-10-12 10:04:59 +04:00
|
|
|
}
|
2005-06-10 04:18:46 +04:00
|
|
|
len += nlen;
|
1997-01-19 17:19:02 +03:00
|
|
|
makeargv();
|
|
|
|
ret = margc > *pargc;
|
|
|
|
*pargc = margc;
|
|
|
|
*pargv = margv;
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
/*
|
|
|
|
* glob files given in argv[] from the remote server.
|
|
|
|
* if errbuf isn't NULL, store error messages there instead
|
|
|
|
* of writing to the screen.
|
|
|
|
*/
|
1997-01-19 17:19:02 +03:00
|
|
|
char *
|
2005-05-19 06:55:37 +04:00
|
|
|
remglob(char *argv[], int doswitch, const char **errbuf)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
2005-05-19 07:14:52 +04:00
|
|
|
static char buf[MAXPATHLEN];
|
|
|
|
static FILE *ftemp = NULL;
|
|
|
|
static char **args;
|
|
|
|
char temp[MAXPATHLEN];
|
|
|
|
int oldverbose, oldhash, oldprogress, fd;
|
2005-06-10 04:18:46 +04:00
|
|
|
char *cp;
|
2009-04-12 11:07:41 +04:00
|
|
|
const char *rmode;
|
2005-05-19 07:05:04 +04:00
|
|
|
size_t len;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
2005-05-19 07:14:52 +04:00
|
|
|
if (!mflag || !connected) {
|
|
|
|
if (!doglob)
|
|
|
|
args = NULL;
|
|
|
|
else {
|
|
|
|
if (ftemp) {
|
|
|
|
(void)fclose(ftemp);
|
|
|
|
ftemp = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if (!doglob) {
|
|
|
|
if (args == NULL)
|
|
|
|
args = argv;
|
|
|
|
if ((cp = *++args) == NULL)
|
|
|
|
args = NULL;
|
|
|
|
return (cp);
|
|
|
|
}
|
|
|
|
if (ftemp == NULL) {
|
1999-10-09 07:00:55 +04:00
|
|
|
len = strlcpy(temp, tmpdir, sizeof(temp));
|
|
|
|
if (temp[len - 1] != '/')
|
1999-10-07 06:05:22 +04:00
|
|
|
(void)strlcat(temp, "/", sizeof(temp));
|
|
|
|
(void)strlcat(temp, TMPFILE, sizeof(temp));
|
2005-05-19 07:14:52 +04:00
|
|
|
if ((fd = mkstemp(temp)) < 0) {
|
2007-04-17 09:52:03 +04:00
|
|
|
warn("Unable to create temporary file `%s'", temp);
|
2005-05-19 07:14:52 +04:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
close(fd);
|
|
|
|
oldverbose = verbose;
|
1997-03-13 09:23:11 +03:00
|
|
|
verbose = (errbuf != NULL) ? -1 : 0;
|
2005-05-19 07:14:52 +04:00
|
|
|
oldhash = hash;
|
2001-02-19 23:02:42 +03:00
|
|
|
oldprogress = progress;
|
2005-05-19 07:14:52 +04:00
|
|
|
hash = 0;
|
2001-02-19 23:02:42 +03:00
|
|
|
progress = 0;
|
2005-05-19 07:14:52 +04:00
|
|
|
if (doswitch)
|
|
|
|
pswitch(!proxy);
|
2009-04-12 11:07:41 +04:00
|
|
|
for (rmode = "w"; *++argv != NULL; rmode = "a")
|
|
|
|
recvrequest("NLST", temp, *argv, rmode, 0, 0);
|
1997-03-13 09:23:11 +03:00
|
|
|
if ((code / 100) != COMPLETE) {
|
|
|
|
if (errbuf != NULL)
|
|
|
|
*errbuf = reply_string;
|
|
|
|
}
|
2005-05-19 07:14:52 +04:00
|
|
|
if (doswitch)
|
|
|
|
pswitch(!proxy);
|
|
|
|
verbose = oldverbose;
|
1997-03-13 09:23:11 +03:00
|
|
|
hash = oldhash;
|
2001-02-19 23:02:42 +03:00
|
|
|
progress = oldprogress;
|
2005-05-19 07:14:52 +04:00
|
|
|
ftemp = fopen(temp, "r");
|
|
|
|
(void)unlink(temp);
|
|
|
|
if (ftemp == NULL) {
|
1997-03-13 09:23:11 +03:00
|
|
|
if (errbuf == NULL)
|
2007-04-17 09:52:03 +04:00
|
|
|
warnx("Can't find list of remote files");
|
1997-03-13 09:23:11 +03:00
|
|
|
else
|
|
|
|
*errbuf =
|
2007-04-17 09:52:03 +04:00
|
|
|
"Can't find list of remote files";
|
2005-05-19 07:14:52 +04:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (fgets(buf, sizeof(buf), ftemp) == NULL) {
|
|
|
|
(void)fclose(ftemp);
|
1997-03-13 09:23:11 +03:00
|
|
|
ftemp = NULL;
|
2005-05-19 07:14:52 +04:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
if ((cp = strchr(buf, '\n')) != NULL)
|
|
|
|
*cp = '\0';
|
|
|
|
return (buf);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-09-28 10:47:38 +04:00
|
|
|
* Glob a local file name specification with the expectation of a single
|
|
|
|
* 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.
|
1997-01-19 17:19:02 +03:00
|
|
|
*/
|
1999-09-28 10:47:38 +04:00
|
|
|
char *
|
2000-05-01 14:35:16 +04:00
|
|
|
globulize(const char *pattern)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
|
|
|
glob_t gl;
|
|
|
|
int flags;
|
1999-09-28 10:47:38 +04:00
|
|
|
char *p;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
if (!doglob)
|
2006-01-31 23:01:23 +03:00
|
|
|
return (ftp_strdup(pattern));
|
1997-01-19 17:19:02 +03:00
|
|
|
|
1998-06-20 02:58:04 +04:00
|
|
|
flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
|
1997-01-19 17:19:02 +03:00
|
|
|
memset(&gl, 0, sizeof(gl));
|
1999-09-28 10:47:38 +04:00
|
|
|
if (glob(pattern, flags, NULL, &gl) || gl.gl_pathc == 0) {
|
2007-04-17 09:52:03 +04:00
|
|
|
warnx("Glob pattern `%s' not found", pattern);
|
1997-01-19 17:19:02 +03:00
|
|
|
globfree(&gl);
|
1999-09-28 10:47:38 +04:00
|
|
|
return (NULL);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
2006-01-31 23:01:23 +03:00
|
|
|
p = ftp_strdup(gl.gl_pathv[0]);
|
1997-01-19 17:19:02 +03:00
|
|
|
globfree(&gl);
|
1999-09-28 10:47:38 +04:00
|
|
|
return (p);
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* determine size of remote file
|
|
|
|
*/
|
|
|
|
off_t
|
2000-05-01 14:35:16 +04:00
|
|
|
remotesize(const char *file, int noisy)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
int overbose, r;
|
1997-01-19 17:19:02 +03:00
|
|
|
off_t size;
|
|
|
|
|
|
|
|
overbose = verbose;
|
|
|
|
size = -1;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (ftp_debug == 0)
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = -1;
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
if (! features[FEAT_SIZE]) {
|
|
|
|
if (noisy)
|
|
|
|
fprintf(ttyout,
|
|
|
|
"SIZE is not supported by remote server.\n");
|
|
|
|
goto cleanup_remotesize;
|
|
|
|
}
|
|
|
|
r = command("SIZE %s", file);
|
|
|
|
if (r == COMPLETE) {
|
1997-07-21 18:03:48 +04:00
|
|
|
char *cp, *ep;
|
|
|
|
|
|
|
|
cp = strchr(reply_string, ' ');
|
|
|
|
if (cp != NULL) {
|
|
|
|
cp++;
|
2000-07-30 08:42:37 +04:00
|
|
|
size = STRTOLL(cp, &ep, 10);
|
1998-05-20 04:55:52 +04:00
|
|
|
if (*ep != '\0' && !isspace((unsigned char)*ep))
|
1997-07-21 18:03:48 +04:00
|
|
|
size = -1;
|
|
|
|
}
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
} else {
|
|
|
|
if (r == ERROR && code == 500 && features[FEAT_SIZE] == -1)
|
|
|
|
features[FEAT_SIZE] = 0;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (noisy && ftp_debug == 0) {
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
fputs(reply_string, ttyout);
|
|
|
|
putc('\n', ttyout);
|
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
}
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
cleanup_remotesize:
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = overbose;
|
|
|
|
return (size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* determine last modification time (in GMT) of remote file
|
|
|
|
*/
|
|
|
|
time_t
|
2000-05-01 14:35:16 +04:00
|
|
|
remotemodtime(const char *file, int noisy)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
int overbose, ocode, r;
|
|
|
|
time_t rtime;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
overbose = verbose;
|
1997-09-21 05:06:30 +04:00
|
|
|
ocode = code;
|
1997-01-19 17:19:02 +03:00
|
|
|
rtime = -1;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (ftp_debug == 0)
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = -1;
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
if (! features[FEAT_MDTM]) {
|
|
|
|
if (noisy)
|
|
|
|
fprintf(ttyout,
|
|
|
|
"MDTM is not supported by remote server.\n");
|
|
|
|
goto cleanup_parse_time;
|
|
|
|
}
|
|
|
|
r = command("MDTM %s", file);
|
|
|
|
if (r == COMPLETE) {
|
1997-01-19 17:19:02 +03:00
|
|
|
struct tm timebuf;
|
2000-01-25 09:11:00 +03:00
|
|
|
char *timestr, *frac;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* time-val = 14DIGIT [ "." 1*DIGIT ]
|
|
|
|
* YYYYMMDDHHMMSS[.sss]
|
|
|
|
* mdtm-response = "213" SP time-val CRLF / error-response
|
|
|
|
*/
|
|
|
|
timestr = reply_string + 4;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* parse fraction.
|
|
|
|
* XXX: ignored for now
|
|
|
|
*/
|
|
|
|
frac = strchr(timestr, '\r');
|
|
|
|
if (frac != NULL)
|
|
|
|
*frac = '\0';
|
|
|
|
frac = strchr(timestr, '.');
|
|
|
|
if (frac != NULL)
|
|
|
|
*frac++ = '\0';
|
|
|
|
if (strlen(timestr) == 15 && strncmp(timestr, "191", 3) == 0) {
|
|
|
|
/*
|
2000-01-25 09:45:18 +03:00
|
|
|
* XXX: Workaround for lame ftpd's that return
|
|
|
|
* `19100' instead of `2000'
|
2000-01-25 09:11:00 +03:00
|
|
|
*/
|
|
|
|
fprintf(ttyout,
|
|
|
|
"Y2K warning! Incorrect time-val `%s' received from server.\n",
|
|
|
|
timestr);
|
|
|
|
timestr++;
|
|
|
|
timestr[0] = '2';
|
|
|
|
timestr[1] = '0';
|
|
|
|
fprintf(ttyout, "Converted to `%s'\n", timestr);
|
|
|
|
}
|
2007-05-22 09:16:48 +04:00
|
|
|
memset(&timebuf, 0, sizeof(timebuf));
|
2000-01-25 09:11:00 +03:00
|
|
|
if (strlen(timestr) != 14 ||
|
2007-05-22 09:16:48 +04:00
|
|
|
(strptime(timestr, "%Y%m%d%H%M%S", &timebuf) == NULL)) {
|
2000-01-25 09:11:00 +03:00
|
|
|
bad_parse_time:
|
2000-01-26 14:31:55 +03:00
|
|
|
fprintf(ttyout, "Can't parse time `%s'.\n", timestr);
|
2000-01-25 09:11:00 +03:00
|
|
|
goto cleanup_parse_time;
|
|
|
|
}
|
2000-01-26 14:31:55 +03:00
|
|
|
timebuf.tm_isdst = -1;
|
1999-09-26 06:00:12 +04:00
|
|
|
rtime = timegm(&timebuf);
|
2000-01-26 13:15:40 +03:00
|
|
|
if (rtime == -1) {
|
2006-01-31 23:05:35 +03:00
|
|
|
if (noisy || ftp_debug != 0)
|
2000-01-26 13:15:40 +03:00
|
|
|
goto bad_parse_time;
|
|
|
|
else
|
|
|
|
goto cleanup_parse_time;
|
2009-04-15 08:19:39 +04:00
|
|
|
} else {
|
2010-03-05 00:40:53 +03:00
|
|
|
DPRINTF("remotemodtime: parsed time `%s' as " LLF
|
2007-12-05 06:46:33 +03:00
|
|
|
", %s",
|
2007-05-24 09:05:18 +04:00
|
|
|
timestr, (LLT)rtime,
|
|
|
|
rfc2822time(localtime(&rtime)));
|
2009-04-15 08:19:39 +04:00
|
|
|
}
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
} else {
|
|
|
|
if (r == ERROR && code == 500 && features[FEAT_MDTM] == -1)
|
|
|
|
features[FEAT_MDTM] = 0;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (noisy && ftp_debug == 0) {
|
add support for FEAT and OPTS commands with `features' and `opts'.
(from RFC 2389).
add support for MLST & MLSD (machine parseble listings) with 'mlst', 'mlsd'
and 'pmlsd' (mlsd |$PAGER) commands. (from draft-ietf-ftpext-mlst-11)
rename remotesyst() to getremoteinfo(), and modify to parse the result from
FEAT (if supported), and take into account the support for the various
extensions such as MDTM, SIZE, REST (STREAM), MLSD, and FEAT/OPTS.
put each feature into one of the following categories:
- known to work (explicit FEAT)
- unknown but assume works until explicit failure, when it's
then tagged as `known not to work'.
- known not to work (FEAT succeeded but didn't return anything,
or was unknown and then explicit failure)
assign results into features[] matrix.
add support to getreply() so that an optional callback will be called
for each line received from the server except for the first and last.
this is used in FEAT (and MLST) parsing.
modify various commands to check if REST (STREAM), MDTM and SIZE are
explicitly or implicitly supported before using.
fix `syst' when verbose is off.
minor knf (indent goto labels by one space, etc).
simply various command usage handlers by assuming that argv != NULL except
for quit() and disconnect().
2000-07-18 11:16:52 +04:00
|
|
|
fputs(reply_string, ttyout);
|
|
|
|
putc('\n', ttyout);
|
|
|
|
}
|
1998-06-04 12:28:35 +04:00
|
|
|
}
|
2000-01-25 09:11:00 +03:00
|
|
|
cleanup_parse_time:
|
1997-01-19 17:19:02 +03:00
|
|
|
verbose = overbose;
|
1997-09-21 05:06:30 +04:00
|
|
|
if (rtime == -1)
|
|
|
|
code = ocode;
|
1997-01-19 17:19:02 +03:00
|
|
|
return (rtime);
|
|
|
|
}
|
|
|
|
|
2007-05-24 09:05:18 +04:00
|
|
|
/*
|
2010-03-05 10:41:10 +03:00
|
|
|
* Format tm in an RFC 2822 compatible manner, with a trailing \n.
|
2007-05-24 09:05:18 +04:00
|
|
|
* Returns a pointer to a static string containing the result.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
rfc2822time(const struct tm *tm)
|
|
|
|
{
|
|
|
|
static char result[50];
|
|
|
|
|
|
|
|
if (strftime(result, sizeof(result),
|
|
|
|
"%a, %d %b %Y %H:%M:%S %z\n", tm) == 0)
|
2010-03-05 10:41:10 +03:00
|
|
|
errx(1, "Can't convert RFC 2822 time: buffer too small");
|
2007-05-24 09:05:18 +04:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2010-03-05 00:40:53 +03:00
|
|
|
/*
|
|
|
|
* Parse HTTP-date as per RFC 2616.
|
|
|
|
* Return a pointer to the next character of the consumed date string,
|
|
|
|
* or NULL if failed.
|
|
|
|
*/
|
|
|
|
const char *
|
|
|
|
parse_rfc2616time(struct tm *parsed, const char *httpdate)
|
|
|
|
{
|
|
|
|
const char *t;
|
|
|
|
const char *curlocale;
|
|
|
|
|
|
|
|
/* The representation of %a depends on the current locale. */
|
|
|
|
curlocale = setlocale(LC_TIME, NULL);
|
|
|
|
(void)setlocale(LC_TIME, "C");
|
2010-03-05 10:41:10 +03:00
|
|
|
/* RFC 1123 */
|
2010-03-05 00:40:53 +03:00
|
|
|
if ((t = strptime(httpdate, "%a, %d %b %Y %H:%M:%S GMT", parsed)) ||
|
2010-03-05 10:41:10 +03:00
|
|
|
/* RFC 850 */
|
2010-03-05 00:40:53 +03:00
|
|
|
(t = strptime(httpdate, "%a, %d-%b-%y %H:%M:%S GMT", parsed)) ||
|
|
|
|
/* asctime */
|
|
|
|
(t = strptime(httpdate, "%a, %b %d %H:%M:%S %Y", parsed))) {
|
|
|
|
; /* do nothing */
|
|
|
|
}
|
|
|
|
(void)setlocale(LC_TIME, curlocale);
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
|
1999-11-11 05:53:02 +03:00
|
|
|
/*
|
2005-01-03 12:50:09 +03:00
|
|
|
* Update global `localcwd', which contains the state of the local cwd
|
1999-11-11 05:53:02 +03:00
|
|
|
*/
|
|
|
|
void
|
2005-01-03 12:50:09 +03:00
|
|
|
updatelocalcwd(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (getcwd(localcwd, sizeof(localcwd)) == NULL)
|
|
|
|
localcwd[0] = '\0';
|
2007-12-05 06:46:33 +03:00
|
|
|
DPRINTF("updatelocalcwd: got `%s'\n", localcwd);
|
2005-01-03 12:50:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update global `remotecwd', which contains the state of the remote cwd
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
updateremotecwd(void)
|
1999-11-11 05:53:02 +03:00
|
|
|
{
|
2009-04-12 14:18:52 +04:00
|
|
|
int overbose, ocode;
|
|
|
|
size_t i;
|
1999-11-11 05:53:02 +03:00
|
|
|
char *cp;
|
|
|
|
|
2017-11-21 00:11:36 +03:00
|
|
|
remcwdvalid = 1; /* whether it works or not, we are done */
|
1999-11-11 05:53:02 +03:00
|
|
|
overbose = verbose;
|
|
|
|
ocode = code;
|
2006-01-31 23:05:35 +03:00
|
|
|
if (ftp_debug == 0)
|
1999-11-11 05:53:02 +03:00
|
|
|
verbose = -1;
|
|
|
|
if (command("PWD") != COMPLETE)
|
2005-01-03 12:50:09 +03:00
|
|
|
goto badremotecwd;
|
1999-11-11 05:53:02 +03:00
|
|
|
cp = strchr(reply_string, ' ');
|
|
|
|
if (cp == NULL || cp[0] == '\0' || cp[1] != '"')
|
2005-01-03 12:50:09 +03:00
|
|
|
goto badremotecwd;
|
1999-11-11 05:53:02 +03:00
|
|
|
cp += 2;
|
2005-01-03 12:50:09 +03:00
|
|
|
for (i = 0; *cp && i < sizeof(remotecwd) - 1; i++, cp++) {
|
1999-11-11 05:53:02 +03:00
|
|
|
if (cp[0] == '"') {
|
|
|
|
if (cp[1] == '"')
|
|
|
|
cp++;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2005-01-03 12:50:09 +03:00
|
|
|
remotecwd[i] = *cp;
|
1999-11-11 05:53:02 +03:00
|
|
|
}
|
2005-01-03 12:50:09 +03:00
|
|
|
remotecwd[i] = '\0';
|
2007-12-05 06:46:33 +03:00
|
|
|
DPRINTF("updateremotecwd: got `%s'\n", remotecwd);
|
2005-01-03 12:50:09 +03:00
|
|
|
goto cleanupremotecwd;
|
|
|
|
badremotecwd:
|
|
|
|
remotecwd[0]='\0';
|
|
|
|
cleanupremotecwd:
|
1999-11-11 05:53:02 +03:00
|
|
|
verbose = overbose;
|
|
|
|
code = ocode;
|
|
|
|
}
|
|
|
|
|
2005-01-03 12:50:09 +03:00
|
|
|
/*
|
|
|
|
* Ensure file is in or under dir.
|
|
|
|
* Returns 1 if so, 0 if not (or an error occurred).
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
fileindir(const char *file, const char *dir)
|
|
|
|
{
|
2005-05-26 06:59:34 +04:00
|
|
|
char parentdirbuf[PATH_MAX+1], *parentdir;
|
|
|
|
char realdir[PATH_MAX+1];
|
2005-01-03 12:50:09 +03:00
|
|
|
size_t dirlen;
|
|
|
|
|
2007-04-12 08:18:22 +04:00
|
|
|
/* determine parent directory of file */
|
2005-05-26 06:59:34 +04:00
|
|
|
(void)strlcpy(parentdirbuf, file, sizeof(parentdirbuf));
|
|
|
|
parentdir = dirname(parentdirbuf);
|
|
|
|
if (strcmp(parentdir, ".") == 0)
|
|
|
|
return 1; /* current directory is ok */
|
|
|
|
|
|
|
|
/* find the directory */
|
|
|
|
if (realpath(parentdir, realdir) == NULL) {
|
|
|
|
warn("Unable to determine real path of `%s'", parentdir);
|
2005-01-03 12:50:09 +03:00
|
|
|
return 0;
|
|
|
|
}
|
2005-05-26 06:59:34 +04:00
|
|
|
if (realdir[0] != '/') /* relative result is ok */
|
2005-01-03 12:50:09 +03:00
|
|
|
return 1;
|
|
|
|
dirlen = strlen(dir);
|
2005-05-26 06:59:34 +04:00
|
|
|
if (strncmp(realdir, dir, dirlen) == 0 &&
|
|
|
|
(realdir[dirlen] == '/' || realdir[dirlen] == '\0'))
|
2005-01-03 12:50:09 +03:00
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
1999-10-05 17:05:39 +04:00
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
/*
|
|
|
|
* List words in stringlist, vertically arranged
|
|
|
|
*/
|
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
list_vertical(StringList *sl)
|
1997-01-19 17:19:02 +03:00
|
|
|
{
|
2009-04-12 14:18:52 +04:00
|
|
|
size_t i, j;
|
|
|
|
size_t columns, lines;
|
1997-01-19 17:19:02 +03:00
|
|
|
char *p;
|
2005-05-19 07:05:04 +04:00
|
|
|
size_t w, width;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
2000-08-27 10:31:23 +04:00
|
|
|
width = 0;
|
1997-01-19 17:19:02 +03:00
|
|
|
|
|
|
|
for (i = 0 ; i < sl->sl_cur ; i++) {
|
|
|
|
w = strlen(sl->sl_str[i]);
|
|
|
|
if (w > width)
|
|
|
|
width = w;
|
|
|
|
}
|
|
|
|
width = (width + 8) &~ 7;
|
|
|
|
|
|
|
|
columns = ttywidth / width;
|
|
|
|
if (columns == 0)
|
|
|
|
columns = 1;
|
|
|
|
lines = (sl->sl_cur + columns - 1) / columns;
|
|
|
|
for (i = 0; i < lines; i++) {
|
|
|
|
for (j = 0; j < columns; j++) {
|
|
|
|
p = sl->sl_str[j * lines + i];
|
|
|
|
if (p)
|
1998-06-04 12:28:35 +04:00
|
|
|
fputs(p, ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
if (j * lines + i + lines >= sl->sl_cur) {
|
1998-06-04 12:28:35 +04:00
|
|
|
putc('\n', ttyout);
|
1997-01-19 17:19:02 +03:00
|
|
|
break;
|
|
|
|
}
|
2006-04-29 00:07:57 +04:00
|
|
|
if (p) {
|
|
|
|
w = strlen(p);
|
|
|
|
while (w < width) {
|
|
|
|
w = (w + 8) &~ 7;
|
|
|
|
(void)putc('\t', ttyout);
|
|
|
|
}
|
1997-01-19 17:19:02 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Update the global ttywidth value, using TIOCGWINSZ.
|
|
|
|
*/
|
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
setttywidth(int a)
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
{
|
|
|
|
struct winsize winsize;
|
1999-10-09 07:00:55 +04:00
|
|
|
int oerrno = errno;
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
|
1998-09-28 13:03:22 +04:00
|
|
|
if (ioctl(fileno(ttyout), TIOCGWINSZ, &winsize) != -1 &&
|
|
|
|
winsize.ws_col != 0)
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
ttywidth = winsize.ws_col;
|
|
|
|
else
|
|
|
|
ttywidth = 80;
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
errno = oerrno;
|
[Yet Another Huge Ftp Commit - hopefully the last for a while,
barring any more little things people want added ...]
New features:
* progressmeter is now asynchronous, so "stalled" transfers can be
detected. "- stalled -" is displayed instead of the ETA in this case.
When the xfer resumes, the time that the xfer was stalled for is
factored out of the ETA. It is debatable whether this is better than
not factoring it out, but I like it this way (I.e, if it stalls for 8
seconds and the ETA was 30 seconds, when it resumes the ETA will still
be 30 seconds).
* verbosity can be disabled on the command line (-V), so that in auto-fetch
mode the only lines displayed will be a description of the file, and
the progress bar (if possible)
* if the screen is resized (and detected via the SIGWINCH signal), the
progress bar will rescale automatically.
Bugs fixed:
* progress bar will not use the last character on the line, as this can
cause problems on some terminals
* screen dimensions (via ioctl(TIOCWINSZ)) should use stdout not stdin
* progressmeter() used some vars before initialising them
* ^D will quit now. [fixes bin/3162]
* use hstrerror() to generate error message for host name lookup failure.
* use getcwd instead of getwd (it should have been OK, but why tempt fate?)
* auto-fetch transfers will always return a positive exit value upon failure
or interruption, relative to the file's position in argv[].
* remote completion of / will work, without putting a leading "///".
This is actually a bug in ftpd(1), where "NLST /" prefixes all names
with "//", but fixing every ftpd(1) is not an option...
1997-02-01 13:44:54 +03:00
|
|
|
}
|
|
|
|
|
1999-10-05 17:05:39 +04:00
|
|
|
/*
|
|
|
|
* Change the rate limit up (SIGUSR1) or down (SIGUSR2)
|
|
|
|
*/
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
crankrate(int sig)
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
switch (sig) {
|
|
|
|
case SIGUSR1:
|
|
|
|
if (rate_get)
|
|
|
|
rate_get += rate_get_incr;
|
|
|
|
if (rate_put)
|
|
|
|
rate_put += rate_put_incr;
|
|
|
|
break;
|
|
|
|
case SIGUSR2:
|
|
|
|
if (rate_get && rate_get > rate_get_incr)
|
|
|
|
rate_get -= rate_get_incr;
|
|
|
|
if (rate_put && rate_put > rate_put_incr)
|
|
|
|
rate_put -= rate_put_incr;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err(1, "crankrate invoked with unknown signal: %d", sig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-04-05 07:27:32 +04:00
|
|
|
/*
|
|
|
|
* Setup or cleanup EditLine structures
|
|
|
|
*/
|
1999-06-21 02:07:28 +04:00
|
|
|
#ifndef NO_EDITCOMPLETE
|
1997-04-05 07:27:32 +04:00
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
controlediting(void)
|
1997-04-05 07:27:32 +04:00
|
|
|
{
|
|
|
|
if (editing && el == NULL && hist == NULL) {
|
1997-10-14 20:31:22 +04:00
|
|
|
HistEvent ev;
|
1998-07-29 06:46:26 +04:00
|
|
|
int editmode;
|
1997-10-14 20:31:22 +04:00
|
|
|
|
2001-02-20 02:03:42 +03:00
|
|
|
el = el_init(getprogname(), stdin, ttyout, stderr);
|
1998-05-20 04:55:52 +04:00
|
|
|
/* init editline */
|
1997-04-05 07:27:32 +04:00
|
|
|
hist = history_init(); /* init the builtin history */
|
1998-05-20 04:55:52 +04:00
|
|
|
history(hist, &ev, H_SETSIZE, 100);/* remember 100 events */
|
1997-04-05 07:27:32 +04:00
|
|
|
el_set(el, EL_HIST, history, hist); /* use history */
|
|
|
|
|
|
|
|
el_set(el, EL_EDITOR, "emacs"); /* default editor is emacs */
|
1999-11-12 05:50:38 +03:00
|
|
|
el_set(el, EL_PROMPT, prompt); /* set the prompt functions */
|
|
|
|
el_set(el, EL_RPROMPT, rprompt);
|
1997-04-05 07:27:32 +04:00
|
|
|
|
|
|
|
/* add local file completion, bind to TAB */
|
|
|
|
el_set(el, EL_ADDFN, "ftp-complete",
|
|
|
|
"Context sensitive argument completion",
|
|
|
|
complete);
|
|
|
|
el_set(el, EL_BIND, "^I", "ftp-complete", NULL);
|
|
|
|
el_source(el, NULL); /* read ~/.editrc */
|
1998-07-29 06:46:26 +04:00
|
|
|
if ((el_get(el, EL_EDITMODE, &editmode) != -1) && editmode == 0)
|
|
|
|
editing = 0; /* the user doesn't want editing,
|
|
|
|
* so disable, and let statement
|
|
|
|
* below cleanup */
|
|
|
|
else
|
|
|
|
el_set(el, EL_SIGNAL, 1);
|
|
|
|
}
|
|
|
|
if (!editing) {
|
1997-04-05 07:27:32 +04:00
|
|
|
if (hist) {
|
|
|
|
history_end(hist);
|
|
|
|
hist = NULL;
|
|
|
|
}
|
|
|
|
if (el) {
|
|
|
|
el_end(el);
|
|
|
|
el = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-21 02:07:28 +04:00
|
|
|
#endif /* !NO_EDITCOMPLETE */
|
1998-07-10 08:39:03 +04:00
|
|
|
|
|
|
|
/*
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
* Convert the string `arg' to an int, which may have an optional SI suffix
|
|
|
|
* (`b', `k', `m', `g'). Returns the number for success, -1 otherwise.
|
1998-07-10 08:39:03 +04:00
|
|
|
*/
|
|
|
|
int
|
2000-05-01 14:35:16 +04:00
|
|
|
strsuftoi(const char *arg)
|
1998-07-10 08:39:03 +04:00
|
|
|
{
|
|
|
|
char *cp;
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
long val;
|
1998-07-10 08:39:03 +04:00
|
|
|
|
1998-11-06 19:52:42 +03:00
|
|
|
if (!isdigit((unsigned char)arg[0]))
|
1998-07-10 08:39:03 +04:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
val = strtol(arg, &cp, 10);
|
|
|
|
if (cp != NULL) {
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
if (cp[0] != '\0' && cp[1] != '\0')
|
1998-07-10 08:39:03 +04:00
|
|
|
return (-1);
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
switch (tolower((unsigned char)cp[0])) {
|
|
|
|
case '\0':
|
|
|
|
case 'b':
|
|
|
|
break;
|
|
|
|
case 'k':
|
|
|
|
val <<= 10;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
val <<= 20;
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
val <<= 30;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return (-1);
|
|
|
|
}
|
1998-07-10 08:39:03 +04:00
|
|
|
}
|
[fear this; more ftp hacking from lukem :-]
features:
---------
* transfer rate throttling with the new `rate' command. syntax:
rate direction [max [incr]]
where direction is `all', `get' or `put'.
if max is not supplied, the current settings are displayed.
if max is supplied, then transfers in the given direction will
be throttled to this value.
if incr is supplied, the increment for the `on-the-fly' scaling
will be set to that, otherwise `1024' is used.
currently implemented for binary get, binary put, and url fetches.
not yet supported for ascii get or put, or local file copies.
* on-the-fly scaling of the throttle based on signals:
- SIGUSR1 raises the throttle rate by the increment for that direction
- SIGUSR2 lowers the throttle rate by the increment for that direction
* -T dir,max[,incr] option to set rate from the command line
* `k', `m', `g' suffix support for bytecounts in the `hash', `rate',
`rcvbuf' and `sndbuf' commands)
bug fixes and code mods:
------------------------
* fix up ftp_login() so that ruserpass() is always called, even for
command-line url fetches.
* implement strsuftoi(), which parses a given number into a int with
suffix support. replaces getsockbufsize()
* implement parserate(), which does the argv parsing for -T and rate
* save and restore errno in signal handlers (may not be necessary, but
it doesn't hurt)
notes:
------
the rate command has had reasonable testing, but I'd like feedback
if it doesn't do the right thing, especially from people on slower
(i.e, modem) links.
I haven't tested the rate throttle against a http server which does
`transfer-encoding: chunked' because I couldn't find a server to
test against.
1999-06-29 14:43:16 +04:00
|
|
|
if (val < 0 || val > INT_MAX)
|
1998-07-10 08:39:03 +04:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up socket buffer sizes before a connection is made.
|
|
|
|
*/
|
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
setupsockbufsize(int sock)
|
1998-07-10 08:39:03 +04:00
|
|
|
{
|
2011-12-10 09:53:58 +04:00
|
|
|
socklen_t slen;
|
|
|
|
|
|
|
|
if (0 == rcvbuf_size) {
|
|
|
|
slen = sizeof(rcvbuf_size);
|
|
|
|
if (getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
|
|
|
|
(void *)&rcvbuf_size, &slen) == -1)
|
|
|
|
err(1, "Unable to determine rcvbuf size");
|
|
|
|
if (rcvbuf_size <= 0)
|
|
|
|
rcvbuf_size = 8 * 1024;
|
|
|
|
if (rcvbuf_size > 8 * 1024 * 1024)
|
|
|
|
rcvbuf_size = 8 * 1024 * 1024;
|
|
|
|
DPRINTF("setupsockbufsize: rcvbuf_size determined as %d\n",
|
|
|
|
rcvbuf_size);
|
|
|
|
}
|
|
|
|
if (0 == sndbuf_size) {
|
|
|
|
slen = sizeof(sndbuf_size);
|
|
|
|
if (getsockopt(sock, SOL_SOCKET, SO_SNDBUF,
|
|
|
|
(void *)&sndbuf_size, &slen) == -1)
|
|
|
|
err(1, "Unable to determine sndbuf size");
|
|
|
|
if (sndbuf_size <= 0)
|
|
|
|
sndbuf_size = 8 * 1024;
|
|
|
|
if (sndbuf_size > 8 * 1024 * 1024)
|
|
|
|
sndbuf_size = 8 * 1024 * 1024;
|
|
|
|
DPRINTF("setupsockbufsize: sndbuf_size determined as %d\n",
|
|
|
|
sndbuf_size);
|
|
|
|
}
|
1998-07-10 08:39:03 +04:00
|
|
|
|
2005-05-11 06:29:12 +04:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
|
2005-05-13 09:03:49 +04:00
|
|
|
(void *)&sndbuf_size, sizeof(sndbuf_size)) == -1)
|
2007-04-17 09:52:03 +04:00
|
|
|
warn("Unable to set sndbuf size %d", sndbuf_size);
|
1998-07-10 08:39:03 +04:00
|
|
|
|
2005-05-11 06:29:12 +04:00
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
|
|
|
|
(void *)&rcvbuf_size, sizeof(rcvbuf_size)) == -1)
|
2007-04-17 09:52:03 +04:00
|
|
|
warn("Unable to set rcvbuf size %d", rcvbuf_size);
|
1998-07-10 08:39:03 +04:00
|
|
|
}
|
|
|
|
|
1999-10-13 06:47:54 +04:00
|
|
|
/*
|
|
|
|
* Copy characters from src into dst, \ quoting characters that require it
|
|
|
|
*/
|
1999-02-07 16:14:06 +03:00
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
ftpvis(char *dst, size_t dstlen, const char *src, size_t srclen)
|
1999-02-07 16:14:06 +03:00
|
|
|
{
|
2009-04-12 14:18:52 +04:00
|
|
|
size_t di, si;
|
1999-02-07 16:14:06 +03:00
|
|
|
|
2010-06-05 17:59:39 +04:00
|
|
|
di = si = 0;
|
|
|
|
while (src[si] != '\0' && di < dstlen && si < srclen) {
|
1999-02-07 16:14:06 +03:00
|
|
|
switch (src[si]) {
|
|
|
|
case '\\':
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\r':
|
1999-02-07 16:15:12 +03:00
|
|
|
case '\n':
|
1999-02-07 16:14:06 +03:00
|
|
|
case '"':
|
2010-06-05 17:59:39 +04:00
|
|
|
/*
|
|
|
|
* Need room for two characters and NUL, avoiding
|
|
|
|
* incomplete escape sequences at end of dst.
|
|
|
|
*/
|
|
|
|
if (di >= dstlen - 3)
|
1999-02-07 16:14:06 +03:00
|
|
|
break;
|
2010-06-05 17:59:39 +04:00
|
|
|
dst[di++] = '\\';
|
1999-02-07 16:14:06 +03:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
2010-06-05 17:59:39 +04:00
|
|
|
dst[di] = src[si++];
|
|
|
|
if (di < dstlen)
|
|
|
|
di++;
|
1999-02-07 16:14:06 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
dst[di] = '\0';
|
|
|
|
}
|
|
|
|
|
1999-11-12 05:50:38 +03:00
|
|
|
/*
|
|
|
|
* Copy src into buf (which is len bytes long), expanding % sequences.
|
|
|
|
*/
|
|
|
|
void
|
2000-05-01 14:35:16 +04:00
|
|
|
formatbuf(char *buf, size_t len, const char *src)
|
1999-11-12 05:50:38 +03:00
|
|
|
{
|
2005-06-10 04:18:46 +04:00
|
|
|
const char *p, *p2, *q;
|
2009-04-12 14:18:52 +04:00
|
|
|
size_t i;
|
|
|
|
int op, updirs, pdirs;
|
1999-11-12 05:50:38 +03:00
|
|
|
|
|
|
|
#define ADDBUF(x) do { \
|
|
|
|
if (i >= len - 1) \
|
|
|
|
goto endbuf; \
|
|
|
|
buf[i++] = (x); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
p = src;
|
|
|
|
for (i = 0; *p; p++) {
|
|
|
|
if (*p != '%') {
|
|
|
|
ADDBUF(*p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p++;
|
|
|
|
|
|
|
|
switch (op = *p) {
|
|
|
|
|
|
|
|
case '/':
|
|
|
|
case '.':
|
|
|
|
case 'c':
|
2017-11-21 00:11:36 +03:00
|
|
|
if (connected && !remcwdvalid)
|
|
|
|
updateremotecwd();
|
2005-01-03 12:50:09 +03:00
|
|
|
p2 = connected ? remotecwd : "";
|
1999-11-12 05:50:38 +03:00
|
|
|
updirs = pdirs = 0;
|
|
|
|
|
|
|
|
/* option to determine fixed # of dirs from path */
|
|
|
|
if (op == '.' || op == 'c') {
|
|
|
|
int skip;
|
|
|
|
|
|
|
|
q = p2;
|
|
|
|
while (*p2) /* calc # of /'s */
|
|
|
|
if (*p2++ == '/')
|
|
|
|
updirs++;
|
|
|
|
if (p[1] == '0') { /* print <x> or ... */
|
|
|
|
pdirs = 1;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p[1] >= '1' && p[1] <= '9') {
|
|
|
|
/* calc # to skip */
|
|
|
|
skip = p[1] - '0';
|
|
|
|
p++;
|
|
|
|
} else
|
|
|
|
skip = 1;
|
|
|
|
|
|
|
|
updirs -= skip;
|
|
|
|
while (skip-- > 0) {
|
|
|
|
while ((p2 > q) && (*p2 != '/'))
|
|
|
|
p2--; /* back up */
|
|
|
|
if (skip && p2 > q)
|
|
|
|
p2--;
|
|
|
|
}
|
|
|
|
if (*p2 == '/' && p2 != q)
|
|
|
|
p2++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (updirs > 0 && pdirs) {
|
|
|
|
if (i >= len - 5)
|
|
|
|
break;
|
|
|
|
if (op == '.') {
|
|
|
|
ADDBUF('.');
|
|
|
|
ADDBUF('.');
|
|
|
|
ADDBUF('.');
|
|
|
|
} else {
|
|
|
|
ADDBUF('/');
|
|
|
|
ADDBUF('<');
|
|
|
|
if (updirs > 9) {
|
|
|
|
ADDBUF('9');
|
|
|
|
ADDBUF('+');
|
|
|
|
} else
|
|
|
|
ADDBUF('0' + updirs);
|
|
|
|
ADDBUF('>');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (; *p2; p2++)
|
|
|
|
ADDBUF(*p2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
case 'm':
|
2005-05-27 18:35:50 +04:00
|
|
|
for (p2 = connected && hostname ? hostname : "-";
|
2003-06-15 17:49:46 +04:00
|
|
|
*p2 ; p2++) {
|
1999-11-12 05:50:38 +03:00
|
|
|
if (op == 'm' && *p2 == '.')
|
|
|
|
break;
|
|
|
|
ADDBUF(*p2);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
for (p2 = connected ? username : "-"; *p2 ; p2++)
|
|
|
|
ADDBUF(*p2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '%':
|
|
|
|
ADDBUF('%');
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: /* display unknown codes literally */
|
|
|
|
ADDBUF('%');
|
|
|
|
ADDBUF(op);
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
endbuf:
|
|
|
|
buf[i] = '\0';
|
|
|
|
}
|
|
|
|
|
1999-07-12 17:20:34 +04:00
|
|
|
/*
|
|
|
|
* Determine if given string is an IPv6 address or not.
|
|
|
|
* Return 1 for yes, 0 for no
|
|
|
|
*/
|
|
|
|
int
|
2000-05-01 14:35:16 +04:00
|
|
|
isipv6addr(const char *addr)
|
1999-07-12 17:20:34 +04:00
|
|
|
{
|
|
|
|
int rv = 0;
|
|
|
|
#ifdef INET6
|
2000-04-24 09:59:39 +04:00
|
|
|
struct addrinfo hints, *res;
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
2008-08-13 08:59:13 +04:00
|
|
|
hints.ai_family = AF_INET6;
|
2000-04-24 09:59:39 +04:00
|
|
|
hints.ai_socktype = SOCK_DGRAM; /*dummy*/
|
|
|
|
hints.ai_flags = AI_NUMERICHOST;
|
|
|
|
if (getaddrinfo(addr, "0", &hints, &res) != 0)
|
|
|
|
rv = 0;
|
|
|
|
else {
|
|
|
|
rv = 1;
|
|
|
|
freeaddrinfo(res);
|
|
|
|
}
|
2005-06-29 06:31:19 +04:00
|
|
|
DPRINTF("isipv6addr: got %d for %s\n", rv, addr);
|
1999-07-12 17:20:34 +04:00
|
|
|
#endif
|
1999-12-03 09:10:01 +03:00
|
|
|
return (rv == 1) ? 1 : 0;
|
1999-07-12 17:20:34 +04:00
|
|
|
}
|
|
|
|
|
2005-06-10 04:18:46 +04:00
|
|
|
/*
|
|
|
|
* Read a line from the FILE stream into buf/buflen using fgets(), so up
|
|
|
|
* to buflen-1 chars will be read and the result will be NUL terminated.
|
|
|
|
* If the line has a trailing newline it will be removed.
|
|
|
|
* If the line is too long, excess characters will be read until
|
|
|
|
* newline/EOF/error.
|
|
|
|
* If EOF/error occurs or a too-long line is encountered and errormsg
|
|
|
|
* isn't NULL, it will be changed to a description of the problem.
|
|
|
|
* (The EOF message has a leading \n for cosmetic purposes).
|
|
|
|
* Returns:
|
|
|
|
* >=0 length of line (excluding trailing newline) if all ok
|
|
|
|
* -1 error occurred
|
|
|
|
* -2 EOF encountered
|
|
|
|
* -3 line was too long
|
|
|
|
*/
|
|
|
|
int
|
2009-07-13 23:05:39 +04:00
|
|
|
get_line(FILE *stream, char *buf, size_t buflen, const char **errormsg)
|
2005-06-10 04:18:46 +04:00
|
|
|
{
|
|
|
|
int rv, ch;
|
|
|
|
size_t len;
|
|
|
|
|
|
|
|
if (fgets(buf, buflen, stream) == NULL) {
|
|
|
|
if (feof(stream)) { /* EOF */
|
|
|
|
rv = -2;
|
|
|
|
if (errormsg)
|
|
|
|
*errormsg = "\nEOF received";
|
|
|
|
} else { /* error */
|
|
|
|
rv = -1;
|
|
|
|
if (errormsg)
|
|
|
|
*errormsg = "Error encountered";
|
|
|
|
}
|
|
|
|
clearerr(stream);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
len = strlen(buf);
|
|
|
|
if (buf[len-1] == '\n') { /* clear any trailing newline */
|
|
|
|
buf[--len] = '\0';
|
|
|
|
} else if (len == buflen-1) { /* line too long */
|
|
|
|
while ((ch = getchar()) != '\n' && ch != EOF)
|
|
|
|
continue;
|
|
|
|
if (errormsg)
|
|
|
|
*errormsg = "Input line is too long";
|
|
|
|
clearerr(stream);
|
|
|
|
return -3;
|
|
|
|
}
|
|
|
|
if (errormsg)
|
|
|
|
*errormsg = NULL;
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
1998-07-10 08:39:03 +04:00
|
|
|
/*
|
2007-04-17 09:52:03 +04:00
|
|
|
* Internal version of connect(2); sets socket buffer sizes,
|
|
|
|
* binds to a specific local address (if set), and
|
2005-04-11 05:43:31 +04:00
|
|
|
* supports a connection timeout using a non-blocking connect(2) with
|
|
|
|
* a poll(2).
|
|
|
|
* Socket fcntl flags are temporarily updated to include O_NONBLOCK;
|
|
|
|
* these will not be reverted on connection failure.
|
2007-04-17 09:52:03 +04:00
|
|
|
* Returns 0 on success, or -1 upon failure (with an appropriate
|
|
|
|
* error message displayed.)
|
1998-07-10 08:39:03 +04:00
|
|
|
*/
|
|
|
|
int
|
2012-07-04 10:09:37 +04:00
|
|
|
ftp_connect(int sock, const struct sockaddr *name, socklen_t namelen, int pe)
|
1998-07-10 08:39:03 +04:00
|
|
|
{
|
2005-04-11 05:43:31 +04:00
|
|
|
int flags, rv, timeout, error;
|
2005-05-11 06:29:12 +04:00
|
|
|
socklen_t slen;
|
2005-04-11 05:43:31 +04:00
|
|
|
struct timeval endtime, now, td;
|
|
|
|
struct pollfd pfd[1];
|
2007-04-17 09:52:03 +04:00
|
|
|
char hname[NI_MAXHOST];
|
2008-04-22 16:59:33 +04:00
|
|
|
char sname[NI_MAXSERV];
|
1998-07-10 08:39:03 +04:00
|
|
|
|
|
|
|
setupsockbufsize(sock);
|
2007-04-17 09:52:03 +04:00
|
|
|
if (getnameinfo(name, namelen,
|
2008-04-22 16:59:33 +04:00
|
|
|
hname, sizeof(hname), sname, sizeof(sname),
|
|
|
|
NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
|
2007-04-17 09:52:03 +04:00
|
|
|
strlcpy(hname, "?", sizeof(hname));
|
2008-04-22 16:59:33 +04:00
|
|
|
strlcpy(sname, "?", sizeof(sname));
|
|
|
|
}
|
2004-04-10 16:21:39 +04:00
|
|
|
|
2007-04-17 09:52:03 +04:00
|
|
|
if (bindai != NULL) { /* bind to specific addr */
|
|
|
|
struct addrinfo *ai;
|
|
|
|
|
|
|
|
for (ai = bindai; ai != NULL; ai = ai->ai_next) {
|
|
|
|
if (ai->ai_family == name->sa_family)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ai == NULL)
|
|
|
|
ai = bindai;
|
|
|
|
if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
|
|
|
|
char bname[NI_MAXHOST];
|
|
|
|
int saveerr;
|
|
|
|
|
|
|
|
saveerr = errno;
|
|
|
|
if (getnameinfo(ai->ai_addr, ai->ai_addrlen,
|
|
|
|
bname, sizeof(bname), NULL, 0, NI_NUMERICHOST) != 0)
|
|
|
|
strlcpy(bname, "?", sizeof(bname));
|
|
|
|
errno = saveerr;
|
|
|
|
warn("Can't bind to `%s'", bname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save current socket flags */
|
|
|
|
if ((flags = fcntl(sock, F_GETFL, 0)) == -1) {
|
2008-04-22 16:59:33 +04:00
|
|
|
warn("Can't %s socket flags for connect to `%s:%s'",
|
|
|
|
"save", hname, sname);
|
2007-04-17 09:52:03 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* set non-blocking connect */
|
|
|
|
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1) {
|
2008-04-22 16:59:33 +04:00
|
|
|
warn("Can't set socket non-blocking for connect to `%s:%s'",
|
|
|
|
hname, sname);
|
2007-04-17 09:52:03 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2005-04-11 05:43:31 +04:00
|
|
|
|
|
|
|
/* NOTE: we now must restore socket flags on successful exit */
|
|
|
|
|
|
|
|
pfd[0].fd = sock;
|
|
|
|
pfd[0].events = POLLIN|POLLOUT;
|
|
|
|
|
|
|
|
if (quit_time > 0) { /* want a non default timeout */
|
|
|
|
(void)gettimeofday(&endtime, NULL);
|
|
|
|
endtime.tv_sec += quit_time; /* determine end time */
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = connect(sock, name, namelen); /* inititate the connection */
|
|
|
|
if (rv == -1) { /* connection error */
|
2007-04-17 09:52:03 +04:00
|
|
|
if (errno != EINPROGRESS) { /* error isn't "please wait" */
|
2012-07-04 10:09:37 +04:00
|
|
|
if (pe || (errno != EHOSTUNREACH))
|
2007-04-17 09:52:03 +04:00
|
|
|
connecterror:
|
2012-07-04 10:09:37 +04:00
|
|
|
warn("Can't connect to `%s:%s'", hname, sname);
|
2005-04-11 05:43:31 +04:00
|
|
|
return -1;
|
2007-04-17 09:52:03 +04:00
|
|
|
}
|
2005-04-11 05:43:31 +04:00
|
|
|
|
|
|
|
/* connect EINPROGRESS; wait */
|
2004-04-10 16:21:39 +04:00
|
|
|
do {
|
2005-04-11 05:43:31 +04:00
|
|
|
if (quit_time > 0) { /* determine timeout */
|
|
|
|
(void)gettimeofday(&now, NULL);
|
|
|
|
timersub(&endtime, &now, &td);
|
|
|
|
timeout = td.tv_sec * 1000 + td.tv_usec/1000;
|
|
|
|
if (timeout < 0)
|
|
|
|
timeout = 0;
|
|
|
|
} else {
|
|
|
|
timeout = INFTIM;
|
|
|
|
}
|
|
|
|
pfd[0].revents = 0;
|
2006-01-31 23:01:23 +03:00
|
|
|
rv = ftp_poll(pfd, 1, timeout);
|
2005-04-11 05:43:31 +04:00
|
|
|
/* loop until poll ! EINTR */
|
2004-04-10 16:21:39 +04:00
|
|
|
} while (rv == -1 && errno == EINTR);
|
2005-04-11 05:43:31 +04:00
|
|
|
|
|
|
|
if (rv == 0) { /* poll (connect) timed out */
|
|
|
|
errno = ETIMEDOUT;
|
2007-04-17 09:52:03 +04:00
|
|
|
goto connecterror;
|
2005-04-11 05:43:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (rv == -1) { /* poll error */
|
2007-04-17 09:52:03 +04:00
|
|
|
goto connecterror;
|
2005-04-11 05:43:31 +04:00
|
|
|
} else if (pfd[0].revents & (POLLIN|POLLOUT)) {
|
2005-05-13 09:03:49 +04:00
|
|
|
slen = sizeof(error); /* OK, or pending error */
|
2005-04-11 05:43:31 +04:00
|
|
|
if (getsockopt(sock, SOL_SOCKET, SO_ERROR,
|
2007-04-17 09:52:03 +04:00
|
|
|
&error, &slen) == -1) {
|
|
|
|
/* Solaris pending error */
|
|
|
|
goto connecterror;
|
|
|
|
} else if (error != 0) {
|
2005-04-11 05:43:31 +04:00
|
|
|
errno = error; /* BSD pending error */
|
2007-04-17 09:52:03 +04:00
|
|
|
goto connecterror;
|
2005-04-11 05:43:31 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
errno = EBADF; /* this shouldn't happen ... */
|
2007-04-17 09:52:03 +04:00
|
|
|
goto connecterror;
|
2005-04-11 05:43:31 +04:00
|
|
|
}
|
2004-04-10 16:21:39 +04:00
|
|
|
}
|
2005-04-11 05:43:31 +04:00
|
|
|
|
2007-04-17 09:52:03 +04:00
|
|
|
if (fcntl(sock, F_SETFL, flags) == -1) {
|
|
|
|
/* restore socket flags */
|
2008-04-22 16:59:33 +04:00
|
|
|
warn("Can't %s socket flags for connect to `%s:%s'",
|
|
|
|
"restore", hname, sname);
|
2005-04-11 05:43:31 +04:00
|
|
|
return -1;
|
2007-04-17 09:52:03 +04:00
|
|
|
}
|
2005-04-11 05:43:31 +04:00
|
|
|
return 0;
|
1998-07-10 08:39:03 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Internal version of listen(2); sets socket buffer sizes first.
|
|
|
|
*/
|
|
|
|
int
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_listen(int sock, int backlog)
|
1998-07-10 08:39:03 +04:00
|
|
|
{
|
|
|
|
|
|
|
|
setupsockbufsize(sock);
|
|
|
|
return (listen(sock, backlog));
|
|
|
|
}
|
1998-08-03 05:49:25 +04:00
|
|
|
|
2005-04-11 05:43:31 +04:00
|
|
|
/*
|
|
|
|
* Internal version of poll(2), to allow reimplementation by select(2)
|
2005-05-07 20:19:13 +04:00
|
|
|
* on platforms without the former.
|
2005-04-11 05:43:31 +04:00
|
|
|
*/
|
|
|
|
int
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_poll(struct pollfd *fds, int nfds, int timeout)
|
2005-04-11 05:43:31 +04:00
|
|
|
{
|
|
|
|
return poll(fds, nfds, timeout);
|
|
|
|
}
|
|
|
|
|
2019-06-23 02:40:53 +03:00
|
|
|
#ifndef SMALL
|
1999-10-13 06:47:54 +04:00
|
|
|
/*
|
|
|
|
* malloc() with inbuilt error checking
|
|
|
|
*/
|
1998-08-03 05:49:25 +04:00
|
|
|
void *
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_malloc(size_t size)
|
1998-08-03 05:49:25 +04:00
|
|
|
{
|
|
|
|
void *p;
|
|
|
|
|
|
|
|
p = malloc(size);
|
|
|
|
if (p == NULL)
|
|
|
|
err(1, "Unable to allocate %ld bytes of memory", (long)size);
|
|
|
|
return (p);
|
|
|
|
}
|
|
|
|
|
1999-11-28 09:32:04 +03:00
|
|
|
/*
|
|
|
|
* sl_init() with inbuilt error checking
|
|
|
|
*/
|
|
|
|
StringList *
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_sl_init(void)
|
1999-11-28 09:32:04 +03:00
|
|
|
{
|
|
|
|
StringList *p;
|
|
|
|
|
|
|
|
p = sl_init();
|
|
|
|
if (p == NULL)
|
|
|
|
err(1, "Unable to allocate memory for stringlist");
|
|
|
|
return (p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* sl_add() with inbuilt error checking
|
|
|
|
*/
|
|
|
|
void
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_sl_add(StringList *sl, char *i)
|
1999-11-28 09:32:04 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
if (sl_add(sl, i) == -1)
|
|
|
|
err(1, "Unable to add `%s' to stringlist", i);
|
|
|
|
}
|
|
|
|
|
1999-10-13 06:47:54 +04:00
|
|
|
/*
|
|
|
|
* strdup() with inbuilt error checking
|
|
|
|
*/
|
1998-08-03 05:49:25 +04:00
|
|
|
char *
|
2006-01-31 23:01:23 +03:00
|
|
|
ftp_strdup(const char *str)
|
1998-08-03 05:49:25 +04:00
|
|
|
{
|
|
|
|
char *s;
|
|
|
|
|
|
|
|
if (str == NULL)
|
2007-04-17 09:52:03 +04:00
|
|
|
errx(1, "ftp_strdup: called with NULL argument");
|
1998-08-03 05:49:25 +04:00
|
|
|
s = strdup(str);
|
|
|
|
if (s == NULL)
|
|
|
|
err(1, "Unable to allocate memory for string copy");
|
|
|
|
return (s);
|
|
|
|
}
|
2019-06-23 02:40:53 +03:00
|
|
|
#endif
|