added depend label
[unix-history] / usr / src / usr.bin / ftp / ftp.c
index f5b68ee..dcf1be4 100644 (file)
 /*
 /*
- * Copyright (c) 1980 Regents of the University of California.
+ * Copyright (c) 1985 Regents of the University of California.
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  */
 
 #ifndef lint
  * All rights reserved.  The Berkeley software License Agreement
  * specifies the terms and conditions for redistribution.
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)ftp.c      5.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)ftp.c      5.15 (Berkeley) %G%";
 #endif not lint
 
 #endif not lint
 
-#include <sys/param.h>
+#include "ftp_var.h"
+
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <sys/time.h>
+#include <sys/param.h>
 
 #include <netinet/in.h>
 #include <arpa/ftp.h>
 
 #include <netinet/in.h>
 #include <arpa/ftp.h>
+#include <arpa/telnet.h>
 
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
 #include <netdb.h>
 
 #include <stdio.h>
 #include <signal.h>
 #include <errno.h>
 #include <netdb.h>
-
-#include "ftp_var.h"
+#include <fcntl.h>
+#include <pwd.h>
 
 struct sockaddr_in hisctladdr;
 struct sockaddr_in data_addr;
 int    data = -1;
 
 struct sockaddr_in hisctladdr;
 struct sockaddr_in data_addr;
 int    data = -1;
+int    abrtflag = 0;
+int    ptflag = 0;
 int    connected;
 struct sockaddr_in myctladdr;
 int    connected;
 struct sockaddr_in myctladdr;
+uid_t  getuid();
 
 FILE   *cin, *cout;
 FILE   *dataconn();
 
 
 FILE   *cin, *cout;
 FILE   *dataconn();
 
-struct hostent *
+char *
 hookup(host, port)
        char *host;
        int port;
 {
 hookup(host, port)
        char *host;
        int port;
 {
-       register struct hostent *hp;
-       int s, len;
+       register struct hostent *hp = 0;
+       int s,len;
+       static char hostnamebuf[80];
 
        bzero((char *)&hisctladdr, sizeof (hisctladdr));
 
        bzero((char *)&hisctladdr, sizeof (hisctladdr));
-       hp = gethostbyname(host);
-       if (hp == NULL) {
-               static struct hostent def;
-               static struct in_addr defaddr;
-               static char namebuf[128];
-               int inet_addr();
-
-               defaddr.s_addr = inet_addr(host);
-               if (defaddr.s_addr == -1) {
-                       fprintf(stderr, "%s: Unknown host.\n", host);
-                       return (0);
-               }
-               strcpy(namebuf, host);
-               def.h_name = namebuf;
-               hostname = namebuf;
-               def.h_addr = (char *)&defaddr;
-               def.h_length = sizeof (struct in_addr);
-               def.h_addrtype = AF_INET;
-               def.h_aliases = 0;
-               hp = &def;
-       }
-       hostname = hp->h_name;
-       hisctladdr.sin_family = hp->h_addrtype;
-       s = socket(hp->h_addrtype, SOCK_STREAM, 0);
+       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 {
+               hp = gethostbyname(host);
+               if (hp == NULL) {
+                       printf("%s: unknown host\n", host);
+                       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);
+       }
+       hostname = hostnamebuf;
+       s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
        if (s < 0) {
                perror("ftp: socket");
        if (s < 0) {
                perror("ftp: socket");
+               code = -1;
                return (0);
        }
                return (0);
        }
-       if (bind(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
-               perror("ftp: bind");
-               goto bad;
-       }
-       bcopy(hp->h_addr, (char *)&hisctladdr.sin_addr, hp->h_length);
        hisctladdr.sin_port = port;
        hisctladdr.sin_port = port;
-       if (connect(s, (char *)&hisctladdr, sizeof (hisctladdr), 0) < 0) {
+       while (connect(s, &hisctladdr, sizeof (hisctladdr)) < 0) {
+               if (hp && hp->h_addr_list[1]) {
+                       int oerrno = errno;
+
+                       fprintf(stderr, "ftp: connect to address %s: ",
+                               inet_ntoa(hisctladdr.sin_addr));
+                       errno = oerrno;
+                       perror((char *) 0);
+                       hp->h_addr_list++;
+                       bcopy(hp->h_addr_list[0],
+                            (caddr_t)&hisctladdr.sin_addr, 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");
+                               code = -1;
+                               return (0);
+                       }
+                       continue;
+               }
                perror("ftp: connect");
                perror("ftp: connect");
+               code = -1;
                goto bad;
        }
        len = sizeof (myctladdr);
        if (getsockname(s, (char *)&myctladdr, &len) < 0) {
                perror("ftp: getsockname");
                goto bad;
        }
        len = sizeof (myctladdr);
        if (getsockname(s, (char *)&myctladdr, &len) < 0) {
                perror("ftp: getsockname");
+               code = -1;
                goto bad;
        }
        cin = fdopen(s, "r");
                goto bad;
        }
        cin = fdopen(s, "r");
@@ -90,50 +111,117 @@ hookup(host, port)
        if (cin == NULL || cout == NULL) {
                fprintf(stderr, "ftp: fdopen failed.\n");
                if (cin)
        if (cin == NULL || cout == NULL) {
                fprintf(stderr, "ftp: fdopen failed.\n");
                if (cin)
-                       fclose(cin);
+                       (void) fclose(cin);
                if (cout)
                if (cout)
-                       fclose(cout);
+                       (void) fclose(cout);
+               code = -1;
                goto bad;
        }
        if (verbose)
                goto bad;
        }
        if (verbose)
-               printf("Connected to %s.\n", hp->h_name);
-       (void) getreply(0);             /* read startup message from server */
-       return (hp);
+               printf("Connected to %s.\n", hostname);
+       if (getreply(0) > 2) {  /* read startup message from server */
+               if (cin)
+                       (void) fclose(cin);
+               if (cout)
+                       (void) fclose(cout);
+               code = -1;
+               goto bad;
+       }
+#ifdef SO_OOBINLINE
+       {
+       int on = 1;
+
+       if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on))
+               < 0 && debug) {
+                       perror("ftp: setsockopt");
+               }
+       }
+#endif SO_OOBINLINE
+
+       return (hostname);
 bad:
 bad:
