home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / ftp / ftp.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  33KB  |  1,582 lines

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