/*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * %sccs.include.redist.c%
*/
#ifndef lint
-static char sccsid[] = "@(#)ftp.c 5.14 (Berkeley) %G%";
-#endif not lint
-
-#include "ftp_var.h"
+static char sccsid[] = "@(#)ftp.c 8.3 (Berkeley) %G%";
+#endif /* not lint */
+#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
-#include <sys/param.h>
+#include <sys/file.h>
#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
#include <arpa/ftp.h>
#include <arpa/telnet.h>
-#include <stdio.h>
-#include <signal.h>
+#include <ctype.h>
+#include <err.h>
#include <errno.h>
-#include <netdb.h>
#include <fcntl.h>
+#include <netdb.h>
#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <varargs.h>
+
+#include "ftp_var.h"
+
+extern int h_errno;
struct sockaddr_in hisctladdr;
struct sockaddr_in data_addr;
int data = -1;
int abrtflag = 0;
+jmp_buf ptabort;
+int ptabflg;
int ptflag = 0;
-int connected;
struct sockaddr_in myctladdr;
-uid_t getuid();
+
FILE *cin, *cout;
-FILE *dataconn();
char *
hookup(host, port)
char *host;
int port;
{
- register struct hostent *hp = 0;
- int s,len;
+ struct hostent *hp = 0;
+ int s, len, tos;
static char hostnamebuf[80];
- bzero((char *)&hisctladdr, sizeof (hisctladdr));
+ memset((char *)&hisctladdr, 0, sizeof (hisctladdr));
hisctladdr.sin_addr.s_addr = inet_addr(host);
if (hisctladdr.sin_addr.s_addr != -1) {
hisctladdr.sin_family = AF_INET;
- (void) strcpy(hostnamebuf, host);
- }
- else {
+ (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
+ } else {
hp = gethostbyname(host);
if (hp == NULL) {
- printf("%s: unknown host\n", host);
+ warnx("%s: %s", host, hstrerror(h_errno));
code = -1;
- return((char *) 0);
+ return ((char *) 0);
}
hisctladdr.sin_family = hp->h_addrtype;
- bcopy(hp->h_addr_list[0],
- (caddr_t)&hisctladdr.sin_addr, hp->h_length);
- (void) strcpy(hostnamebuf, hp->h_name);
+ memmove((caddr_t)&hisctladdr.sin_addr,
+ hp->h_addr_list[0], hp->h_length);
+ (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
}
hostname = hostnamebuf;
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
if (s < 0) {
- perror("ftp: socket");
+ warn("socket");
code = -1;
return (0);
}
hisctladdr.sin_port = port;
- while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
+ while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
if (hp && hp->h_addr_list[1]) {
int oerrno = errno;
+ char *ia;
- fprintf(stderr, "ftp: connect to address %s: ",
- inet_ntoa(hisctladdr.sin_addr));
+ ia = inet_ntoa(hisctladdr.sin_addr);
errno = oerrno;
- perror((char *) 0);
+ warn("connect to address %s", ia);
hp->h_addr_list++;
- bcopy(hp->h_addr_list[0],
- (caddr_t)&hisctladdr.sin_addr, hp->h_length);
+ memmove((caddr_t)&hisctladdr.sin_addr,
+ hp->h_addr_list[0], hp->h_length);
fprintf(stdout, "Trying %s...\n",
inet_ntoa(hisctladdr.sin_addr));
(void) close(s);
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
if (s < 0) {
- perror("ftp: socket");
+ warn("socket");
code = -1;
return (0);
}
continue;
}
- perror("ftp: connect");
+ warn("connect");
code = -1;
goto bad;
}
len = sizeof (myctladdr);
- if (getsockname(s, (char *)&myctladdr, &len) < 0) {
- perror("ftp: getsockname");
+ if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
+ warn("getsockname");
code = -1;
goto bad;
}
+#ifdef IP_TOS
+ tos = IPTOS_LOWDELAY;
+ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+ warn("setsockopt TOS (ignored)");
+#endif
cin = fdopen(s, "r");
cout = fdopen(s, "w");
if (cin == NULL || cout == NULL) {
- fprintf(stderr, "ftp: fdopen failed.\n");
+ warnx("fdopen failed.");
if (cin)
(void) fclose(cin);
if (cout)
{
int on = 1;
- if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
+ if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
< 0 && debug) {
- perror("ftp: setsockopt");
+ warn("setsockopt");
}
}
-#endif SO_OOBINLINE
+#endif /* SO_OOBINLINE */
return (hostname);
bad:
return ((char *)0);
}
+int
login(host)
char *host;
{
char tmp[80];
- char *user, *pass, *acct, *getlogin(), *mygetpass();
+ char *user, *pass, *acct;
int n, aflag = 0;
user = pass = acct = 0;
if (ruserpass(host, &user, &pass, &acct) < 0) {
- disconnect();
code = -1;
- return(0);
+ return (0);
}
- if (user == NULL) {
+ while (user == NULL) {
char *myname = getlogin();
if (myname == NULL) {
if (pp != NULL)
myname = pp->pw_name;
}
- printf("Name (%s:%s): ", host, myname);
+ if (myname)
+ printf("Name (%s:%s): ", host, myname);
+ else
+ printf("Name (%s): ", host);
(void) fgets(tmp, sizeof(tmp) - 1, stdin);
tmp[strlen(tmp) - 1] = '\0';
if (*tmp == '\0')
n = command("USER %s", user);
if (n == CONTINUE) {
if (pass == NULL)
- pass = mygetpass("Password:");
+ pass = getpass("Password:");
n = command("PASS %s", pass);
}
if (n == CONTINUE) {
aflag++;
- acct = mygetpass("Account:");
+ acct = getpass("Account:");
n = command("ACCT %s", acct);
}
if (n != COMPLETE) {
- fprintf(stderr, "Login failed.\n");
+ warnx("Login failed.");
return (0);
}
if (!aflag && acct != NULL)
(void) command("ACCT %s", acct);
if (proxy)
- return(1);
+ return (1);
for (n = 0; n < macnum; ++n) {
if (!strcmp("init", macros[n].mac_name)) {
(void) strcpy(line, "$init");
return (1);
}
+void
cmdabort()
{
- extern jmp_buf ptabort;
printf("\n");
(void) fflush(stdout);
longjmp(ptabort,1);
}
-/*VARARGS1*/
-command(fmt, args)
- char *fmt;
+/*VARARGS*/
+int
+command(va_alist)
+va_dcl
{
- int r, (*oldintr)(), cmdabort();
+ va_list ap;
+ char *fmt;
+ int r;
+ sig_t oldintr;
abrtflag = 0;
if (debug) {
printf("---> ");
- _doprnt(fmt, &args, stdout);
+ va_start(ap);
+ fmt = va_arg(ap, char *);
+ if (strncmp("PASS ", fmt, 5) == 0)
+ printf("PASS XXXX");
+ else
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
printf("\n");
(void) fflush(stdout);
}
if (cout == NULL) {
- perror ("No control connection for command");
+ warn("No control connection for command");
code = -1;
return (0);
}
- oldintr = signal(SIGINT,cmdabort);
- _doprnt(fmt, &args, cout);
+ oldintr = signal(SIGINT, cmdabort);
+ va_start(ap);
+ fmt = va_arg(ap, char *);
+ vfprintf(cout, fmt, ap);
+ va_end(ap);
fprintf(cout, "\r\n");
(void) fflush(cout);
cpend = 1;
r = getreply(!strcmp(fmt, "QUIT"));
if (abrtflag && oldintr != SIG_IGN)
- (*oldintr)();
+ (*oldintr)(SIGINT);
(void) signal(SIGINT, oldintr);
- return(r);
+ return (r);
}
-#include <ctype.h>
+char reply_string[BUFSIZ]; /* last line of previous reply */
+int
getreply(expecteof)
int expecteof;
{
- register int c, n;
- register int dig;
- int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
+ int c, n;
+ int dig;
+ int originalcode = 0, continuation = 0;
+ sig_t oldintr;
int pflag = 0;
- char *pt = pasv;
+ char *cp, *pt = pasv;
- oldintr = signal(SIGINT,cmdabort);
+ oldintr = signal(SIGINT, cmdabort);
for (;;) {
dig = n = code = 0;
+ cp = reply_string;
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,WONT,c);
+ fprintf(cout, "%c%c%c", IAC, DONT, c);
(void) fflush(cout);
break;
case DO:
case DONT:
c = getc(cin);
- fprintf(cout, "%c%c%c",IAC,DONT,c);
+ fprintf(cout, "%c%c%c", IAC, WONT, c);
(void) fflush(cout);
break;
default:
if (verbose) {
printf("421 Service not available, remote server has closed connection\n");
(void) fflush(stdout);
- code = 421;
- return(4);
}
+ code = 421;
+ return (4);
}
if (c != '\r' && (verbose > 0 ||
(verbose > -1 && n == '5' && dig > 4))) {
}
if (n == 0)
n = c;
+ if (cp < &reply_string[sizeof(reply_string) - 1])
+ *cp++ = c;
}
if (verbose > 0 || verbose > -1 && n == '5') {
(void) putchar(c);
originalcode = code;
continue;
}
+ *cp = '\0';
if (n != '1')
cpend = 0;
(void) signal(SIGINT,oldintr);
if (code == 421 || originalcode == 421)
lostpeer();
if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
- (*oldintr)();
+ (*oldintr)(SIGINT);
return (n - '0');
}
}
+int
empty(mask, sec)
struct fd_set *mask;
int sec;
t.tv_sec = (long) sec;
t.tv_usec = 0;
- return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
+ return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
}
jmp_buf sendabort;
+void
abortsend()
{
mflag = 0;
abrtflag = 0;
- printf("\nsend aborted\n");
+ printf("\nsend aborted\nwaiting for remote to finish abort\n");
(void) fflush(stdout);
longjmp(sendabort, 1);
}
-sendrequest(cmd, local, remote)
+#define HASHBYTES 1024
+
+void
+sendrequest(cmd, local, remote, printnames)
char *cmd, *local, *remote;
+ int printnames;
{
- FILE *fin, *dout = 0, *mypopen();
- int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)();
- int abortsend();
- char buf[BUFSIZ];
- long bytes = 0, hashbytes = sizeof (buf);
- register int c, d;
struct stat st;
struct timeval start, stop;
-
+ int c, d;
+ FILE *fin, *dout = 0, *popen();
+ int (*closefunc) __P((FILE *));
+ char buf[BUFSIZ], *bufp;
+ long bytes = 0, hashbytes = HASHBYTES;
+ char *lmode, buf[BUFSIZ], *bufp;
+
+ 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;
+ lmode = "w";
if (setjmp(sendabort)) {
while (cpend) {
(void) getreply(0);
fin = stdin;
else if (*local == '|') {
oldintp = signal(SIGPIPE,SIG_IGN);
- fin = mypopen(local + 1, "r");
+ fin = popen(local + 1, "r");
if (fin == NULL) {
- perror(local + 1);
+ warn("%s", local + 1);
(void) signal(SIGINT, oldintr);
(void) signal(SIGPIPE, oldintp);
code = -1;
return;
}
- closefunc = mypclose;
+ closefunc = pclose;
} else {
fin = fopen(local, "r");
if (fin == NULL) {
- perror(local);
+ warn("local: %s", local);
(void) signal(SIGINT, oldintr);
code = -1;
return;
(st.st_mode&S_IFMT) != S_IFREG) {
fprintf(stdout, "%s: not a plain file.\n", local);
(void) signal(SIGINT, oldintr);
+ fclose(fin);
code = -1;
return;
}
if (oldintp)
(void) signal(SIGPIPE, oldintp);
code = -1;
+ if (closefunc != NULL)
+ (*closefunc)(fin);
return;
}
if (setjmp(sendabort))
goto abort;
+
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void) signal(SIGINT, oldintr);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
return;
}
} else
(void) signal(SIGINT, oldintr);
if (oldintp)
(void) signal(SIGPIPE, oldintp);
+ if (closefunc != NULL)
+ (*closefunc)(fin);
return;
}
- dout = dataconn("w");
+ dout = dataconn(lmode);
if (dout == NULL)
goto abort;
(void) gettimeofday(&start, (struct timezone *)0);
- switch (type) {
+ oldintp = signal(SIGPIPE, SIG_IGN);
+ switch (curtype) {
case TYPE_I:
case TYPE_L:
errno = d = 0;
- while ((c = read(fileno (fin), buf, sizeof (buf))) > 0) {
- if ((d = write(fileno (dout), buf, c)) < 0)
- break;
+ while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
bytes += c;
+ for (bufp = buf; c > 0; c -= d, bufp += d)
+ if ((d = write(fileno(dout), bufp, c)) <= 0)
+ break;
+ for (bufp = buf; c > 0; c -= d, bufp += d)
+ if ((d = write(fileno(dout), bufp, c)) <= 0)
+ break;
if (hash) {
- (void) putchar('#');
+ while (bytes >= hashbytes) {
+ (void) putchar('#');
+ hashbytes += HASHBYTES;
+ }
(void) fflush(stdout);
}
}
if (hash && bytes > 0) {
+ if (bytes < HASHBYTES)
+ (void) putchar('#');
(void) putchar('\n');
(void) fflush(stdout);
}
if (c < 0)
- perror(local);
- if (d < 0)
- perror("netout");
+ warn("local: %s", local);
+ if (d <= 0) {
+ if (d == 0)
+ fprintf(stderr, "netout: write returned 0?\n");
+ else if (errno != EPIPE)
+ warn("netout");
+ bytes = -1;
+ }
break;
case TYPE_A:
while (hash && (bytes >= hashbytes)) {
(void) putchar('#');
(void) fflush(stdout);
- hashbytes += sizeof (buf);
+ hashbytes += HASHBYTES;
}
if (ferror(dout))
break;
(void) putc(c, dout);
bytes++;
/* if (c == '\r') { */
- /* (void) putc('\0', dout); /* this violates rfc */
+ /* (void) putc('\0', dout); // this violates rfc */
/* bytes++; */
/* } */
}
(void) fflush(stdout);
}
if (ferror(fin))
- perror(local);
- if (ferror(dout))
- perror("netout");
+ warn("local: %s", local);
+ if (ferror(dout)) {
+ if (errno != EPIPE)
+ warn("netout");
+ bytes = -1;
+ }
break;
}
(void) gettimeofday(&stop, (struct timezone *)0);
(void) fclose(dout);
(void) getreply(0);
(void) signal(SIGINT, oldintr);
- if (bytes > 0 && verbose)
- ptransfer("sent", bytes, &start, &stop, local, remote);
+ if (oldintp)
+ (void) signal(SIGPIPE, oldintp);
+ if (bytes > 0)
+ ptransfer("sent", bytes, &start, &stop);
return;
abort:
(void) gettimeofday(&stop, (struct timezone *)0);
code = -1;
if (closefunc != NULL && fin != NULL)
(*closefunc)(fin);
- if (bytes > 0 && verbose)
- ptransfer("sent", bytes, &start, &stop, local, remote);
+ if (bytes > 0)
+ ptransfer("sent", bytes, &start, &stop);
}
jmp_buf recvabort;
+void
abortrecv()
{
mflag = 0;
abrtflag = 0;
- printf("\n");
+ printf("\nreceive aborted\nwaiting for remote to finish abort\n");
(void) fflush(stdout);
longjmp(recvabort, 1);
}
-recvrequest(cmd, local, remote, mode)
- char *cmd, *local, *remote, *mode;
+void
+recvrequest(cmd, local, remote, lmode, printnames)
+ char *cmd, *local, *remote, *lmode;
+ int printnames;
{
- FILE *fout, *din = 0, *mypopen();
- int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)();
- int abortrecv(), oldverbose, oldtype = 0, tcrflag, nfnd;
- char buf[BUFSIZ], *gunique(), msg;
- long bytes = 0, hashbytes = sizeof (buf);
- struct fd_set mask;
- register int c, d;
+ char *bufp, *gunique(), msg;
+ static char *buf;
+ static int bufsize;
+ static char *buf;
+ long bytes = 0, hashbytes = HASHBYTES;
struct timeval start, stop;
+ struct stat st;
- if (proxy && strcmp(cmd,"RETR") == 0) {
+ 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 && !strcmp(cmd, "RETR");
+ tcrflag = !crflag && is_retr;
if (setjmp(recvabort)) {
while (cpend) {
(void) getreply(0);
oldintr = signal(SIGINT, abortrecv);
if (strcmp(local, "-") && *local != '|') {
if (access(local, 2) < 0) {
- char *dir = rindex(local, '/');
+ char *dir = strrchr(local, '/');
if (errno != ENOENT && errno != EACCES) {
- perror(local);
+ warn("local: %s", local);
(void) signal(SIGINT, oldintr);
code = -1;
return;
if (dir != NULL)
*dir = '/';
if (d < 0) {
- perror(local);
+ warn("local: %s", local);
(void) signal(SIGINT, oldintr);
code = -1;
return;
}
if (!runique && errno == EACCES &&
- chmod(local,0600) < 0) {
- perror(local);
+ chmod(local, 0600) < 0) {
+ warn("local: %s", local);
+ (void) signal(SIGINT, oldintr);
(void) signal(SIGINT, oldintr);
code = -1;
return;
return;
}
}
+ if (!is_retr) {
+ if (curtype != TYPE_A)
+ changetype(TYPE_A, 0);
+ } else if (curtype != type)
+ changetype(type, 0);
if (initconn()) {
(void) signal(SIGINT, oldintr);
code = -1;
}
if (setjmp(recvabort))
goto abort;
- if (strcmp(cmd, "RETR") && type != TYPE_A) {
- oldtype = type;
- oldverbose = verbose;
- if (!debug)
- verbose = 0;
- setascii();
- verbose = oldverbose;
- }
+ if (is_retr && restart_point &&
+ command("REST %ld", (long) restart_point) != CONTINUE)
+ return;
if (remote) {
if (command("%s %s", cmd, remote) != PRELIM) {
(void) signal(SIGINT, oldintr);
- if (oldtype) {
- if (!debug)
- verbose = 0;
- switch (oldtype) {
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- verbose = oldverbose;
- }
return;
}
} else {
if (command("%s", cmd) != PRELIM) {
(void) signal(SIGINT, oldintr);
- if (oldtype) {
- if (!debug)
- verbose = 0;
- switch (oldtype) {
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- verbose = oldverbose;
- }
return;
}
}
fout = stdout;
else if (*local == '|') {
oldintp = signal(SIGPIPE, SIG_IGN);
- fout = mypopen(local + 1, "w");
+ fout = popen(local + 1, "w");
if (fout == NULL) {
- perror(local+1);
+ warn("%s", local+1);
goto abort;
}
- closefunc = mypclose;
- }
- else {
- fout = fopen(local, mode);
+ closefunc = pclose;
+ } else {
+ fout = fopen(local, lmode);
if (fout == NULL) {
- perror(local);
+ warn("local: %s", local);
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)
+ (void) free(buf);
+ buf = malloc((unsigned)st.st_blksize);
+ if (buf == NULL) {
+ warn("malloc");
+ bufsize = 0;
+ bufsize = 0;
+ goto abort;
+ }
+ bufsize = st.st_blksize;
+ }
(void) gettimeofday(&start, (struct timezone *)0);
- switch (type) {
+ switch (curtype) {
case TYPE_I:
case TYPE_L:
errno = d = 0;
- while ((c = read(fileno(din), buf, sizeof (buf))) > 0) {
- if ((d = write(fileno(fout), buf, c)) < 0)
+ while ((c = read(fileno(din), buf, bufsize)) > 0) {
+ if ((d = write(fileno(fout), buf, c)) != c)
break;
bytes += c;
if (hash) {
- (void) putchar('#');
+ while (bytes >= hashbytes) {
+ (void) putchar('#');
+ hashbytes += HASHBYTES;
+ }
(void) fflush(stdout);
}
}
if (hash && bytes > 0) {
+ if (bytes < HASHBYTES)
+ (void) putchar('#');
(void) putchar('\n');
(void) fflush(stdout);
}
- if (c < 0)
- perror("netin");
- if (d < 0)
- perror(local);
+ if (c < 0) {
+ if (errno != EPIPE)
+ warn("netin");
+ bytes = -1;
+ }
+ if (d < c) {
+ if (d < 0)
+ perror(local);
+ else
+ fprintf(stderr, "%s: short write\n", local);
+ }
break;
case TYPE_A:
while ((c = getc(din)) != EOF) {
+ if (c == '\n')
+ bare_lfs++;
while (c == '\r') {
while (hash && (bytes >= hashbytes)) {
(void) putchar('#');
(void) fflush(stdout);
- hashbytes += sizeof (buf);
+ hashbytes += HASHBYTES;
}
bytes++;
if ((c = getc(din)) != '\n' || tcrflag) {
- if (ferror (fout))
- break;
- (void) putc ('\r', fout);
+ if (ferror(fout))
+ goto break2;
+ (void) putc('\r', fout);
+ if (c == '\0') {
+ bytes++;
+ goto contin2;
+ }
+ if (c == EOF)
+ goto contin2;
+ }
+ if (c == EOF)
+ goto contin2;
}
- /*if (c == '\0') {
- bytes++;
- continue;
- }*/
}
- (void) putc (c, fout);
+ (void) putc(c, fout);
bytes++;
+ contin2: ;
+ }
+break2:
+ if (bare_lfs) {
+ printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
+ printf("File may not have transferred correctly.\n");
}
if (hash) {
if (bytes < hashbytes)
(void) putchar('\n');
(void) fflush(stdout);
}
- if (ferror (din))
- perror ("netin");
- if (ferror (fout))
- perror (local);
+ if (ferror(din)) {
+ if (errno != EPIPE)
+ warn("netin");
+ bytes = -1;
+ }
+ if (ferror(fout))
+ warn("local: %s", local);
break;
}
if (closefunc != NULL)
(void) gettimeofday(&stop, (struct timezone *)0);
(void) fclose(din);
(void) getreply(0);
- if (bytes > 0 && verbose)
- ptransfer("received", bytes, &start, &stop, local, remote);
- if (oldtype) {
- if (!debug)
- verbose = 0;
- switch (oldtype) {
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- verbose = oldverbose;
- }
+ if (bytes > 0 && is_retr)
+ ptransfer("received", bytes, &start, &stop);
return;
abort:
(void) gettimeofday(&stop, (struct timezone *)0);
if (oldintp)
(void) signal(SIGPIPE, oldintr);
- (void) signal(SIGINT,SIG_IGN);
- if (oldtype) {
- if (!debug)
- verbose = 0;
- switch (oldtype) {
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- verbose = oldverbose;
- }
+ (void) signal(SIGINT, SIG_IGN);
if (!cpend) {
code = -1;
- (void) signal(SIGINT,oldintr);
+ (void) signal(SIGINT, oldintr);
return;
}
- fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- msg = IAC;
-/* send IAC in urgent mode instead of DM because UNIX places oob mark */
-/* after urgent byte rather than before as now is protocol */
- if (send(fileno(cout),&msg,1,MSG_OOB) != 1) {
- perror("abort");
- }
- fprintf(cout,"%cABOR\r\n",DM);
- (void) fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if (din) {
- FD_SET(fileno(din), &mask);
- }
- if ((nfnd = empty(&mask,10)) <= 0) {
- if (nfnd < 0) {
- perror("abort");
- }
- code = -1;
- lostpeer();
- }
- if (din && FD_ISSET(fileno(din), &mask)) {
- while ((c = read(fileno(din), buf, sizeof (buf))) > 0)
- ;
- }
- if ((c = getreply(0)) == ERROR && code == 552) { /* needed for nic style abort */
- if (data >= 0) {
- (void) close(data);
- data = -1;
- }
- (void) getreply(0);
- }
- (void) getreply(0);
+ abort_remote(din);
code = -1;
if (data >= 0) {
(void) close(data);
(*closefunc)(fout);
if (din)
(void) fclose(din);
- if (bytes > 0 && verbose)
- ptransfer("received", bytes, &start, &stop, local, remote);
- (void) signal(SIGINT,oldintr);
+ if (bytes > 0)
+ ptransfer("received", bytes, &start, &stop);
+ (void) signal(SIGINT, oldintr);
}
/*
- * Need to start a listen on the data channel
- * before we send the command, otherwise the
- * server's connect may fail.
+ * Need to start a listen on the data channel before we send the command,
+ * otherwise the server's connect may fail.
*/
-static int sendport = -1;
-
+int
initconn()
{
- register char *p, *a;
+ char *p, *a;
int result, len, tmpno = 0;
int on = 1;
if (sendport)
data_addr.sin_port = 0; /* let system pick one */
if (data != -1)
- (void) close (data);
+ (void) close(data);
data = socket(AF_INET, SOCK_STREAM, 0);
if (data < 0) {
- perror("ftp: socket");
+ warn("socket");
if (tmpno)
sendport = 1;
return (1);
}
if (!sendport)
if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
- perror("ftp: setsockopt (resuse address)");
+ warn("setsockopt (reuse address)");
goto bad;
}
if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
- perror("ftp: bind");
+ warn("bind");
goto bad;
}
if (options & SO_DEBUG &&
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
- perror("ftp: setsockopt (ignored)");
+ warn("setsockopt (ignored)");
len = sizeof (data_addr);
- if (getsockname(data, (char *)&data_addr, &len) < 0) {
- perror("ftp: getsockname");
+ if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
+ warn("getsockname");
goto bad;
}
if (listen(data, 1) < 0)
- perror("ftp: listen");
+ warn("listen");
if (sendport) {
a = (char *)&data_addr.sin_addr;
p = (char *)&data_addr.sin_port;
}
if (tmpno)
sendport = 1;
+#ifdef IP_TOS
+ on = IPTOS_THROUGHPUT;
+ if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
+ warn("setsockopt TOS (ignored)");
+#endif
return (0);
bad:
(void) close(data), data = -1;
}
FILE *
-dataconn(mode)
- char *mode;
+dataconn(lmode)
+ char *lmode;
{
struct sockaddr_in from;
- int s, fromlen = sizeof (from);
+ int s, fromlen = sizeof (from), tos;
s = accept(data, (struct sockaddr *) &from, &fromlen);
if (s < 0) {
- perror("ftp: accept");
+ warn("accept");
(void) close(data), data = -1;
return (NULL);
}
(void) close(data);
data = s;
- return (fdopen(data, mode));
+#ifdef IP_TOS
+ tos = IPTOS_THROUGHPUT;
+ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
+ warn("setsockopt TOS (ignored)");
+#endif
+ return (fdopen(data, lmode));
}
-ptransfer(direction, bytes, t0, t1, local, remote)
- char *direction, *local, *remote;
+void
+ptransfer(direction, bytes, t0, t1)
+ char *direction;
long bytes;
struct timeval *t0, *t1;
{
struct timeval td;
float s, bs;
- tvsub(&td, t1, t0);
- s = td.tv_sec + (td.tv_usec / 1000000.);
+ if (verbose) {
+ tvsub(&td, t1, t0);
+ s = td.tv_sec + (td.tv_usec / 1000000.);
#define nz(x) ((x) == 0 ? 1 : (x))
- bs = bytes / nz(s);
- if (local && *local != '-')
- printf("local: %s ", local);
- if (remote)
- printf("remote: %s\n", remote);
- printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
- bytes, direction, s, bs / 1024.);
+ bs = bytes / nz(s);
+ printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
+ bytes, direction, s, bs / 1024.);
+ }
}
-/*tvadd(tsum, t0)
+/*
+void
+tvadd(tsum, t0)
struct timeval *tsum, *t0;
{
tsum->tv_usec += t0->tv_usec;
if (tsum->tv_usec > 1000000)
tsum->tv_sec++, tsum->tv_usec -= 1000000;
-} */
+}
+*/
+void
tvsub(tdiff, t1, t0)
struct timeval *tdiff, *t1, *t0;
{
tdiff->tv_sec--, tdiff->tv_usec += 1000000;
}
+void
psabort()
{
- extern int abrtflag;
abrtflag++;
}
+void
pswitch(flag)
int flag;
{
- extern int proxy, abrtflag;
- int (*oldintr)();
+ sig_t oldintr;
static struct comvars {
int connect;
char name[MAXHOSTNAMELEN];
FILE *in;
FILE *out;
int tpe;
+ int curtpe;
int cpnd;
int sunqe;
int runqe;
int mapflg;
char mi[MAXPATHLEN];
char mo[MAXPATHLEN];
- } proxstruct, tmpstruct;
+ } proxstruct, tmpstruct;
struct comvars *ip, *op;
abrtflag = 0;
ip = &tmpstruct;
op = &proxstruct;
proxy++;
- }
- else {
+ } else {
if (!proxy)
return;
ip = &proxstruct;
cout = op->out;
ip->tpe = type;
type = op->tpe;
- if (!type)
- type = 1;
+ ip->curtpe = curtype;
+ curtype = op->curtpe;
ip->cpnd = cpend;
cpend = op->cpnd;
ip->sunqe = sunique;
(void) signal(SIGINT, oldintr);
if (abrtflag) {
abrtflag = 0;
- (*oldintr)();
+ (*oldintr)(SIGINT);
}
}
-jmp_buf ptabort;
-int ptabflg;
-
+void
abortpt()
{
+
printf("\n");
(void) fflush(stdout);
ptabflg++;
longjmp(ptabort, 1);
}
+void
proxtrans(cmd, local, remote)
char *cmd, *local, *remote;
{
- int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
- extern jmp_buf ptabort;
+ sig_t oldintr;
+ int secndflag = 0, prox_type, nfnd;
char *cmd2;
struct fd_set mask;
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) {
- printf("proxy server does not support third part transfers.\n");
+ printf("proxy server does not support third party transfers.\n");
return;
}
- tmptype = type;
pswitch(0);
if (!connected) {
printf("No primary connection\n");
code = -1;
return;
}
- if (type != tmptype) {
- oldtype = type;
- switch (tmptype) {
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- }
+ if (curtype != prox_type)
+ changetype(prox_type, 1);
if (command("PORT %s", pasv) != COMPLETE) {
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
pswitch(1);
return;
}
oldintr = signal(SIGINT, abortpt);
if (command("%s %s", cmd, remote) != PRELIM) {
(void) signal(SIGINT, oldintr);
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
pswitch(1);
return;
}
pswitch(0);
(void) getreply(0);
(void) signal(SIGINT, oldintr);
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
pswitch(1);
ptflag = 0;
printf("local: %s remote: %s\n", local, remote);
if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */
if (command("%s %s", cmd2, local) != PRELIM) {
pswitch(0);
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- if (cpend) {
- char msg[2];
-
- fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- *msg = IAC;
- *(msg+1) = DM;
- if (send(fileno(cout),msg,2,MSG_OOB) != 2)
- perror("abort");
- fprintf(cout,"ABOR\r\n");
- (void) fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,10)) <= 0) {
- if (nfnd < 0) {
- perror("abort");
- }
- if (ptabflg)
- code = -1;
- lostpeer();
- }
- (void) getreply(0);
- (void) getreply(0);
- }
+ if (cpend)
+ abort_remote((FILE *) NULL);
}
pswitch(1);
if (ptabflg)
(void) signal(SIGINT, oldintr);
return;
}
- if (cpend) {
- char msg[2];
-
- fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- *msg = IAC;
- *(msg+1) = DM;
- if (send(fileno(cout),msg,2,MSG_OOB) != 2)
- perror("abort");
- fprintf(cout,"ABOR\r\n");
- (void) fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,10)) <= 0) {
- if (nfnd < 0) {
- perror("abort");
- }
- if (ptabflg)
- code = -1;
- lostpeer();
- }
- (void) getreply(0);
- (void) getreply(0);
- }
+ 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);
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
- if (cpend) {
- char msg[2];
-
- fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- *msg = IAC;
- *(msg+1) = DM;
- if (send(fileno(cout),msg,2,MSG_OOB) != 2)
- perror("abort");
- fprintf(cout,"ABOR\r\n");
- (void) fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,10)) <= 0) {
- if (nfnd < 0) {
- perror("abort");
- }
- if (ptabflg)
- code = -1;
- lostpeer();
- }
- (void) getreply(0);
- (void) getreply(0);
- }
+ if (cpend)
+ abort_remote((FILE *) NULL);
pswitch(1);
if (ptabflg)
code = -1;
return;
}
}
- if (cpend) {
- char msg[2];
-
- fprintf(cout,"%c%c",IAC,IP);
- (void) fflush(cout);
- *msg = IAC;
- *(msg+1) = DM;
- if (send(fileno(cout),msg,2,MSG_OOB) != 2)
- perror("abort");
- fprintf(cout,"ABOR\r\n");
- (void) fflush(cout);
- FD_ZERO(&mask);
- FD_SET(fileno(cin), &mask);
- if ((nfnd = empty(&mask,10)) <= 0) {
- if (nfnd < 0) {
- perror("abort");
- }
- if (ptabflg)
- code = -1;
- lostpeer();
- }
- (void) getreply(0);
- (void) getreply(0);
- }
+ 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 = empty(&mask, 10)) <= 0) {
if (nfnd < 0) {
- perror("abort");
+ warn("abort");
}
if (ptabflg)
code = -1;
}
if (proxy)
pswitch(0);
- switch (oldtype) {
- case 0:
- break;
- case TYPE_A:
- setascii();
- break;
- case TYPE_I:
- setbinary();
- break;
- case TYPE_E:
- setebcdic();
- break;
- case TYPE_L:
- settenex();
- break;
- }
pswitch(1);
if (ptabflg)
code = -1;
(void) signal(SIGINT, oldintr);
}
-reset()
+void
+reset(argc, argv)
+ int argc;
+ char *argv[];
{
struct fd_set mask;
int nfnd = 1;
FD_ZERO(&mask);
- while (nfnd) {
+ while (nfnd > 0) {
FD_SET(fileno(cin), &mask);
if ((nfnd = empty(&mask,0)) < 0) {
- perror("reset");
+ warn("reset");
code = -1;
lostpeer();
}
char *local;
{
static char new[MAXPATHLEN];
- char *cp = rindex(local, '/');
+ char *cp = strrchr(local, '/');
int d, count=0;
char ext = '1';
if (cp)
*cp = '/';
if (d < 0) {
- perror(local);
- return((char *) 0);
+ warn("local: %s", local);
+ return ((char *) 0);
}
(void) strcpy(new, local);
cp = new + strlen(new);
while (!d) {
if (++count == 100) {
printf("runique: can't find unique file name.\n");
- return((char *) 0);
+ return ((char *) 0);
}
*cp++ = ext;
*cp = '\0';
cp--;
}
}
- return(new);
+ return (new);
+}
+
+void
+abort_remote(din)
+ FILE *din;
+{
+ char buf[BUFSIZ];
+ int nfnd;
+ struct fd_set mask;
+
+ /*
+ * 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)
+ warn("abort");
+ fprintf(cout,"%cABOR\r\n", DM);
+ (void) fflush(cout);
+ FD_ZERO(&mask);
+ FD_SET(fileno(cin), &mask);
+ if (din) {
+ FD_SET(fileno(din), &mask);
+ }
+ if ((nfnd = empty(&mask, 10)) <= 0) {
+ if (nfnd < 0) {
+ warn("abort");
+ }
+ 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 */
+ (void) getreply(0);
+ }
+ (void) getreply(0);
}