-       close(s);
-       return ((struct hostent *)0);
+       (void) close(s);
+       return ((char *)0);
 }
 
 }
 
-login(hp)
-       struct hostent *hp;
+login(host)
+       char *host;
 {
 {
-       char acct[80];
-       char *user, *pass;
-       int n;
+       char tmp[80];
+       char *user, *pass, *acct, *getlogin(), *mygetpass();
+       int n, aflag = 0;
+
+       user = pass = acct = 0;
+       if (ruserpass(host, &user, &pass, &acct) < 0) {
+               disconnect();
+               code = -1;
+               return(0);
+       }
+       if (user == NULL) {
+               char *myname = getlogin();
 
 
-       user = pass = 0;
-       ruserpass(hp->h_name, &user, &pass);
+               if (myname == NULL) {
+                       struct passwd *pp = getpwuid(getuid());
+
+                       if (pp != NULL)
+                               myname = pp->pw_name;
+               }
+               printf("Name (%s:%s): ", host, myname);
+               (void) fgets(tmp, sizeof(tmp) - 1, stdin);
+               tmp[strlen(tmp) - 1] = '\0';
+               if (*tmp == '\0')
+                       user = myname;
+               else
+                       user = tmp;
+       }
        n = command("USER %s", user);
        n = command("USER %s", user);
-       if (n == CONTINUE)
+       if (n == CONTINUE) {
+               if (pass == NULL)
+                       pass = mygetpass("Password:");
                n = command("PASS %s", pass);
                n = command("PASS %s", pass);
+       }
        if (n == CONTINUE) {
        if (n == CONTINUE) {
-               printf("Account: "); (void) fflush(stdout);
-               (void) fgets(acct, sizeof(acct) - 1, stdin);
-               acct[strlen(acct) - 1] = '\0';
+               aflag++;
+               acct = mygetpass("Account:");
                n = command("ACCT %s", acct);
        }
        if (n != COMPLETE) {
                fprintf(stderr, "Login failed.\n");
                return (0);
        }
                n = command("ACCT %s", acct);
        }
        if (n != COMPLETE) {
                fprintf(stderr, "Login failed.\n");
                return (0);
        }
+       if (!aflag && acct != NULL)
+               (void) command("ACCT %s", acct);
+       if (proxy)
+               return(1);
+       for (n = 0; n < macnum; ++n) {
+               if (!strcmp("init", macros[n].mac_name)) {
+                       (void) strcpy(line, "$init");
+                       makeargv();
+                       domacro(margc, margv);
+                       break;
+               }
+       }
        return (1);
 }
 
        return (1);
 }
 
-/*VARARGS 1*/
+cmdabort()
+{
+       extern jmp_buf ptabort;
+
+       printf("\n");
+       (void) fflush(stdout);
+       abrtflag++;
+       if (ptflag)
+               longjmp(ptabort,1);
+}
+
+/*VARARGS1*/
 command(fmt, args)
        char *fmt;
 {
 command(fmt, args)
        char *fmt;
 {
+       int r, (*oldintr)(), cmdabort();
 
 
+       abrtflag = 0;
        if (debug) {
                printf("---> ");
                _doprnt(fmt, &args, stdout);
        if (debug) {
                printf("---> ");
                _doprnt(fmt, &args, stdout);
@@ -142,12 +230,19 @@ command(fmt, args)
        }
        if (cout == NULL) {
                perror ("No control connection for command");
        }
        if (cout == NULL) {
                perror ("No control connection for command");
+               code = -1;
                return (0);
        }
                return (0);
        }
+       oldintr = signal(SIGINT,cmdabort);
        _doprnt(fmt, &args, cout);
        fprintf(cout, "\r\n");
        (void) fflush(cout);
        _doprnt(fmt, &args, cout);
        fprintf(cout, "\r\n");
        (void) fflush(cout);
-       return (getreply(!strcmp(fmt, "QUIT")));
+       cpend = 1;
+       r = getreply(!strcmp(fmt, "QUIT"));
+       if (abrtflag && oldintr != SIG_IGN)
+               (*oldintr)();
+       (void) signal(SIGINT, oldintr);
+       return(r);
 }
 
 #include <ctype.h>
 }
 
 #include <ctype.h>
