/*
- * Copyright (c) 1985 Regents of the University of California.
+ * Copyright (c) 1985, 1989 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at 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'' without express or implied warranty.
+ * 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.
*/
#ifndef lint
-static char sccsid[] = "@(#)ftp.c 5.17 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c 5.31 (Berkeley) %G%";
#endif /* not lint */
-#include "ftp_var.h"
-
+#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 <arpa/ftp.h>
#include <netdb.h>
#include <fcntl.h>
#include <pwd.h>
+#include <varargs.h>
+
+#include "ftp_var.h"
struct sockaddr_in hisctladdr;
struct sockaddr_in data_addr;
int connected;
struct sockaddr_in myctladdr;
uid_t getuid();
+sig_t lostpeer();
+
+extern char *strerror();
+extern int errno;
FILE *cin, *cout;
FILE *dataconn();
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);
+ fprintf(stderr, "ftp: %s: ", host);
+ herror((char *)NULL);
code = -1;
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);
+ (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
}
hostname = hostnamebuf;
s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
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;
+ extern char *inet_ntoa();
fprintf(stderr, "ftp: connect to address %s: ",
inet_ntoa(hisctladdr.sin_addr));
goto bad;
}
len = sizeof (myctladdr);
- if (getsockname(s, (char *)&myctladdr, &len) < 0) {
+ if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
perror("ftp: getsockname");
code = -1;
goto bad;
perror("ftp: setsockopt");
}
}
-#endif SO_OOBINLINE
+#endif /* SO_OOBINLINE */
return (hostname);
bad:
char *host;
{
char tmp[80];
- char *user, *pass, *acct, *getlogin(), *mygetpass();
+ char *user, *pass, *acct, *getlogin(), *getpass();
int n, aflag = 0;
user = pass = acct = 0;
if (ruserpass(host, &user, &pass, &acct) < 0) {
- disconnect();
code = -1;
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) {
return (1);
}
+sig_t
cmdabort()
{
extern jmp_buf ptabort;
longjmp(ptabort,1);
}
-/*VARARGS1*/
-command(fmt, args)
- char *fmt;
+/*VARARGS*/
+command(va_alist)
+va_dcl
{
- int r, (*oldintr)(), cmdabort();
+ va_list ap;
+ char *fmt;
+ int r;
+ sig_t (*oldintr)(), cmdabort();
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);
}
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;
return(r);
}
+char reply_string[BUFSIZ]; /* last line of previous reply */
+
#include <ctype.h>
getreply(expecteof)
{
register int c, n;
register int dig;
- int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
+ register char *cp;
+ int originalcode = 0, continuation = 0;
+ sig_t (*oldintr)(), cmdabort();
int pflag = 0;
char *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);
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
+
+sendrequest(cmd, local, remote, printnames)
char *cmd, *local, *remote;
+ int printnames;
{
- FILE *fin, *dout = 0, *mypopen();
- int (*closefunc)(), mypclose(), fclose(), (*oldintr)(), (*oldintp)();
+ FILE *fin, *dout = 0, *popen();
+ int (*closefunc)(), pclose(), fclose();
+ sig_t (*oldintr)(), (*oldintp)();
int abortsend();
- char buf[BUFSIZ];
- long bytes = 0, hashbytes = sizeof (buf);
+ char buf[BUFSIZ], *bufp;
+ long bytes = 0, hashbytes = HASHBYTES;
register int c, d;
struct stat st;
struct timeval start, stop;
+ char *mode;
+ 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";
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);
(void) signal(SIGINT, oldintr);
code = -1;
return;
}
- closefunc = mypclose;
+ closefunc = pclose;
} else {
fin = fopen(local, "r");
if (fin == NULL) {
- perror(local);
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
(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(mode);
if (dout == NULL)
goto abort;
(void) gettimeofday(&start, (struct timezone *)0);
+ oldintp = signal(SIGPIPE, SIG_IGN);
switch (type) {
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");
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (d <= 0) {
+ if (d == 0)
+ fprintf(stderr, "netout: write returned 0?\n");
+ else if (errno != EPIPE)
+ perror("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) fflush(stdout);
}
if (ferror(fin))
- perror(local);
- if (ferror(dout))
- perror("netout");
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ if (ferror(dout)) {
+ if (errno != EPIPE)
+ perror("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;
+sig_t
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)
+recvrequest(cmd, local, remote, mode, printnames)
char *cmd, *local, *remote, *mode;
{
- 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;
+ FILE *fout, *din = 0, *popen();
+ char *bufp, *gunique(), msg;
+ static char *buf;
+ static int bufsize;
+ static char *buf;
+ long bytes = 0, hashbytes = HASHBYTES;
register int c, d;
struct timeval start, stop;
+ struct stat st;
+ extern char *malloc();
- 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);
char *dir = rindex(local, '/');
if (errno != ENOENT && errno != EACCES) {
- perror(local);
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
(void) signal(SIGINT, oldintr);
code = -1;
return;
if (dir != NULL)
*dir = '/';
if (d < 0) {
- perror(local);
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
(void) signal(SIGINT, oldintr);
code = -1;
return;
}
if (!runique && errno == EACCES &&
- chmod(local,0600) < 0) {
- perror(local);
+ chmod(local, 0600) < 0) {
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
+ (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);
goto abort;
}
- closefunc = mypclose;
- }
- else {
+ closefunc = pclose;
+ } else {
fout = fopen(local, mode);
if (fout == NULL) {
- perror(local);
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
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) {
+ perror("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)
+ perror("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)
+ perror("netin");
+ bytes = -1;
+ }
+ if (ferror(fout))
+ fprintf(stderr, "local: %s: %s\n", local,
+ strerror(errno));
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);
}
/*
* before we send the command, otherwise the
* server's connect may fail.
*/
-int sendport = -1;
+int sendport;
initconn()
{
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");
setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
perror("ftp: setsockopt (ignored)");
len = sizeof (data_addr);
- if (getsockname(data, (char *)&data_addr, &len) < 0) {
+ if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
perror("ftp: getsockname");
goto bad;
}
return (fdopen(data, mode));
}
-ptransfer(direction, bytes, t0, t1, local, remote)
- char *direction, *local, *remote;
+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)
tdiff->tv_sec--, tdiff->tv_usec += 1000000;
}
+sig_t
psabort()
{
extern int abrtflag;
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;
jmp_buf ptabort;
int ptabflg;
+sig_t
abortpt()
{
printf("\n");
proxtrans(cmd, local, remote)
char *cmd, *local, *remote;
{
- int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
+ sig_t (*oldintr)(), abortpt();
+ int secndflag = 0, prox_type, nfnd;
extern jmp_buf ptabort;
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");
}
}
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;
if (cp)
*cp = '/';
if (d < 0) {
- perror(local);
+ fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
return((char *) 0);
}
(void) strcpy(new, local);
}
return(new);
}
+
+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)
+ 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");
+ }
+ 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);
+}