home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / netkit-b.05 / netkit-b / NetKit-B-0.05 / ftp / ftp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-24  |  32.0 KB  |  1,515 lines

  1. /*
  2.  * Copyright (c) 1985, 1989 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. /*static char sccsid[] = "from: @(#)ftp.c    5.38 (Berkeley) 4/22/91";*/
  36. static char rcsid[] = "$Id: ftp.c,v 1.1 1994/05/23 09:03:41 rzsfl Exp rzsfl $";
  37. #endif /* not lint */
  38.  
  39. #include <sys/param.h>
  40. #include <sys/stat.h>
  41. #include <sys/ioctl.h>
  42. #include <sys/socket.h>
  43. #include <sys/time.h>
  44. #include <sys/file.h>
  45.  
  46. #include <netinet/in.h>
  47. #include <netinet/ip.h>
  48. #include <arpa/ftp.h>
  49. #include <arpa/telnet.h>
  50.  
  51. #include <stdio.h>
  52. #include <signal.h>
  53. #include <errno.h>
  54. #include <netdb.h>
  55. #include <fcntl.h>
  56. #include <pwd.h>
  57. #include <varargs.h>
  58.  
  59. #include "ftp_var.h"
  60.  
  61. struct    sockaddr_in hisctladdr;
  62. struct    sockaddr_in data_addr;
  63. int    data = -1;
  64. int    abrtflag = 0;
  65. int    ptflag = 0;
  66. struct    sockaddr_in myctladdr;
  67. uid_t    getuid();
  68. sig_t    lostpeer();
  69. off_t    restart_point = 0;
  70.  
  71. extern char *strerror();
  72. extern int connected, errno;
  73.  
  74. FILE    *cin, *cout;
  75. FILE    *dataconn();
  76.  
  77. char *
  78. hookup(host, port)
  79.     char *host;
  80.     int port;
  81. {
  82.     register struct hostent *hp = 0;
  83.     int s, len, tos;
  84.     static char hostnamebuf[80];
  85.  
  86.     bzero((char *)&hisctladdr, sizeof (hisctladdr));
  87.     hisctladdr.sin_addr.s_addr = inet_addr(host);
  88.     if (hisctladdr.sin_addr.s_addr != -1) {
  89.         hisctladdr.sin_family = AF_INET;
  90.         (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf));
  91.     } else {
  92.         hp = gethostbyname(host);
  93.         if (hp == NULL) {
  94.             fprintf(stderr, "ftp: %s: ", host);
  95.             herror((char *)NULL);
  96.             code = -1;
  97.             return((char *) 0);
  98.         }
  99.         hisctladdr.sin_family = hp->h_addrtype;
  100.         bcopy(hp->h_addr_list[0],
  101.             (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  102.         (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf));
  103.     }
  104.     hostname = hostnamebuf;
  105.     s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  106.     if (s < 0) {
  107.         perror("ftp: socket");
  108.         code = -1;
  109.         return (0);
  110.     }
  111.     hisctladdr.sin_port = port;
  112.     while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) {
  113.         if (hp && hp->h_addr_list[1]) {
  114.             int oerrno = errno;
  115.             extern char *inet_ntoa();
  116.  
  117.             fprintf(stderr, "ftp: connect to address %s: ",
  118.                 inet_ntoa(hisctladdr.sin_addr));
  119.             errno = oerrno;
  120.             perror((char *) 0);
  121.             hp->h_addr_list++;
  122.             bcopy(hp->h_addr_list[0],
  123.                  (caddr_t)&hisctladdr.sin_addr, hp->h_length);
  124.             fprintf(stdout, "Trying %s...\n",
  125.                 inet_ntoa(hisctladdr.sin_addr));
  126.             (void) close(s);
  127.             s = socket(hisctladdr.sin_family, SOCK_STREAM, 0);
  128.             if (s < 0) {
  129.                 perror("ftp: socket");
  130.                 code = -1;
  131.                 return (0);
  132.             }
  133.             continue;
  134.         }
  135.         perror("ftp: connect");
  136.         code = -1;
  137.         goto bad;
  138.     }
  139.     len = sizeof (myctladdr);
  140.     if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) {
  141.         perror("ftp: getsockname");
  142.         code = -1;
  143.         goto bad;
  144.     }
  145. #ifdef IP_TOS
  146.     tos = IPTOS_LOWDELAY;
  147.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  148.         perror("ftp: setsockopt TOS (ignored)");
  149. #endif
  150.     cin = fdopen(s, "r");
  151.     cout = fdopen(s, "w");
  152.     if (cin == NULL || cout == NULL) {
  153.         fprintf(stderr, "ftp: fdopen failed.\n");
  154.         if (cin)
  155.             (void) fclose(cin);
  156.         if (cout)
  157.             (void) fclose(cout);
  158.         code = -1;
  159.         goto bad;
  160.     }
  161.     if (verbose)
  162.         printf("Connected to %s.\n", hostname);
  163.     if (getreply(0) > 2) {     /* read startup message from server */
  164.         if (cin)
  165.             (void) fclose(cin);
  166.         if (cout)
  167.             (void) fclose(cout);
  168.         code = -1;
  169.         goto bad;
  170.     }
  171. #ifdef SO_OOBINLINE
  172.     {
  173.     int on = 1;
  174.  
  175.     if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on))
  176.         < 0 && debug) {
  177.             perror("ftp: setsockopt");
  178.         }
  179.     }
  180. #endif /* SO_OOBINLINE */
  181.  
  182.     return (hostname);
  183. bad:
  184.     (void) close(s);
  185.     return ((char *)0);
  186. }
  187.  
  188. login(host)
  189.     char *host;
  190. {
  191.     char tmp[80];
  192.     char *user, *pass, *acct, *getlogin(), *getpass();
  193.     int n, aflag = 0;
  194.  
  195.     user = pass = acct = 0;
  196.     if (ruserpass(host, &user, &pass, &acct) < 0) {
  197.         code = -1;
  198.         return(0);
  199.     }
  200.     while (user == NULL) {
  201.         char *myname = getlogin();
  202.  
  203.         if (myname == NULL) {
  204.             struct passwd *pp = getpwuid(getuid());
  205.  
  206.             if (pp != NULL)
  207.                 myname = pp->pw_name;
  208.         }
  209.         if (myname)
  210.             printf("Name (%s:%s): ", host, myname);
  211.         else
  212.             printf("Name (%s): ", host);
  213.         (void) fgets(tmp, sizeof(tmp) - 1, stdin);
  214.         tmp[strlen(tmp) - 1] = '\0';
  215.         if (*tmp == '\0')
  216.             user = myname;
  217.         else
  218.             user = tmp;
  219.     }
  220.     n = command("USER %s", user);
  221.     if (n == CONTINUE) {
  222.         if (pass == NULL) {
  223.             /* fflush(stdout); */
  224.             pass = getpass("Password:");
  225.         }
  226.         n = command("PASS %s", pass);
  227.     }
  228.     if (n == CONTINUE) {
  229.         aflag++;
  230.         /* fflush(stdout); */
  231.         acct = getpass("Account:");
  232.         n = command("ACCT %s", acct);
  233.     }
  234.     if (n != COMPLETE) {
  235.         fprintf(stderr, "Login failed.\n");
  236.         return (0);
  237.     }
  238.     if (!aflag && acct != NULL)
  239.         (void) command("ACCT %s", acct);
  240.     if (proxy)
  241.         return(1);
  242.     for (n = 0; n < macnum; ++n) {
  243.         if (!strcmp("init", macros[n].mac_name)) {
  244.             (void) strcpy(line, "$init");
  245.             makeargv();
  246.             domacro(margc, margv);
  247.             break;
  248.         }
  249.     }
  250.     return (1);
  251. }
  252.  
  253. void
  254. cmdabort()
  255. {
  256.     extern jmp_buf ptabort;
  257.  
  258.     printf("\n");
  259.     (void) fflush(stdout);
  260.     abrtflag++;
  261.     if (ptflag)
  262.         longjmp(ptabort,1);
  263. }
  264.  
  265. /*VARARGS*/
  266. command(va_alist)
  267. va_dcl
  268. {
  269.     va_list ap;
  270.     char *fmt;
  271.     int r;
  272.     sig_t oldintr;
  273.     void cmdabort();
  274.  
  275.     abrtflag = 0;
  276.     if (debug) {
  277.         printf("---> ");
  278.         va_start(ap);
  279.         fmt = va_arg(ap, char *);
  280.         if (strncmp("PASS ", fmt, 5) == 0)
  281.             printf("PASS XXXX");
  282.         else 
  283.             vfprintf(stdout, fmt, ap);
  284.         va_end(ap);
  285.         printf("\n");
  286.         (void) fflush(stdout);
  287.     }
  288.     if (cout == NULL) {
  289.         perror ("No control connection for command");
  290.         code = -1;
  291.         return (0);
  292.     }
  293.     oldintr = signal(SIGINT, cmdabort);
  294.     va_start(ap);
  295.     fmt = va_arg(ap, char *);
  296.     vfprintf(cout, fmt, ap);
  297.     va_end(ap);
  298.     fprintf(cout, "\r\n");
  299.     (void) fflush(cout);
  300.     cpend = 1;
  301.     r = getreply(!strcmp(fmt, "QUIT"));
  302.     if (abrtflag && oldintr != SIG_IGN)
  303.         (*oldintr)(SIGINT);
  304.     (void) signal(SIGINT, oldintr);
  305.     return(r);
  306. }
  307.  
  308. char reply_string[BUFSIZ];        /* last line of previous reply */
  309.  
  310. #include <ctype.h>
  311.  
  312. getreply(expecteof)
  313.     int expecteof;
  314. {
  315.     register int c, n;
  316.     register int dig;
  317.     register char *cp;
  318.     int originalcode = 0, continuation = 0;
  319.     sig_t oldintr;
  320.     int pflag = 0;
  321.     char *pt = pasv;
  322.     void cmdabort();
  323.  
  324.     oldintr = signal(SIGINT, cmdabort);
  325.     for (;;) {
  326.         dig = n = code = 0;
  327.         cp = reply_string;
  328.         while ((c = getc(cin)) != '\n') {
  329.             if (c == IAC) {     /* handle telnet commands */
  330.                 switch (c = getc(cin)) {
  331.                 case WILL:
  332.                 case WONT:
  333.                     c = getc(cin);
  334.                     fprintf(cout, "%c%c%c", IAC, DONT, c);
  335.                     (void) fflush(cout);
  336.                     break;
  337.                 case DO:
  338.                 case DONT:
  339.                     c = getc(cin);
  340.                     fprintf(cout, "%c%c%c", IAC, WONT, c);
  341.                     (void) fflush(cout);
  342.                     break;
  343.                 default:
  344.                     break;
  345.                 }
  346.                 continue;
  347.             }
  348.             dig++;
  349.             if (c == EOF) {
  350.                 if (expecteof) {
  351.                     (void) signal(SIGINT,oldintr);
  352.                     code = 221;
  353.                     return (0);
  354.                 }
  355.                 lostpeer();
  356.                 if (verbose) {
  357.                     printf("421 Service not available, remote server has closed connection\n");
  358.                     (void) fflush(stdout);
  359.                 }
  360.                 code = 421;
  361.                 return(4);
  362.             }
  363.             if (c != '\r' && (verbose > 0 ||
  364.                 (verbose > -1 && n == '5' && dig > 4))) {
  365.                 if (proxflag &&
  366.                    (dig == 1 || dig == 5 && verbose == 0))
  367.                     printf("%s:",hostname);
  368.                 (void) putchar(c);
  369.             }
  370.             if (dig < 4 && isdigit(c))
  371.                 code = code * 10 + (c - '0');
  372.             if (!pflag && code == 227)
  373.                 pflag = 1;
  374.             if (dig > 4 && pflag == 1 && isdigit(c))
  375.                 pflag = 2;
  376.             if (pflag == 2) {
  377.                 if (c != '\r' && c != ')')
  378.                     *pt++ = c;
  379.                 else {
  380.                     *pt = '\0';
  381.                     pflag = 3;
  382.                 }
  383.             }
  384.             if (dig == 4 && c == '-') {
  385.                 if (continuation)
  386.                     code = 0;
  387.                 continuation++;
  388.             }
  389.             if (n == 0)
  390.                 n = c;
  391.             if (cp < &reply_string[sizeof(reply_string) - 1])
  392.                 *cp++ = c;
  393.         }
  394.         if (verbose > 0 || verbose > -1 && n == '5') {
  395.             (void) putchar(c);
  396.             (void) fflush (stdout);
  397.         }
  398.         if (continuation && code != originalcode) {
  399.             if (originalcode == 0)
  400.                 originalcode = code;
  401.             continue;
  402.         }
  403.         *cp = '\0';
  404.         if (n != '1')
  405.             cpend = 0;
  406.         (void) signal(SIGINT,oldintr);
  407.         if (code == 421 || originalcode == 421)
  408.             lostpeer();
  409.         if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
  410.             (*oldintr)(SIGINT);
  411.         return (n - '0');
  412.     }
  413. }
  414.  
  415. empty(mask, sec)
  416.     struct fd_set *mask;
  417.     int sec;
  418. {
  419.     struct timeval t;
  420.  
  421.     t.tv_sec = (long) sec;
  422.     t.tv_usec = 0;
  423.     return(select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t));
  424. }
  425.  
  426. jmp_buf    sendabort;
  427.  
  428. void
  429. abortsend()
  430. {
  431.  
  432.     mflag = 0;
  433.     abrtflag = 0;
  434.     printf("\nsend aborted\nwaiting for remote to finish abort\n");
  435.     (void) fflush(stdout);
  436.     longjmp(sendabort, 1);
  437. }
  438.  
  439. #define HASHBYTES 1024
  440.  
  441. sendrequest(cmd, local, remote, printnames)
  442.     char *cmd, *local, *remote;
  443.     int printnames;
  444. {
  445.     struct stat st;
  446.     struct timeval start, stop;
  447.     register int c, d;
  448.     FILE *fin, *dout = 0, *popen();
  449.     int (*closefunc)(), pclose(), fclose();
  450.     sig_t oldintr, oldintp;
  451.     long bytes = 0, hashbytes = HASHBYTES;
  452.     char *lmode, buf[BUFSIZ], *bufp;
  453.     void abortsend();
  454.  
  455.     if (verbose && printnames) {
  456.         if (local && *local != '-')
  457.             printf("local: %s ", local);
  458.         if (remote)
  459.             printf("remote: %s\n", remote);
  460.     }
  461.     if (proxy) {
  462.         proxtrans(cmd, local, remote);
  463.         return;
  464.     }
  465.     if (curtype != type)
  466.         changetype(type, 0);
  467.     closefunc = NULL;
  468.     oldintr = NULL;
  469.     oldintp = NULL;
  470.     lmode = "w";
  471.     if (setjmp(sendabort)) {
  472.         while (cpend) {
  473.             (void) getreply(0);
  474.         }
  475.         if (data >= 0) {
  476.             (void) close(data);
  477.             data = -1;
  478.         }
  479.         if (oldintr)
  480.             (void) signal(SIGINT,oldintr);
  481.         if (oldintp)
  482.             (void) signal(SIGPIPE,oldintp);
  483.         code = -1;
  484.         return;
  485.     }
  486.     oldintr = signal(SIGINT, abortsend);
  487.     if (strcmp(local, "-") == 0)
  488.         fin = stdin;
  489.     else if (*local == '|') {
  490.         oldintp = signal(SIGPIPE,SIG_IGN);
  491.         fin = popen(local + 1, "r");
  492.         if (fin == NULL) {
  493.             perror(local + 1);
  494.             (void) signal(SIGINT, oldintr);
  495.             (void) signal(SIGPIPE, oldintp);
  496.             code = -1;
  497.             return;
  498.         }
  499.         closefunc = pclose;
  500.     } else {
  501.         fin = fopen(local, "r");
  502.         if (fin == NULL) {
  503.             fprintf(stderr, "local: %s: %s\n", local,
  504.                 strerror(errno));
  505.             (void) signal(SIGINT, oldintr);
  506.             code = -1;
  507.             return;
  508.         }
  509.         closefunc = fclose;
  510.         if (fstat(fileno(fin), &st) < 0 ||
  511.             (st.st_mode&S_IFMT) != S_IFREG) {
  512.             fprintf(stdout, "%s: not a plain file.\n", local);
  513.             (void) signal(SIGINT, oldintr);
  514.             fclose(fin);
  515.             code = -1;
  516.             return;
  517.         }
  518.     }
  519.     if (initconn()) {
  520.         (void) signal(SIGINT, oldintr);
  521.         if (oldintp)
  522.             (void) signal(SIGPIPE, oldintp);
  523.         code = -1;
  524.         if (closefunc != NULL)
  525.             (*closefunc)(fin);
  526.         return;
  527.     }
  528.     if (setjmp(sendabort))
  529.         goto abort;
  530.  
  531.     if (restart_point &&
  532.         (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) {
  533.         if (fseek(fin, (long) restart_point, 0) < 0) {
  534.             fprintf(stderr, "local: %s: %s\n", local,
  535.                 strerror(errno));
  536.             restart_point = 0;
  537.             if (closefunc != NULL)
  538.                 (*closefunc)(fin);
  539.             return;
  540.         }
  541.         if (command("REST %ld", (long) restart_point)
  542.             != CONTINUE) {
  543.             restart_point = 0;
  544.             if (closefunc != NULL)
  545.                 (*closefunc)(fin);
  546.             return;
  547.         }
  548.         restart_point = 0;
  549.         lmode = "r+w";
  550.     }
  551.     if (remote) {
  552.         if (command("%s %s", cmd, remote) != PRELIM) {
  553.             (void) signal(SIGINT, oldintr);
  554.             if (oldintp)
  555.                 (void) signal(SIGPIPE, oldintp);
  556.             if (closefunc != NULL)
  557.                 (*closefunc)(fin);
  558.             return;
  559.         }
  560.     } else
  561.         if (command("%s", cmd) != PRELIM) {
  562.             (void) signal(SIGINT, oldintr);
  563.             if (oldintp)
  564.                 (void) signal(SIGPIPE, oldintp);
  565.             if (closefunc != NULL)
  566.                 (*closefunc)(fin);
  567.             return;
  568.         }
  569.     dout = dataconn(lmode);
  570.     if (dout == NULL)
  571.         goto abort;
  572.     (void) gettimeofday(&start, (struct timezone *)0);
  573.     oldintp = signal(SIGPIPE, SIG_IGN);
  574.     switch (curtype) {
  575.  
  576.     case TYPE_I:
  577.     case TYPE_L:
  578.         errno = d = 0;
  579.         while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) {
  580.             bytes += c;
  581.             for (bufp = buf; c > 0; c -= d, bufp += d)
  582.                 if ((d = write(fileno(dout), bufp, c)) <= 0)
  583.                     break;
  584.             if (hash) {
  585.                 while (bytes >= hashbytes) {
  586.                     (void) putchar('#');
  587.                     hashbytes += HASHBYTES;
  588.                 }
  589.                 (void) fflush(stdout);
  590.             }
  591.             if (tick && (bytes >= hashbytes)) {
  592.                 printf("\rBytes transferred: %d", bytes);
  593.                 (void) fflush(stdout);
  594.                 while (bytes >= hashbytes)
  595.                     hashbytes += TICKBYTES;
  596.             }
  597.         }
  598.         if (hash && (bytes > 0)) {
  599.             if (bytes < HASHBYTES)
  600.                 (void) putchar('#');
  601.             (void) putchar('\n');
  602.             (void) fflush(stdout);
  603.         }
  604.         if (tick) {
  605.             (void) printf("\rBytes transferred: %d\n", bytes);
  606.             (void) fflush(stdout);
  607.         }
  608.         if (c < 0)
  609.             fprintf(stderr, "local: %s: %s\n", local,
  610.                 strerror(errno));
  611.         if (d < 0) {
  612.             if (errno != EPIPE) 
  613.                 perror("netout");
  614.             bytes = -1;
  615.         }
  616.         break;
  617.  
  618.     case TYPE_A:
  619.         while ((c = getc(fin)) != EOF) {
  620.             if (c == '\n') {
  621.                 while (hash && (bytes >= hashbytes)) {
  622.                     (void) putchar('#');
  623.                     (void) fflush(stdout);
  624.                     hashbytes += HASHBYTES;
  625.                 }
  626.                 if (tick && (bytes >= hashbytes)) {
  627.                     (void) printf("\rBytes transferred: %d",
  628.                         bytes);
  629.                     (void) fflush(stdout);
  630.                     while (bytes >= hashbytes)
  631.                         hashbytes += TICKBYTES;
  632.                 }
  633.                 if (ferror(dout))
  634.                     break;
  635.                 (void) putc('\r', dout);
  636.                 bytes++;
  637.             }
  638.             (void) putc(c, dout);
  639.             bytes++;
  640.     /*        if (c == '\r') {                  */
  641.     /*        (void)    putc('\0', dout);  /* this violates rfc */
  642.     /*            bytes++;                */
  643.     /*        }                                      */    
  644.         }
  645.         if (hash) {
  646.             if (bytes < hashbytes)
  647.                 (void) putchar('#');
  648.             (void) putchar('\n');
  649.             (void) fflush(stdout);
  650.         }
  651.         if (tick) {
  652.             (void) printf("\rBytes transferred: %d\n", bytes);
  653.             (void) fflush(stdout);
  654.         }
  655.         if (ferror(fin))
  656.             fprintf(stderr, "local: %s: %s\n", local,
  657.                 strerror(errno));
  658.         if (ferror(dout)) {
  659.             if (errno != EPIPE)
  660.                 perror("netout");
  661.             bytes = -1;
  662.         }
  663.         break;
  664.     }
  665.     (void) gettimeofday(&stop, (struct timezone *)0);
  666.     if (closefunc != NULL)
  667.         (*closefunc)(fin);
  668.     (void) fclose(dout);
  669.     (void) getreply(0);
  670.     (void) signal(SIGINT, oldintr);
  671.     if (oldintp)
  672.         (void) signal(SIGPIPE, oldintp);
  673.     if (bytes > 0)
  674.         ptransfer("sent", bytes, &start, &stop);
  675.     return;
  676. abort:
  677.     (void) gettimeofday(&stop, (struct timezone *)0);
  678.     (void) signal(SIGINT, oldintr);
  679.     if (oldintp)
  680.         (void) signal(SIGPIPE, oldintp);
  681.     if (!cpend) {
  682.         code = -1;
  683.         return;
  684.     }
  685.     if (data >= 0) {
  686.         (void) close(data);
  687.         data = -1;
  688.     }
  689.     if (dout)
  690.         (void) fclose(dout);
  691.     (void) getreply(0);
  692.     code = -1;
  693.     if (closefunc != NULL && fin != NULL)
  694.         (*closefunc)(fin);
  695.     if (bytes > 0)
  696.         ptransfer("sent", bytes, &start, &stop);
  697. }
  698.  
  699. jmp_buf    recvabort;
  700.  
  701. void
  702. abortrecv()
  703. {
  704.  
  705.     mflag = 0;
  706.     abrtflag = 0;
  707.     printf("\nreceive aborted\nwaiting for remote to finish abort\n");
  708.     (void) fflush(stdout);
  709.     longjmp(recvabort, 1);
  710. }
  711.  
  712. recvrequest(cmd, local, remote, lmode, printnames)
  713.     char *cmd, *local, *remote, *lmode;
  714. {
  715.     FILE *fout, *din = 0, *popen();
  716.     int (*closefunc)(), pclose(), fclose();
  717.     sig_t oldintr, oldintp;
  718.     int is_retr, tcrflag, bare_lfs = 0;
  719.     char *gunique();
  720.     static int bufsize;
  721.     static char *buf;
  722.     long bytes = 0, hashbytes = HASHBYTES;
  723.     register int c, d;
  724.     struct timeval start, stop;
  725.     struct stat st;
  726.     off_t lseek();
  727.     void abortrecv();
  728.     char *malloc();
  729.  
  730.     is_retr = strcmp(cmd, "RETR") == 0;
  731.     if (is_retr && verbose && printnames) {
  732.         if (local && *local != '-')
  733.             printf("local: %s ", local);
  734.         if (remote)
  735.             printf("remote: %s\n", remote);
  736.     }
  737.     if (proxy && is_retr) {
  738.         proxtrans(cmd, local, remote);
  739.         return;
  740.     }
  741.     closefunc = NULL;
  742.     oldintr = NULL;
  743.     oldintp = NULL;
  744.     tcrflag = !crflag && is_retr;
  745.     if (setjmp(recvabort)) {
  746.         while (cpend) {
  747.             (void) getreply(0);
  748.         }
  749.         if (data >= 0) {
  750.             (void) close(data);
  751.             data = -1;
  752.         }
  753.         if (oldintr)
  754.             (void) signal(SIGINT, oldintr);
  755.         code = -1;
  756.         return;
  757.     }
  758.     oldintr = signal(SIGINT, abortrecv);
  759.     if (strcmp(local, "-") && *local != '|') {
  760.         if (access(local, 2) < 0) {
  761.             char *dir = rindex(local, '/');
  762.  
  763.             if (errno != ENOENT && errno != EACCES) {
  764.                 fprintf(stderr, "local: %s: %s\n", local,
  765.                     strerror(errno));
  766.                 (void) signal(SIGINT, oldintr);
  767.                 code = -1;
  768.                 return;
  769.             }
  770.             if (dir != NULL)
  771.                 *dir = 0;
  772.             d = access(dir ? local : ".", 2);
  773.             if (dir != NULL)
  774.                 *dir = '/';
  775.             if (d < 0) {
  776.                 fprintf(stderr, "local: %s: %s\n", local,
  777.                     strerror(errno));
  778.                 (void) signal(SIGINT, oldintr);
  779.                 code = -1;
  780.                 return;
  781.             }
  782.             if (!runique && errno == EACCES &&
  783.                 chmod(local, 0600) < 0) {
  784.                 fprintf(stderr, "local: %s: %s\n", local,
  785.                     strerror(errno));
  786.                 (void) signal(SIGINT, oldintr);
  787.                 (void) signal(SIGINT, oldintr);
  788.                 code = -1;
  789.                 return;
  790.             }
  791.             if (runique && errno == EACCES &&
  792.                (local = gunique(local)) == NULL) {
  793.                 (void) signal(SIGINT, oldintr);
  794.                 code = -1;
  795.                 return;
  796.             }
  797.         }
  798.         else if (runique && (local = gunique(local)) == NULL) {
  799.             (void) signal(SIGINT, oldintr);
  800.             code = -1;
  801.             return;
  802.         }
  803.     }
  804.     if (!is_retr) {
  805.         if (curtype != TYPE_A)
  806.             changetype(TYPE_A, 0);
  807.     } else if (curtype != type)
  808.         changetype(type, 0);
  809.     if (initconn()) {
  810.         (void) signal(SIGINT, oldintr);
  811.         code = -1;
  812.         return;
  813.     }
  814.     if (setjmp(recvabort))
  815.         goto abort;
  816.     if (is_retr && restart_point &&
  817.         command("REST %ld", (long) restart_point) != CONTINUE)
  818.         return;
  819.     if (remote) {
  820.         if (command("%s %s", cmd, remote) != PRELIM) {
  821.             (void) signal(SIGINT, oldintr);
  822.             return;
  823.         }
  824.     } else {
  825.         if (command("%s", cmd) != PRELIM) {
  826.             (void) signal(SIGINT, oldintr);
  827.             return;
  828.         }
  829.     }
  830.     din = dataconn("r");
  831.     if (din == NULL)
  832.         goto abort;
  833.     if (strcmp(local, "-") == 0)
  834.         fout = stdout;
  835.     else if (*local == '|') {
  836.         oldintp = signal(SIGPIPE, SIG_IGN);
  837.         fout = popen(local + 1, "w");
  838.         if (fout == NULL) {
  839.             perror(local+1);
  840.             goto abort;
  841.         }
  842.         closefunc = pclose;
  843.     } else {
  844.         fout = fopen(local, lmode);
  845.         if (fout == NULL) {
  846.             fprintf(stderr, "local: %s: %s\n", local,
  847.                 strerror(errno));
  848.             goto abort;
  849.         }
  850.         closefunc = fclose;
  851.     }
  852.     if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0)
  853.         st.st_blksize = BUFSIZ;
  854.     if (st.st_blksize > bufsize) {
  855.         if (buf)
  856.             (void) free(buf);
  857.         buf = malloc((unsigned)st.st_blksize);
  858.         if (buf == NULL) {
  859.             perror("malloc");
  860.             bufsize = 0;
  861.             goto abort;
  862.         }
  863.         bufsize = st.st_blksize;
  864.     }
  865.     (void) gettimeofday(&start, (struct timezone *)0);
  866.     switch (curtype) {
  867.  
  868.     case TYPE_I:
  869.     case TYPE_L:
  870.         if (restart_point &&
  871.             lseek(fileno(fout), (long) restart_point, L_SET) < 0) {
  872.             fprintf(stderr, "local: %s: %s\n", local,
  873.                 strerror(errno));
  874.             if (closefunc != NULL)
  875.                 (*closefunc)(fout);
  876.             return;
  877.         }
  878.         errno = d = 0;
  879.         while ((c = read(fileno(din), buf, bufsize)) > 0) {
  880.             if ((d = write(fileno(fout), buf, c)) != c)
  881.                 break;
  882.             bytes += c;
  883.             if (hash && is_retr) {
  884.                 while (bytes >= hashbytes) {
  885.                     (void) putchar('#');
  886.                     hashbytes += HASHBYTES;
  887.                 }
  888.                 (void) fflush(stdout);
  889.             }
  890.             if (tick && (bytes >= hashbytes) && is_retr) {
  891.                 (void) printf("\rBytes transferred: %d",
  892.                     bytes);
  893.                 (void) fflush(stdout);
  894.                 while (bytes >= hashbytes)
  895.                     hashbytes += TICKBYTES;
  896.             }
  897.         }
  898.         if (hash && bytes > 0) {
  899.             if (bytes < HASHBYTES)
  900.                 (void) putchar('#');
  901.             (void) putchar('\n');
  902.             (void) fflush(stdout);
  903.         }
  904.         if (tick && is_retr) {
  905.             (void) printf("\rBytes transferred: %d\n", bytes);
  906.             (void) fflush(stdout);
  907.         }
  908.         if (c < 0) {
  909.             if (errno != EPIPE)
  910.                 perror("netin");
  911.             bytes = -1;
  912.         }
  913.         if (d < c) {
  914.             if (d < 0)
  915.                 fprintf(stderr, "local: %s: %s\n", local,
  916.                     strerror(errno));
  917.             else
  918.                 fprintf(stderr, "%s: short write\n", local);
  919.         }
  920.         break;
  921.  
  922.     case TYPE_A:
  923.         if (restart_point) {
  924.             register int i, n, ch;
  925.  
  926.             if (fseek(fout, 0L, L_SET) < 0)
  927.                 goto done;
  928.             n = restart_point;
  929.             for (i = 0; i++ < n;) {
  930.                 if ((ch = getc(fout)) == EOF)
  931.                     goto done;
  932.                 if (ch == '\n')
  933.                     i++;
  934.             }
  935.             if (fseek(fout, 0L, L_INCR) < 0) {
  936. done:
  937.                 fprintf(stderr, "local: %s: %s\n", local,
  938.                     strerror(errno));
  939.                 if (closefunc != NULL)
  940.                     (*closefunc)(fout);
  941.                 return;
  942.             }
  943.         }
  944.         while ((c = getc(din)) != EOF) {
  945.             if (c == '\n')
  946.                 bare_lfs++;
  947.             while (c == '\r') {
  948.                 while (hash && (bytes >= hashbytes)
  949.                     && is_retr) {
  950.                     (void) putchar('#');
  951.                     (void) fflush(stdout);
  952.                     hashbytes += HASHBYTES;
  953.                 }
  954.                 if (tick && (bytes >= hashbytes) && is_retr) {
  955.                     (void) printf("\rBytes transferred: %d",
  956.                         bytes);
  957.                     (void) fflush(stdout);
  958.                     while (bytes >= hashbytes)
  959.                         hashbytes += TICKBYTES;
  960.                 }
  961.                 bytes++;
  962.                 if ((c = getc(din)) != '\n' || tcrflag) {
  963.                     if (ferror(fout))
  964.                         goto break2;
  965.                     (void) putc('\r', fout);
  966.                     if (c == '\0') {
  967.                         bytes++;
  968.                         goto contin2;
  969.                     }
  970.                     if (c == EOF)
  971.                         goto contin2;
  972.                 }
  973.             }
  974.             (void) putc(c, fout);
  975.             bytes++;
  976.     contin2:    ;
  977.         }
  978. break2:
  979.         if (hash && is_retr) {
  980.             if (bytes < hashbytes)
  981.                 (void) putchar('#');
  982.             (void) putchar('\n');
  983.             (void) fflush(stdout);
  984.         }
  985.         if (tick && is_retr) {
  986.             (void) printf("\rBytes transferred: %d\n", bytes);
  987.             (void) fflush(stdout);
  988.         }
  989.         if (bare_lfs) {
  990.             printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs);
  991.             printf("File may not have transferred correctly.\n");
  992.         }
  993.         if (ferror(din)) {
  994.             if (errno != EPIPE)
  995.                 perror("netin");
  996.             bytes = -1;
  997.         }
  998.         if (ferror(fout))
  999.             fprintf(stderr, "local: %s: %s\n", local,
  1000.                 strerror(errno));
  1001.         break;
  1002.     }
  1003.     if (closefunc != NULL)
  1004.         (*closefunc)(fout);
  1005.     (void) signal(SIGINT, oldintr);
  1006.     if (oldintp)
  1007.         (void) signal(SIGPIPE, oldintp);
  1008.     (void) gettimeofday(&stop, (struct timezone *)0);
  1009.     (void) fclose(din);
  1010.     (void) getreply(0);
  1011.     if (bytes > 0 && is_retr)
  1012.         ptransfer("received", bytes, &start, &stop);
  1013.     return;
  1014. abort:
  1015.  
  1016. /* abort using RFC959 recommended IP,SYNC sequence  */
  1017.  
  1018.     (void) gettimeofday(&stop, (struct timezone *)0);
  1019.     if (oldintp)
  1020.         (void) signal(SIGPIPE, oldintr);
  1021.     (void) signal(SIGINT, SIG_IGN);
  1022.     if (!cpend) {
  1023.         code = -1;
  1024.         (void) signal(SIGINT, oldintr);
  1025.         return;
  1026.     }
  1027.  
  1028.     abort_remote(din);
  1029.     code = -1;
  1030.     if (data >= 0) {
  1031.         (void) close(data);
  1032.         data = -1;
  1033.     }
  1034.     if (closefunc != NULL && fout != NULL)
  1035.         (*closefunc)(fout);
  1036.     if (din)
  1037.         (void) fclose(din);
  1038.     if (bytes > 0)
  1039.         ptransfer("received", bytes, &start, &stop);
  1040.     (void) signal(SIGINT, oldintr);
  1041. }
  1042.  
  1043. /*
  1044.  * Need to start a listen on the data channel before we send the command,
  1045.  * otherwise the server's connect may fail.
  1046.  */
  1047. initconn()
  1048. {
  1049.     register char *p, *a;
  1050.     int result, len, tmpno = 0;
  1051.     int on = 1;
  1052.  
  1053. noport:
  1054.     data_addr = myctladdr;
  1055.     if (sendport)
  1056.         data_addr.sin_port = 0;    /* let system pick one */ 
  1057.     if (data != -1)
  1058.         (void) close(data);
  1059.     data = socket(AF_INET, SOCK_STREAM, 0);
  1060.     if (data < 0) {
  1061.         perror("ftp: socket");
  1062.         if (tmpno)
  1063.             sendport = 1;
  1064.         return (1);
  1065.     }
  1066.     if (!sendport)
  1067.         if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) {
  1068.             perror("ftp: setsockopt (reuse address)");
  1069.             goto bad;
  1070.         }
  1071.     if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) {
  1072.         perror("ftp: bind");
  1073.         goto bad;
  1074.     }
  1075.     if (options & SO_DEBUG &&
  1076.         setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0)
  1077.         perror("ftp: setsockopt (ignored)");
  1078.     len = sizeof (data_addr);
  1079.     if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) {
  1080.         perror("ftp: getsockname");
  1081.         goto bad;
  1082.     }
  1083.     if (listen(data, 1) < 0)
  1084.         perror("ftp: listen");
  1085.     if (sendport) {
  1086.         a = (char *)&data_addr.sin_addr;
  1087.         p = (char *)&data_addr.sin_port;
  1088. #define    UC(b)    (((int)b)&0xff)
  1089.         result =
  1090.             command("PORT %d,%d,%d,%d,%d,%d",
  1091.               UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
  1092.               UC(p[0]), UC(p[1]));
  1093.         if (result == ERROR && sendport == -1) {
  1094.             sendport = 0;
  1095.             tmpno = 1;
  1096.             goto noport;
  1097.         }
  1098.         return (result != COMPLETE);
  1099.     }
  1100.     if (tmpno)
  1101.         sendport = 1;
  1102. #ifdef IP_TOS
  1103.     on = IPTOS_THROUGHPUT;
  1104.     if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
  1105.         perror("ftp: setsockopt TOS (ignored)");
  1106. #endif
  1107.     return (0);
  1108. bad:
  1109.     (void) close(data), data = -1;
  1110.     if (tmpno)
  1111.         sendport = 1;
  1112.     return (1);
  1113. }
  1114.  
  1115. FILE *
  1116. dataconn(lmode)
  1117.     char *lmode;
  1118. {
  1119.     struct sockaddr_in from;
  1120.     int s, fromlen = sizeof (from), tos;
  1121.  
  1122.     s = accept(data, (struct sockaddr *) &from, &fromlen);
  1123.     if (s < 0) {
  1124.         perror("ftp: accept");
  1125.         (void) close(data), data = -1;
  1126.         return (NULL);
  1127.     }
  1128.     (void) close(data);
  1129.     data = s;
  1130. #ifdef IP_TOS
  1131.     tos = IPTOS_THROUGHPUT;
  1132.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
  1133.         perror("ftp: setsockopt TOS (ignored)");
  1134. #endif
  1135.     return (fdopen(data, lmode));
  1136. }
  1137.  
  1138. ptransfer(direction, bytes, t0, t1)
  1139.     char *direction;
  1140.     long bytes;
  1141.     struct timeval *t0, *t1;
  1142. {
  1143.     struct timeval td;
  1144.     float s, bs;
  1145.  
  1146.     if (verbose) {
  1147.         tvsub(&td, t1, t0);
  1148.         s = td.tv_sec + (td.tv_usec / 1000000.);
  1149. #define    nz(x)    ((x) == 0 ? 1 : (x))
  1150.         bs = bytes / nz(s);
  1151.         printf("%ld bytes %s in %.3g secs (%.2g Kbytes/sec)\n",
  1152.             bytes, direction, s, bs / 1024.0);
  1153.     }
  1154. }
  1155.  
  1156. /*tvadd(tsum, t0)
  1157.     struct timeval *tsum, *t0;
  1158. {
  1159.  
  1160.     tsum->tv_sec += t0->tv_sec;
  1161.     tsum->tv_usec += t0->tv_usec;
  1162.     if (tsum->tv_usec > 1000000)
  1163.         tsum->tv_sec++, tsum->tv_usec -= 1000000;
  1164. } */
  1165.  
  1166. tvsub(tdiff, t1, t0)
  1167.     struct timeval *tdiff, *t1, *t0;
  1168. {
  1169.  
  1170.     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
  1171.     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
  1172.     if (tdiff->tv_usec < 0)
  1173.         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
  1174. }
  1175.  
  1176. void
  1177. psabort()
  1178. {
  1179.     extern int abrtflag;
  1180.  
  1181.     abrtflag++;
  1182. }
  1183.  
  1184. pswitch(flag)
  1185.     int flag;
  1186. {
  1187.     extern int proxy, abrtflag;
  1188.     sig_t oldintr;
  1189.     static struct comvars {
  1190.         int connect;
  1191.         char name[MAXHOSTNAMELEN];
  1192.         struct sockaddr_in mctl;
  1193.         struct sockaddr_in hctl;
  1194.         FILE *in;
  1195.         FILE *out;
  1196.         int tpe;
  1197.         int curtpe;
  1198.         int cpnd;
  1199.         int sunqe;
  1200.         int runqe;
  1201.         int mcse;
  1202.         int ntflg;
  1203.         char nti[17];
  1204.         char nto[17];
  1205.         int mapflg;
  1206.         char mi[MAXPATHLEN];
  1207.         char mo[MAXPATHLEN];
  1208.     } proxstruct, tmpstruct;
  1209.     struct comvars *ip, *op;
  1210.  
  1211.     abrtflag = 0;
  1212.     oldintr = signal(SIGINT, psabort);
  1213.     if (flag) {
  1214.         if (proxy)
  1215.             return;
  1216.         ip = &tmpstruct;
  1217.         op = &proxstruct;
  1218.         proxy++;
  1219.     } else {
  1220.         if (!proxy)
  1221.             return;
  1222.         ip = &proxstruct;
  1223.         op = &tmpstruct;
  1224.         proxy = 0;
  1225.     }
  1226.     ip->connect = connected;
  1227.     connected = op->connect;
  1228.     if (hostname) {
  1229.         (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1);
  1230.         ip->name[strlen(ip->name)] = '\0';
  1231.     } else
  1232.         ip->name[0] = 0;
  1233.     hostname = op->name;
  1234.     ip->hctl = hisctladdr;
  1235.     hisctladdr = op->hctl;
  1236.     ip->mctl = myctladdr;
  1237.     myctladdr = op->mctl;
  1238.     ip->in = cin;
  1239.     cin = op->in;
  1240.     ip->out = cout;
  1241.     cout = op->out;
  1242.     ip->tpe = type;
  1243.     type = op->tpe;
  1244.     ip->curtpe = curtype;
  1245.     curtype = op->curtpe;
  1246.     ip->cpnd = cpend;
  1247.     cpend = op->cpnd;
  1248.     ip->sunqe = sunique;
  1249.     sunique = op->sunqe;
  1250.     ip->runqe = runique;
  1251.     runique = op->runqe;
  1252.     ip->mcse = mcase;
  1253.     mcase = op->mcse;
  1254.     ip->ntflg = ntflag;
  1255.     ntflag = op->ntflg;
  1256.     (void) strncpy(ip->nti, ntin, 16);
  1257.     (ip->nti)[strlen(ip->nti)] = '\0';
  1258.     (void) strcpy(ntin, op->nti);
  1259.     (void) strncpy(ip->nto, ntout, 16);
  1260.     (ip->nto)[strlen(ip->nto)] = '\0';
  1261.     (void) strcpy(ntout, op->nto);
  1262.     ip->mapflg = mapflag;
  1263.     mapflag = op->mapflg;
  1264.     (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1);
  1265.     (ip->mi)[strlen(ip->mi)] = '\0';
  1266.     (void) strcpy(mapin, op->mi);
  1267.     (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1);
  1268.     (ip->mo)[strlen(ip->mo)] = '\0';
  1269.     (void) strcpy(mapout, op->mo);
  1270.     (void) signal(SIGINT, oldintr);
  1271.     if (abrtflag) {
  1272.         abrtflag = 0;
  1273.         (*oldintr)(SIGINT);
  1274.     }
  1275. }
  1276.  
  1277. jmp_buf ptabort;
  1278. int ptabflg;
  1279.  
  1280. void
  1281. abortpt()
  1282. {
  1283.     printf("\n");
  1284.     (void) fflush(stdout);
  1285.     ptabflg++;
  1286.     mflag = 0;
  1287.     abrtflag = 0;
  1288.     longjmp(ptabort, 1);
  1289. }
  1290.  
  1291. proxtrans(cmd, local, remote)
  1292.     char *cmd, *local, *remote;
  1293. {
  1294.     sig_t oldintr;
  1295.     int secndflag = 0, prox_type, nfnd;
  1296.     extern jmp_buf ptabort;
  1297.     char *cmd2;
  1298.     struct fd_set mask;
  1299.     void abortpt();
  1300.  
  1301.     if (strcmp(cmd, "RETR"))
  1302.         cmd2 = "RETR";
  1303.     else
  1304.         cmd2 = runique ? "STOU" : "STOR";
  1305.     if ((prox_type = type) == 0) {
  1306.         if (unix_server && unix_proxy)
  1307.             prox_type = TYPE_I;
  1308.         else
  1309.             prox_type = TYPE_A;
  1310.     }
  1311.     if (curtype != prox_type)
  1312.         changetype(prox_type, 1);
  1313.     if (command("PASV") != COMPLETE) {
  1314.         printf("proxy server does not support third party transfers.\n");
  1315.         return;
  1316.     }
  1317.     pswitch(0);
  1318.     if (!connected) {
  1319.         printf("No primary connection\n");
  1320.         pswitch(1);
  1321.         code = -1;
  1322.         return;
  1323.     }
  1324.     if (curtype != prox_type)
  1325.         changetype(prox_type, 1);
  1326.     if (command("PORT %s", pasv) != COMPLETE) {
  1327.         pswitch(1);
  1328.         return;
  1329.     }
  1330.     if (setjmp(ptabort))
  1331.         goto abort;
  1332.     oldintr = signal(SIGINT, abortpt);
  1333.     if (command("%s %s", cmd, remote) != PRELIM) {
  1334.         (void) signal(SIGINT, oldintr);
  1335.         pswitch(1);
  1336.         return;
  1337.     }
  1338.     sleep(2);
  1339.     pswitch(1);
  1340.     secndflag++;
  1341.     if (command("%s %s", cmd2, local) != PRELIM)
  1342.         goto abort;
  1343.     ptflag++;
  1344.     (void) getreply(0);
  1345.     pswitch(0);
  1346.     (void) getreply(0);
  1347.     (void) signal(SIGINT, oldintr);
  1348.     pswitch(1);
  1349.     ptflag = 0;
  1350.     printf("local: %s remote: %s\n", local, remote);
  1351.     return;
  1352. abort:
  1353.     (void) signal(SIGINT, SIG_IGN);
  1354.     ptflag = 0;
  1355.     if (strcmp(cmd, "RETR") && !proxy)
  1356.         pswitch(1);
  1357.     else if (!strcmp(cmd, "RETR") && proxy)
  1358.         pswitch(0);
  1359.     if (!cpend && !secndflag) {  /* only here if cmd = "STOR" (proxy=1) */
  1360.         if (command("%s %s", cmd2, local) != PRELIM) {
  1361.             pswitch(0);
  1362.             if (cpend)
  1363.                 abort_remote((FILE *) NULL);
  1364.         }
  1365.         pswitch(1);
  1366.         if (ptabflg)
  1367.             code = -1;
  1368.         (void) signal(SIGINT, oldintr);
  1369.         return;
  1370.     }
  1371.     if (cpend)
  1372.         abort_remote((FILE *) NULL);
  1373.     pswitch(!proxy);
  1374.     if (!cpend && !secndflag) {  /* only if cmd = "RETR" (proxy=1) */
  1375.         if (command("%s %s", cmd2, local) != PRELIM) {
  1376.             pswitch(0);
  1377.             if (cpend)
  1378.                 abort_remote((FILE *) NULL);
  1379.             pswitch(1);
  1380.             if (ptabflg)
  1381.                 code = -1;
  1382.             (void) signal(SIGINT, oldintr);
  1383.             return;
  1384.         }
  1385.     }
  1386.     if (cpend)
  1387.         abort_remote((FILE *) NULL);
  1388.     pswitch(!proxy);
  1389.     if (cpend) {
  1390.         FD_ZERO(&mask);
  1391.         FD_SET(fileno(cin), &mask);
  1392.         if ((nfnd = empty(&mask, 10)) <= 0) {
  1393.             if (nfnd < 0) {
  1394.                 perror("abort");
  1395.             }
  1396.             if (ptabflg)
  1397.                 code = -1;
  1398.             lostpeer();
  1399.         }
  1400.         (void) getreply(0);
  1401.         (void) getreply(0);
  1402.     }
  1403.     if (proxy)
  1404.         pswitch(0);
  1405.     pswitch(1);
  1406.     if (ptabflg)
  1407.         code = -1;
  1408.     (void) signal(SIGINT, oldintr);
  1409. }
  1410.  
  1411. reset()
  1412. {
  1413.     struct fd_set mask;
  1414.     int nfnd = 1;
  1415.  
  1416.     FD_ZERO(&mask);
  1417.     while (nfnd > 0) {
  1418.         FD_SET(fileno(cin), &mask);
  1419.         if ((nfnd = empty(&mask,0)) < 0) {
  1420.             perror("reset");
  1421.             code = -1;
  1422.             lostpeer();
  1423.         }
  1424.         else if (nfnd) {
  1425.             (void) getreply(0);
  1426.         }
  1427.     }
  1428. }
  1429.  
  1430. char *
  1431. gunique(local)
  1432.     char *local;
  1433. {
  1434.     static char new[MAXPATHLEN];
  1435.     char *cp = rindex(local, '/');
  1436.     int d, count=0;
  1437.     char ext = '1';
  1438.  
  1439.     if (cp)
  1440.         *cp = '\0';
  1441.     d = access(cp ? local : ".", 2);
  1442.     if (cp)
  1443.         *cp = '/';
  1444.     if (d < 0) {
  1445.         fprintf(stderr, "local: %s: %s\n", local, strerror(errno));
  1446.         return((char *) 0);
  1447.     }
  1448.     (void) strcpy(new, local);
  1449.     cp = new + strlen(new);
  1450.     *cp++ = '.';
  1451.     while (!d) {
  1452.         if (++count == 100) {
  1453.             printf("runique: can't find unique file name.\n");
  1454.             return((char *) 0);
  1455.         }
  1456.         *cp++ = ext;
  1457.         *cp = '\0';
  1458.         if (ext == '9')
  1459.             ext = '0';
  1460.         else
  1461.             ext++;
  1462.         if ((d = access(new, 0)) < 0)
  1463.             break;
  1464.         if (ext != '0')
  1465.             cp--;
  1466.         else if (*(cp - 2) == '.')
  1467.             *(cp - 1) = '1';
  1468.         else {
  1469.             *(cp - 2) = *(cp - 2) + 1;
  1470.             cp--;
  1471.         }
  1472.     }
  1473.     return(new);
  1474. }
  1475.  
  1476. abort_remote(din)
  1477. FILE *din;
  1478. {
  1479.     char buf[BUFSIZ];
  1480.     int nfnd;
  1481.     struct fd_set mask;
  1482.  
  1483.     /*
  1484.      * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
  1485.      * after urgent byte rather than before as is protocol now
  1486.      */
  1487.     sprintf(buf, "%c%c%c", IAC, IP, IAC);
  1488.     if (send(fileno(cout), buf, 3, MSG_OOB) != 3)
  1489.         perror("abort");
  1490.     fprintf(cout,"%cABOR\r\n", DM);
  1491.     (void) fflush(cout);
  1492.     FD_ZERO(&mask);
  1493.     FD_SET(fileno(cin), &mask);
  1494.     if (din) { 
  1495.         FD_SET(fileno(din), &mask);
  1496.     }
  1497.     if ((nfnd = empty(&mask, 10)) <= 0) {
  1498.         if (nfnd < 0) {
  1499.             perror("abort");
  1500.         }
  1501.         if (ptabflg)
  1502.             code = -1;
  1503.         lostpeer();
  1504.     }
  1505.     if (din && FD_ISSET(fileno(din), &mask)) {
  1506.         while (read(fileno(din), buf, BUFSIZ) > 0)
  1507.             /* LOOP */;
  1508.     }
  1509.     if (getreply(0) == ERROR && code == 552) {
  1510.         /* 552 needed for nic style abort */
  1511.         (void) getreply(0);
  1512.     }
  1513.     (void) getreply(0);
  1514. }
  1515.