@@ -156,31 +251,80 @@ getreply(expecteof)
        int expecteof;
 {
        register int c, n;
        int expecteof;
 {
        register int c, n;
-       register int code, dig;
-       int originalcode = 0, continuation = 0;
+       register int dig;
+       int originalcode = 0, continuation = 0, (*oldintr)(), cmdabort();
+       int pflag = 0;
+       char *pt = pasv;
 
 
+       oldintr = signal(SIGINT,cmdabort);
        for (;;) {
                dig = n = code = 0;
                while ((c = getc(cin)) != '\n') {
        for (;;) {
                dig = n = code = 0;
                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);
+                                       (void) fflush(cout);
+                                       break;
+                               case DO:
+                               case DONT:
+                                       c = getc(cin);
+                                       fprintf(cout, "%c%c%c",IAC,DONT,c);
+                                       (void) fflush(cout);
+                                       break;
+                               default:
+                                       break;
+                               }
+                               continue;
+                       }
                        dig++;
                        if (c == EOF) {
                        dig++;
                        if (c == EOF) {
-                               if (expecteof)
+                               if (expecteof) {
+                                       (void) signal(SIGINT,oldintr);
+                                       code = 221;
                                        return (0);
                                        return (0);
+                               }
                                lostpeer();
                                lostpeer();
-                               exit(1);
+                               if (verbose) {
+                                       printf("421 Service not available, remote server has closed connection\n");
+                                       (void) fflush(stdout);
+                                       code = 421;
+                                       return(4);
+                               }
+                       }
+                       if (c != '\r' && (verbose > 0 ||
+                           (verbose > -1 && n == '5' && dig > 4))) {
+                               if (proxflag &&
+                                  (dig == 1 || dig == 5 && verbose == 0))
+                                       printf("%s:",hostname);
+                               (void) putchar(c);
                        }
                        }
-                       if (verbose && c != '\r' ||
-                           (n == '5' && dig > 4))
-                               putchar(c);
                        if (dig < 4 && isdigit(c))
                                code = code * 10 + (c - '0');
                        if (dig < 4 && isdigit(c))
                                code = code * 10 + (c - '0');
-                       if (dig == 4 && c == '-')
+                       if (!pflag && code == 227)
+                               pflag = 1;
+                       if (dig > 4 && pflag == 1 && isdigit(c))
+                               pflag = 2;
+                       if (pflag == 2) {
+                               if (c != '\r' && c != ')')
+                                       *pt++ = c;
+                               else {
+                                       *pt = '\0';
+                                       pflag = 3;
+                               }
+                       }
+                       if (dig == 4 && c == '-') {
+                               if (continuation)
+                                       code = 0;
                                continuation++;
                                continuation++;
+                       }
                        if (n == 0)
                                n = c;
                }
                        if (n == 0)
                                n = c;
                }
-               if (verbose || n == '5') {
-                       putchar(c);
+               if (verbose > 0 || verbose > -1 && n == '5') {
+                       (void) putchar(c);
                        (void) fflush (stdout);
                }
                if (continuation && code != originalcode) {
                        (void) fflush (stdout);
                }
                if (continuation && code != originalcode) {
@@ -188,23 +332,26 @@ getreply(expecteof)
                                originalcode = code;
                        continue;
                }
                                originalcode = code;
                        continue;
                }
-               if (expecteof || empty(cin))
-                       return (n - '0');
+               if (n != '1')
+                       cpend = 0;
+               (void) signal(SIGINT,oldintr);
+               if (code == 421 || originalcode == 421)
+                       lostpeer();
+               if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
+                       (*oldintr)();
+               return (n - '0');
        }
 }
 
        }
 }
 
-empty(f)
-       FILE *f;
+empty(mask, sec)
+       struct fd_set *mask;
+       int sec;
 {
 {
-       long mask;
        struct timeval t;
 
        struct timeval t;
 
-       if (f->_cnt > 0)
-               return (0);
-       mask = (1 << fileno(f));
-       t.tv_sec = t.tv_usec = 0;
-       (void) select(20, &mask, 0, 0, &t);
-       return (mask == 0);
+       t.tv_sec = (long) sec;
+       t.tv_usec = 0;
+       return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
 }
 
 jmp_buf        sendabort;
 }
 
 jmp_buf        sendabort;
