/*
- * Copyright (c) 1985, 1989 Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1985, 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
*
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * %sccs.include.redist.c%
*/
#ifndef lint
-static char sccsid[] = "@(#)ftp.c 5.25 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c 8.3 (Berkeley) %G%";
#endif /* not lint */
#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;
} else {
hp = gethostbyname(host);
if (hp == NULL) {
- fprintf(stderr, "ftp: %s: ", host);
- herror((char *)NULL);
+ 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);
+ 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(), *getpass();
+ char *user, *pass, *acct;
int n, aflag = 0;
user = pass = acct = 0;
if (ruserpass(host, &user, &pass, &acct) < 0) {
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("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);
}
-char reply_string[BUFSIZ];
-
-#include <ctype.h>
+char reply_string[BUFSIZ]; /* last line of previous reply */
+int
getreply(expecteof)
int expecteof;
{
- register int c, n;
- register int dig;
- register char *cp;
- 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;
- cp = reply_string;
- 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,DONT,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,WONT,c);
+ fprintf(cout, "%c%c%c", IAC, WONT, c);
(void) fflush(cout);
break;
default:
(void) fflush(stdout);
}
code = 421;
- return(4);
+ return (4);
}
if (c != '\r' && (verbose > 0 ||
(verbose > -1 && n == '5' && dig > 4))) {
}
if (n == 0)
n = c;
- *cp++ = c;
+ if (cp < &reply_string[sizeof(reply_string) - 1])
+ *cp++ = c;
}
if (verbose > 0 || verbose > -1 && n == '5') {
(void) putchar(c);
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);
}
#define HASHBYTES 1024
-sendrequest(cmd, local, remote)
+void
+sendrequest(cmd, local, remote, printnames)
char *cmd, *local, *remote;
+ int printnames;
{
+ struct stat st;
+ struct timeval start, stop;
+ int c, d;
FILE *fin, *dout = 0, *popen();
- int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
- int abortsend();
+ int (*closefunc) __P((FILE *));
char buf[BUFSIZ], *bufp;
long bytes = 0, hashbytes = HASHBYTES;
- register int c, d;
- struct stat st;
- struct timeval start, stop;
- char *mode;
+ 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;
- mode = "w";
+ lmode = "w";
if (setjmp(sendabort)) {
while (cpend) {
(void) getreply(0);
oldintp = signal(SIGPIPE,SIG_IGN);
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;
} else {
fin = fopen(local, "r");
if (fin == NULL) {
- perror(local);
+ warn("local: %s", local);
(void) signal(SIGINT, oldintr);
code = -1;
return;
(*closefunc)(fin);
return;
}
- dout = dataconn(mode);
+ dout = dataconn(lmode);
if (dout == NULL)
goto abort;
(void) gettimeofday(&start, (struct timezone *)0);
oldintp = signal(SIGPIPE, SIG_IGN);
- switch (type) {
+ switch (curtype) {
case TYPE_I:
case TYPE_L:
(void) fflush(stdout);
}
if (c < 0)
- perror(local);
+ warn("local: %s", local);
if (d <= 0) {
if (d == 0)
fprintf(stderr, "netout: write returned 0?\n");
else if (errno != EPIPE)
- perror("netout");
+ warn("netout");
bytes = -1;
}
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);
+ warn("local: %s", local);
if (ferror(dout)) {
if (errno != EPIPE)
- perror("netout");
+ warn("netout");
bytes = -1;
}
break;
if (oldintp)
(void) signal(SIGPIPE, oldintp);
if (bytes > 0)
- ptransfer("sent", bytes, &start, &stop, local, remote);
+ ptransfer("sent", bytes, &start, &stop);
return;
abort:
(void) gettimeofday(&stop, (struct timezone *)0);
if (closefunc != NULL && fin != NULL)
(*closefunc)(fin);
if (bytes > 0)
- ptransfer("sent", bytes, &start, &stop, local, remote);
+ 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, *popen();
- int (*closefunc)(), pclose(), fclose(), (*oldintr)(), (*oldintp)();
- int abortrecv(), oldverbose, oldtype = 0, is_retr, tcrflag, nfnd;
- char *buf, *bufp, *gunique(), msg;
+ char *bufp, *gunique(), msg;
+ static char *buf;
static int bufsize;
+ static char *buf;
long bytes = 0, hashbytes = HASHBYTES;
- struct fd_set mask;
- register int c, d;
struct timeval start, stop;
struct stat st;
- extern char *malloc();
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;
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);
+ 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 (!is_retr) {
- if (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;
}
}
oldintp = signal(SIGPIPE, SIG_IGN);
fout = popen(local + 1, "w");
if (fout == NULL) {
- perror(local+1);
+ warn("%s", local+1);
goto abort;
}
closefunc = pclose;
} else {
- fout = fopen(local, mode);
+ fout = fopen(local, lmode);
if (fout == NULL) {
- perror(local);
+ warn("local: %s", local);
goto abort;
}
closefunc = fclose;
if (st.st_blksize > bufsize) {
if (buf)
(void) free(buf);
- buf = malloc(st.st_blksize);
+ buf = malloc((unsigned)st.st_blksize);
if (buf == NULL) {
- perror("malloc");
+ 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, bufsize)) > 0) {
- if ((d = write(fileno(fout), bufp, c)) != c)
+ if ((d = write(fileno(fout), buf, c)) != c)
break;
bytes += c;
if (hash) {
}
if (c < 0) {
if (errno != EPIPE)
- perror("netin");
+ warn("netin");
bytes = -1;
}
if (d < c) {
case TYPE_A:
while ((c = getc(din)) != EOF) {
+ if (c == '\n')
+ bare_lfs++;
while (c == '\r') {
while (hash && (bytes >= hashbytes)) {
(void) putchar('#');
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('#');
}
if (ferror(din)) {
if (errno != EPIPE)
- perror("netin");
+ warn("netin");
bytes = -1;
}
if (ferror(fout))
- perror(local);
+ warn("local: %s", local);
break;
}
if (closefunc != NULL)
(void) fclose(din);
(void) getreply(0);
if (bytes > 0 && is_retr)
- 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;
- }
+ 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, bufsize)) > 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);
if (din)
(void) fclose(din);
if (bytes > 0)
- ptransfer("received", bytes, &start, &stop, local, remote);
- (void) signal(SIGINT,oldintr);
+ 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.
*/
-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 (reuse 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;
{
bs = bytes / nz(s);
printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
bytes, direction, s, bs / 1024.);
- } else {
- if (local && *local != '-')
- printf("local: %s ", local);
- if (remote)
- printf("remote: %s\n", remote);
}
}
-/*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;
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);
}