1997-03-13 09:23:11 +03:00
|
|
|
/* $NetBSD: ftp.c,v 1.23 1997/03/13 06:23:17 lukem Exp $ */
|
1995-09-08 05:05:59 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1994-08-25 07:47:50 +04:00
|
|
|
* Copyright (c) 1985, 1989, 1993, 1994
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-03-21 12:45:37 +03: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.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef lint
|
1995-09-08 05:05:59 +04:00
|
|
|
#if 0
|
|
|
|
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94";
|
|
|
|
#else
|
1997-03-13 09:23:11 +03:00
|
|
|
static char rcsid[] = "$NetBSD: ftp.c,v 1.23 1997/03/13 06:23:17 lukem Exp $";
|
1995-09-08 05:05:59 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
#include <sys/types.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/ip.h>
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <arpa/inet.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <arpa/ftp.h>
|
|
|
|
#include <arpa/telnet.h>
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <ctype.h>
|
|
|
|
#include <err.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <errno.h>
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <netdb.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <pwd.h>
|
1994-08-25 07:47:50 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
1997-03-13 09:23:11 +03:00
|
|
|
#ifdef __STDC__
|
|
|
|
#include <stdarg.h>
|
|
|
|
#else
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <varargs.h>
|
1997-03-13 09:23:11 +03:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
#include "ftp_var.h"
|
|
|
|
|
|
|
|
struct sockaddr_in hisctladdr;
|
|
|
|
struct sockaddr_in data_addr;
|
|
|
|
int data = -1;
|
|
|
|
int abrtflag = 0;
|
1994-08-25 07:47:50 +04:00
|
|
|
jmp_buf ptabort;
|
|
|
|
int ptabflg;
|
1993-03-21 12:45:37 +03:00
|
|
|
int ptflag = 0;
|
|
|
|
struct sockaddr_in myctladdr;
|
|
|
|
off_t restart_point = 0;
|
|
|
|
|
|
|
|
|
|
|
|
FILE *cin, *cout;
|
|
|
|
|
|
|
|
char *
|
|
|
|
hookup(host, port)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *host;
|
1993-03-21 12:45:37 +03:00
|
|
|
int port;
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
struct hostent *hp = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
int s, len, tos;
|
1996-11-25 08:13:18 +03:00
|
|
|
static char hostnamebuf[MAXHOSTNAMELEN];
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
memset((void *)&hisctladdr, 0, sizeof(hisctladdr));
|
1995-05-21 19:50:45 +04:00
|
|
|
if (inet_aton(host, &hisctladdr.sin_addr) != 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
hisctladdr.sin_family = AF_INET;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(hostnamebuf, host, sizeof(hostnamebuf) - 1);
|
|
|
|
hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
} else {
|
|
|
|
hp = gethostbyname(host);
|
|
|
|
if (hp == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warnx("%s: %s", host, hstrerror(h_errno));
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
1994-08-25 07:47:50 +04:00
|
|
|
return ((char *) 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
hisctladdr.sin_family = hp->h_addrtype;
|
1995-05-21 19:50:45 +04:00
|
|
|
memcpy(&hisctladdr.sin_addr, hp->h_addr, hp->h_length);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf) - 1);
|
|
|
|
hostnamebuf[sizeof(hostnamebuf) - 1] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
hostname = hostnamebuf;
|
|
|
|
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
|
|
|
|
if (s < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("socket");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
hisctladdr.sin_port = port;
|
1996-11-28 06:12:28 +03:00
|
|
|
while (connect(s, (struct sockaddr *)&hisctladdr,
|
1997-03-13 09:23:11 +03:00
|
|
|
sizeof(hisctladdr)) < 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (hp && hp->h_addr_list[1]) {
|
|
|
|
int oerrno = errno;
|
1994-08-25 07:47:50 +04:00
|
|
|
char *ia;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
ia = inet_ntoa(hisctladdr.sin_addr);
|
1993-03-21 12:45:37 +03:00
|
|
|
errno = oerrno;
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("connect to address %s", ia);
|
1993-03-21 12:45:37 +03:00
|
|
|
hp->h_addr_list++;
|
1997-03-13 09:23:11 +03:00
|
|
|
memcpy(&hisctladdr.sin_addr, hp->h_addr, hp->h_length);
|
|
|
|
printf("Trying %s...\n",
|
|
|
|
inet_ntoa(hisctladdr.sin_addr));
|
|
|
|
(void)close(s);
|
1993-03-21 12:45:37 +03:00
|
|
|
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
|
|
|
|
if (s < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("socket");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("connect");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
goto bad;
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
len = sizeof(myctladdr);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("getsockname");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
#ifdef IP_TOS
|
|
|
|
tos = IPTOS_LOWDELAY;
|
|
|
|
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt TOS (ignored)");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif
|
|
|
|
cin = fdopen(s, "r");
|
|
|
|
cout = fdopen(s, "w");
|
|
|
|
if (cin == NULL || cout == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warnx("fdopen failed.");
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cin)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(cin);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cout)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (verbose)
|
|
|
|
printf("Connected to %s.\n", hostname);
|
|
|
|
if (getreply(0) > 2) { /* read startup message from server */
|
|
|
|
if (cin)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(cin);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cout)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
#ifdef SO_OOBINLINE
|
|
|
|
{
|
|
|
|
int on = 1;
|
|
|
|
|
|
|
|
if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
|
|
|
|
< 0 && debug) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* SO_OOBINLINE */
|
|
|
|
|
|
|
|
return (hostname);
|
|
|
|
bad:
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(s);
|
1993-03-21 12:45:37 +03:00
|
|
|
return ((char *)0);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
login(host)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *host;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
char tmp[80];
|
1994-08-25 07:47:50 +04:00
|
|
|
char *user, *pass, *acct;
|
1997-03-13 09:23:11 +03:00
|
|
|
char anonpass[MAXLOGNAME + 1 + MAXHOSTNAMELEN]; /* "user@hostname" */
|
|
|
|
char hostname[MAXHOSTNAMELEN];
|
1993-03-21 12:45:37 +03:00
|
|
|
int n, aflag = 0;
|
|
|
|
|
1996-11-25 08:13:18 +03:00
|
|
|
user = pass = acct = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ruserpass(host, &user, &pass, &acct) < 0) {
|
|
|
|
code = -1;
|
1994-08-25 07:47:50 +04:00
|
|
|
return (0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-25 08:13:18 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up arguments for an anonymous FTP session, if necessary.
|
|
|
|
*/
|
|
|
|
if ((user == NULL || pass == NULL) && anonftp) {
|
|
|
|
memset(anonpass, 0, sizeof(anonpass));
|
|
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up anonymous login password.
|
|
|
|
*/
|
|
|
|
user = getlogin();
|
|
|
|
gethostname(hostname, MAXHOSTNAMELEN);
|
|
|
|
#ifndef DONT_CHEAT_ANONPASS
|
|
|
|
/*
|
|
|
|
* Every anonymous FTP server I've encountered
|
|
|
|
* will accept the string "username@", and will
|
|
|
|
* append the hostname itself. We do this by default
|
|
|
|
* since many servers are picky about not having
|
1996-12-06 05:06:46 +03:00
|
|
|
* a FQDN in the anonymous password. - thorpej@netbsd.org
|
1996-11-25 08:13:18 +03:00
|
|
|
*/
|
|
|
|
snprintf(anonpass, sizeof(anonpass) - 1, "%s@",
|
|
|
|
user);
|
|
|
|
#else
|
|
|
|
snprintf(anonpass, sizeof(anonpass) - 1, "%s@%s",
|
|
|
|
user, hp->h_name);
|
|
|
|
#endif
|
|
|
|
pass = anonpass;
|
|
|
|
user = "anonymous";
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
while (user == NULL) {
|
|
|
|
char *myname = getlogin();
|
|
|
|
|
|
|
|
if (myname == NULL) {
|
|
|
|
struct passwd *pp = getpwuid(getuid());
|
|
|
|
|
|
|
|
if (pp != NULL)
|
|
|
|
myname = pp->pw_name;
|
|
|
|
}
|
|
|
|
if (myname)
|
|
|
|
printf("Name (%s:%s): ", host, myname);
|
|
|
|
else
|
|
|
|
printf("Name (%s): ", host);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fgets(tmp, sizeof(tmp) - 1, stdin);
|
1993-03-21 12:45:37 +03:00
|
|
|
tmp[strlen(tmp) - 1] = '\0';
|
|
|
|
if (*tmp == '\0')
|
|
|
|
user = myname;
|
|
|
|
else
|
|
|
|
user = tmp;
|
|
|
|
}
|
|
|
|
n = command("USER %s", user);
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
if (pass == NULL)
|
|
|
|
pass = getpass("Password:");
|
|
|
|
n = command("PASS %s", pass);
|
|
|
|
}
|
|
|
|
if (n == CONTINUE) {
|
|
|
|
aflag++;
|
|
|
|
acct = getpass("Account:");
|
|
|
|
n = command("ACCT %s", acct);
|
|
|
|
}
|
|
|
|
if (n != COMPLETE) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warnx("Login failed.");
|
1993-03-21 12:45:37 +03:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
if (!aflag && acct != NULL)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)command("ACCT %s", acct);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (proxy)
|
1994-08-25 07:47:50 +04:00
|
|
|
return (1);
|
1993-03-21 12:45:37 +03:00
|
|
|
for (n = 0; n < macnum; ++n) {
|
|
|
|
if (!strcmp("init", macros[n].mac_name)) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strcpy(line, "$init");
|
1993-03-21 12:45:37 +03:00
|
|
|
makeargv();
|
|
|
|
domacro(margc, margv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1997-03-13 09:23:11 +03:00
|
|
|
cmdabort(notused)
|
|
|
|
int notused;
|
1993-03-21 12:45:37 +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
|
|
|
alarmtimer(0);
|
1997-03-13 09:23:11 +03:00
|
|
|
putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
abrtflag++;
|
|
|
|
if (ptflag)
|
1996-11-28 06:12:28 +03:00
|
|
|
longjmp(ptabort, 1);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*VARARGS*/
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1997-03-13 09:23:11 +03:00
|
|
|
#ifdef __STDC__
|
|
|
|
command(const char *fmt, ...)
|
|
|
|
#else
|
1993-03-21 12:45:37 +03:00
|
|
|
command(va_alist)
|
1997-03-13 09:23:11 +03:00
|
|
|
va_dcl
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int r;
|
|
|
|
sig_t oldintr;
|
1997-03-13 09:23:11 +03:00
|
|
|
#ifndef __STDC__
|
|
|
|
const char *fmt;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
abrtflag = 0;
|
|
|
|
if (debug) {
|
1997-03-13 09:23:11 +03:00
|
|
|
fputs("---> ", stdout);
|
|
|
|
#ifdef __STDC__
|
|
|
|
va_start(ap, fmt);
|
|
|
|
#else
|
1993-03-21 12:45:37 +03:00
|
|
|
va_start(ap);
|
1997-03-13 09:23:11 +03:00
|
|
|
fmt = va_arg(ap, const char *);
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
if (strncmp("PASS ", fmt, 5) == 0)
|
1997-03-13 09:23:11 +03:00
|
|
|
fputs("PASS XXXX", stdout);
|
1996-11-25 08:13:18 +03:00
|
|
|
else if (strncmp("ACCT ", fmt, 5) == 0)
|
1997-03-13 09:23:11 +03:00
|
|
|
fputs("ACCT XXXX", stdout);
|
1996-11-25 08:13:18 +03:00
|
|
|
else
|
1997-03-13 09:23:11 +03:00
|
|
|
vprintf(fmt, ap);
|
1993-03-21 12:45:37 +03:00
|
|
|
va_end(ap);
|
1997-03-13 09:23:11 +03:00
|
|
|
putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (cout == NULL) {
|
1997-03-13 09:23:11 +03:00
|
|
|
warnx("No control connection for command.");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
oldintr = signal(SIGINT, cmdabort);
|
1997-03-13 09:23:11 +03:00
|
|
|
#ifdef __STDC__
|
|
|
|
va_start(ap, fmt);
|
|
|
|
#else
|
1993-03-21 12:45:37 +03:00
|
|
|
va_start(ap);
|
|
|
|
fmt = va_arg(ap, char *);
|
1997-03-13 09:23:11 +03:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
vfprintf(cout, fmt, ap);
|
|
|
|
va_end(ap);
|
1997-03-13 09:23:11 +03:00
|
|
|
fputs("\r\n", cout);
|
|
|
|
(void)fflush(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
cpend = 1;
|
|
|
|
r = getreply(!strcmp(fmt, "QUIT"));
|
|
|
|
if (abrtflag && oldintr != SIG_IGN)
|
|
|
|
(*oldintr)(SIGINT);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1994-08-25 07:47:50 +04:00
|
|
|
return (r);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1996-12-06 05:06:46 +03:00
|
|
|
char reply_string[BUFSIZ]; /* first line of previous reply */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
getreply(expecteof)
|
|
|
|
int expecteof;
|
|
|
|
{
|
1996-12-06 05:06:46 +03:00
|
|
|
char current_line[BUFSIZ]; /* last line of previous reply */
|
|
|
|
int c, n, line;
|
1994-08-25 07:47:50 +04:00
|
|
|
int dig;
|
1993-03-21 12:45:37 +03:00
|
|
|
int originalcode = 0, continuation = 0;
|
|
|
|
sig_t oldintr;
|
|
|
|
int pflag = 0;
|
1994-08-25 07:47:50 +04:00
|
|
|
char *cp, *pt = pasv;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
oldintr = signal(SIGINT, cmdabort);
|
1996-12-06 05:06:46 +03:00
|
|
|
for (line = 0 ;; line++) {
|
1993-03-21 12:45:37 +03:00
|
|
|
dig = n = code = 0;
|
1996-12-06 05:06:46 +03:00
|
|
|
cp = current_line;
|
1993-03-21 12:45:37 +03:00
|
|
|
while ((c = getc(cin)) != '\n') {
|
|
|
|
if (c == IAC) { /* handle telnet commands */
|
|
|
|
switch (c = getc(cin)) {
|
|
|
|
case WILL:
|
|
|
|
case WONT:
|
|
|
|
c = getc(cin);
|
|
|
|
fprintf(cout, "%c%c%c", IAC, DONT, c);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fflush(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case DO:
|
|
|
|
case DONT:
|
|
|
|
c = getc(cin);
|
|
|
|
fprintf(cout, "%c%c%c", IAC, WONT, c);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fflush(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
dig++;
|
|
|
|
if (c == EOF) {
|
|
|
|
if (expecteof) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = 221;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
lostpeer();
|
|
|
|
if (verbose) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts(
|
|
|
|
"421 Service not available, remote server has closed connection.");
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
code = 421;
|
1994-08-25 07:47:50 +04:00
|
|
|
return (4);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (c != '\r' && (verbose > 0 ||
|
|
|
|
(verbose > -1 && n == '5' && dig > 4))) {
|
|
|
|
if (proxflag &&
|
1996-12-06 05:06:46 +03:00
|
|
|
(dig == 1 || (dig == 5 && verbose == 0)))
|
1996-11-28 06:12:28 +03:00
|
|
|
printf("%s:", hostname);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar(c);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (dig < 4 && isdigit(c))
|
|
|
|
code = code * 10 + (c - '0');
|
|
|
|
if (!pflag && code == 227)
|
|
|
|
pflag = 1;
|
|
|
|
if (dig > 4 && pflag == 1 && isdigit(c))
|
|
|
|
pflag = 2;
|
|
|
|
if (pflag == 2) {
|
|
|
|
if (c != '\r' && c != ')')
|
|
|
|
*pt++ = c;
|
|
|
|
else {
|
|
|
|
*pt = '\0';
|
|
|
|
pflag = 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dig == 4 && c == '-') {
|
|
|
|
if (continuation)
|
|
|
|
code = 0;
|
|
|
|
continuation++;
|
|
|
|
}
|
|
|
|
if (n == 0)
|
|
|
|
n = c;
|
1996-12-06 05:06:46 +03:00
|
|
|
if (cp < ¤t_line[sizeof(current_line) - 1])
|
1993-03-21 12:45:37 +03:00
|
|
|
*cp++ = c;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
if (verbose > 0 || (verbose > -1 && n == '5')) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar(c);
|
|
|
|
(void)fflush (stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-12-25 19:02:06 +03:00
|
|
|
if (line == 0) {
|
|
|
|
size_t len = cp - current_line;
|
|
|
|
|
|
|
|
if (len > sizeof(reply_string))
|
|
|
|
len = sizeof(reply_string);
|
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(reply_string, current_line, len);
|
1996-12-25 19:02:06 +03:00
|
|
|
reply_string[len] = '\0';
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (continuation && code != originalcode) {
|
|
|
|
if (originalcode == 0)
|
|
|
|
originalcode = code;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*cp = '\0';
|
|
|
|
if (n != '1')
|
|
|
|
cpend = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (code == 421 || originalcode == 421)
|
|
|
|
lostpeer();
|
|
|
|
if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
|
|
|
|
(*oldintr)(SIGINT);
|
|
|
|
return (n - '0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
empty(mask, sec)
|
|
|
|
struct fd_set *mask;
|
|
|
|
int sec;
|
|
|
|
{
|
|
|
|
struct timeval t;
|
|
|
|
|
|
|
|
t.tv_sec = (long) sec;
|
|
|
|
t.tv_usec = 0;
|
1994-08-25 07:47:50 +04:00
|
|
|
return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
jmp_buf sendabort;
|
|
|
|
|
|
|
|
void
|
1997-03-13 09:23:11 +03:00
|
|
|
abortsend(notused)
|
|
|
|
int notused;
|
1993-03-21 12:45:37 +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
|
|
|
alarmtimer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag = 0;
|
|
|
|
abrtflag = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("\nsend aborted\nwaiting for remote to finish abort.");
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
longjmp(sendabort, 1);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
sendrequest(cmd, local, remote, printnames)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *cmd, *local, *remote;
|
1993-03-21 12:45:37 +03:00
|
|
|
int printnames;
|
|
|
|
{
|
|
|
|
struct stat st;
|
1994-08-25 07:47:50 +04:00
|
|
|
int c, d;
|
1996-12-06 05:06:46 +03:00
|
|
|
FILE *fin, *dout = 0;
|
1994-08-25 07:47:50 +04:00
|
|
|
int (*closefunc) __P((FILE *));
|
1996-11-25 08:13:18 +03:00
|
|
|
sig_t oldinti, oldintr, oldintp;
|
1996-12-06 05:06:46 +03:00
|
|
|
off_t hashbytes;
|
1993-03-21 12:45:37 +03:00
|
|
|
char *lmode, buf[BUFSIZ], *bufp;
|
1997-03-13 09:23:11 +03:00
|
|
|
int oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-12-06 05:06:46 +03:00
|
|
|
hashbytes = mark;
|
1996-11-25 08:13:18 +03:00
|
|
|
direction = "sent";
|
|
|
|
bytes = 0;
|
1996-12-06 05:06:46 +03:00
|
|
|
filesize = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
oprogress = progress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (verbose && printnames) {
|
|
|
|
if (local && *local != '-')
|
|
|
|
printf("local: %s ", local);
|
|
|
|
if (remote)
|
|
|
|
printf("remote: %s\n", remote);
|
|
|
|
}
|
|
|
|
if (proxy) {
|
|
|
|
proxtrans(cmd, local, remote);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (curtype != type)
|
|
|
|
changetype(type, 0);
|
|
|
|
closefunc = NULL;
|
|
|
|
oldintr = NULL;
|
|
|
|
oldintp = NULL;
|
1996-11-25 08:13:18 +03:00
|
|
|
oldinti = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
lmode = "w";
|
|
|
|
if (setjmp(sendabort)) {
|
|
|
|
while (cpend) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (data >= 0) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = -1;
|
|
|
|
}
|
|
|
|
if (oldintr)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1996-11-25 08:13:18 +03:00
|
|
|
if (oldinti)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINFO, oldinti);
|
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
oldintr = signal(SIGINT, abortsend);
|
1996-11-25 08:13:18 +03:00
|
|
|
oldinti = signal(SIGINFO, psummary);
|
1997-03-13 09:23:11 +03:00
|
|
|
if (strcmp(local, "-") == 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
fin = stdin;
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = 0;
|
|
|
|
} else if (*local == '|') {
|
1996-11-28 06:12:28 +03:00
|
|
|
oldintp = signal(SIGPIPE, SIG_IGN);
|
1993-03-21 12:45:37 +03:00
|
|
|
fin = popen(local + 1, "r");
|
|
|
|
if (fin == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("%s", local + 1);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGPIPE, oldintp);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
closefunc = pclose;
|
|
|
|
} else {
|
|
|
|
fin = fopen(local, "r");
|
|
|
|
if (fin == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
closefunc = fclose;
|
|
|
|
if (fstat(fileno(fin), &st) < 0 ||
|
|
|
|
(st.st_mode&S_IFMT) != S_IFREG) {
|
1997-03-13 09:23:11 +03:00
|
|
|
printf("%s: not a plain file.\n", local);
|
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
fclose(fin);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
filesize = st.st_size;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (initconn()) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (setjmp(sendabort))
|
|
|
|
goto abort;
|
|
|
|
|
|
|
|
if (restart_point &&
|
|
|
|
(strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
|
1994-08-25 07:47:50 +04:00
|
|
|
int rc;
|
|
|
|
|
1997-01-19 17:19:02 +03:00
|
|
|
rc = -1;
|
1994-08-25 07:47:50 +04:00
|
|
|
switch (curtype) {
|
|
|
|
case TYPE_A:
|
|
|
|
rc = fseek(fin, (long) restart_point, SEEK_SET);
|
|
|
|
break;
|
|
|
|
case TYPE_I:
|
|
|
|
case TYPE_L:
|
|
|
|
rc = lseek(fileno(fin), restart_point, SEEK_SET);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rc < 0) {
|
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
restart_point = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (command("REST %ld", (long) restart_point)
|
|
|
|
!= CONTINUE) {
|
|
|
|
restart_point = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
restart_point = 0;
|
|
|
|
lmode = "r+w";
|
|
|
|
}
|
|
|
|
if (remote) {
|
|
|
|
if (command("%s %s", cmd, remote) != PRELIM) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (command("%s", cmd) != PRELIM) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
dout = dataconn(lmode);
|
|
|
|
if (dout == NULL)
|
|
|
|
goto abort;
|
1996-12-06 05:06:46 +03:00
|
|
|
progressmeter(-1);
|
1993-03-21 12:45:37 +03:00
|
|
|
oldintp = signal(SIGPIPE, SIG_IGN);
|
|
|
|
switch (curtype) {
|
|
|
|
|
|
|
|
case TYPE_I:
|
|
|
|
case TYPE_L:
|
|
|
|
errno = d = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
while ((c = read(fileno(fin), buf, sizeof(buf))) > 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes += c;
|
|
|
|
for (bufp = buf; c > 0; c -= d, bufp += d)
|
|
|
|
if ((d = write(fileno(dout), bufp, c)) <= 0)
|
|
|
|
break;
|
[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
|
|
|
if (hash && (!progress || filesize < 0) ) {
|
1993-03-21 12:45:37 +03:00
|
|
|
while (bytes >= hashbytes) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
1996-11-25 08:13:18 +03:00
|
|
|
hashbytes += mark;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +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
|
|
|
if (hash && (!progress || filesize < 0) && bytes > 0) {
|
1996-11-25 08:13:18 +03:00
|
|
|
if (bytes < mark)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (c < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (d < 0) {
|
1996-11-25 08:13:18 +03:00
|
|
|
if (errno != EPIPE)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("netout");
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_A:
|
|
|
|
while ((c = getc(fin)) != EOF) {
|
|
|
|
if (c == '\n') {
|
[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
|
|
|
while (hash && (!progress || filesize < 0) &&
|
1996-12-06 05:06:46 +03:00
|
|
|
(bytes >= hashbytes)) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)fflush(stdout);
|
1996-11-25 08:13:18 +03:00
|
|
|
hashbytes += mark;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (ferror(dout))
|
|
|
|
break;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putc('\r', dout);
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes++;
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putc(c, dout);
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes++;
|
1996-12-06 05:06:46 +03:00
|
|
|
#if 0 /* this violates RFC */
|
|
|
|
if (c == '\r') {
|
|
|
|
(void)putc('\0', dout);
|
|
|
|
bytes++;
|
|
|
|
}
|
|
|
|
#endif
|
1993-03-21 12:45:37 +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
|
|
|
if (hash && (!progress || filesize < 0)) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (bytes < hashbytes)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (ferror(fin))
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (ferror(dout)) {
|
|
|
|
if (errno != EPIPE)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("netout");
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes = -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
[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
|
|
|
progressmeter(1);
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fin);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(dout);
|
|
|
|
(void)getreply(0);
|
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (bytes > 0)
|
1996-12-06 05:06:46 +03:00
|
|
|
ptransfer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
abort:
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (!cpend) {
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (data >= 0) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = -1;
|
|
|
|
}
|
|
|
|
if (dout)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(dout);
|
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
if (closefunc != NULL && fin != NULL)
|
|
|
|
(*closefunc)(fin);
|
|
|
|
if (bytes > 0)
|
1996-12-06 05:06:46 +03:00
|
|
|
ptransfer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
jmp_buf recvabort;
|
|
|
|
|
|
|
|
void
|
1997-03-13 09:23:11 +03:00
|
|
|
abortrecv(notused)
|
|
|
|
int notused;
|
1993-03-21 12:45:37 +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
|
|
|
alarmtimer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
mflag = 0;
|
|
|
|
abrtflag = 0;
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("\nreceive aborted\nwaiting for remote to finish abort.");
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
longjmp(recvabort, 1);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
recvrequest(cmd, local, remote, lmode, printnames)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *cmd, *local, *remote, *lmode;
|
1994-08-25 07:47:50 +04:00
|
|
|
int printnames;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
FILE *fout, *din = 0;
|
|
|
|
int (*closefunc) __P((FILE *));
|
1996-11-25 08:13:18 +03:00
|
|
|
sig_t oldinti, oldintr, oldintp;
|
1994-08-25 07:47:50 +04:00
|
|
|
int c, d, is_retr, tcrflag, bare_lfs = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
static int bufsize;
|
|
|
|
static char *buf;
|
1996-12-06 05:06:46 +03:00
|
|
|
off_t hashbytes;
|
1993-03-21 12:45:37 +03:00
|
|
|
struct stat st;
|
1996-11-28 06:12:28 +03:00
|
|
|
time_t mtime;
|
1996-12-06 05:06:46 +03:00
|
|
|
struct timeval tval[2];
|
1997-03-13 09:23:11 +03:00
|
|
|
int oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1996-12-06 05:06:46 +03:00
|
|
|
hashbytes = mark;
|
1996-11-25 08:13:18 +03:00
|
|
|
direction = "received";
|
|
|
|
bytes = 0;
|
1996-12-06 05:06:46 +03:00
|
|
|
filesize = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
oprogress = progress;
|
1993-03-21 12:45:37 +03:00
|
|
|
is_retr = strcmp(cmd, "RETR") == 0;
|
|
|
|
if (is_retr && verbose && printnames) {
|
|
|
|
if (local && *local != '-')
|
|
|
|
printf("local: %s ", local);
|
|
|
|
if (remote)
|
|
|
|
printf("remote: %s\n", remote);
|
|
|
|
}
|
|
|
|
if (proxy && is_retr) {
|
|
|
|
proxtrans(cmd, local, remote);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
closefunc = NULL;
|
|
|
|
oldintr = NULL;
|
|
|
|
oldintp = NULL;
|
|
|
|
tcrflag = !crflag && is_retr;
|
|
|
|
if (setjmp(recvabort)) {
|
|
|
|
while (cpend) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (data >= 0) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = -1;
|
|
|
|
}
|
|
|
|
if (oldintr)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1996-11-25 08:13:18 +03:00
|
|
|
if (oldinti)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINFO, oldinti);
|
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
oldintr = signal(SIGINT, abortrecv);
|
1996-11-25 08:13:18 +03:00
|
|
|
oldinti = signal(SIGINFO, psummary);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (strcmp(local, "-") && *local != '|') {
|
|
|
|
if (access(local, 2) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
char *dir = strrchr(local, '/');
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
if (errno != ENOENT && errno != EACCES) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (dir != NULL)
|
|
|
|
*dir = 0;
|
1996-11-25 08:13:18 +03:00
|
|
|
d = access(dir == local ? "/" : dir ? local : ".", 2);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (dir != NULL)
|
|
|
|
*dir = '/';
|
|
|
|
if (d < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!runique && errno == EACCES &&
|
|
|
|
chmod(local, 0600) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (runique && errno == EACCES &&
|
|
|
|
(local = gunique(local)) == NULL) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (runique && (local = gunique(local)) == NULL) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!is_retr) {
|
|
|
|
if (curtype != TYPE_A)
|
|
|
|
changetype(TYPE_A, 0);
|
1996-12-06 05:06:46 +03:00
|
|
|
} else {
|
|
|
|
if (curtype != type)
|
|
|
|
changetype(type, 0);
|
1996-12-29 07:05:29 +03:00
|
|
|
filesize = remotesize(remote, 0);
|
1996-12-06 05:06:46 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
if (initconn()) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (setjmp(recvabort))
|
|
|
|
goto abort;
|
|
|
|
if (is_retr && restart_point &&
|
|
|
|
command("REST %ld", (long) restart_point) != CONTINUE)
|
|
|
|
return;
|
|
|
|
if (remote) {
|
|
|
|
if (command("%s %s", cmd, remote) != PRELIM) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (command("%s", cmd) != PRELIM) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
din = dataconn("r");
|
|
|
|
if (din == NULL)
|
|
|
|
goto abort;
|
1997-03-13 09:23:11 +03:00
|
|
|
if (strcmp(local, "-") == 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
fout = stdout;
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = 0;
|
|
|
|
} else if (*local == '|') {
|
1993-03-21 12:45:37 +03:00
|
|
|
oldintp = signal(SIGPIPE, SIG_IGN);
|
|
|
|
fout = popen(local + 1, "w");
|
|
|
|
if (fout == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("%s", local+1);
|
1993-03-21 12:45:37 +03:00
|
|
|
goto abort;
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
closefunc = pclose;
|
|
|
|
} else {
|
|
|
|
fout = fopen(local, lmode);
|
|
|
|
if (fout == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
goto abort;
|
|
|
|
}
|
|
|
|
closefunc = fclose;
|
|
|
|
}
|
|
|
|
if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
|
|
|
|
st.st_blksize = BUFSIZ;
|
|
|
|
if (st.st_blksize > bufsize) {
|
|
|
|
if (buf)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)free(buf);
|
1993-03-21 12:45:37 +03:00
|
|
|
buf = malloc((unsigned)st.st_blksize);
|
|
|
|
if (buf == NULL) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("malloc");
|
1993-03-21 12:45:37 +03:00
|
|
|
bufsize = 0;
|
|
|
|
goto abort;
|
|
|
|
}
|
|
|
|
bufsize = st.st_blksize;
|
|
|
|
}
|
1996-12-06 05:06:46 +03:00
|
|
|
progressmeter(-1);
|
1993-03-21 12:45:37 +03:00
|
|
|
switch (curtype) {
|
|
|
|
|
|
|
|
case TYPE_I:
|
|
|
|
case TYPE_L:
|
1994-03-28 11:11:18 +04:00
|
|
|
if (restart_point &&
|
1994-08-25 07:47:50 +04:00
|
|
|
lseek(fileno(fout), restart_point, SEEK_SET) < 0) {
|
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fout);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
errno = d = 0;
|
|
|
|
while ((c = read(fileno(din), buf, bufsize)) > 0) {
|
|
|
|
if ((d = write(fileno(fout), buf, c)) != c)
|
|
|
|
break;
|
|
|
|
bytes += c;
|
[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
|
|
|
if (hash && (!progress || filesize < 0)) {
|
1993-03-21 12:45:37 +03:00
|
|
|
while (bytes >= hashbytes) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
1996-11-25 08:13:18 +03:00
|
|
|
hashbytes += mark;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +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
|
|
|
if (hash && (!progress || filesize < 0) && bytes > 0) {
|
1996-11-25 08:13:18 +03:00
|
|
|
if (bytes < mark)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (c < 0) {
|
|
|
|
if (errno != EPIPE)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("netin");
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes = -1;
|
|
|
|
}
|
|
|
|
if (d < c) {
|
|
|
|
if (d < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
else
|
1994-08-25 07:47:50 +04:00
|
|
|
warnx("%s: short write", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case TYPE_A:
|
|
|
|
if (restart_point) {
|
1994-08-25 07:47:50 +04:00
|
|
|
int i, n, ch;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
if (fseek(fout, 0L, SEEK_SET) < 0)
|
1993-03-21 12:45:37 +03:00
|
|
|
goto done;
|
|
|
|
n = restart_point;
|
|
|
|
for (i = 0; i++ < n;) {
|
|
|
|
if ((ch = getc(fout)) == EOF)
|
|
|
|
goto done;
|
|
|
|
if (ch == '\n')
|
|
|
|
i++;
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
if (fseek(fout, 0L, SEEK_CUR) < 0) {
|
1993-03-21 12:45:37 +03:00
|
|
|
done:
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fout);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while ((c = getc(din)) != EOF) {
|
|
|
|
if (c == '\n')
|
|
|
|
bare_lfs++;
|
|
|
|
while (c == '\r') {
|
[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
|
|
|
while (hash && (!progress || filesize < 0) &&
|
1996-12-06 05:06:46 +03:00
|
|
|
(bytes >= hashbytes)) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)fflush(stdout);
|
1996-11-25 08:13:18 +03:00
|
|
|
hashbytes += mark;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
bytes++;
|
|
|
|
if ((c = getc(din)) != '\n' || tcrflag) {
|
|
|
|
if (ferror(fout))
|
|
|
|
goto break2;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putc('\r', fout);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (c == '\0') {
|
|
|
|
bytes++;
|
|
|
|
goto contin2;
|
|
|
|
}
|
|
|
|
if (c == EOF)
|
|
|
|
goto contin2;
|
|
|
|
}
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putc(c, fout);
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes++;
|
|
|
|
contin2: ;
|
|
|
|
}
|
|
|
|
break2:
|
|
|
|
if (bare_lfs) {
|
1997-03-13 09:23:11 +03:00
|
|
|
printf(
|
|
|
|
"WARNING! %d bare linefeeds received in ASCII mode.\n", bare_lfs);
|
|
|
|
puts("File may not have transferred correctly.");
|
1993-03-21 12:45:37 +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
|
|
|
if (hash && (!progress || filesize < 0)) {
|
1993-03-21 12:45:37 +03:00
|
|
|
if (bytes < hashbytes)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)putchar('#');
|
|
|
|
(void)putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (ferror(din)) {
|
|
|
|
if (errno != EPIPE)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("netin");
|
1993-03-21 12:45:37 +03:00
|
|
|
bytes = -1;
|
|
|
|
}
|
|
|
|
if (ferror(fout))
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
}
|
[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
|
|
|
progressmeter(1);
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (closefunc != NULL)
|
|
|
|
(*closefunc)(fout);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
|
|
|
(void)fclose(din);
|
|
|
|
(void)getreply(0);
|
1996-12-29 07:05:29 +03:00
|
|
|
if (bytes >= 0 && is_retr) {
|
|
|
|
if (bytes > 0)
|
|
|
|
ptransfer(0);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (preserve && (closefunc == fclose)) {
|
1996-12-29 07:05:29 +03:00
|
|
|
mtime = remotemodtime(remote, 0);
|
1996-11-28 06:12:28 +03:00
|
|
|
if (mtime != -1) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)gettimeofday(&tval[0],
|
1996-12-06 05:06:46 +03:00
|
|
|
(struct timezone *)0);
|
|
|
|
tval[1].tv_sec = mtime;
|
|
|
|
tval[1].tv_usec = 0;
|
|
|
|
if (utimes(local, tval) == -1) {
|
1997-03-13 09:23:11 +03:00
|
|
|
printf(
|
|
|
|
"Can't change modification time on %s to %s",
|
|
|
|
local, asctime(localtime(&mtime)));
|
1996-11-28 06:12:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
1997-03-13 09:23:11 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
abort:
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
/* abort using RFC959 recommended IP,SYNC sequence */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
progress = oprogress;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (oldintp)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGPIPE, oldintp);
|
|
|
|
(void)signal(SIGINT, SIG_IGN);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (!cpend) {
|
|
|
|
code = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
abort_remote(din);
|
|
|
|
code = -1;
|
|
|
|
if (data >= 0) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = -1;
|
|
|
|
}
|
|
|
|
if (closefunc != NULL && fout != NULL)
|
|
|
|
(*closefunc)(fout);
|
|
|
|
if (din)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fclose(din);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (bytes > 0)
|
1996-12-06 05:06:46 +03:00
|
|
|
ptransfer(0);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
|
|
|
(void)signal(SIGINFO, oldinti);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Need to start a listen on the data channel before we send the command,
|
|
|
|
* otherwise the server's connect may fail.
|
|
|
|
*/
|
1994-08-25 07:47:50 +04:00
|
|
|
int
|
1993-03-21 12:45:37 +03:00
|
|
|
initconn()
|
|
|
|
{
|
1994-08-25 07:47:50 +04:00
|
|
|
char *p, *a;
|
1993-03-21 12:45:37 +03:00
|
|
|
int result, len, tmpno = 0;
|
|
|
|
int on = 1;
|
1994-08-25 08:27:41 +04:00
|
|
|
int a0, a1, a2, a3, p0, p1;
|
|
|
|
|
|
|
|
if (passivemode) {
|
|
|
|
data = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (data < 0) {
|
1996-12-29 07:05:29 +03:00
|
|
|
warn("socket");
|
1997-01-19 17:19:02 +03:00
|
|
|
return (1);
|
1994-08-25 08:27:41 +04:00
|
|
|
}
|
|
|
|
if ((options & SO_DEBUG) &&
|
|
|
|
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
|
1997-03-13 09:23:11 +03:00
|
|
|
sizeof(on)) < 0)
|
1996-12-29 07:05:29 +03:00
|
|
|
warn("setsockopt (ignored)");
|
1994-08-25 08:27:41 +04:00
|
|
|
if (command("PASV") != COMPLETE) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("Passive mode refused.");
|
1994-08-25 08:27:41 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* What we've got at this point is a string of comma
|
1995-09-08 05:05:59 +04:00
|
|
|
* separated one-byte unsigned integer values.
|
|
|
|
* The first four are the an IP address. The fifth is
|
|
|
|
* the MSB of the port number, the sixth is the LSB.
|
|
|
|
* From that we'll prepare a sockaddr_in.
|
1994-08-25 08:27:41 +04:00
|
|
|
*/
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
if (sscanf(pasv, "%d,%d,%d,%d,%d,%d",
|
1994-08-25 08:27:41 +04:00
|
|
|
&a0, &a1, &a2, &a3, &p0, &p1) != 6) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts(
|
|
|
|
"Passive mode address scan failure. Shouldn't happen!");
|
1994-08-25 08:27:41 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
|
1996-11-28 06:12:28 +03:00
|
|
|
memset(&data_addr, 0, sizeof(data_addr));
|
1994-08-25 08:27:41 +04:00
|
|
|
data_addr.sin_family = AF_INET;
|
|
|
|
a = (char *)&data_addr.sin_addr.s_addr;
|
|
|
|
a[0] = a0 & 0xff;
|
|
|
|
a[1] = a1 & 0xff;
|
|
|
|
a[2] = a2 & 0xff;
|
|
|
|
a[3] = a3 & 0xff;
|
|
|
|
p = (char *)&data_addr.sin_port;
|
|
|
|
p[0] = p0 & 0xff;
|
|
|
|
p[1] = p1 & 0xff;
|
|
|
|
|
|
|
|
if (connect(data, (struct sockaddr *)&data_addr,
|
|
|
|
sizeof(data_addr)) < 0) {
|
1996-12-29 07:05:29 +03:00
|
|
|
warn("connect");
|
1994-08-25 08:27:41 +04:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
#ifdef IP_TOS
|
|
|
|
on = IPTOS_THROUGHPUT;
|
|
|
|
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on,
|
|
|
|
sizeof(int)) < 0)
|
1996-12-29 07:05:29 +03:00
|
|
|
warn("setsockopt TOS (ignored)");
|
1994-08-25 08:27:41 +04:00
|
|
|
#endif
|
1997-01-19 17:19:02 +03:00
|
|
|
return (0);
|
1994-08-25 08:27:41 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
noport:
|
|
|
|
data_addr = myctladdr;
|
|
|
|
if (sendport)
|
1996-11-25 08:13:18 +03:00
|
|
|
data_addr.sin_port = 0; /* let system pick one */
|
1993-03-21 12:45:37 +03:00
|
|
|
if (data != -1)
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = socket(AF_INET, SOCK_STREAM, 0);
|
|
|
|
if (data < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("socket");
|
1993-03-21 12:45:37 +03:00
|
|
|
if (tmpno)
|
|
|
|
sendport = 1;
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
if (!sendport)
|
1996-11-28 06:12:28 +03:00
|
|
|
if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on,
|
1997-03-13 09:23:11 +03:00
|
|
|
sizeof(on)) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt (reuse address)");
|
1993-03-21 12:45:37 +03:00
|
|
|
goto bad;
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
if (bind(data, (struct sockaddr *)&data_addr, sizeof(data_addr)) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("bind");
|
1993-03-21 12:45:37 +03:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (options & SO_DEBUG &&
|
1996-11-28 06:12:28 +03:00
|
|
|
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on,
|
1997-03-13 09:23:11 +03:00
|
|
|
sizeof(on)) < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt (ignored)");
|
1997-03-13 09:23:11 +03:00
|
|
|
len = sizeof(data_addr);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("getsockname");
|
1993-03-21 12:45:37 +03:00
|
|
|
goto bad;
|
|
|
|
}
|
|
|
|
if (listen(data, 1) < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("listen");
|
1993-03-21 12:45:37 +03:00
|
|
|
if (sendport) {
|
|
|
|
a = (char *)&data_addr.sin_addr;
|
|
|
|
p = (char *)&data_addr.sin_port;
|
|
|
|
#define UC(b) (((int)b)&0xff)
|
|
|
|
result =
|
|
|
|
command("PORT %d,%d,%d,%d,%d,%d",
|
|
|
|
UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
|
|
|
|
UC(p[0]), UC(p[1]));
|
|
|
|
if (result == ERROR && sendport == -1) {
|
|
|
|
sendport = 0;
|
|
|
|
tmpno = 1;
|
|
|
|
goto noport;
|
|
|
|
}
|
|
|
|
return (result != COMPLETE);
|
|
|
|
}
|
|
|
|
if (tmpno)
|
|
|
|
sendport = 1;
|
|
|
|
#ifdef IP_TOS
|
|
|
|
on = IPTOS_THROUGHPUT;
|
|
|
|
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt TOS (ignored)");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif
|
|
|
|
return (0);
|
|
|
|
bad:
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data), data = -1;
|
1993-03-21 12:45:37 +03:00
|
|
|
if (tmpno)
|
|
|
|
sendport = 1;
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
FILE *
|
|
|
|
dataconn(lmode)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *lmode;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
struct sockaddr_in from;
|
1997-03-13 09:23:11 +03:00
|
|
|
int s, fromlen, tos;
|
|
|
|
|
|
|
|
fromlen = sizeof(from);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1994-08-25 08:27:41 +04:00
|
|
|
if (passivemode)
|
|
|
|
return (fdopen(data, lmode));
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
s = accept(data, (struct sockaddr *) &from, &fromlen);
|
|
|
|
if (s < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("accept");
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data), data = -1;
|
1993-03-21 12:45:37 +03:00
|
|
|
return (NULL);
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)close(data);
|
1993-03-21 12:45:37 +03:00
|
|
|
data = s;
|
|
|
|
#ifdef IP_TOS
|
|
|
|
tos = IPTOS_THROUGHPUT;
|
|
|
|
if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("setsockopt TOS (ignored)");
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif
|
|
|
|
return (fdopen(data, lmode));
|
|
|
|
}
|
|
|
|
|
1996-11-25 08:13:18 +03:00
|
|
|
void
|
|
|
|
psummary(notused)
|
|
|
|
int notused;
|
|
|
|
{
|
1996-12-06 05:06:46 +03:00
|
|
|
|
1996-11-25 08:13:18 +03:00
|
|
|
if (bytes > 0)
|
1996-12-06 05:06:46 +03:00
|
|
|
ptransfer(1);
|
1996-11-25 08:13:18 +03:00
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
void
|
1997-03-13 09:23:11 +03:00
|
|
|
psabort(notused)
|
|
|
|
int notused;
|
1993-03-21 12:45:37 +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
|
|
|
alarmtimer(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
abrtflag++;
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(flag)
|
|
|
|
int flag;
|
|
|
|
{
|
|
|
|
sig_t oldintr;
|
|
|
|
static struct comvars {
|
|
|
|
int connect;
|
|
|
|
char name[MAXHOSTNAMELEN];
|
|
|
|
struct sockaddr_in mctl;
|
|
|
|
struct sockaddr_in hctl;
|
|
|
|
FILE *in;
|
|
|
|
FILE *out;
|
|
|
|
int tpe;
|
|
|
|
int curtpe;
|
|
|
|
int cpnd;
|
|
|
|
int sunqe;
|
|
|
|
int runqe;
|
|
|
|
int mcse;
|
|
|
|
int ntflg;
|
|
|
|
char nti[17];
|
|
|
|
char nto[17];
|
|
|
|
int mapflg;
|
|
|
|
char mi[MAXPATHLEN];
|
|
|
|
char mo[MAXPATHLEN];
|
|
|
|
} proxstruct, tmpstruct;
|
|
|
|
struct comvars *ip, *op;
|
|
|
|
|
|
|
|
abrtflag = 0;
|
|
|
|
oldintr = signal(SIGINT, psabort);
|
|
|
|
if (flag) {
|
|
|
|
if (proxy)
|
|
|
|
return;
|
|
|
|
ip = &tmpstruct;
|
|
|
|
op = &proxstruct;
|
|
|
|
proxy++;
|
|
|
|
} else {
|
|
|
|
if (!proxy)
|
|
|
|
return;
|
|
|
|
ip = &proxstruct;
|
|
|
|
op = &tmpstruct;
|
|
|
|
proxy = 0;
|
|
|
|
}
|
|
|
|
ip->connect = connected;
|
|
|
|
connected = op->connect;
|
|
|
|
if (hostname) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(ip->name, hostname, sizeof(ip->name) - 1);
|
|
|
|
ip->name[sizeof(ip->name) - 1] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
} else
|
1997-03-13 09:23:11 +03:00
|
|
|
ip->name[0] = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
hostname = op->name;
|
|
|
|
ip->hctl = hisctladdr;
|
|
|
|
hisctladdr = op->hctl;
|
|
|
|
ip->mctl = myctladdr;
|
|
|
|
myctladdr = op->mctl;
|
|
|
|
ip->in = cin;
|
|
|
|
cin = op->in;
|
|
|
|
ip->out = cout;
|
|
|
|
cout = op->out;
|
|
|
|
ip->tpe = type;
|
|
|
|
type = op->tpe;
|
|
|
|
ip->curtpe = curtype;
|
|
|
|
curtype = op->curtpe;
|
|
|
|
ip->cpnd = cpend;
|
|
|
|
cpend = op->cpnd;
|
|
|
|
ip->sunqe = sunique;
|
|
|
|
sunique = op->sunqe;
|
|
|
|
ip->runqe = runique;
|
|
|
|
runique = op->runqe;
|
|
|
|
ip->mcse = mcase;
|
|
|
|
mcase = op->mcse;
|
|
|
|
ip->ntflg = ntflag;
|
|
|
|
ntflag = op->ntflg;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(ip->nti, ntin, sizeof(ip->nti) - 1);
|
|
|
|
(ip->nti)[sizeof(ip->nti) - 1] = '\0';
|
|
|
|
(void)strcpy(ntin, op->nti);
|
|
|
|
(void)strncpy(ip->nto, ntout, sizeof(ip->nto) - 1);
|
|
|
|
(ip->nto)[sizeof(ip->nto) - 1] = '\0';
|
|
|
|
(void)strcpy(ntout, op->nto);
|
1993-03-21 12:45:37 +03:00
|
|
|
ip->mapflg = mapflag;
|
|
|
|
mapflag = op->mapflg;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strncpy(ip->mi, mapin, sizeof(ip->mi) - 1);
|
|
|
|
(ip->mi)[sizeof(ip->mi) - 1] = '\0';
|
|
|
|
(void)strcpy(mapin, op->mi);
|
|
|
|
(void)strncpy(ip->mo, mapout, sizeof(ip->mo) - 1);
|
|
|
|
(ip->mo)[sizeof(ip->mo) - 1] = '\0';
|
|
|
|
(void)strcpy(mapout, op->mo);
|
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (abrtflag) {
|
|
|
|
abrtflag = 0;
|
|
|
|
(*oldintr)(SIGINT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1997-03-13 09:23:11 +03:00
|
|
|
abortpt(notused)
|
|
|
|
int notused;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
1994-08-25 07:47:50 +04: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
|
|
|
alarmtimer(0);
|
1997-03-13 09:23:11 +03:00
|
|
|
putchar('\n');
|
|
|
|
(void)fflush(stdout);
|
1993-03-21 12:45:37 +03:00
|
|
|
ptabflg++;
|
|
|
|
mflag = 0;
|
|
|
|
abrtflag = 0;
|
|
|
|
longjmp(ptabort, 1);
|
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
proxtrans(cmd, local, remote)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *cmd, *local, *remote;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
sig_t oldintr;
|
|
|
|
int secndflag = 0, prox_type, nfnd;
|
|
|
|
char *cmd2;
|
|
|
|
struct fd_set mask;
|
|
|
|
|
|
|
|
if (strcmp(cmd, "RETR"))
|
|
|
|
cmd2 = "RETR";
|
|
|
|
else
|
|
|
|
cmd2 = runique ? "STOU" : "STOR";
|
|
|
|
if ((prox_type = type) == 0) {
|
|
|
|
if (unix_server && unix_proxy)
|
|
|
|
prox_type = TYPE_I;
|
|
|
|
else
|
|
|
|
prox_type = TYPE_A;
|
|
|
|
}
|
|
|
|
if (curtype != prox_type)
|
|
|
|
changetype(prox_type, 1);
|
|
|
|
if (command("PASV") != COMPLETE) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("proxy server does not support third party transfers.");
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
pswitch(0);
|
|
|
|
if (!connected) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("No primary connection.");
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(1);
|
|
|
|
code = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (curtype != prox_type)
|
|
|
|
changetype(prox_type, 1);
|
|
|
|
if (command("PORT %s", pasv) != COMPLETE) {
|
|
|
|
pswitch(1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (setjmp(ptabort))
|
|
|
|
goto abort;
|
|
|
|
oldintr = signal(SIGINT, abortpt);
|
|
|
|
if (command("%s %s", cmd, remote) != PRELIM) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
sleep(2);
|
|
|
|
pswitch(1);
|
|
|
|
secndflag++;
|
|
|
|
if (command("%s %s", cmd2, local) != PRELIM)
|
|
|
|
goto abort;
|
|
|
|
ptflag++;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(0);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
pswitch(1);
|
|
|
|
ptflag = 0;
|
|
|
|
printf("local: %s remote: %s\n", local, remote);
|
|
|
|
return;
|
|
|
|
abort:
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, SIG_IGN);
|
1993-03-21 12:45:37 +03:00
|
|
|
ptflag = 0;
|
|
|
|
if (strcmp(cmd, "RETR") && !proxy)
|
|
|
|
pswitch(1);
|
|
|
|
else if (!strcmp(cmd, "RETR") && proxy)
|
|
|
|
pswitch(0);
|
|
|
|
if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
|
|
|
|
if (command("%s %s", cmd2, local) != PRELIM) {
|
|
|
|
pswitch(0);
|
|
|
|
if (cpend)
|
|
|
|
abort_remote((FILE *) NULL);
|
|
|
|
}
|
|
|
|
pswitch(1);
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cpend)
|
|
|
|
abort_remote((FILE *) NULL);
|
|
|
|
pswitch(!proxy);
|
|
|
|
if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */
|
|
|
|
if (command("%s %s", cmd2, local) != PRELIM) {
|
|
|
|
pswitch(0);
|
|
|
|
if (cpend)
|
|
|
|
abort_remote((FILE *) NULL);
|
|
|
|
pswitch(1);
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cpend)
|
|
|
|
abort_remote((FILE *) NULL);
|
|
|
|
pswitch(!proxy);
|
|
|
|
if (cpend) {
|
|
|
|
FD_ZERO(&mask);
|
|
|
|
FD_SET(fileno(cin), &mask);
|
|
|
|
if ((nfnd = empty(&mask, 10)) <= 0) {
|
|
|
|
if (nfnd < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("abort");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
|
|
|
lostpeer();
|
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (proxy)
|
|
|
|
pswitch(0);
|
|
|
|
pswitch(1);
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)signal(SIGINT, oldintr);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
|
|
|
reset(argc, argv)
|
|
|
|
int argc;
|
|
|
|
char *argv[];
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
struct fd_set mask;
|
|
|
|
int nfnd = 1;
|
|
|
|
|
|
|
|
FD_ZERO(&mask);
|
|
|
|
while (nfnd > 0) {
|
|
|
|
FD_SET(fileno(cin), &mask);
|
1996-11-28 06:12:28 +03:00
|
|
|
if ((nfnd = empty(&mask, 0)) < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("reset");
|
1993-03-21 12:45:37 +03:00
|
|
|
code = -1;
|
|
|
|
lostpeer();
|
|
|
|
}
|
|
|
|
else if (nfnd) {
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
gunique(local)
|
1996-11-28 06:12:28 +03:00
|
|
|
const char *local;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
static char new[MAXPATHLEN];
|
1994-08-25 07:47:50 +04:00
|
|
|
char *cp = strrchr(local, '/');
|
1993-03-21 12:45:37 +03:00
|
|
|
int d, count=0;
|
|
|
|
char ext = '1';
|
|
|
|
|
|
|
|
if (cp)
|
|
|
|
*cp = '\0';
|
1996-11-25 08:13:18 +03:00
|
|
|
d = access(cp == local ? "/" : cp ? local : ".", 2);
|
1993-03-21 12:45:37 +03:00
|
|
|
if (cp)
|
|
|
|
*cp = '/';
|
|
|
|
if (d < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("local: %s", local);
|
|
|
|
return ((char *) 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)strcpy(new, local);
|
1993-03-21 12:45:37 +03:00
|
|
|
cp = new + strlen(new);
|
|
|
|
*cp++ = '.';
|
|
|
|
while (!d) {
|
|
|
|
if (++count == 100) {
|
1997-03-13 09:23:11 +03:00
|
|
|
puts("runique: can't find unique file name.");
|
1994-08-25 07:47:50 +04:00
|
|
|
return ((char *) 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
*cp++ = ext;
|
|
|
|
*cp = '\0';
|
|
|
|
if (ext == '9')
|
|
|
|
ext = '0';
|
|
|
|
else
|
|
|
|
ext++;
|
|
|
|
if ((d = access(new, 0)) < 0)
|
|
|
|
break;
|
|
|
|
if (ext != '0')
|
|
|
|
cp--;
|
|
|
|
else if (*(cp - 2) == '.')
|
|
|
|
*(cp - 1) = '1';
|
|
|
|
else {
|
|
|
|
*(cp - 2) = *(cp - 2) + 1;
|
|
|
|
cp--;
|
|
|
|
}
|
|
|
|
}
|
1994-08-25 07:47:50 +04:00
|
|
|
return (new);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-08-25 07:47:50 +04:00
|
|
|
void
|
1993-03-21 12:45:37 +03:00
|
|
|
abort_remote(din)
|
1994-08-25 07:47:50 +04:00
|
|
|
FILE *din;
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
int nfnd;
|
|
|
|
struct fd_set mask;
|
|
|
|
|
1997-03-13 09:23:11 +03:00
|
|
|
if (cout == NULL) {
|
|
|
|
warnx("Lost control connection for abort.");
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
|
|
|
lostpeer();
|
|
|
|
return;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* send IAC in urgent mode instead of DM because 4.3BSD places oob mark
|
|
|
|
* after urgent byte rather than before as is protocol now
|
|
|
|
*/
|
|
|
|
sprintf(buf, "%c%c%c", IAC, IP, IAC);
|
|
|
|
if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("abort");
|
1996-11-28 06:12:28 +03:00
|
|
|
fprintf(cout, "%cABOR\r\n", DM);
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)fflush(cout);
|
1993-03-21 12:45:37 +03:00
|
|
|
FD_ZERO(&mask);
|
|
|
|
FD_SET(fileno(cin), &mask);
|
1996-11-25 08:13:18 +03:00
|
|
|
if (din) {
|
1993-03-21 12:45:37 +03:00
|
|
|
FD_SET(fileno(din), &mask);
|
|
|
|
}
|
|
|
|
if ((nfnd = empty(&mask, 10)) <= 0) {
|
|
|
|
if (nfnd < 0) {
|
1994-08-25 07:47:50 +04:00
|
|
|
warn("abort");
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
if (ptabflg)
|
|
|
|
code = -1;
|
|
|
|
lostpeer();
|
|
|
|
}
|
|
|
|
if (din && FD_ISSET(fileno(din), &mask)) {
|
|
|
|
while (read(fileno(din), buf, BUFSIZ) > 0)
|
|
|
|
/* LOOP */;
|
|
|
|
}
|
|
|
|
if (getreply(0) == ERROR && code == 552) {
|
|
|
|
/* 552 needed for nic style abort */
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1997-03-13 09:23:11 +03:00
|
|
|
(void)getreply(0);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|