@@ -212,58 +359,105 @@ jmp_buf  sendabort;
 abortsend()
 {
 
 abortsend()
 {
 
+       mflag = 0;
+       abrtflag = 0;
+       printf("\nsend aborted\n");
+       (void) fflush(stdout);
        longjmp(sendabort, 1);
 }
 
 sendrequest(cmd, local, remote)
        char *cmd, *local, *remote;
 {
        longjmp(sendabort, 1);
 }
 
 sendrequest(cmd, local, remote)
        char *cmd, *local, *remote;
 {
-       FILE *fin, *dout, *popen();
-       int (*closefunc)(), pclose(), fclose(), (*oldintr)();
+       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;
 
        char buf[BUFSIZ];
        long bytes = 0, hashbytes = sizeof (buf);
        register int c, d;
        struct stat st;
        struct timeval start, stop;
 
+       if (proxy) {
+               proxtrans(cmd, local, remote);
+               return;
+       }
        closefunc = NULL;
        closefunc = NULL;
-       if (setjmp(sendabort))
-               goto bad;
+       oldintr = NULL;
+       oldintp = NULL;
+       if (setjmp(sendabort)) {
+               while (cpend) {
+                       (void) getreply(0);
+               }
+               if (data >= 0) {
+                       (void) close(data);
+                       data = -1;
+               }
+               if (oldintr)
+                       (void) signal(SIGINT,oldintr);
+               if (oldintp)
+                       (void) signal(SIGPIPE,oldintp);
+               code = -1;
+               return;
+       }
        oldintr = signal(SIGINT, abortsend);
        if (strcmp(local, "-") == 0)
                fin = stdin;
        else if (*local == '|') {
        oldintr = signal(SIGINT, abortsend);
        if (strcmp(local, "-") == 0)
                fin = stdin;
        else if (*local == '|') {
-               fin = popen(local + 1, "r");
+               oldintp = signal(SIGPIPE,SIG_IGN);
+               fin = mypopen(local + 1, "r");
                if (fin == NULL) {
                        perror(local + 1);
                if (fin == NULL) {
                        perror(local + 1);
-                       goto bad;
+                       (void) signal(SIGINT, oldintr);
+                       (void) signal(SIGPIPE, oldintp);
+                       code = -1;
+                       return;
                }
                }
-               closefunc = pclose;
+               closefunc = mypclose;
        } else {
                fin = fopen(local, "r");
                if (fin == NULL) {
                        perror(local);
        } else {
                fin = fopen(local, "r");
                if (fin == NULL) {
                        perror(local);
-                       goto bad;
+                       (void) signal(SIGINT, oldintr);
+                       code = -1;
+                       return;
                }
                closefunc = fclose;
                if (fstat(fileno(fin), &st) < 0 ||
                    (st.st_mode&S_IFMT) != S_IFREG) {
                }
                closefunc = fclose;
                if (fstat(fileno(fin), &st) < 0 ||
                    (st.st_mode&S_IFMT) != S_IFREG) {
-                       fprintf(stderr, "%s: not a plain file.\n", local);
-                       goto bad;
+                       fprintf(stdout, "%s: not a plain file.\n", local);
+                       (void) signal(SIGINT, oldintr);
+                       code = -1;
+                       return;
                }
        }
                }
        }
-       if (initconn())
-               goto bad;
+       if (initconn()) {
+               (void) signal(SIGINT, oldintr);
+               if (oldintp)
+                       (void) signal(SIGPIPE, oldintp);
+               code = -1;
+               return;
+       }
+       if (setjmp(sendabort))
+               goto abort;
        if (remote) {
        if (remote) {
-               if (command("%s %s", cmd, remote) != PRELIM)
-                       goto bad;
+               if (command("%s %s", cmd, remote) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       if (oldintp)
+                               (void) signal(SIGPIPE, oldintp);
+                       return;
+               }
        } else
        } else
-               if (command("%s", cmd) != PRELIM)
-                       goto bad;
+               if (command("%s", cmd) != PRELIM) {
+                       (void) signal(SIGINT, oldintr);
+                       if (oldintp)
+                               (void) signal(SIGPIPE, oldintp);
+                       return;
+               }
        dout = dataconn("w");
        if (dout == NULL)
        dout = dataconn("w");
        if (dout == NULL)
-               goto bad;
-       gettimeofday(&start, (struct timezone *)0);
+               goto abort;
+       (void) gettimeofday(&start, (struct timezone *)0);
        switch (type) {
 
        case TYPE_I:
        switch (type) {
 
        case TYPE_I:
@@ -274,13 +468,13 @@ sendrequest(cmd, local, remote)
                                break;
                        bytes += c;
                        if (hash) {
                                break;
                        bytes += c;
                        if (hash) {
-                               putchar('#');
-                               fflush(stdout);
+                               (void) putchar('#');
+                               (void) fflush(stdout);
                        }
                }
                if (hash && bytes > 0) {
                        }
                }
                if (hash && bytes > 0) {
-                       putchar('\n');
-                       fflush(stdout);
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
                }
                if (c < 0)
                        perror(local);
                }
                if (c < 0)
                        perror(local);
@@ -292,27 +486,27 @@ sendrequest(cmd, local, remote)
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
                                while (hash && (bytes >= hashbytes)) {
                while ((c = getc(fin)) != EOF) {
                        if (c == '\n') {
                                while (hash && (bytes >= hashbytes)) {
-                                       putchar('#');
-                                       fflush(stdout);
+                                       (void) putchar('#');
+                                       (void) fflush(stdout);
                                        hashbytes += sizeof (buf);
                                }
                                if (ferror(dout))
                                        break;
                                        hashbytes += sizeof (buf);
                                }
                                if (ferror(dout))
                                        break;
-                               putc('\r', dout);
+                               (void) putc('\r', dout);
                                bytes++;
                        }
                                bytes++;
                        }
-                       putc(c, dout);
+                       (void) putc(c, dout);
                        bytes++;
                        bytes++;
-                       if (c == '\r') {
-                               putc('\0', dout);
-                               bytes++;
-                       }
+       /*              if (c == '\r') {                                */
+       /*              (void)  putc('\0', dout);  /* this violates rfc */
+       /*                      bytes++;                                */
+       /*              }                                               */      
                }
                if (hash) {
                        if (bytes < hashbytes)
                }
                if (hash) {
                        if (bytes < hashbytes)
-                               putchar('#');
-                       putchar('\n');
-                       fflush(stdout);
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
                }
                if (ferror(fin))
                        perror(local);
                }
                if (ferror(fin))
                        perror(local);
@@ -320,22 +514,36 @@ sendrequest(cmd, local, remote)
                        perror("netout");
                break;
        }
                        perror("netout");
                break;
        }
-       gettimeofday(&stop, (struct timezone *)0);
+       (void) gettimeofday(&stop, (struct timezone *)0);
        if (closefunc != NULL)
                (*closefunc)(fin);
        (void) fclose(dout);
        (void) getreply(0);
        if (closefunc != NULL)
                (*closefunc)(fin);
        (void) fclose(dout);
        (void) getreply(0);
-done:
-       signal(SIGINT, oldintr);
+       (void) signal(SIGINT, oldintr);
        if (bytes > 0 && verbose)
        if (bytes > 0 && verbose)
