version 1.9, 1997/01/08 13:19:11 |
version 1.10, 1997/02/03 01:02:39 |
|
|
/* $OpenBSD$ */ |
/* $NetBSD: ftp.c,v 1.22 1997/02/01 10:45:03 lukem Exp $ */ |
/* $NetBSD: ftp.c,v 1.13 1995/09/16 22:32:59 pk Exp $ */ |
|
|
|
/* |
/* |
* Copyright (c) 1985, 1989, 1993, 1994 |
* Copyright (c) 1985, 1989, 1993, 1994 |
|
|
#if 0 |
#if 0 |
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; |
static char sccsid[] = "@(#)ftp.c 8.6 (Berkeley) 10/27/94"; |
#else |
#else |
static char rcsid[] = "$OpenBSD$"; |
static char rcsid[] = "$NetBSD: ftp.c,v 1.22 1997/02/01 10:45:03 lukem Exp $"; |
#endif |
#endif |
#endif /* not lint */ |
#endif /* not lint */ |
|
|
#include <sys/param.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <sys/stat.h> |
#include <sys/ioctl.h> |
|
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/time.h> |
|
#include <sys/file.h> |
|
|
|
#include <netinet/in.h> |
#include <netinet/in.h> |
#include <netinet/in_systm.h> |
#include <netinet/in_systm.h> |
|
|
#include <ctype.h> |
#include <ctype.h> |
#include <err.h> |
#include <err.h> |
#include <errno.h> |
#include <errno.h> |
#include <fcntl.h> |
|
#include <netdb.h> |
#include <netdb.h> |
#include <pwd.h> |
#include <pwd.h> |
#include <signal.h> |
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
|
|
|
|
#include "ftp_var.h" |
#include "ftp_var.h" |
|
|
extern int h_errno; |
|
|
|
struct sockaddr_in hisctladdr; |
struct sockaddr_in hisctladdr; |
struct sockaddr_in data_addr; |
struct sockaddr_in data_addr; |
int data = -1; |
int data = -1; |
|
|
|
|
char * |
char * |
hookup(host, port) |
hookup(host, port) |
char *host; |
const char *host; |
int port; |
int port; |
{ |
{ |
struct hostent *hp = 0; |
struct hostent *hp = 0; |
int s, len, tos; |
int s, len, tos; |
static char hostnamebuf[80]; |
static char hostnamebuf[MAXHOSTNAMELEN]; |
|
|
memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); |
memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); |
if (inet_aton(host, &hisctladdr.sin_addr) != 0) { |
if (inet_aton(host, &hisctladdr.sin_addr) != 0) { |
|
|
return (0); |
return (0); |
} |
} |
hisctladdr.sin_port = port; |
hisctladdr.sin_port = port; |
while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { |
while (connect(s, (struct sockaddr *)&hisctladdr, |
|
sizeof (hisctladdr)) < 0) { |
if (hp && hp->h_addr_list[1]) { |
if (hp && hp->h_addr_list[1]) { |
int oerrno = errno; |
int oerrno = errno; |
char *ia; |
char *ia; |
|
|
|
|
int |
int |
login(host) |
login(host) |
char *host; |
const char *host; |
{ |
{ |
char tmp[80]; |
char tmp[80]; |
char *user, *pass, *acct; |
char *user, *pass, *acct; |
|
char anonpass[MAXLOGNAME + MAXHOSTNAMELEN + 2]; /* "user@hostname\0" */ |
|
char hostname[MAXHOSTNAMELEN + 1]; |
int n, aflag = 0; |
int n, aflag = 0; |
char anonpass[64 + 1]; |
|
|
|
user = pass = acct = 0; |
user = pass = acct = NULL; |
if (ruserpass(host, &user, &pass, &acct) < 0) { |
if (ruserpass(host, &user, &pass, &acct) < 0) { |
code = -1; |
code = -1; |
return (0); |
return (0); |
} |
} |
if (anonftp) { |
|
|
/* |
|
* 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(); |
user = getlogin(); |
strncpy(anonpass, user, sizeof anonpass - 1); |
gethostname(hostname, MAXHOSTNAMELEN); |
anonpass[sizeof anonpass - 1] = '\0'; |
#ifndef DONT_CHEAT_ANONPASS |
strncat(anonpass, "@anon.openbsd.org", /* XXX ugly */ |
/* |
sizeof anonpass - strlen(anonpass) - 1); |
* Every anonymous FTP server I've encountered |
|
* will accept the string "username@", and will |
|
* append the hostname itself. We do this by default |
|
* since many servers are picky about not having |
|
* a FQDN in the anonymous password. - thorpej@netbsd.org |
|
*/ |
|
snprintf(anonpass, sizeof(anonpass) - 1, "%s@", |
|
user); |
|
#else |
|
snprintf(anonpass, sizeof(anonpass) - 1, "%s@%s", |
|
user, hp->h_name); |
|
#endif |
pass = anonpass; |
pass = anonpass; |
user = "anonymous"; |
user = "anonymous"; |
} |
} |
|
|
while (user == NULL) { |
while (user == NULL) { |
char *myname = getlogin(); |
char *myname = getlogin(); |
|
|
|
|
cmdabort() |
cmdabort() |
{ |
{ |
|
|
|
alarmtimer(0); |
printf("\n"); |
printf("\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
abrtflag++; |
abrtflag++; |
if (ptflag) |
if (ptflag) |
longjmp(ptabort,1); |
longjmp(ptabort, 1); |
} |
} |
|
|
/*VARARGS*/ |
/*VARARGS*/ |
|
|
fmt = va_arg(ap, char *); |
fmt = va_arg(ap, char *); |
if (strncmp("PASS ", fmt, 5) == 0) |
if (strncmp("PASS ", fmt, 5) == 0) |
printf("PASS XXXX"); |
printf("PASS XXXX"); |
else |
else if (strncmp("ACCT ", fmt, 5) == 0) |
|
printf("ACCT XXXX"); |
|
else |
vfprintf(stdout, fmt, ap); |
vfprintf(stdout, fmt, ap); |
va_end(ap); |
va_end(ap); |
printf("\n"); |
printf("\n"); |
|
|
return (r); |
return (r); |
} |
} |
|
|
char reply_string[BUFSIZ]; /* last line of previous reply */ |
char reply_string[BUFSIZ]; /* first line of previous reply */ |
|
|
int |
int |
getreply(expecteof) |
getreply(expecteof) |
int expecteof; |
int expecteof; |
{ |
{ |
int c, n; |
char current_line[BUFSIZ]; /* last line of previous reply */ |
|
int c, n, line; |
int dig; |
int dig; |
int originalcode = 0, continuation = 0; |
int originalcode = 0, continuation = 0; |
sig_t oldintr; |
sig_t oldintr; |
|
|
char *cp, *pt = pasv; |
char *cp, *pt = pasv; |
|
|
oldintr = signal(SIGINT, cmdabort); |
oldintr = signal(SIGINT, cmdabort); |
for (;;) { |
for (line = 0 ;; line++) { |
dig = n = code = 0; |
dig = n = code = 0; |
cp = reply_string; |
cp = current_line; |
while ((c = getc(cin)) != '\n') { |
while ((c = getc(cin)) != '\n') { |
if (c == IAC) { /* handle telnet commands */ |
if (c == IAC) { /* handle telnet commands */ |
switch (c = getc(cin)) { |
switch (c = getc(cin)) { |
|
|
dig++; |
dig++; |
if (c == EOF) { |
if (c == EOF) { |
if (expecteof) { |
if (expecteof) { |
(void) signal(SIGINT,oldintr); |
(void) signal(SIGINT, oldintr); |
code = 221; |
code = 221; |
return (0); |
return (0); |
} |
} |
lostpeer(); |
lostpeer(); |
if (verbose) { |
if (verbose) { |
printf("421 Service not available, remote server has closed connection\n"); |
printf("421 Service not available, " |
|
"remote server has closed " |
|
"connection\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
code = 421; |
code = 421; |
return (4); |
return (4); |
} |
} |
if (n == 0) |
if (c != '\r' && (verbose > 0 || |
n = c; |
(verbose > -1 && n == '5' && dig > 4))) { |
if (c != '\r' && (n < '5' || !retry_connect) && |
|
(verbose > 0 || |
|
(verbose > -1 && n == '5' && dig > 4))) { |
|
if (proxflag && |
if (proxflag && |
(dig == 1 || dig == 5 && verbose == 0)) |
(dig == 1 || (dig == 5 && verbose == 0))) |
printf("%s:",hostname); |
printf("%s:", hostname); |
(void) putchar(c); |
(void) putchar(c); |
} |
} |
if (dig < 4 && isdigit(c)) |
if (dig < 4 && isdigit(c)) |
|
|
code = 0; |
code = 0; |
continuation++; |
continuation++; |
} |
} |
if (cp < &reply_string[sizeof(reply_string) - 1]) |
if (n == 0) |
|
n = c; |
|
if (cp < ¤t_line[sizeof(current_line) - 1]) |
*cp++ = c; |
*cp++ = c; |
} |
} |
if ((verbose > 0 || (verbose > -1 && n == '5')) && |
if (verbose > 0 || (verbose > -1 && n == '5')) { |
(n < '5' || !retry_connect)) { |
|
(void) putchar(c); |
(void) putchar(c); |
(void) fflush (stdout); |
(void) fflush (stdout); |
} |
} |
|
if (line == 0) { |
|
size_t len = cp - current_line; |
|
|
|
if (len > sizeof(reply_string)) |
|
len = sizeof(reply_string); |
|
|
|
(void) strncpy(reply_string, current_line, len); |
|
reply_string[len] = '\0'; |
|
} |
if (continuation && code != originalcode) { |
if (continuation && code != originalcode) { |
if (originalcode == 0) |
if (originalcode == 0) |
originalcode = code; |
originalcode = code; |
|
|
*cp = '\0'; |
*cp = '\0'; |
if (n != '1') |
if (n != '1') |
cpend = 0; |
cpend = 0; |
(void) signal(SIGINT,oldintr); |
(void) signal(SIGINT, oldintr); |
if (code == 421 || originalcode == 421) |
if (code == 421 || originalcode == 421) |
lostpeer(); |
lostpeer(); |
if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) |
if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) |
|
|
abortsend() |
abortsend() |
{ |
{ |
|
|
|
alarmtimer(0); |
mflag = 0; |
mflag = 0; |
abrtflag = 0; |
abrtflag = 0; |
printf("\nsend aborted\nwaiting for remote to finish abort\n"); |
printf("\nsend aborted\nwaiting for remote to finish abort\n"); |
|
|
|
|
void |
void |
sendrequest(cmd, local, remote, printnames) |
sendrequest(cmd, local, remote, printnames) |
char *cmd, *local, *remote; |
const char *cmd, *local, *remote; |
int printnames; |
int printnames; |
{ |
{ |
struct stat st; |
struct stat st; |
struct timeval start, stop; |
|
int c, d; |
int c, d; |
FILE *fin, *dout = 0, *popen(); |
FILE *fin, *dout = 0; |
int (*closefunc) __P((FILE *)); |
int (*closefunc) __P((FILE *)); |
sig_t oldintr, oldintp; |
sig_t oldinti, oldintr, oldintp; |
long bytes = 0, hashbytes = mark; |
off_t hashbytes; |
char *lmode, buf[BUFSIZ], *bufp; |
char *lmode, buf[BUFSIZ], *bufp; |
|
|
|
hashbytes = mark; |
|
direction = "sent"; |
|
bytes = 0; |
|
filesize = -1; |
if (verbose && printnames) { |
if (verbose && printnames) { |
if (local && *local != '-') |
if (local && *local != '-') |
printf("local: %s ", local); |
printf("local: %s ", local); |
|
|
closefunc = NULL; |
closefunc = NULL; |
oldintr = NULL; |
oldintr = NULL; |
oldintp = NULL; |
oldintp = NULL; |
|
oldinti = NULL; |
lmode = "w"; |
lmode = "w"; |
if (setjmp(sendabort)) { |
if (setjmp(sendabort)) { |
while (cpend) { |
while (cpend) { |
|
|
data = -1; |
data = -1; |
} |
} |
if (oldintr) |
if (oldintr) |
(void) signal(SIGINT,oldintr); |
(void) signal(SIGINT, oldintr); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE,oldintp); |
(void) signal(SIGPIPE, oldintp); |
|
if (oldinti) |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
oldintr = signal(SIGINT, abortsend); |
oldintr = signal(SIGINT, abortsend); |
|
oldinti = signal(SIGINFO, psummary); |
if (strcmp(local, "-") == 0) |
if (strcmp(local, "-") == 0) |
fin = stdin; |
fin = stdin; |
else if (*local == '|') { |
else if (*local == '|') { |
oldintp = signal(SIGPIPE,SIG_IGN); |
oldintp = signal(SIGPIPE, SIG_IGN); |
fin = popen(local + 1, "r"); |
fin = popen(local + 1, "r"); |
if (fin == NULL) { |
if (fin == NULL) { |
warn("%s", local + 1); |
warn("%s", local + 1); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
|
if (fin == NULL) { |
if (fin == NULL) { |
warn("local: %s", local); |
warn("local: %s", local); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
|
(st.st_mode&S_IFMT) != S_IFREG) { |
(st.st_mode&S_IFMT) != S_IFREG) { |
fprintf(stdout, "%s: not a plain file.\n", local); |
fprintf(stdout, "%s: not a plain file.\n", local); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
fclose(fin); |
fclose(fin); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
filesize = st.st_size; |
} |
} |
if (initconn()) { |
if (initconn()) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
code = -1; |
code = -1; |
|
|
(strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { |
(strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { |
int rc; |
int rc; |
|
|
|
rc = -1; |
switch (curtype) { |
switch (curtype) { |
case TYPE_A: |
case TYPE_A: |
rc = fseek(fin, (long) restart_point, SEEK_SET); |
rc = fseek(fin, (long) restart_point, SEEK_SET); |
|
|
if (remote) { |
if (remote) { |
if (command("%s %s", cmd, remote) != PRELIM) { |
if (command("%s %s", cmd, remote) != PRELIM) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
if (closefunc != NULL) |
if (closefunc != NULL) |
|
|
} else |
} else |
if (command("%s", cmd) != PRELIM) { |
if (command("%s", cmd) != PRELIM) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
if (closefunc != NULL) |
if (closefunc != NULL) |
|
|
dout = dataconn(lmode); |
dout = dataconn(lmode); |
if (dout == NULL) |
if (dout == NULL) |
goto abort; |
goto abort; |
(void) gettimeofday(&start, (struct timezone *)0); |
progressmeter(-1); |
oldintp = signal(SIGPIPE, SIG_IGN); |
oldintp = signal(SIGPIPE, SIG_IGN); |
switch (curtype) { |
switch (curtype) { |
|
|
|
|
for (bufp = buf; c > 0; c -= d, bufp += d) |
for (bufp = buf; c > 0; c -= d, bufp += d) |
if ((d = write(fileno(dout), bufp, c)) <= 0) |
if ((d = write(fileno(dout), bufp, c)) <= 0) |
break; |
break; |
if (hash) { |
if (hash && (!progress || filesize < 0) ) { |
while (bytes >= hashbytes) { |
while (bytes >= hashbytes) { |
(void) putchar('#'); |
(void) putchar('#'); |
hashbytes += mark; |
hashbytes += mark; |
|
|
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
} |
} |
if (hash && bytes > 0) { |
if (hash && (!progress || filesize < 0) && bytes > 0) { |
if (bytes < mark) |
if (bytes < mark) |
(void) putchar('#'); |
(void) putchar('#'); |
(void) putchar('\n'); |
(void) putchar('\n'); |
|
|
if (c < 0) |
if (c < 0) |
warn("local: %s", local); |
warn("local: %s", local); |
if (d < 0) { |
if (d < 0) { |
if (errno != EPIPE) |
if (errno != EPIPE) |
warn("netout"); |
warn("netout"); |
bytes = -1; |
bytes = -1; |
} |
} |
|
|
case TYPE_A: |
case TYPE_A: |
while ((c = getc(fin)) != EOF) { |
while ((c = getc(fin)) != EOF) { |
if (c == '\n') { |
if (c == '\n') { |
while (hash && (bytes >= hashbytes)) { |
while (hash && (!progress || filesize < 0) && |
|
(bytes >= hashbytes)) { |
(void) putchar('#'); |
(void) putchar('#'); |
(void) fflush(stdout); |
(void) fflush(stdout); |
hashbytes += mark; |
hashbytes += mark; |
|
|
} |
} |
(void) putc(c, dout); |
(void) putc(c, dout); |
bytes++; |
bytes++; |
/* if (c == '\r') { */ |
#if 0 /* this violates RFC */ |
/* (void) putc('\0', dout); // this violates rfc */ |
if (c == '\r') { |
/* bytes++; */ |
(void)putc('\0', dout); |
/* } */ |
bytes++; |
|
} |
|
#endif |
} |
} |
if (hash) { |
if (hash && (!progress || filesize < 0)) { |
if (bytes < hashbytes) |
if (bytes < hashbytes) |
(void) putchar('#'); |
(void) putchar('#'); |
(void) putchar('\n'); |
(void) putchar('\n'); |
|
|
} |
} |
break; |
break; |
} |
} |
|
progressmeter(1); |
if (closefunc != NULL) |
if (closefunc != NULL) |
(*closefunc)(fin); |
(*closefunc)(fin); |
(void) fclose(dout); |
(void) fclose(dout); |
(void) gettimeofday(&stop, (struct timezone *)0); |
|
(void) getreply(0); |
(void) getreply(0); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
if (bytes > 0) |
if (bytes > 0) |
ptransfer("sent", bytes, &start, &stop); |
ptransfer(0); |
return; |
return; |
abort: |
abort: |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
if (!cpend) { |
if (!cpend) { |
|
|
code = -1; |
code = -1; |
if (closefunc != NULL && fin != NULL) |
if (closefunc != NULL && fin != NULL) |
(*closefunc)(fin); |
(*closefunc)(fin); |
(void) gettimeofday(&stop, (struct timezone *)0); |
|
if (bytes > 0) |
if (bytes > 0) |
ptransfer("sent", bytes, &start, &stop); |
ptransfer(0); |
} |
} |
|
|
jmp_buf recvabort; |
jmp_buf recvabort; |
|
|
abortrecv() |
abortrecv() |
{ |
{ |
|
|
|
alarmtimer(0); |
mflag = 0; |
mflag = 0; |
abrtflag = 0; |
abrtflag = 0; |
printf("\nreceive aborted\nwaiting for remote to finish abort\n"); |
printf("\nreceive aborted\nwaiting for remote to finish abort\n"); |
|
|
|
|
void |
void |
recvrequest(cmd, local, remote, lmode, printnames) |
recvrequest(cmd, local, remote, lmode, printnames) |
char *cmd, *local, *remote, *lmode; |
const char *cmd, *local, *remote, *lmode; |
int printnames; |
int printnames; |
{ |
{ |
FILE *fout, *din = 0; |
FILE *fout, *din = 0; |
int (*closefunc) __P((FILE *)); |
int (*closefunc) __P((FILE *)); |
sig_t oldintr, oldintp; |
sig_t oldinti, oldintr, oldintp; |
int c, d, is_retr, tcrflag, bare_lfs = 0; |
int c, d, is_retr, tcrflag, bare_lfs = 0; |
static int bufsize; |
static int bufsize; |
static char *buf; |
static char *buf; |
long bytes = 0, hashbytes = mark; |
off_t hashbytes; |
struct timeval start, stop; |
|
struct stat st; |
struct stat st; |
|
time_t mtime; |
|
struct timeval tval[2]; |
|
|
|
hashbytes = mark; |
|
direction = "received"; |
|
bytes = 0; |
|
filesize = -1; |
is_retr = strcmp(cmd, "RETR") == 0; |
is_retr = strcmp(cmd, "RETR") == 0; |
if (is_retr && verbose && printnames) { |
if (is_retr && verbose && printnames) { |
if (local && *local != '-') |
if (local && *local != '-') |
|
|
} |
} |
if (oldintr) |
if (oldintr) |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
if (oldinti) |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
oldintr = signal(SIGINT, abortrecv); |
oldintr = signal(SIGINT, abortrecv); |
|
oldinti = signal(SIGINFO, psummary); |
if (strcmp(local, "-") && *local != '|') { |
if (strcmp(local, "-") && *local != '|') { |
if (access(local, 2) < 0) { |
if (access(local, 2) < 0) { |
char *dir = strrchr(local, '/'); |
char *dir = strrchr(local, '/'); |
|
|
if (errno != ENOENT && errno != EACCES) { |
if (errno != ENOENT && errno != EACCES) { |
warn("local: %s", local); |
warn("local: %s", local); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
if (dir != NULL) |
if (dir != NULL) |
*dir = 0; |
*dir = 0; |
d = access(dir ? local : ".", 2); |
d = access(dir == local ? "/" : dir ? local : ".", 2); |
if (dir != NULL) |
if (dir != NULL) |
*dir = '/'; |
*dir = '/'; |
if (d < 0) { |
if (d < 0) { |
warn("local: %s", local); |
warn("local: %s", local); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
|
chmod(local, 0600) < 0) { |
chmod(local, 0600) < 0) { |
warn("local: %s", local); |
warn("local: %s", local); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
if (runique && errno == EACCES && |
if (runique && errno == EACCES && |
(local = gunique(local)) == NULL) { |
(local = gunique(local)) == NULL) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
} |
} |
else if (runique && (local = gunique(local)) == NULL) { |
else if (runique && (local = gunique(local)) == NULL) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
|
if (!is_retr) { |
if (!is_retr) { |
if (curtype != TYPE_A) |
if (curtype != TYPE_A) |
changetype(TYPE_A, 0); |
changetype(TYPE_A, 0); |
} else if (curtype != type) |
} else { |
changetype(type, 0); |
if (curtype != type) |
|
changetype(type, 0); |
|
filesize = remotesize(remote, 0); |
|
} |
if (initconn()) { |
if (initconn()) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
code = -1; |
code = -1; |
return; |
return; |
} |
} |
|
|
if (remote) { |
if (remote) { |
if (command("%s %s", cmd, remote) != PRELIM) { |
if (command("%s %s", cmd, remote) != PRELIM) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
return; |
return; |
} |
} |
} else { |
} else { |
if (command("%s", cmd) != PRELIM) { |
if (command("%s", cmd) != PRELIM) { |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
return; |
return; |
} |
} |
} |
} |
|
|
} |
} |
bufsize = st.st_blksize; |
bufsize = st.st_blksize; |
} |
} |
(void) gettimeofday(&start, (struct timezone *)0); |
progressmeter(-1); |
switch (curtype) { |
switch (curtype) { |
|
|
case TYPE_I: |
case TYPE_I: |
|
|
if ((d = write(fileno(fout), buf, c)) != c) |
if ((d = write(fileno(fout), buf, c)) != c) |
break; |
break; |
bytes += c; |
bytes += c; |
if (hash) { |
if (hash && (!progress || filesize < 0)) { |
while (bytes >= hashbytes) { |
while (bytes >= hashbytes) { |
(void) putchar('#'); |
(void) putchar('#'); |
hashbytes += mark; |
hashbytes += mark; |
|
|
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
} |
} |
if (hash && bytes > 0) { |
if (hash && (!progress || filesize < 0) && bytes > 0) { |
if (bytes < mark) |
if (bytes < mark) |
(void) putchar('#'); |
(void) putchar('#'); |
(void) putchar('\n'); |
(void) putchar('\n'); |
|
|
if (c == '\n') |
if (c == '\n') |
bare_lfs++; |
bare_lfs++; |
while (c == '\r') { |
while (c == '\r') { |
while (hash && (bytes >= hashbytes)) { |
while (hash && (!progress || filesize < 0) && |
|
(bytes >= hashbytes)) { |
(void) putchar('#'); |
(void) putchar('#'); |
(void) fflush(stdout); |
(void) fflush(stdout); |
hashbytes += mark; |
hashbytes += mark; |
|
|
} |
} |
break2: |
break2: |
if (bare_lfs) { |
if (bare_lfs) { |
printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); |
printf("WARNING! %d bare linefeeds received in ASCII " |
|
"mode\n", bare_lfs); |
printf("File may not have transferred correctly.\n"); |
printf("File may not have transferred correctly.\n"); |
} |
} |
if (hash) { |
if (hash && (!progress || filesize < 0)) { |
if (bytes < hashbytes) |
if (bytes < hashbytes) |
(void) putchar('#'); |
(void) putchar('#'); |
(void) putchar('\n'); |
(void) putchar('\n'); |
|
|
warn("local: %s", local); |
warn("local: %s", local); |
break; |
break; |
} |
} |
|
progressmeter(1); |
if (closefunc != NULL) |
if (closefunc != NULL) |
(*closefunc)(fout); |
(*closefunc)(fout); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGPIPE, oldintp); |
(void) fclose(din); |
(void) fclose(din); |
(void) gettimeofday(&stop, (struct timezone *)0); |
|
(void) getreply(0); |
(void) getreply(0); |
if (bytes > 0 && is_retr) |
if (bytes >= 0 && is_retr) { |
ptransfer("received", bytes, &start, &stop); |
if (bytes > 0) |
|
ptransfer(0); |
|
if (preserve && (closefunc == fclose)) { |
|
mtime = remotemodtime(remote, 0); |
|
if (mtime != -1) { |
|
(void) gettimeofday(&tval[0], |
|
(struct timezone *)0); |
|
tval[1].tv_sec = mtime; |
|
tval[1].tv_usec = 0; |
|
if (utimes(local, tval) == -1) { |
|
printf("Can't change modification time " |
|
"on %s to %s", local, |
|
asctime(localtime(&mtime))); |
|
} |
|
} |
|
} |
|
} |
return; |
return; |
abort: |
abort: |
|
|
/* abort using RFC959 recommended IP,SYNC sequence */ |
/* abort using RFC959 recommended IP,SYNC sequence */ |
|
|
if (oldintp) |
if (oldintp) |
(void) signal(SIGPIPE, oldintr); |
(void) signal(SIGPIPE, oldintp); |
(void) signal(SIGINT, SIG_IGN); |
(void) signal(SIGINT, SIG_IGN); |
if (!cpend) { |
if (!cpend) { |
code = -1; |
code = -1; |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
return; |
return; |
} |
} |
|
|
|
|
(*closefunc)(fout); |
(*closefunc)(fout); |
if (din) |
if (din) |
(void) fclose(din); |
(void) fclose(din); |
(void) gettimeofday(&stop, (struct timezone *)0); |
|
if (bytes > 0) |
if (bytes > 0) |
ptransfer("received", bytes, &start, &stop); |
ptransfer(0); |
(void) signal(SIGINT, oldintr); |
(void) signal(SIGINT, oldintr); |
|
(void) signal(SIGINFO, oldinti); |
} |
} |
|
|
/* |
/* |
|
|
if (passivemode) { |
if (passivemode) { |
data = socket(AF_INET, SOCK_STREAM, 0); |
data = socket(AF_INET, SOCK_STREAM, 0); |
if (data < 0) { |
if (data < 0) { |
perror("ftp: socket"); |
warn("socket"); |
return(1); |
return (1); |
} |
} |
if ((options & SO_DEBUG) && |
if ((options & SO_DEBUG) && |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
sizeof (on)) < 0) |
sizeof (on)) < 0) |
perror("ftp: setsockopt (ignored)"); |
warn("setsockopt (ignored)"); |
if (command("PASV") != COMPLETE) { |
if (command("PASV") != COMPLETE) { |
printf("Passive mode refused.\n"); |
printf("Passive mode refused.\n"); |
goto bad; |
goto bad; |
|
|
* From that we'll prepare a sockaddr_in. |
* From that we'll prepare a sockaddr_in. |
*/ |
*/ |
|
|
if (sscanf(pasv,"%d,%d,%d,%d,%d,%d", |
if (sscanf(pasv, "%d,%d,%d,%d,%d,%d", |
&a0, &a1, &a2, &a3, &p0, &p1) != 6) { |
&a0, &a1, &a2, &a3, &p0, &p1) != 6) { |
printf("Passive mode address scan failure. " |
printf("Passive mode address scan failure. " |
"Shouldn't happen!\n"); |
"Shouldn't happen!\n"); |
goto bad; |
goto bad; |
} |
} |
|
|
bzero(&data_addr, sizeof(data_addr)); |
memset(&data_addr, 0, sizeof(data_addr)); |
data_addr.sin_family = AF_INET; |
data_addr.sin_family = AF_INET; |
a = (char *)&data_addr.sin_addr.s_addr; |
a = (char *)&data_addr.sin_addr.s_addr; |
a[0] = a0 & 0xff; |
a[0] = a0 & 0xff; |
|
|
|
|
if (connect(data, (struct sockaddr *)&data_addr, |
if (connect(data, (struct sockaddr *)&data_addr, |
sizeof(data_addr)) < 0) { |
sizeof(data_addr)) < 0) { |
perror("ftp: connect"); |
warn("connect"); |
goto bad; |
goto bad; |
} |
} |
#ifdef IP_TOS |
#ifdef IP_TOS |
on = IPTOS_THROUGHPUT; |
on = IPTOS_THROUGHPUT; |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, |
if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, |
sizeof(int)) < 0) |
sizeof(int)) < 0) |
perror("ftp: setsockopt TOS (ignored)"); |
warn("setsockopt TOS (ignored)"); |
#endif |
#endif |
return(0); |
return (0); |
} |
} |
|
|
noport: |
noport: |
data_addr = myctladdr; |
data_addr = myctladdr; |
if (sendport) |
if (sendport) |
data_addr.sin_port = 0; /* let system pick one */ |
data_addr.sin_port = 0; /* let system pick one */ |
if (data != -1) |
if (data != -1) |
(void) close(data); |
(void) close(data); |
data = socket(AF_INET, SOCK_STREAM, 0); |
data = socket(AF_INET, SOCK_STREAM, 0); |
|
|
return (1); |
return (1); |
} |
} |
if (!sendport) |
if (!sendport) |
if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { |
if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, |
|
sizeof (on)) < 0) { |
warn("setsockopt (reuse address)"); |
warn("setsockopt (reuse address)"); |
goto bad; |
goto bad; |
} |
} |
|
|
goto bad; |
goto bad; |
} |
} |
if (options & SO_DEBUG && |
if (options & SO_DEBUG && |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) |
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, |
|
sizeof (on)) < 0) |
warn("setsockopt (ignored)"); |
warn("setsockopt (ignored)"); |
len = sizeof (data_addr); |
len = sizeof (data_addr); |
if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { |
if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { |
|
|
|
|
FILE * |
FILE * |
dataconn(lmode) |
dataconn(lmode) |
char *lmode; |
const char *lmode; |
{ |
{ |
struct sockaddr_in from; |
struct sockaddr_in from; |
int s, fromlen = sizeof (from), tos; |
int s, fromlen = sizeof (from), tos; |
|
|
} |
} |
|
|
void |
void |
ptransfer(direction, bytes, t0, t1) |
psummary(notused) |
char *direction; |
int notused; |
long bytes; |
|
struct timeval *t0, *t1; |
|
{ |
{ |
struct timeval td; |
|
float s; |
|
long bs; |
|
|
|
if (verbose) { |
if (bytes > 0) |
timersub(t1, t0, &td); |
ptransfer(1); |
s = td.tv_sec + (td.tv_usec / 1000000.); |
|
#define nz(x) ((x) == 0 ? 1 : (x)) |
|
bs = bytes / nz(s); |
|
printf("%ld bytes %s in %.3g seconds (%ld bytes/s)\n", |
|
bytes, direction, s, bs); |
|
} |
|
} |
} |
|
|
void |
void |
psabort() |
psabort() |
{ |
{ |
|
|
|
alarmtimer(0); |
abrtflag++; |
abrtflag++; |
} |
} |
|
|
|
|
abortpt() |
abortpt() |
{ |
{ |
|
|
|
alarmtimer(0); |
printf("\n"); |
printf("\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
ptabflg++; |
ptabflg++; |
|
|
|
|
void |
void |
proxtrans(cmd, local, remote) |
proxtrans(cmd, local, remote) |
char *cmd, *local, *remote; |
const char *cmd, *local, *remote; |
{ |
{ |
sig_t oldintr; |
sig_t oldintr; |
int secndflag = 0, prox_type, nfnd; |
int secndflag = 0, prox_type, nfnd; |
|
|
if (curtype != prox_type) |
if (curtype != prox_type) |
changetype(prox_type, 1); |
changetype(prox_type, 1); |
if (command("PASV") != COMPLETE) { |
if (command("PASV") != COMPLETE) { |
printf("proxy server does not support third party transfers.\n"); |
printf("proxy server does not support third party " |
|
"transfers.\n"); |
return; |
return; |
} |
} |
pswitch(0); |
pswitch(0); |
|
|
FD_ZERO(&mask); |
FD_ZERO(&mask); |
while (nfnd > 0) { |
while (nfnd > 0) { |
FD_SET(fileno(cin), &mask); |
FD_SET(fileno(cin), &mask); |
if ((nfnd = empty(&mask,0)) < 0) { |
if ((nfnd = empty(&mask, 0)) < 0) { |
warn("reset"); |
warn("reset"); |
code = -1; |
code = -1; |
lostpeer(); |
lostpeer(); |
|
|
|
|
char * |
char * |
gunique(local) |
gunique(local) |
char *local; |
const char *local; |
{ |
{ |
static char new[MAXPATHLEN]; |
static char new[MAXPATHLEN]; |
char *cp = strrchr(local, '/'); |
char *cp = strrchr(local, '/'); |
|
|
|
|
if (cp) |
if (cp) |
*cp = '\0'; |
*cp = '\0'; |
d = access(cp ? local : ".", 2); |
d = access(cp == local ? "/" : cp ? local : ".", 2); |
if (cp) |
if (cp) |
*cp = '/'; |
*cp = '/'; |
if (d < 0) { |
if (d < 0) { |
|
|
sprintf(buf, "%c%c%c", IAC, IP, IAC); |
sprintf(buf, "%c%c%c", IAC, IP, IAC); |
if (send(fileno(cout), buf, 3, MSG_OOB) != 3) |
if (send(fileno(cout), buf, 3, MSG_OOB) != 3) |
warn("abort"); |
warn("abort"); |
fprintf(cout,"%cABOR\r\n", DM); |
fprintf(cout, "%cABOR\r\n", DM); |
(void) fflush(cout); |
(void) fflush(cout); |
FD_ZERO(&mask); |
FD_ZERO(&mask); |
FD_SET(fileno(cin), &mask); |
FD_SET(fileno(cin), &mask); |
if (din) { |
if (din) { |
FD_SET(fileno(din), &mask); |
FD_SET(fileno(din), &mask); |
} |
} |
if ((nfnd = empty(&mask, 10)) <= 0) { |
if ((nfnd = empty(&mask, 10)) <= 0) { |