-               ptransfer("sent", bytes, &start, &stop);
+               ptransfer("sent", bytes, &start, &stop, local, remote);
        return;
        return;
-bad:
-       if (data >= 0)
-               (void) close(data), data = -1;
+abort:
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       (void) signal(SIGINT, oldintr);
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintp);
+       if (!cpend) {
+               code = -1;
+               return;
+       }
+       if (data >= 0) {
+               (void) close(data);
+               data = -1;
+       }
+       if (dout)
+               (void) fclose(dout);
+       (void) getreply(0);
+       code = -1;
        if (closefunc != NULL && fin != NULL)
                (*closefunc)(fin);
        if (closefunc != NULL && fin != NULL)
                (*closefunc)(fin);
-       goto done;
+       if (bytes > 0 && verbose)
+               ptransfer("sent", bytes, &start, &stop, local, remote);
 }
 
 jmp_buf        recvabort;
 }
 
 jmp_buf        recvabort;
@@ -343,27 +551,57 @@ jmp_buf   recvabort;
 abortrecv()
 {
 
 abortrecv()
 {
 
+       mflag = 0;
+       abrtflag = 0;
+       printf("\n");
+       (void) fflush(stdout);
        longjmp(recvabort, 1);
 }
 
 recvrequest(cmd, local, remote, mode)
        char *cmd, *local, *remote, *mode;
 {
        longjmp(recvabort, 1);
 }
 
 recvrequest(cmd, local, remote, mode)
        char *cmd, *local, *remote, *mode;
 {
-       FILE *fout, *din, *popen();
-       int (*closefunc)(), pclose(), fclose(), (*oldintr)();
-       char buf[BUFSIZ];
+       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);
        long bytes = 0, hashbytes = sizeof (buf);
+       struct fd_set mask;
        register int c, d;
        struct timeval start, stop;
 
        register int c, d;
        struct timeval start, stop;
 
+       if (proxy && strcmp(cmd,"RETR") == 0) {
+               proxtrans(cmd, local, remote);
+               return;
+       }
        closefunc = NULL;
        closefunc = NULL;
-       if (setjmp(recvabort))
-               goto bad;
+       oldintr = NULL;
+       oldintp = NULL;
+       tcrflag = !crflag && !strcmp(cmd, "RETR");
+       if (setjmp(recvabort)) {
+               while (cpend) {
+                       (void) getreply(0);
+               }
+               if (data >= 0) {
+                       (void) close(data);
+                       data = -1;
+               }
+               if (oldintr)
+                       (void) signal(SIGINT, oldintr);
+               code = -1;
+               return;
+       }
        oldintr = signal(SIGINT, abortrecv);
        oldintr = signal(SIGINT, abortrecv);
-       if (strcmp(local, "-") && *local != '|')
+       if (strcmp(local, "-") && *local != '|') {
                if (access(local, 2) < 0) {
                        char *dir = rindex(local, '/');
 
                if (access(local, 2) < 0) {
                        char *dir = rindex(local, '/');
 
+                       if (errno != ENOENT && errno != EACCES) {
+                               perror(local);
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
                        if (dir != NULL)
                                *dir = 0;
                        d = access(dir ? local : ".", 2);
                        if (dir != NULL)
                                *dir = 0;
                        d = access(dir ? local : ".", 2);
@@ -371,34 +609,111 @@ recvrequest(cmd, local, remote, mode)
                                *dir = '/';
                        if (d < 0) {
                                perror(local);
                                *dir = '/';
                        if (d < 0) {
                                perror(local);
-                               goto bad;
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+                       if (!runique && errno == EACCES &&
+                           chmod(local,0600) < 0) {
+                               perror(local);
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
+                       }
+                       if (runique && errno == EACCES &&
+                          (local = gunique(local)) == NULL) {
+                               (void) signal(SIGINT, oldintr);
+                               code = -1;
+                               return;
                        }
                }
                        }
                }
-       if (initconn())
-               goto bad;
+               else if (runique && (local = gunique(local)) == NULL) {
+                       (void) signal(SIGINT, oldintr);
+                       code = -1;
+                       return;
+               }
+       }
+       if (initconn()) {
+               (void) signal(SIGINT, oldintr);
+               code = -1;
+               return;
+       }
+       if (setjmp(recvabort))
+               goto abort;
+       if (strcmp(cmd, "RETR") && type != TYPE_A) {
+               oldtype = type;
+               oldverbose = verbose;
+               if (!debug)
+                       verbose = 0;
+               setascii();
+               verbose = oldverbose;
+       }
        if (remote) {
        if (remote) {
-               if (command("%s %s", cmd, remote) != PRELIM)
-                       goto bad;
-       } else
-               if (command("%s", cmd) != PRELIM)
-                       goto bad;
+               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;
+               }
+       }
+       din = dataconn("r");
+       if (din == NULL)
+               goto abort;
        if (strcmp(local, "-") == 0)
                fout = stdout;
        else if (*local == '|') {
        if (strcmp(local, "-") == 0)
                fout = stdout;
        else if (*local == '|') {
-               fout = popen(local + 1, "w");
-               closefunc = pclose;
-       } else {
+               oldintp = signal(SIGPIPE, SIG_IGN);
+               fout = mypopen(local + 1, "w");
+               if (fout == NULL) {
+                       perror(local+1);
+                       goto abort;
+               }
+               closefunc = mypclose;
+       }
+       else {
                fout = fopen(local, mode);
                fout = fopen(local, mode);
+               if (fout == NULL) {
+                       perror(local);
+                       goto abort;
+               }
                closefunc = fclose;
        }
                closefunc = fclose;
        }
-       if (fout == NULL) {
-               perror(local + 1);
-               goto bad;
-       }
-       din = dataconn("r");
-       if (din == NULL)
-               goto bad;
-       gettimeofday(&start, (struct timezone *)0);
+       (void) gettimeofday(&start, (struct timezone *)0);
        switch (type) {
 
        case TYPE_I:
        switch (type) {
 
        case TYPE_I:
@@ -409,13 +724,13 @@ recvrequest(cmd, local, remote, mode)
                                break;
                        bytes += c;
                        if (hash) {
                                break;
                        bytes += c;
                        if (hash) {
-                               putchar('#');
-                               fflush(stdout);
+                               (void) putchar('#');
+                               (void) fflush(stdout);
                        }
                }
                if (hash && bytes > 0) {
                        }
                }
                if (hash && bytes > 0) {
-                       putchar('\n');
-                       fflush(stdout);
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
                }
                if (c < 0)
                        perror("netin");
                }
                if (c < 0)
                        perror("netin");
@@ -425,31 +740,31 @@ recvrequest(cmd, local, remote, mode)
 
        case TYPE_A:
                while ((c = getc(din)) != EOF) {
 
        case TYPE_A:
                while ((c = getc(din)) != EOF) {
-                       if (c == '\r') {
+                       while (c == '\r') {
                                while (hash && (bytes >= hashbytes)) {
                                while (hash && (bytes >= hashbytes)) {
-                                       putchar('#');
-                                       fflush(stdout);
+                                       (void) putchar('#');
+                                       (void) fflush(stdout);
                                        hashbytes += sizeof (buf);
                                }
                                bytes++;
                                        hashbytes += sizeof (buf);
                                }
                                bytes++;
-                               if ((c = getc(din)) != '\n') {
+                               if ((c = getc(din)) != '\n' || tcrflag) {
                                        if (ferror (fout))
                                                break;
                                        if (ferror (fout))
                                                break;
-                                       putc ('\r', fout);
+                                       (void) putc ('\r', fout);
                                }
                                }
-                               if (c == '\0') {
+                               /*if (c == '\0') {
                                        bytes++;
                                        continue;
                                        bytes++;
                                        continue;
-                               }
+                               }*/
                        }
                        }
-                       putc (c, fout);
+                       (void) putc (c, fout);
                        bytes++;
                }
                if (hash) {
                        if (bytes < hashbytes)
                        bytes++;
                }
                if (hash) {
                        if (bytes < hashbytes)
-                               putchar('#');
-                       putchar('\n');
-                       fflush(stdout);
+                               (void) putchar('#');
+                       (void) putchar('\n');
+                       (void) fflush(stdout);
                }
                if (ferror (din))
                        perror ("netin");
                }
                if (ferror (din))
                        perror ("netin");
@@ -457,22 +772,109 @@ recvrequest(cmd, local, remote, mode)
                        perror (local);
                break;
        }
                        perror (local);
                break;
        }
-       gettimeofday(&stop, (struct timezone *)0);
-       (void) fclose(din);
        if (closefunc != NULL)
                (*closefunc)(fout);
        if (closefunc != NULL)
                (*closefunc)(fout);
+       (void) signal(SIGINT, oldintr);
+       if (oldintp)
+               (void) signal(SIGPIPE, oldintp);
+       (void) gettimeofday(&stop, (struct timezone *)0);
+       (void) fclose(din);
        (void) getreply(0);
        (void) getreply(0);
-done:
-       signal(SIGINT, oldintr);
        if (bytes > 0 && verbose)
        if (bytes > 0 && verbose)
-               ptransfer("received", bytes, &start, &stop);
+               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;
+       }
        return;
        return;
-bad:
-       if (data >= 0)
-               (void) close(data), data = -1;
+abort:
+
+/* abort using RFC959 recommended IP,SYNC sequence  */
+
+       (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;
+       }
+       if (!cpend) {
+               code = -1;
+               (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);
+       code = -1;
+       if (data >= 0) {
+               (void) close(data);
+               data = -1;
+       }
        if (closefunc != NULL && fout != NULL)
                (*closefunc)(fout);
        if (closefunc != NULL && fout != NULL)
                (*closefunc)(fout);
-       goto done;
+       if (din)
+               (void) fclose(din);
+       if (bytes > 0 && verbose)
+               ptransfer("received", bytes, &start, &stop, local, remote);
+       (void) signal(SIGINT,oldintr);
 }
 
 /*
 }
 
 /*
@@ -485,7 +887,7 @@ static int sendport = -1;
 initconn()
 {
        register char *p, *a;
 initconn()
 {
        register char *p, *a;
-       int result, len;
+       int result, len, tmpno = 0;
        int on = 1;
 
 noport:
        int on = 1;
 
 noport:
@@ -497,29 +899,29 @@ noport:
        data = socket(AF_INET, SOCK_STREAM, 0);
        if (data < 0) {
                perror("ftp: socket");
        data = socket(AF_INET, SOCK_STREAM, 0);
        if (data < 0) {
                perror("ftp: socket");
+               if (tmpno)
+                       sendport = 1;
                return (1);
        }
        if (!sendport)
                return (1);
        }
        if (!sendport)
-               if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) {
+               if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
                        perror("ftp: setsockopt (resuse address)");
                        goto bad;
                }
                        perror("ftp: setsockopt (resuse address)");
                        goto bad;
                }
-       if (bind(data, (char *)&data_addr, sizeof (data_addr), 0) < 0) {
+       if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
                perror("ftp: bind");
                goto bad;
        }
        if (options & SO_DEBUG &&
                perror("ftp: bind");
                goto bad;
        }
        if (options & SO_DEBUG &&
-           setsockopt(data, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
+           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) {
                perror("ftp: getsockname");
                goto bad;
        }
                perror("ftp: setsockopt (ignored)");
        len = sizeof (data_addr);
        if (getsockname(data, (char *)&data_addr, &len) < 0) {
                perror("ftp: getsockname");
                goto bad;
        }
-       if (listen(data, 1) < 0) {
+       if (listen(data, 1) < 0)
                perror("ftp: listen");
                perror("ftp: listen");
-               goto bad;
-       }
        if (sendport) {
                a = (char *)&data_addr.sin_addr;
                p = (char *)&data_addr.sin_port;
        if (sendport) {
                a = (char *)&data_addr.sin_addr;
                p = (char *)&data_addr.sin_port;
@@ -530,13 +932,18 @@ noport:
                      UC(p[0]), UC(p[1]));
                if (result == ERROR && sendport == -1) {
                        sendport = 0;
                      UC(p[0]), UC(p[1]));
                if (result == ERROR && sendport == -1) {
                        sendport = 0;
+                       tmpno = 1;
                        goto noport;
                }
                return (result != COMPLETE);
        }
                        goto noport;
                }
                return (result != COMPLETE);
        }
+       if (tmpno)
+               sendport = 1;
        return (0);
 bad:
        (void) close(data), data = -1;
        return (0);
 bad:
        (void) close(data), data = -1;
+       if (tmpno)
+               sendport = 1;
        return (1);
 }
 
        return (1);
 }
 
@@ -547,7 +954,7 @@ dataconn(mode)
        struct sockaddr_in from;
        int s, fromlen = sizeof (from);
 
        struct sockaddr_in from;
        int s, fromlen = sizeof (from);
 
-       s = accept(data, &from, &fromlen, 0);
+       s = accept(data, (struct sockaddr *) &from, &fromlen);
        if (s < 0) {
                perror("ftp: accept");
                (void) close(data), data = -1;
        if (s < 0) {
                perror("ftp: accept");
                (void) close(data), data = -1;
@@ -558,8 +965,8 @@ dataconn(mode)
        return (fdopen(data, mode));
 }
 
        return (fdopen(data, mode));
 }
 
-ptransfer(direction, bytes, t0, t1)
-       char *direction;
+ptransfer(direction, bytes, t0, t1, local, remote)
+       char *direction, *local, *remote;
        long bytes;
        struct timeval *t0, *t1;
 {
        long bytes;
        struct timeval *t0, *t1;
 {
@@ -570,11 +977,15 @@ ptransfer(direction, bytes, t0, t1)
        s = td.tv_sec + (td.tv_usec / 1000000.);
 #define        nz(x)   ((x) == 0 ? 1 : (x))
        bs = bytes / nz(s);
        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.);
 }
 
        printf("%ld bytes %s in %.2g seconds (%.2g Kbytes/s)\n",
                bytes, direction, s, bs / 1024.);
 }
 
-tvadd(tsum, t0)
+/*tvadd(tsum, t0)
        struct timeval *tsum, *t0;
 {
 
        struct timeval *tsum, *t0;
 {
 
@@ -582,7 +993,7 @@ tvadd(tsum, t0)
        tsum->tv_usec += t0->tv_usec;
        if (tsum->tv_usec > 1000000)
                tsum->tv_sec++, tsum->tv_usec -= 1000000;
        tsum->tv_usec += t0->tv_usec;
        if (tsum->tv_usec > 1000000)
                tsum->tv_sec++, tsum->tv_usec -= 1000000;
-}
+} */
 
 tvsub(tdiff, t1, t0)
        struct timeval *tdiff, *t1, *t0;
 
 tvsub(tdiff, t1, t0)
        struct timeval *tdiff, *t1, *t0;
@@ -593,3 +1004,491 @@ tvsub(tdiff, t1, t0)
        if (tdiff->tv_usec < 0)
                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
 }
        if (tdiff->tv_usec < 0)
                tdiff->tv_sec--, tdiff->tv_usec += 1000000;
 }
+
+psabort()
+{
+       extern int abrtflag;
+
+       abrtflag++;
+}
+
+pswitch(flag)
+       int flag;
+{
+       extern int proxy, abrtflag;
+       int (*oldintr)();
+       static struct comvars {
+               int connect;
+               char name[MAXHOSTNAMELEN];
+               struct sockaddr_in mctl;
+               struct sockaddr_in hctl;
+               FILE *in;
+               FILE *out;
+               int tpe;
+               int cpnd;
+               int sunqe;
+               int runqe;
+               int mcse;
+               int ntflg;
+               char nti[17];
+               char nto[17];
+               int mapflg;
+               char mi[MAXPATHLEN];
+               char mo[MAXPATHLEN];
+               } proxstruct, tmpstruct;
+       struct comvars *ip, *op;
+
+       abrtflag = 0;
+       oldintr = signal(SIGINT, psabort);
+       if (flag) {
+               if (proxy)
+                       return;
+               ip = &tmpstruct;
+               op = &proxstruct;
+               proxy++;
+       }
+       else {
+               if (!proxy)
+                       return;
+               ip = &proxstruct;
+               op = &tmpstruct;
+               proxy = 0;
+       }
+       ip->connect = connected;
+       connected = op->connect;
+       if (hostname) {
+               (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
+               ip->name[strlen(ip->name)] = '\0';
+       } else
+               ip->name[0] = 0;
+       hostname = op->name;
+       ip->hctl = hisctladdr;
+       hisctladdr = op->hctl;
+       ip->mctl = myctladdr;
+       myctladdr = op->mctl;
+       ip->in = cin;
+       cin = op->in;
+       ip->out = cout;
+       cout = op->out;
+       ip->tpe = type;
+       type = op->tpe;
+       if (!type)
+               type = 1;
+       ip->cpnd = cpend;
+       cpend = op->cpnd;
+       ip->sunqe = sunique;
+       sunique = op->sunqe;
+       ip->runqe = runique;
+       runique = op->runqe;
+       ip->mcse = mcase;
+       mcase = op->mcse;
+       ip->ntflg = ntflag;
+       ntflag = op->ntflg;
+       (void) strncpy(ip->nti, ntin, 16);
+       (ip->nti)[strlen(ip->nti)] = '\0';
+       (void) strcpy(ntin, op->nti);
+       (void) strncpy(ip->nto, ntout, 16);
+       (ip->nto)[strlen(ip->nto)] = '\0';
+       (void) strcpy(ntout, op->nto);
+       ip->mapflg = mapflag;
+       mapflag = op->mapflg;
+       (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
+       (ip->mi)[strlen(ip->mi)] = '\0';
+       (void) strcpy(mapin, op->mi);
+       (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
+       (ip->mo)[strlen(ip->mo)] = '\0';
+       (void) strcpy(mapout, op->mo);
+       (void) signal(SIGINT, oldintr);
+       if (abrtflag) {
+               abrtflag = 0;
+               (*oldintr)();
+       }
+}
+
+jmp_buf ptabort;
+int ptabflg;
+
+abortpt()
+{
+       printf("\n");
+       (void) fflush(stdout);
+       ptabflg++;
+       mflag = 0;
+       abrtflag = 0;
+       longjmp(ptabort, 1);
+}
+
+proxtrans(cmd, local, remote)
+       char *cmd, *local, *remote;
+{
+       int (*oldintr)(), abortpt(), tmptype, oldtype = 0, secndflag = 0, nfnd;
+       extern jmp_buf ptabort;
+       char *cmd2;
+       struct fd_set mask;
+
+       if (strcmp(cmd, "RETR"))
+               cmd2 = "RETR";
+       else
+               cmd2 = runique ? "STOU" : "STOR";
+       if (command("PASV") != COMPLETE) {
+               printf("proxy server does not support third part transfers.\n");
+               return;
+       }
+       tmptype = type;
+       pswitch(0);
+       if (!connected) {
+               printf("No primary connection\n");
+               pswitch(1);
+               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 (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;
+       }
+       if (setjmp(ptabort))
+               goto abort;
+       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;
+       }
+       sleep(2);
+       pswitch(1);
+       secndflag++;
+       if (command("%s %s", cmd2, local) != PRELIM)
+               goto abort;
+       ptflag++;
+       (void) getreply(0);
+       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);
+       return;
+abort:
+       (void) signal(SIGINT, SIG_IGN);
+       ptflag = 0;
+       if (strcmp(cmd, "RETR") && !proxy)
+               pswitch(1);
+       else if (!strcmp(cmd, "RETR") && proxy)
+               pswitch(0);
+       if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
+               if (command("%s %s", cmd2, local) != PRELIM) {
+                       pswitch(0);
+                       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);
+                       }
+               }
+               pswitch(1);
+               if (ptabflg)
+                       code = -1;
+               (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);
+       }
+       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);
+                       }
+                       pswitch(1);
+                       if (ptabflg)
+                               code = -1;
+                       (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);
+       }
+       pswitch(!proxy);
+       if (cpend) {
+               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 (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()
+{
+       struct fd_set mask;
+       int nfnd = 1;
+
+       FD_ZERO(&mask);
+       while (nfnd > 0) {
+               FD_SET(fileno(cin), &mask);
+               if ((nfnd = empty(&mask,0)) < 0) {
+                       perror("reset");
+                       code = -1;
+                       lostpeer();
+               }
+               else if (nfnd) {
+                       (void) getreply(0);
+               }
+       }
+}
+
+char *
+gunique(local)
+       char *local;
+{
+       static char new[MAXPATHLEN];
+       char *cp = rindex(local, '/');
+       int d, count=0;
+       char ext = '1';
+
+       if (cp)
+               *cp = '\0';
+       d = access(cp ? local : ".", 2);
+       if (cp)
+               *cp = '/';
+       if (d < 0) {
+               perror(local);
+               return((char *) 0);
+       }
+       (void) strcpy(new, local);
+       cp = new + strlen(new);
+       *cp++ = '.';
+       while (!d) {
+               if (++count == 100) {
+                       printf("runique: can't find unique file name.\n");
+                       return((char *) 0);
+               }
+               *cp++ = ext;
+               *cp = '\0';
+               if (ext == '9')
+                       ext = '0';
+               else
+                       ext++;
+               if ((d = access(new, 0)) < 0)
+                       break;
+               if (ext != '0')
+                       cp--;
+               else if (*(cp - 2) == '.')
+                       *(cp - 1) = '1';
+               else {
+                       *(cp - 2) = *(cp - 2) + 1;
+                       cp--;
+               }
+       }
+       return(new);
+}