LCOV - code coverage report
Current view: top level - ftp - ftp.c (source / functions) Hit Total Coverage
Test: GNU inetutils Lines: 54 1102 4.9 %
Date: 2015-05-12 15:20:19 Functions: 1 21 4.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
       3             :   2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014,
       4             :   2015 Free Software Foundation, Inc.
       5             : 
       6             :   This file is part of GNU Inetutils.
       7             : 
       8             :   GNU Inetutils is free software: you can redistribute it and/or modify
       9             :   it under the terms of the GNU General Public License as published by
      10             :   the Free Software Foundation, either version 3 of the License, or (at
      11             :   your option) any later version.
      12             : 
      13             :   GNU Inetutils is distributed in the hope that it will be useful, but
      14             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :   General Public License for more details.
      17             : 
      18             :   You should have received a copy of the GNU General Public License
      19             :   along with this program.  If not, see `http://www.gnu.org/licenses/'. */
      20             : 
      21             : /*
      22             :  * Copyright (c) 1985, 1989, 1993, 1994
      23             :  *      The Regents of the University of California.  All rights reserved.
      24             :  *
      25             :  * Redistribution and use in source and binary forms, with or without
      26             :  * modification, are permitted provided that the following conditions
      27             :  * are met:
      28             :  * 1. Redistributions of source code must retain the above copyright
      29             :  *    notice, this list of conditions and the following disclaimer.
      30             :  * 2. Redistributions in binary form must reproduce the above copyright
      31             :  *    notice, this list of conditions and the following disclaimer in the
      32             :  *    documentation and/or other materials provided with the distribution.
      33             :  * 3. Neither the name of the University nor the names of its contributors
      34             :  *    may be used to endorse or promote products derived from this software
      35             :  *    without specific prior written permission.
      36             :  *
      37             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      38             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      39             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      40             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      41             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      42             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      43             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      44             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      45             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      46             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      47             :  * SUCH DAMAGE.
      48             :  */
      49             : 
      50             : #include <config.h>
      51             : 
      52             : #include <sys/param.h>
      53             : #include <sys/stat.h>
      54             : #include <sys/ioctl.h>
      55             : #include <sys/socket.h>
      56             : #include <sys/time.h>
      57             : #include <time.h>
      58             : #include <sys/file.h>
      59             : 
      60             : #include <netinet/in.h>
      61             : #ifdef HAVE_NETINET_IN_SYSTM_H
      62             : # include <netinet/in_systm.h>
      63             : #endif
      64             : #ifdef HAVE_NETINET_IP_H
      65             : # include <netinet/ip.h>
      66             : #endif
      67             : #include <arpa/inet.h>
      68             : #include <arpa/ftp.h>
      69             : #include <arpa/telnet.h>
      70             : 
      71             : #include <ctype.h>
      72             : #include <error.h>
      73             : #include <errno.h>
      74             : #include <fcntl.h>
      75             : #include <netdb.h>
      76             : #include <pwd.h>
      77             : #include <signal.h>
      78             : #include <stdio.h>
      79             : #include <stdlib.h>
      80             : #include <stdint.h>       /* intmax_t */
      81             : #include <string.h>
      82             : #include <unistd.h>
      83             : #include <stdarg.h>
      84             : #include <sys/select.h>
      85             : 
      86             : #ifdef HAVE_IDNA_H
      87             : # include <idna.h>
      88             : #endif
      89             : 
      90             : #include "ftp_var.h"
      91             : #include "unused-parameter.h"
      92             : 
      93             : #if !HAVE_DECL_FCLOSE
      94             : /* Some systems don't declare fclose in <stdio.h>, so do it ourselves.  */
      95             : extern int fclose (FILE *);
      96             : #endif
      97             : 
      98             : #if !HAVE_DECL_PCLOSE
      99             : /* Some systems don't declare pclose in <stdio.h>, so do it ourselves.  */
     100             : extern int pclose (FILE *);
     101             : #endif
     102             : 
     103             : extern int h_errno;
     104             : 
     105             : int data = -1;
     106             : int abrtflag = 0;
     107             : jmp_buf ptabort;
     108             : int ptabflg;
     109             : int ptflag = 0;
     110             : off_t restart_point = 0;
     111             : 
     112             : struct sockaddr_storage myctladdr;
     113             : struct sockaddr_storage hisctladdr;
     114             : struct sockaddr_storage data_addr;
     115             : socklen_t ctladdrlen;   /* Applies to all addresses.  */
     116             : 
     117             : /* For temporary resolving: hookup() and initconn()/noport.  */
     118             : static char ia[INET6_ADDRSTRLEN];
     119             : static char portstr[10];
     120             : 
     121             : FILE *cin, *cout;
     122             : 
     123             : #if ! defined FTP_CONNECT_TIMEOUT || FTP_CONNECT_TIMEOUT < 1
     124             : # define FTP_CONNECT_TIMEOUT 5
     125             : #endif
     126             : 
     127             : char *
     128           0 : hookup (char *host, int port)
     129             : {
     130           0 :   struct addrinfo hints, *ai = NULL, *res = NULL;
     131             :   struct timeval timeout;
     132           0 :   int status, again = 0;
     133             :   int s, tos;
     134             :   socklen_t len;
     135             :   static char hostnamebuf[80];
     136             :   char *rhost;
     137             : 
     138             : #ifdef HAVE_IDN
     139             :   status = idna_to_ascii_lz (host, &rhost, 0);
     140             :   if (status)
     141             :     {
     142             :       error (0, 0, "%s: %s", host, idna_strerror (status));
     143             :       code = -1;
     144             :       return ((char *) 0);
     145             :     }
     146             : #else /* !HAVE_IDN */
     147           0 :   rhost = strdup (host);
     148             : #endif
     149             : 
     150           0 :   snprintf (portstr, sizeof (portstr) - 1, "%u", port);
     151           0 :   memset (&hisctladdr, 0, sizeof (hisctladdr));
     152           0 :   memset (&hints, 0, sizeof (hints));
     153             : 
     154           0 :   hints.ai_family = usefamily;
     155           0 :   hints.ai_socktype = SOCK_STREAM;
     156           0 :   hints.ai_flags = AI_CANONNAME;
     157             : #ifdef AI_IDN
     158           0 :   hints.ai_flags |= AI_IDN;
     159             : #endif
     160             : #ifdef AI_CANONIDN
     161           0 :   hints.ai_flags |= AI_CANONIDN;
     162             : #endif
     163             : 
     164           0 :   status = getaddrinfo (rhost, portstr, &hints, &res);
     165           0 :   if (status)
     166             :     {
     167           0 :       error (0, 0, "%s: %s", rhost, gai_strerror (status));
     168           0 :       code = -1;
     169           0 :       free (rhost);
     170           0 :       return ((char *) 0);
     171             :     }
     172             : 
     173           0 :   if (res->ai_canonname)
     174           0 :     strncpy (hostnamebuf, res->ai_canonname, sizeof (hostnamebuf));
     175             :   else
     176           0 :     strncpy (hostnamebuf, rhost, sizeof (hostnamebuf));
     177             : 
     178           0 :   hostname = hostnamebuf;
     179           0 :   free (rhost);
     180             : 
     181           0 :   for (ai = res; ai != NULL; ai = ai->ai_next, ++again)
     182             :     {
     183           0 :       if (again)
     184             :         {
     185           0 :           getnameinfo (ai->ai_addr, ai->ai_addrlen, ia, sizeof (ia),
     186             :                         NULL, 0, NI_NUMERICHOST);
     187           0 :           error (0, 0, "Trying %s ...", ia);
     188             :         }
     189             : 
     190           0 :       s = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
     191           0 :       if (s < 0)
     192           0 :         continue;
     193             : 
     194           0 :       timeout.tv_sec = FTP_CONNECT_TIMEOUT;
     195           0 :       timeout.tv_usec = 0;
     196           0 :       if (setsockopt (s, SOL_SOCKET, SO_SNDTIMEO, &timeout,
     197           0 :                         sizeof (timeout)) < 0 && debug)
     198           0 :         error (0, errno, "setsockopt (SO_SNDTIMEO)");
     199             : 
     200           0 :       if (connect (s, ai->ai_addr, ai->ai_addrlen) < 0)
     201             :         {
     202           0 :           int oerrno = (errno != EINPROGRESS) ? errno : ETIMEDOUT;
     203             : 
     204           0 :           getnameinfo (ai->ai_addr, ai->ai_addrlen, ia, sizeof (ia),
     205             :                         NULL, 0, NI_NUMERICHOST);
     206           0 :           error (0, oerrno, "connect to address %s", ia);
     207           0 :           close (s);
     208           0 :           s = -1;
     209           0 :           continue;
     210             :         }
     211             : 
     212             :       /* A standing connection is found: register the address.  */
     213           0 :       timeout.tv_sec = 0;
     214           0 :       timeout.tv_usec = 0;
     215           0 :       (void) setsockopt (s, SOL_SOCKET, SO_SNDTIMEO, &timeout,
     216             :                           sizeof (timeout));
     217             : 
     218           0 :       ctladdrlen = ai->ai_addrlen;
     219           0 :       memmove ((caddr_t) &hisctladdr, ai->ai_addr, ai->ai_addrlen);
     220           0 :       break;
     221             :     } /* for (ai = ai->ai_next) */
     222             : 
     223           0 :   if (res)
     224           0 :     freeaddrinfo (res);
     225             : 
     226           0 :   if (ai == NULL)
     227             :     {
     228           0 :       error (0, 0, "no response from host");
     229           0 :       code = -1;
     230           0 :       goto bad;
     231             :     }
     232             : 
     233           0 :   len = sizeof (myctladdr);
     234           0 :   if (getsockname (s, (struct sockaddr *) &myctladdr, &len) < 0)
     235             :     {
     236           0 :       error (0, errno, "getsockname");
     237           0 :       code = -1;
     238           0 :       goto bad;
     239             :     }
     240             : 
     241             : #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_LOWDELAY
     242           0 :   tos = IPTOS_LOWDELAY;
     243           0 :   if (myctladdr.ss_family == AF_INET &&
     244           0 :         setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
     245           0 :     error (0, errno, "setsockopt TOS (ignored)");
     246             : #endif
     247             : 
     248           0 :   cin = fdopen (s, "r");
     249             :   /* dup(s) is for sake of stdio implementations who do not
     250             :      allow two fdopen's on the same file-descriptor */
     251           0 :   cout = fdopen (dup (s), "w");
     252           0 :   if (cin == NULL || cout == NULL)
     253             :     {
     254           0 :       error (0, 0, "fdopen failed.");
     255           0 :       if (cin)
     256           0 :         fclose (cin);
     257           0 :       if (cout)
     258           0 :         fclose (cout);
     259           0 :       code = -1;
     260           0 :       goto bad;
     261             :     }
     262           0 :   if (verbose)
     263           0 :     printf ("Connected to %s.\n", hostname);
     264           0 :   if (getreply (0) > 2)
     265             :     {                           /* read startup message from server */
     266           0 :       if (cin)
     267           0 :         fclose (cin);
     268           0 :       if (cout)
     269           0 :         fclose (cout);
     270           0 :       code = -1;
     271           0 :       goto bad;
     272             :     }
     273             : 
     274             : #ifdef SO_OOBINLINE
     275             :   {
     276           0 :     int on = 1;
     277             : 
     278           0 :     if (setsockopt (s, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof (on))
     279           0 :         < 0 && debug)
     280             :       {
     281           0 :         error (0, errno, "setsockopt");
     282             :       }
     283             :   }
     284             : #endif /* SO_OOBINLINE */
     285             : 
     286           0 :   return (hostname);
     287             : bad:
     288           0 :   close (s);
     289           0 :   return ((char *) 0);
     290             : }
     291             : 
     292             : int
     293           0 : login (char *host)
     294             : {
     295             :   char tmp[80];
     296             :   char *user, *pass, *acct;
     297           0 :   int n, aflag = 0;
     298             : 
     299           0 :   user = pass = acct = 0;
     300           0 :   if (remote_userpass (host, &user, &pass, &acct) < 0)
     301             :     {
     302           0 :       code = -1;
     303           0 :       return (0);
     304             :     }
     305           0 :   while (user == NULL)
     306             :     {
     307           0 :       char *myname = getlogin ();
     308             : 
     309           0 :       if (myname == NULL)
     310             :         {
     311           0 :           struct passwd *pp = getpwuid (getuid ());
     312             : 
     313           0 :           if (pp != NULL)
     314           0 :             myname = pp->pw_name;
     315             :         }
     316           0 :       if (myname)
     317           0 :         printf ("Name (%s:%s): ", host, myname);
     318             :       else
     319           0 :         printf ("Name (%s): ", host);
     320           0 :       if (fgets (tmp, sizeof (tmp) - 1, stdin))
     321             :         {
     322             :           /* If the user presses return immediately, we get "\n".
     323             :            * In all other cases, the assignment is a no-op,
     324             :            * and is always well defined thanks to fgets().
     325             :            */
     326           0 :           tmp[strlen (tmp) - 1] = '\0';
     327             :         }
     328             :       else
     329           0 :         *tmp = '\0';            /* Ctrl-D received.  */
     330           0 :       if (*tmp == '\0')
     331           0 :         user = myname;
     332             :       else
     333           0 :         user = tmp;
     334             :     }
     335           0 :   n = command ("USER %s", user);
     336           0 :   if (n == CONTINUE)
     337             :     {
     338             :       /* Is this a case of challenge-response?
     339             :        * RFC 2228 stipulates code 336 for this.
     340             :        * Suppress the message in verbose mode,
     341             :        * since it has already been displayed.
     342             :        */
     343           0 :       if (code == 336 && !verbose)
     344           0 :         printf ("%s\n", reply_string + strlen ("336 "));
     345             :       /* In addition, any password given on the
     346             :        * command line is irrelevant, so ignore it.
     347             :        */
     348           0 :       if (pass == NULL || code == 336)
     349           0 :         pass = getpass ("Password: ");
     350           0 :       n = command ("PASS %s", pass);
     351           0 :       if (pass)
     352           0 :         memset (pass, 0, strlen (pass));
     353             :     }
     354           0 :   if (n == CONTINUE)
     355             :     {
     356           0 :       aflag++;
     357           0 :       acct = getpass ("Account: ");
     358           0 :       n = command ("ACCT %s", acct);
     359           0 :       if (acct)
     360           0 :         memset (acct, 0, strlen (acct));
     361             :     }
     362           0 :   if (n != COMPLETE)
     363             :     {
     364           0 :       error (0, 0, "Login failed.");
     365           0 :       return (0);
     366             :     }
     367           0 :   if (!aflag && acct != NULL)
     368             :     {
     369           0 :       command ("ACCT %s", acct);
     370           0 :       memset (acct, 0, strlen (acct));
     371             :     }
     372           0 :   if (proxy)
     373           0 :     return (1);
     374           0 :   for (n = 0; n < macnum; ++n)
     375             :     {
     376           0 :       if (!strcmp ("init", macros[n].mac_name))
     377             :         {
     378           0 :           free (line);
     379           0 :           line = calloc (MAXLINE, sizeof (*line));
     380           0 :           linelen = MAXLINE;
     381           0 :           if (!line)
     382           0 :             quit (0, 0);
     383             : 
     384             :           /* Simulate input of the macro 'init'.  */
     385           0 :           strcpy (line, "$init");
     386           0 :           makeargv ();
     387           0 :           domacro (margc, margv);
     388           0 :           break;
     389             :         }
     390             :     }
     391           0 :   return (1);
     392             : }
     393             : 
     394             : void
     395           0 : cmdabort (int sig _GL_UNUSED_PARAMETER)
     396             : {
     397             : 
     398           0 :   printf ("\n");
     399           0 :   fflush (stdout);
     400           0 :   abrtflag++;
     401           0 :   if (ptflag)
     402           0 :     longjmp (ptabort, 1);
     403           0 : }
     404             : 
     405             : int
     406           0 : command (const char *fmt, ...)
     407             : {
     408             :   va_list ap;
     409             :   int r;
     410             :   sighandler_t oldintr;
     411             : 
     412           0 :   abrtflag = 0;
     413           0 :   if (debug)
     414             :     {
     415           0 :       printf ("---> ");
     416           0 :       va_start (ap, fmt);
     417           0 :       if (strncmp ("PASS ", fmt, 5) == 0)
     418           0 :         printf ("PASS XXXX");
     419           0 :       else if (strncmp ("ACCT ", fmt, 5) == 0)
     420           0 :         printf ("ACCT XXXX");
     421             :       else
     422           0 :         vfprintf (stdout, fmt, ap);
     423           0 :       va_end (ap);
     424           0 :       printf ("\n");
     425           0 :       fflush (stdout);
     426             :     }
     427           0 :   if (cout == NULL)
     428             :     {
     429           0 :       error (0, 0, "No control connection for command");
     430           0 :       code = -1;
     431           0 :       return (0);
     432             :     }
     433           0 :   oldintr = signal (SIGINT, cmdabort);
     434             :   /* Under weird circumstances, we get a SIGPIPE from fflush().  */
     435           0 :   signal (SIGPIPE, SIG_IGN);
     436           0 :   va_start (ap, fmt);
     437           0 :   vfprintf (cout, fmt, ap);
     438           0 :   va_end (ap);
     439           0 :   fprintf (cout, "\r\n");
     440           0 :   fflush (cout);
     441           0 :   cpend = 1;
     442           0 :   r = getreply (!strcmp (fmt, "QUIT"));
     443           0 :   if (abrtflag && oldintr != SIG_IGN)
     444           0 :     (*oldintr) (SIGINT);
     445           0 :   signal (SIGINT, oldintr);
     446           0 :   signal (SIGPIPE, SIG_DFL);
     447           0 :   return (r);
     448             : }
     449             : 
     450             : char reply_string[BUFSIZ];      /* last line of previous reply */
     451             : 
     452             : int
     453           0 : getreply (int expecteof)
     454             : {
     455             :   int c, n;
     456             :   int dig;
     457           0 :   int originalcode = 0, continuation = 0;
     458             :   sighandler_t oldintr;
     459           0 :   int pflag = 0;
     460           0 :   char *cp, *pt = pasv;
     461             : 
     462           0 :   oldintr = signal (SIGINT, cmdabort);
     463             :   for (;;)
     464             :     {
     465           0 :       dig = n = code = 0;
     466           0 :       cp = reply_string;
     467           0 :       while ((c = getc (cin)) != '\n')
     468             :         {
     469           0 :           if (c == IAC)
     470             :             {                   /* handle telnet commands */
     471           0 :               switch (c = getc (cin))
     472             :                 {
     473             :                 case WILL:
     474             :                 case WONT:
     475           0 :                   c = getc (cin);
     476           0 :                   fprintf (cout, "%c%c%c", IAC, DONT, c);
     477           0 :                   fflush (cout);
     478           0 :                   break;
     479             :                 case DO:
     480             :                 case DONT:
     481           0 :                   c = getc (cin);
     482           0 :                   fprintf (cout, "%c%c%c", IAC, WONT, c);
     483           0 :                   fflush (cout);
     484           0 :                   break;
     485             :                 default:
     486           0 :                   break;
     487             :                 }
     488           0 :               continue;
     489             :             }
     490           0 :           dig++;
     491           0 :           if (c == EOF)
     492             :             {
     493           0 :               if (expecteof)
     494             :                 {
     495           0 :                   signal (SIGINT, oldintr);
     496           0 :                   code = 221;
     497           0 :                   return (0);
     498             :                 }
     499           0 :               lostpeer (0);
     500           0 :               if (verbose)
     501             :                 {
     502           0 :                   printf
     503             :                     ("421 Service not available, remote server has closed connection\n");
     504           0 :                   fflush (stdout);
     505             :                 }
     506           0 :               code = 421;
     507           0 :               return (TRANSIENT);
     508             :             }
     509           0 :           if (c != '\r' && (verbose > 0 ||
     510           0 :                             (verbose > -1 && n == ERROR && dig > 4)))
     511             :             {
     512           0 :               if (proxflag && (dig == 1 || (dig == 5 && verbose == 0)))
     513           0 :                 printf ("%s:", hostname);
     514           0 :               putchar (c);
     515             :             }
     516           0 :           if (dig < 4 && isdigit (c))
     517           0 :             code = code * 10 + (c - '0');
     518           0 :           if (!pflag && (code == 227 || code == 228 || code == 229)) /* PASV || LPSV || EPSV */
     519           0 :             pflag = 1;
     520           0 :           if (dig > 4 && pflag == 1 && isdigit (c))
     521           0 :             pflag = 2;
     522           0 :           if (pflag == 2)
     523             :             {
     524           0 :               if (c != '\r' && c != ')')
     525           0 :                 *pt++ = c;
     526             :               else
     527             :                 {
     528           0 :                   *pt = '\0';
     529           0 :                   pflag = 3;
     530             :                 }
     531             :             }
     532           0 :           if (dig == 4 && c == '-')
     533             :             {
     534           0 :               if (continuation)
     535           0 :                 code = 0;
     536           0 :               continuation++;
     537             :             }
     538           0 :           if (n == 0)
     539           0 :             n = c - '0';        /* Extract ARPA's reply code.  */
     540           0 :           if (cp < &reply_string[sizeof (reply_string) - 1])
     541           0 :             *cp++ = c;
     542             :         }
     543           0 :       if (verbose > 0 || (verbose > -1 && n == ERROR))
     544             :         {
     545           0 :           putchar (c);
     546           0 :           fflush (stdout);
     547             :         }
     548           0 :       if (continuation && code != originalcode)
     549             :         {
     550           0 :           if (originalcode == 0)
     551           0 :             originalcode = code;
     552           0 :           continue;
     553             :         }
     554           0 :       *cp = '\0';
     555           0 :       if (n != PRELIM)
     556           0 :         cpend = 0;
     557           0 :       signal (SIGINT, oldintr);
     558           0 :       if (code == 421 || originalcode == 421)
     559           0 :         lostpeer (0);
     560           0 :       if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN)
     561           0 :         (*oldintr) (SIGINT);
     562           0 :       return n;
     563           0 :     }
     564             : }
     565             : 
     566             : int
     567           0 : empty (fd_set *mask, int sec)
     568             : {
     569             :   struct timeval t;
     570             : 
     571           0 :   t.tv_sec = (long) sec;
     572           0 :   t.tv_usec = 0;
     573           0 :   return (select (32, mask, (fd_set *) 0, (fd_set *) 0, &t));
     574             : }
     575             : 
     576             : jmp_buf sendabort;
     577             : 
     578             : void
     579           0 : abortsend (int sig _GL_UNUSED_PARAMETER)
     580             : {
     581             : 
     582           0 :   mflag = 0;
     583           0 :   abrtflag = 0;
     584           0 :   printf ("\nsend aborted\nwaiting for remote to finish abort\n");
     585           0 :   fflush (stdout);
     586           0 :   longjmp (sendabort, 1);
     587             : }
     588             : 
     589             : void
     590           0 : sendrequest (char *cmd, char *local, char *remote, int printnames)
     591             : {
     592             :   struct stat st;
     593             :   struct timeval start, stop;
     594             :   int c, d;
     595           0 :   FILE *fin, *dout = 0, *popen (const char *, const char *);
     596             :   int (*closefunc) (FILE *);
     597             :   sighandler_t oldintr, oldintp;
     598           0 :   long long bytes = 0, local_hashbytes = hashbytes;
     599             :   char *lmode, *bufp;
     600           0 :   int blksize = BUFSIZ;
     601             :   static int bufsize = 0;
     602             :   static char *buf;
     603             : 
     604           0 :   if (verbose && printnames)
     605             :     {
     606           0 :       if (local && *local != '-')
     607           0 :         printf ("local: %s ", local);
     608           0 :       if (remote)
     609           0 :         printf ("remote: %s\n", remote);
     610             :     }
     611           0 :   if (proxy)
     612             :     {
     613           0 :       proxtrans (cmd, local, remote);
     614           0 :       return;
     615             :     }
     616           0 :   if (curtype != type)
     617           0 :     changetype (type, 0);
     618           0 :   closefunc = NULL;
     619           0 :   oldintr = NULL;
     620           0 :   oldintp = NULL;
     621           0 :   lmode = "w";
     622           0 :   if (setjmp (sendabort))
     623             :     {
     624           0 :       while (cpend)
     625             :         {
     626           0 :           getreply (0);
     627             :         }
     628           0 :       if (data >= 0)
     629             :         {
     630           0 :           close (data);
     631           0 :           data = -1;
     632             :         }
     633           0 :       if (oldintr)
     634           0 :         signal (SIGINT, oldintr);
     635           0 :       if (oldintp)
     636           0 :         signal (SIGPIPE, oldintp);
     637           0 :       code = -1;
     638           0 :       return;
     639             :     }
     640           0 :   oldintr = signal (SIGINT, abortsend);
     641           0 :   if (strcmp (local, "-") == 0)
     642           0 :     fin = stdin;
     643           0 :   else if (*local == '|')
     644             :     {
     645           0 :       oldintp = signal (SIGPIPE, SIG_IGN);
     646           0 :       fin = popen (local + 1, "r");
     647           0 :       if (fin == NULL)
     648             :         {
     649           0 :           error (0, errno, "%s", local + 1);
     650           0 :           signal (SIGINT, oldintr);
     651           0 :           signal (SIGPIPE, oldintp);
     652           0 :           code = -1;
     653           0 :           return;
     654             :         }
     655           0 :       closefunc = pclose;
     656             :     }
     657             :   else
     658             :     {
     659           0 :       fin = fopen (local, "r");
     660           0 :       if (fin == NULL)
     661             :         {
     662           0 :           error (0, errno, "local: %s", local);
     663           0 :           signal (SIGINT, oldintr);
     664           0 :           code = -1;
     665           0 :           return;
     666             :         }
     667           0 :       closefunc = fclose;
     668           0 :       if (fstat (fileno (fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)
     669             :         {
     670           0 :           fprintf (stdout, "%s: not a plain file.\n", local);
     671           0 :           signal (SIGINT, oldintr);
     672           0 :           fclose (fin);
     673           0 :           code = -1;
     674           0 :           return;
     675             :         }
     676           0 :         blksize = st.st_blksize;
     677             :     }
     678           0 :   if (initconn ())
     679             :     {
     680           0 :       signal (SIGINT, oldintr);
     681           0 :       if (oldintp)
     682           0 :         signal (SIGPIPE, oldintp);
     683           0 :       code = -1;
     684           0 :       if (closefunc != NULL)
     685           0 :         (*closefunc) (fin);
     686           0 :       return;
     687             :     }
     688           0 :   if (setjmp (sendabort))
     689           0 :     goto abort;
     690             : 
     691           0 :   if (restart_point &&
     692           0 :       (strcmp (cmd, "STOR") == 0 || strcmp (cmd, "APPE") == 0))
     693             :     {
     694             :       off_t rc;
     695             : 
     696           0 :       switch (curtype)
     697             :         {
     698             :         case TYPE_A:
     699           0 :           rc = fseeko (fin, restart_point, SEEK_SET);
     700           0 :           break;
     701             :         case TYPE_I:
     702             :         case TYPE_L:
     703           0 :           rc = lseek (fileno (fin), restart_point, SEEK_SET);
     704           0 :           break;
     705             :         }
     706           0 :       if (rc < 0)
     707             :         {
     708           0 :           (void) command ("ABOR");
     709           0 :           getreply (0);
     710           0 :           error (0, errno, "local: %s", local);
     711           0 :           restart_point = 0;
     712           0 :           if (closefunc != NULL)
     713           0 :             (*closefunc) (fin);
     714           0 :           return;
     715             :         }
     716           0 :       if (command ("REST %jd", (intmax_t) restart_point) != CONTINUE)
     717             :         {
     718           0 :           restart_point = 0;
     719           0 :           if (closefunc != NULL)
     720           0 :             (*closefunc) (fin);
     721           0 :           return;
     722             :         }
     723           0 :       restart_point = 0;
     724           0 :       lmode = "r+w";
     725             :     }
     726           0 :   if (remote)
     727             :     {
     728           0 :       if (command ("%s %s", cmd, remote) != PRELIM)
     729             :         {
     730           0 :           signal (SIGINT, oldintr);
     731           0 :           if (oldintp)
     732           0 :             signal (SIGPIPE, oldintp);
     733           0 :           if (closefunc != NULL)
     734           0 :             (*closefunc) (fin);
     735           0 :           return;
     736             :         }
     737             :     }
     738           0 :   else if (command ("%s", cmd) != PRELIM)
     739             :     {
     740           0 :       signal (SIGINT, oldintr);
     741           0 :       if (oldintp)
     742           0 :         signal (SIGPIPE, oldintp);
     743           0 :       if (closefunc != NULL)
     744           0 :         (*closefunc) (fin);
     745           0 :       return;
     746             :     }
     747           0 :   dout = dataconn (lmode);
     748           0 :   if (dout == NULL)
     749           0 :     goto abort;
     750             : 
     751           0 :   if (blksize > bufsize)
     752             :     {
     753           0 :       free (buf);
     754           0 :       buf = malloc ((unsigned) blksize);
     755           0 :       if (buf == NULL)
     756             :         {
     757           0 :           error (0, errno, "malloc");
     758           0 :           bufsize = 0;
     759           0 :           goto abort;
     760             :         }
     761           0 :       bufsize = blksize;
     762             :     }
     763             : 
     764           0 :   gettimeofday (&start, (struct timezone *) 0);
     765           0 :   oldintp = signal (SIGPIPE, SIG_IGN);
     766           0 :   switch (curtype)
     767             :     {
     768             : 
     769             :     case TYPE_I:
     770             :     case TYPE_L:
     771           0 :       errno = d = 0;
     772           0 :       while ((c = read (fileno (fin), buf, bufsize)) > 0)
     773             :         {
     774           0 :           bytes += c;
     775           0 :           for (bufp = buf; c > 0; c -= d, bufp += d)
     776           0 :             if ((d = write (fileno (dout), bufp, c)) <= 0)
     777           0 :               break;
     778           0 :           if (hash)
     779             :             {
     780           0 :               while (bytes >= local_hashbytes)
     781             :                 {
     782           0 :                   putchar ('#');
     783           0 :                   local_hashbytes += hashbytes;
     784             :                 }
     785           0 :               fflush (stdout);
     786             :             }
     787             :         }
     788           0 :       if (hash && bytes > 0)
     789             :         {
     790           0 :           if (bytes < local_hashbytes)
     791           0 :             putchar ('#');
     792           0 :           putchar ('\n');
     793           0 :           fflush (stdout);
     794             :         }
     795           0 :       if (c < 0)
     796           0 :         error (0, errno, "local: %s", local);
     797           0 :       if (d < 0)
     798             :         {
     799           0 :           if (errno != EPIPE)
     800           0 :             error (0, errno, "netout");
     801           0 :           bytes = -1;
     802             :         }
     803           0 :       break;
     804             : 
     805             :     case TYPE_A:
     806           0 :       while ((c = getc (fin)) != EOF)
     807             :         {
     808           0 :           if (c == '\n')
     809             :             {
     810           0 :               while (hash && (bytes >= local_hashbytes))
     811             :                 {
     812           0 :                   putchar ('#');
     813           0 :                   fflush (stdout);
     814           0 :                   local_hashbytes += hashbytes;
     815             :                 }
     816           0 :               if (ferror (dout))
     817           0 :                 break;
     818           0 :               putc ('\r', dout);
     819           0 :               bytes++;
     820             :             }
     821           0 :           putc (c, dout);
     822           0 :           bytes++;
     823             :           /*              if (c == '\r') {                                */
     824             :           /*                      putc('\0', dout);  // this violates rfc */
     825             :           /*                      bytes++;                                */
     826             :           /*              }                                               */
     827             :         }
     828           0 :       if (hash)
     829             :         {
     830           0 :           if (bytes < local_hashbytes)
     831           0 :             putchar ('#');
     832           0 :           putchar ('\n');
     833           0 :           fflush (stdout);
     834             :         }
     835           0 :       if (ferror (fin))
     836           0 :         error (0, errno, "local: %s", local);
     837           0 :       if (ferror (dout))
     838             :         {
     839           0 :           if (errno != EPIPE)
     840           0 :             error (0, errno, "netout");
     841           0 :           bytes = -1;
     842             :         }
     843           0 :       break;
     844             :     }
     845           0 :   if (closefunc != NULL)
     846           0 :     (*closefunc) (fin);
     847           0 :   fclose (dout);
     848           0 :   gettimeofday (&stop, (struct timezone *) 0);
     849           0 :   getreply (0);
     850           0 :   signal (SIGINT, oldintr);
     851           0 :   if (oldintp)
     852           0 :     signal (SIGPIPE, oldintp);
     853           0 :   if (bytes > 0)
     854           0 :     ptransfer ("sent", bytes, &start, &stop);
     855           0 :   return;
     856             : abort:
     857           0 :   signal (SIGINT, oldintr);
     858           0 :   if (oldintp)
     859           0 :     signal (SIGPIPE, oldintp);
     860           0 :   if (!cpend)
     861             :     {
     862           0 :       code = -1;
     863           0 :       return;
     864             :     }
     865           0 :   if (data >= 0)
     866             :     {
     867           0 :       close (data);
     868           0 :       data = -1;
     869             :     }
     870           0 :   if (dout)
     871           0 :     fclose (dout);
     872           0 :   getreply (0);
     873           0 :   code = -1;
     874           0 :   if (closefunc != NULL && fin != NULL)
     875           0 :     (*closefunc) (fin);
     876           0 :   gettimeofday (&stop, (struct timezone *) 0);
     877           0 :   if (bytes > 0)
     878           0 :     ptransfer ("sent", bytes, &start, &stop);
     879             : }
     880             : 
     881             : jmp_buf recvabort;
     882             : 
     883             : void
     884           0 : abortrecv (int sig _GL_UNUSED_PARAMETER)
     885             : {
     886             : 
     887           0 :   mflag = 0;
     888           0 :   abrtflag = 0;
     889           0 :   printf ("\nreceive aborted\nwaiting for remote to finish abort\n");
     890           0 :   fflush (stdout);
     891           0 :   longjmp (recvabort, 1);
     892             : }
     893             : 
     894             : void
     895           0 : recvrequest (char *cmd, char *local, char *remote, char *lmode, int printnames)
     896             : {
     897           0 :   FILE *fout, *din = 0;
     898             :   int (*closefunc) (FILE *);
     899             :   sighandler_t oldintr, oldintp;
     900           0 :   int c, d, is_retr, tcrflag, bare_lfs = 0;
     901           0 :   int blksize = BUFSIZ;
     902             :   static int bufsize = 0;
     903             :   static char *buf;
     904           0 :   long long bytes = 0, local_hashbytes = hashbytes;
     905             :   struct timeval start, stop;
     906             : 
     907           0 :   is_retr = strcmp (cmd, "RETR") == 0;
     908           0 :   if (is_retr && verbose && printnames)
     909             :     {
     910           0 :       if (local && *local != '-')
     911           0 :         printf ("local: %s ", local);
     912           0 :       if (remote)
     913           0 :         printf ("remote: %s\n", remote);
     914             :     }
     915           0 :   if (proxy && is_retr)
     916             :     {
     917           0 :       proxtrans (cmd, local, remote);
     918           0 :       return;
     919             :     }
     920           0 :   closefunc = NULL;
     921           0 :   oldintr = NULL;
     922           0 :   oldintp = NULL;
     923           0 :   tcrflag = !crflag && is_retr;
     924           0 :   if (setjmp (recvabort))
     925             :     {
     926           0 :       while (cpend)
     927             :         {
     928           0 :           getreply (0);
     929             :         }
     930           0 :       if (data >= 0)
     931             :         {
     932           0 :           close (data);
     933           0 :           data = -1;
     934             :         }
     935           0 :       if (oldintr)
     936           0 :         signal (SIGINT, oldintr);
     937           0 :       code = -1;
     938           0 :       return;
     939             :     }
     940           0 :   oldintr = signal (SIGINT, abortrecv);
     941           0 :   if (strcmp (local, "-") && *local != '|')
     942             :     {
     943           0 :       if (runique && (local = gunique (local)) == NULL)
     944             :         {
     945           0 :           signal (SIGINT, oldintr);
     946           0 :           code = -1;
     947           0 :           return;
     948             :         }
     949             :     }
     950           0 :   if (!is_retr)
     951             :     {
     952           0 :       if (curtype != TYPE_A)
     953           0 :         changetype (TYPE_A, 0);
     954             :     }
     955           0 :   else if (curtype != type)
     956           0 :     changetype (type, 0);
     957           0 :   if (initconn ())
     958             :     {
     959           0 :       signal (SIGINT, oldintr);
     960           0 :       code = -1;
     961           0 :       return;
     962             :     }
     963           0 :   if (setjmp (recvabort))
     964           0 :     goto abort;
     965           0 :   if (is_retr && restart_point &&
     966           0 :       command ("REST %jd", (intmax_t) restart_point) != CONTINUE)
     967           0 :     return;
     968           0 :   if (remote)
     969             :     {
     970           0 :       if (command ("%s %s", cmd, remote) != PRELIM)
     971             :         {
     972           0 :           signal (SIGINT, oldintr);
     973           0 :           return;
     974             :         }
     975             :     }
     976             :   else
     977             :     {
     978           0 :       if (command ("%s", cmd) != PRELIM)
     979             :         {
     980           0 :           signal (SIGINT, oldintr);
     981           0 :           return;
     982             :         }
     983             :     }
     984           0 :   din = dataconn ("r");
     985           0 :   if (din == NULL)
     986           0 :     goto abort;
     987             : 
     988           0 :   if (strcmp (local, "-") == 0)
     989           0 :     fout = stdout;
     990           0 :   else if (*local == '|')
     991             :     {
     992           0 :       oldintp = signal (SIGPIPE, SIG_IGN);
     993           0 :       fout = popen (local + 1, "w");
     994           0 :       if (fout == NULL)
     995             :         {
     996           0 :           error (0, errno, "%s", local + 1);
     997           0 :           goto abort;
     998             :         }
     999           0 :       closefunc = pclose;
    1000             :     }
    1001             :   else
    1002             :     {
    1003             :       struct stat st;
    1004             : 
    1005           0 :       fout = fopen (local, lmode);
    1006           0 :       if (fout == NULL || fstat (fileno (fout), &st) < 0)
    1007             :         {
    1008           0 :           error (0, errno, "local: %s", local);
    1009           0 :           goto abort;
    1010             :         }
    1011           0 :       closefunc = fclose;
    1012           0 :       blksize = st.st_blksize;
    1013             :     }
    1014             : 
    1015           0 :   if (blksize > bufsize)
    1016             :     {
    1017           0 :       free (buf);
    1018           0 :       buf = malloc ((unsigned) blksize);
    1019           0 :       if (buf == NULL)
    1020             :         {
    1021           0 :           error (0, errno, "malloc");
    1022           0 :           bufsize = 0;
    1023           0 :           goto abort;
    1024             :         }
    1025           0 :       bufsize = blksize;
    1026             :     }
    1027             : 
    1028           0 :   gettimeofday (&start, (struct timezone *) 0);
    1029           0 :   switch (curtype)
    1030             :     {
    1031             : 
    1032             :     case TYPE_I:
    1033             :     case TYPE_L:
    1034           0 :       if (restart_point && lseek (fileno (fout), restart_point, SEEK_SET) < 0)
    1035             :         {
    1036           0 :           error (0, errno, "local: %s", local);
    1037           0 :           if (closefunc != NULL)
    1038           0 :             (*closefunc) (fout);
    1039           0 :           return;
    1040             :         }
    1041           0 :       errno = d = 0;
    1042           0 :       while ((c = read (fileno (din), buf, bufsize)) > 0)
    1043             :         {
    1044           0 :           if ((d = write (fileno (fout), buf, c)) != c)
    1045           0 :             break;
    1046           0 :           bytes += c;
    1047           0 :           if (hash)
    1048             :             {
    1049           0 :               while (bytes >= local_hashbytes)
    1050             :                 {
    1051           0 :                   putchar ('#');
    1052           0 :                   local_hashbytes += hashbytes;
    1053             :                 }
    1054           0 :               fflush (stdout);
    1055             :             }
    1056             :         }
    1057             : 
    1058           0 :       if (hash && bytes > 0)
    1059             :         {
    1060           0 :           if (bytes < local_hashbytes)
    1061           0 :             putchar ('#');
    1062           0 :           putchar ('\n');
    1063           0 :           fflush (stdout);
    1064             :         }
    1065           0 :       if (c < 0)
    1066             :         {
    1067           0 :           if (errno != EPIPE)
    1068           0 :             error (0, errno, "netin");
    1069           0 :           bytes = -1;
    1070             :         }
    1071           0 :       if (d < c)
    1072             :         {
    1073           0 :           if (d < 0)
    1074           0 :             error (0, errno, "local: %s", local);
    1075             :           else
    1076           0 :             error (0, 0, "%s: short write", local);
    1077             :         }
    1078           0 :       break;
    1079             : 
    1080             :     case TYPE_A:
    1081           0 :       if (restart_point)
    1082             :         {
    1083             :           off_t i, n;
    1084             :           int ch;
    1085             : 
    1086           0 :           errno = 0;
    1087             : 
    1088           0 :           if (fseeko (fout, 0L, SEEK_SET) < 0)
    1089           0 :             goto done;
    1090           0 :           n = restart_point;
    1091           0 :           for (i = 0; i++ < n;)
    1092             :             {
    1093           0 :               if ((ch = getc (fout)) == EOF)
    1094           0 :                 goto done;
    1095           0 :               if (ch == '\n')
    1096           0 :                 i++;
    1097             :             }
    1098           0 :           if (fseeko (fout, 0L, SEEK_CUR) < 0)
    1099             :             {
    1100             :             done:
    1101             :               /* Cancel server's action quickly.  */
    1102           0 :               (void) command ("ABOR");
    1103           0 :               getreply (0);
    1104             : 
    1105             :               /* Explain our failure.  */
    1106           0 :               if (ch == EOF)
    1107           0 :                 printf ("Action not taken: offset %jd is outside of %s.\n",
    1108             :                        restart_point, local);
    1109             :               else
    1110           0 :                 error (0, errno, "local: %s", local);
    1111             : 
    1112           0 :               if (closefunc != NULL)
    1113           0 :                 (*closefunc) (fout);
    1114           0 :               return;
    1115             :             }
    1116             :         }
    1117           0 :       while ((c = getc (din)) != EOF)
    1118             :         {
    1119           0 :           if (c == '\n')
    1120           0 :             bare_lfs++;
    1121           0 :           while (c == '\r')
    1122             :             {
    1123           0 :               while (hash && (bytes >= local_hashbytes))
    1124             :                 {
    1125           0 :                   putchar ('#');
    1126           0 :                   fflush (stdout);
    1127           0 :                   local_hashbytes += hashbytes;
    1128             :                 }
    1129           0 :               bytes++;
    1130           0 :               if ((c = getc (din)) != '\n' || tcrflag)
    1131             :                 {
    1132           0 :                   if (ferror (fout))
    1133           0 :                     goto break2;
    1134           0 :                   putc ('\r', fout);
    1135           0 :                   if (c == '\0')
    1136             :                     {
    1137           0 :                       bytes++;
    1138           0 :                       goto contin2;
    1139             :                     }
    1140           0 :                   if (c == EOF)
    1141           0 :                     goto contin2;
    1142             :                 }
    1143             :             }
    1144           0 :           putc (c, fout);
    1145           0 :           bytes++;
    1146             :         contin2:;
    1147             :         }
    1148             :     break2:
    1149           0 :       if (bare_lfs)
    1150             :         {
    1151           0 :           printf ("WARNING! %d bare linefeeds received in ASCII mode\n",
    1152             :                   bare_lfs);
    1153           0 :           printf ("File may not have transferred correctly.\n");
    1154             :         }
    1155           0 :       if (hash)
    1156             :         {
    1157           0 :           if (bytes < local_hashbytes)
    1158           0 :             putchar ('#');
    1159           0 :           putchar ('\n');
    1160           0 :           fflush (stdout);
    1161             :         }
    1162           0 :       if (ferror (din))
    1163             :         {
    1164           0 :           if (errno != EPIPE)
    1165           0 :             error (0, errno, "netin");
    1166           0 :           bytes = -1;
    1167             :         }
    1168           0 :       if (ferror (fout))
    1169           0 :         error (0, errno, "local: %s", local);
    1170           0 :       break;
    1171             :     }
    1172           0 :   if (closefunc != NULL)
    1173           0 :     (*closefunc) (fout);
    1174           0 :   signal (SIGINT, oldintr);
    1175           0 :   if (oldintp)
    1176           0 :     signal (SIGPIPE, oldintp);
    1177           0 :   fclose (din);
    1178           0 :   gettimeofday (&stop, (struct timezone *) 0);
    1179           0 :   getreply (0);
    1180           0 :   if (bytes > 0 && is_retr)
    1181           0 :     ptransfer ("received", bytes, &start, &stop);
    1182           0 :   return;
    1183             : abort:
    1184             : 
    1185             : /* abort using RFC959 recommended IP,SYNC sequence  */
    1186             : 
    1187           0 :   if (oldintp)
    1188           0 :     signal (SIGPIPE, oldintr);
    1189           0 :   signal (SIGINT, SIG_IGN);
    1190           0 :   if (!cpend)
    1191             :     {
    1192           0 :       code = -1;
    1193           0 :       signal (SIGINT, oldintr);
    1194           0 :       return;
    1195             :     }
    1196             : 
    1197           0 :   abort_remote (din);
    1198           0 :   code = -1;
    1199           0 :   if (data >= 0)
    1200             :     {
    1201           0 :       close (data);
    1202           0 :       data = -1;
    1203             :     }
    1204           0 :   if (closefunc != NULL && fout != NULL)
    1205           0 :     (*closefunc) (fout);
    1206           0 :   if (din)
    1207           0 :     fclose (din);
    1208           0 :   gettimeofday (&stop, (struct timezone *) 0);
    1209           0 :   if (bytes > 0)
    1210           0 :     ptransfer ("received", bytes, &start, &stop);
    1211           0 :   signal (SIGINT, oldintr);
    1212             : }
    1213             : 
    1214             : /*
    1215             :  * Need to start a listen on the data channel before we send the command,
    1216             :  * otherwise the server's connect may fail.
    1217             :  */
    1218             : int
    1219           0 : initconn (void)
    1220             : {
    1221           0 :   char *p = NULL, *a = NULL;
    1222           0 :   int result, tmpno = 0;
    1223           0 :   int good_epsv = 0, good_lpsv = 0, j;
    1224             :   socklen_t len;
    1225           0 :   int on = 1;
    1226             :   uint32_t a0, a1, a2, a3, p0, p1, port;
    1227             :   uint32_t af, hal, h[16], pal; /* RFC 1639: LPSV resonse.  */
    1228           0 :   struct sockaddr_in *data_addr_sa4 = (struct sockaddr_in *) &data_addr;
    1229           0 :   struct sockaddr_in6 *data_addr_sa6 = (struct sockaddr_in6 *) &data_addr;
    1230             : 
    1231           0 :   if (passivemode)
    1232             :     {
    1233           0 :       data = socket (myctladdr.ss_family, SOCK_STREAM, 0);
    1234           0 :       if (data < 0)
    1235             :         {
    1236           0 :           perror ("ftp: socket");
    1237           0 :           return (1);
    1238             :         }
    1239           0 :       if ((options & SO_DEBUG) &&
    1240           0 :           setsockopt (data, SOL_SOCKET, SO_DEBUG, (char *) &on,
    1241             :                       sizeof (on)) < 0)
    1242           0 :         if (errno != EACCES)    /* Ignore insufficient permission.  */
    1243           0 :           error (0, errno, "setsockopt DEBUG (ignored)");
    1244             : 
    1245             :       /* Be contemporary:
    1246             :        *   first try EPSV,
    1247             :        *   then fall back to PASV/LPSV.
    1248             :        */
    1249           0 :       switch (myctladdr.ss_family)
    1250             :         {
    1251             :           case AF_INET:
    1252           0 :             if (doepsv4 && command ("EPSV") == COMPLETE)
    1253             :               {
    1254           0 :                 good_epsv = 1;
    1255           0 :                 break;
    1256             :               }
    1257           0 :             if (doepsv4)
    1258             :               {
    1259             :                 /* When arriving here, EPSV failed. Prevent new attempts.  */
    1260           0 :                 doepsv4 = 0;
    1261             :               }
    1262           0 :             if (command ("PASV") == COMPLETE)
    1263           0 :                 break;
    1264           0 :             if (command ("LPSV") == COMPLETE)
    1265             :               {
    1266           0 :                 good_lpsv = 1;
    1267           0 :                 break;
    1268             :               }
    1269           0 :             printf ("Passive mode refused.\n");
    1270           0 :             goto bad;
    1271             :             break;
    1272             :           case AF_INET6:
    1273           0 :             if (command ("EPSV") == COMPLETE)
    1274             :               {
    1275           0 :                 good_epsv = 1;
    1276           0 :                 break;
    1277             :               }
    1278           0 :             if (command ("LPSV") == COMPLETE)
    1279             :               {
    1280           0 :                 good_lpsv = 1;
    1281           0 :                 break;
    1282             :               }
    1283           0 :             printf ("Passive mode refused.\n");
    1284           0 :             goto bad;
    1285             :             break;
    1286             :         }
    1287             : 
    1288           0 :       if (good_epsv)
    1289             :         {
    1290             :           /* EPSV: IPv4 or IPv6
    1291             :            *
    1292             :            * Expected response (perl): pasv =~ '%u|'
    1293             :            * This communicates a port number.
    1294             :            */
    1295           0 :           if (sscanf (pasv, "%u|", &port) != 1)
    1296             :             {
    1297           0 :               printf ("Extended passive mode scan failure. "
    1298             :                         "Should not happen!\n");
    1299           0 :               (void) command ("ABOR");        /* Cancel any open connection.  */
    1300           0 :               goto bad;
    1301             :             }
    1302           0 :           data_addr = hisctladdr;
    1303           0 :           switch (data_addr.ss_family)
    1304             :             {
    1305             :               case AF_INET:
    1306           0 :                 data_addr_sa4->sin_port = htons (port);
    1307           0 :                 break;
    1308             :               case AF_INET6:
    1309           0 :                 data_addr_sa6->sin6_port = htons (port);
    1310           0 :                 break;
    1311             :             }
    1312             :         } /* EPSV */
    1313           0 :       else if (good_lpsv)
    1314             :         {
    1315             :           /* LPSV: IPv4 or IPv6
    1316             :            *
    1317             :            * At this point we have got a string of comma
    1318             :            * separated, one-byte unsigned integer values.
    1319             :            * Length and interpretation depends on address
    1320             :            * family.
    1321             :            */
    1322             : 
    1323           0 :           if (myctladdr.ss_family == AF_INET)
    1324             :             {
    1325           0 :               if ((sscanf (pasv, "%u," /* af */
    1326             :                                 "%u,%u,%u,%u,%u," /* hal, h[4] */
    1327             :                                 "%u,%u,%u", /* pal, p0, p1 */
    1328             :                                 &af, &hal, &h[0], &h[1], &h[2], &h[3], &pal, &p0, &p1) != 9)
    1329           0 :                   || (/* Strong checking */ af != 4 || hal != 4 || pal != 2) )
    1330             :                 {
    1331           0 :                   printf ("Passive mode address scan failure. "
    1332             :                           "Shouldn't happen!\n");
    1333           0 :                   (void) command ("ABOR");    /* Cancel any open connection.  */
    1334           0 :                   goto bad;
    1335             :                 }
    1336           0 :               for (j = 0; j < 4; ++j)
    1337           0 :                 h[j] &= 0xff; /* Mask only the significant bits.  */
    1338             : 
    1339           0 :               data_addr.ss_family = AF_INET;
    1340           0 :               data_addr_sa4->sin_port =
    1341           0 :                   htons (((p0 & 0xff) << 8) | (p1 & 0xff));
    1342             : 
    1343             :                 {
    1344           0 :                   uint32_t *pu32 = (uint32_t *) &data_addr_sa4->sin_addr.s_addr;
    1345           0 :                   pu32[0] = htonl ( (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]);
    1346             :                 }
    1347             :             } /* LPSV IPv4 */
    1348             :           else /* IPv6 */
    1349             :             {
    1350           0 :               if ((sscanf (pasv, "%u," /* af */
    1351             :                                 "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u," /* hal, h[16] */
    1352             :                                 "%u,%u,%u", /* pal, p0, p1 */
    1353             :                                 &af, &hal, &h[0], &h[1], &h[2], &h[3], &h[4], &h[5], &h[6], &h[7],
    1354             :                                 &h[8], &h[9], &h[10], &h[11], &h[12], &h[13], &h[14], &h[15],
    1355             :                                 &pal, &p0, &p1) != 21)
    1356           0 :                   || (/* Strong checking */ af != 6 || hal != 16 || pal != 2) )
    1357             :                 {
    1358           0 :                   printf ("Passive mode address scan failure. "
    1359             :                           "Shouldn't happen!\n");
    1360           0 :                   (void) command ("ABOR");    /* Cancel any open connection.  */
    1361           0 :                   goto bad;
    1362             :                 }
    1363           0 :               for (j = 0; j < 16; ++j)
    1364           0 :                 h[j] &= 0xff; /* Mask only the significant bits.  */
    1365             : 
    1366           0 :               data_addr.ss_family = AF_INET6;
    1367           0 :               data_addr_sa6->sin6_port =
    1368           0 :                   htons (((p0 & 0xff) << 8) | (p1 & 0xff));
    1369             : 
    1370             :                 {
    1371           0 :                   uint32_t *pu32 = (uint32_t *) &data_addr_sa6->sin6_addr.s6_addr;
    1372           0 :                   pu32[0] = htonl ( (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]);
    1373           0 :                   pu32[1] = htonl ( (h[4] << 24) | (h[5] << 16) | (h[6] << 8) | h[7]);
    1374           0 :                   pu32[2] = htonl ( (h[8] << 24) | (h[9] << 16) | (h[10] << 8) | h[11]);
    1375           0 :                   pu32[3] = htonl ( (h[12] << 24) | (h[13] << 16) | (h[14] << 8) | h[15]);
    1376             :                 }
    1377             :             } /* LPSV IPv6 */
    1378             :         }
    1379             :       else /* !EPSV && !LPSV */
    1380             :         { /* PASV */
    1381           0 :           if (myctladdr.ss_family == AF_INET)
    1382             :             { /* PASV */
    1383           0 :               if (sscanf (pasv, "%u,%u,%u,%u,%u,%u",
    1384             :                           &a0, &a1, &a2, &a3, &p0, &p1) != 6)
    1385             :                 {
    1386           0 :                   printf ("Passive mode address scan failure. "
    1387             :                           "Shouldn't happen!\n");
    1388           0 :                   (void) command ("ABOR");    /* Cancel any open connection.  */
    1389           0 :                   goto bad;
    1390             :                 }
    1391           0 :               data_addr.ss_family = AF_INET;
    1392           0 :               data_addr_sa4->sin_addr.s_addr =
    1393           0 :                   htonl ( (a0 << 24) | ((a1 & 0xff) << 16)
    1394           0 :                          | ((a2 & 0xff) << 8) | (a3 & 0xff) );
    1395           0 :               data_addr_sa4->sin_port =
    1396           0 :                   htons (((p0 & 0xff) << 8) | (p1 & 0xff));
    1397             :             } /* PASV */
    1398             :           else
    1399             :             {
    1400             :               /* Catch all impossible cases.  */
    1401           0 :               printf ("Passive mode address scan failure. Shouldn't happen!\n");
    1402           0 :               goto bad;
    1403             :             }
    1404             :         } /* PASV */
    1405             : 
    1406           0 :       if (connect (data, (struct sockaddr *) &data_addr, ctladdrlen) < 0)
    1407             :         {
    1408           0 :           perror ("ftp: connect");
    1409           0 :           goto bad;
    1410             :         }
    1411             : #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
    1412           0 :       on = IPTOS_THROUGHPUT;
    1413           0 :       if (data_addr.ss_family == AF_INET &&
    1414           0 :            setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on,
    1415             :                       sizeof (int)) < 0)
    1416           0 :         perror ("ftp: setsockopt TOS (ignored)");
    1417             : #endif
    1418           0 :       return (0);
    1419             :     }
    1420             : 
    1421             : noport:
    1422           0 :   data_addr = myctladdr;
    1423           0 :   if (sendport)
    1424             :     /* Let the system pick a port.  */
    1425           0 :     switch (myctladdr.ss_family)
    1426             :       {
    1427             :         case AF_INET:
    1428           0 :           data_addr_sa4->sin_port = 0;
    1429           0 :           break;
    1430             :         case AF_INET6:
    1431           0 :           data_addr_sa6->sin6_port = 0;
    1432           0 :           break;
    1433             :       }
    1434             : 
    1435           0 :   if (data != -1)
    1436           0 :     close (data);
    1437           0 :   data = socket (myctladdr.ss_family, SOCK_STREAM, 0);
    1438           0 :   if (data < 0)
    1439             :     {
    1440           0 :       error (0, errno, "socket");
    1441           0 :       if (tmpno)
    1442           0 :         sendport = 1;
    1443           0 :       return (1);
    1444             :     }
    1445           0 :   if (!sendport)
    1446           0 :     if (setsockopt (data, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on))
    1447             :         < 0)
    1448             :       {
    1449           0 :         error (0, errno, "setsockopt (reuse address)");
    1450           0 :         goto bad;
    1451             :       }
    1452           0 :   if (bind (data, (struct sockaddr *) &data_addr, ctladdrlen) < 0)
    1453             :     {
    1454           0 :       error (0, errno, "bind");
    1455           0 :       goto bad;
    1456             :     }
    1457           0 :   if (options & SO_DEBUG
    1458           0 :       && setsockopt (data, SOL_SOCKET, SO_DEBUG,
    1459             :                      (char *) &on, sizeof (on)) < 0)
    1460           0 :     if (errno != EACCES)        /* Ignore insufficient permission.  */
    1461           0 :       error (0, errno, "setsockopt DEBUG (ignored)");
    1462           0 :   len = sizeof (data_addr);
    1463           0 :   if (getsockname (data, (struct sockaddr *) &data_addr, &len) < 0)
    1464             :     {
    1465           0 :       error (0, errno, "getsockname");
    1466           0 :       goto bad;
    1467             :     }
    1468           0 :   if (listen (data, 1) < 0)
    1469           0 :     error (0, errno, "listen");
    1470           0 :   if (sendport)
    1471             :     {
    1472             : #define UC(b)   (((int)b)&0xff)
    1473             :       /* Preferences:
    1474             :        *   IPv4: EPRT, PORT, LPRT
    1475             :        *   IPv6: EPRT, LPRT
    1476             :        */
    1477           0 :       result = ERROR;   /* For success detection.  */
    1478           0 :       if (data_addr.ss_family != AF_INET || doepsv4)
    1479             :         {
    1480             :           /* Use EPRT mode.  */
    1481           0 :           getnameinfo ((struct sockaddr *) &data_addr, ctladdrlen,
    1482             :                         ia, sizeof (ia), portstr, sizeof (portstr),
    1483             :                         NI_NUMERICHOST | NI_NUMERICSERV);
    1484           0 :           result = command ("EPRT |%d|%s|%s|",
    1485           0 :                             (data_addr.ss_family == AF_INET) ? 1 : 2,
    1486             :                             ia, portstr);
    1487             :         }
    1488             : 
    1489           0 :       if (data_addr.ss_family == AF_INET && doepsv4 && result != COMPLETE)
    1490             :         /* Do not try EPRT with IPv4 again.  It fails for this host.  */
    1491           0 :         doepsv4 = 0;
    1492             : 
    1493           0 :       if (data_addr.ss_family == AF_INET && result != COMPLETE)
    1494             :         {
    1495             :           /* PORT for IPv4; possibly EPRT has failed.  */
    1496           0 :           a = (char *) &data_addr_sa4->sin_addr;
    1497           0 :           p = (char *) &data_addr_sa4->sin_port;
    1498           0 :           result = command ("PORT %d,%d,%d,%d,%d,%d",
    1499           0 :                             UC (a[0]), UC (a[1]), UC (a[2]), UC (a[3]),
    1500           0 :                             UC (p[0]), UC (p[1]));
    1501             :         }
    1502             : 
    1503           0 :       if (result != COMPLETE)
    1504             :         {
    1505             :           /* Fall back to LPRT.  */
    1506             :           uint8_t *h, *p;
    1507             : 
    1508           0 :           switch (data_addr.ss_family)
    1509             :             {
    1510             :               case AF_INET:
    1511           0 :                 h = (uint8_t *) &data_addr_sa4->sin_addr;
    1512           0 :                 p = (uint8_t *) &data_addr_sa4->sin_port;
    1513           0 :                 result = command ("LPRT 4,4,%u,%u,%u,%u,2,%u,%u",
    1514           0 :                                   h[0], h[1], h[2], h[3], p[0], p[1]);
    1515           0 :                 break;
    1516             :               case AF_INET6:
    1517           0 :                 h = (uint8_t *) &data_addr_sa6->sin6_addr;
    1518           0 :                 p = (uint8_t *) &data_addr_sa6->sin6_port;
    1519           0 :                 result = command ("LPRT 6,16," /* af, hal */
    1520             :                                   "%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u," /* h[16] */
    1521             :                                   "2,%u,%u", /* pal, p[2] */
    1522           0 :                                   h[0], h[1], h[2], h[3], h[4], h[5], h[6], h[7],
    1523           0 :                                   h[8], h[9], h[10], h[11], h[12], h[13], h[14], h[15],
    1524           0 :                                   p[0], p[1]);
    1525           0 :                 break;
    1526             :             }
    1527             :         }
    1528             : 
    1529           0 :       if (result == ERROR && sendport == -1)
    1530             :         {
    1531           0 :           sendport = 0;
    1532           0 :           tmpno = 1;
    1533           0 :           goto noport;
    1534             :         }
    1535           0 :       return (result != COMPLETE);
    1536             :     }
    1537           0 :   if (tmpno)
    1538           0 :     sendport = 1;
    1539             : #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
    1540           0 :   on = IPTOS_THROUGHPUT;
    1541           0 :   if (data_addr.ss_family == AF_INET &&
    1542           0 :         setsockopt (data, IPPROTO_IP, IP_TOS, (char *) &on, sizeof (int)) < 0)
    1543           0 :     error (0, errno, "setsockopt TOS (ignored)");
    1544             : #endif
    1545           0 :   return (0);
    1546             : bad:
    1547           0 :   close (data), data = -1;
    1548           0 :   if (tmpno)
    1549           0 :     sendport = 1;
    1550           0 :   return (1);
    1551             : }
    1552             : 
    1553             : FILE *
    1554           0 : dataconn (char *lmode)
    1555             : {
    1556             :   struct sockaddr_storage from;
    1557             :   int s, tos;
    1558           0 :   socklen_t fromlen = sizeof (from);
    1559             : 
    1560           0 :   if (passivemode)
    1561           0 :     return (fdopen (data, lmode));
    1562             : 
    1563           0 :   s = accept (data, (struct sockaddr *) &from, &fromlen);
    1564           0 :   if (s < 0)
    1565             :     {
    1566           0 :       error (0, errno, "accept");
    1567           0 :       close (data), data = -1;
    1568           0 :       return (NULL);
    1569             :     }
    1570           0 :   close (data);
    1571           0 :   data = s;
    1572             : #if defined IP_TOS && defined IPPROTO_IP && defined IPTOS_THROUGHPUT
    1573           0 :   tos = IPTOS_THROUGHPUT;
    1574           0 :   if (from.ss_family == AF_INET &&
    1575           0 :         setsockopt (s, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof (int)) < 0)
    1576           0 :     error (0, errno, "setsockopt TOS (ignored)");
    1577             : #endif
    1578           0 :   return (fdopen (data, lmode));
    1579             : }
    1580             : 
    1581             : void
    1582           0 : ptransfer (char *direction, long long int bytes,
    1583             :            struct timeval *t0, struct timeval *t1)
    1584             : {
    1585             :   struct timeval td;
    1586             :   float s, bs;
    1587             : 
    1588           0 :   if (verbose)
    1589             :     {
    1590           0 :       tvsub (&td, t1, t0);
    1591           0 :       s = td.tv_sec + (td.tv_usec / 1000000.);
    1592             : #define nz(x)   ((x) == 0 ? 1 : (x))
    1593           0 :       bs = bytes / nz (s);
    1594             : 
    1595           0 :       printf ("%lld bytes %s in %.3g seconds", bytes, direction, s);
    1596             : 
    1597           0 :       if (bs > 1048576.0)
    1598           0 :         printf (" (%.3g Mbytes/s)\n", bs / 1048576.0);
    1599           0 :       else if (bs > 1024.0)
    1600           0 :         printf (" (%.3g kbytes/s)\n", bs / 1024.0);
    1601             :       else
    1602           0 :         printf (" (%.3g bytes/s)\n", bs);
    1603             :     }
    1604           0 : }
    1605             : 
    1606             : /*
    1607             : void
    1608             : tvadd(tsum, t0)
    1609             :         struct timeval *tsum, *t0;
    1610             : {
    1611             : 
    1612             :         tsum->tv_sec += t0->tv_sec;
    1613             :         tsum->tv_usec += t0->tv_usec;
    1614             :         if (tsum->tv_usec > 1000000)
    1615             :                 tsum->tv_sec++, tsum->tv_usec -= 1000000;
    1616             : }
    1617             : */
    1618             : 
    1619             : void
    1620           0 : tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
    1621             : {
    1622             : 
    1623           0 :   tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
    1624           0 :   tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
    1625           0 :   if (tdiff->tv_usec < 0)
    1626           0 :     tdiff->tv_sec--, tdiff->tv_usec += 1000000;
    1627           0 : }
    1628             : 
    1629             : void
    1630           0 : psabort (int sig _GL_UNUSED_PARAMETER)
    1631             : {
    1632             : 
    1633           0 :   abrtflag++;
    1634           0 : }
    1635             : 
    1636             : void
    1637           6 : pswitch (int flag)
    1638             : {
    1639             :   sighandler_t oldintr;
    1640             :   static struct comvars
    1641             :   {
    1642             :     int connect;
    1643             :     char *name;
    1644             :     struct sockaddr_storage mctl;
    1645             :     struct sockaddr_storage hctl;
    1646             :     FILE *in;
    1647             :     FILE *out;
    1648             :     int tpe;
    1649             :     int curtpe;
    1650             :     int cpnd;
    1651             :     int sunqe;
    1652             :     int runqe;
    1653             :     int mcse;
    1654             :     int ntflg;
    1655             :     char nti[sizeof (ntin)];
    1656             :     char nto[sizeof (ntout)];
    1657             :     int mapflg;
    1658             :     char *mi;
    1659             :     char *mo;
    1660             :   } proxstruct =
    1661             :   {
    1662             :   0}, tmpstruct =
    1663             :   {
    1664             :   0};
    1665             :   struct comvars *ip, *op;
    1666             : 
    1667           6 :   abrtflag = 0;
    1668           6 :   oldintr = signal (SIGINT, psabort);
    1669           6 :   if (flag)
    1670             :     {
    1671           6 :       if (proxy)
    1672           0 :         return;
    1673           6 :       ip = &tmpstruct;
    1674           6 :       op = &proxstruct;
    1675           6 :       proxy++;
    1676             :     }
    1677             :   else
    1678             :     {
    1679           0 :       if (!proxy)
    1680           0 :         return;
    1681           0 :       ip = &proxstruct;
    1682           0 :       op = &tmpstruct;
    1683           0 :       proxy = 0;
    1684             :     }
    1685           6 :   ip->connect = connected;
    1686           6 :   connected = op->connect;
    1687             : 
    1688           6 :   free (ip->name);
    1689           6 :   ip->name = hostname;
    1690           6 :   hostname = op->name;
    1691           6 :   op->name = 0;
    1692             : 
    1693           6 :   ip->hctl = hisctladdr;
    1694           6 :   hisctladdr = op->hctl;
    1695           6 :   ip->mctl = myctladdr;
    1696           6 :   myctladdr = op->mctl;
    1697           6 :   ip->in = cin;
    1698           6 :   cin = op->in;
    1699           6 :   ip->out = cout;
    1700           6 :   cout = op->out;
    1701           6 :   ip->tpe = type;
    1702           6 :   type = op->tpe;
    1703           6 :   ip->curtpe = curtype;
    1704           6 :   curtype = op->curtpe;
    1705           6 :   ip->cpnd = cpend;
    1706           6 :   cpend = op->cpnd;
    1707           6 :   ip->sunqe = sunique;
    1708           6 :   sunique = op->sunqe;
    1709           6 :   ip->runqe = runique;
    1710           6 :   runique = op->runqe;
    1711           6 :   ip->mcse = mcase;
    1712           6 :   mcase = op->mcse;
    1713           6 :   ip->ntflg = ntflag;
    1714           6 :   ntflag = op->ntflg;
    1715           6 :   strncpy (ip->nti, ntin, sizeof (ntin) - 1);
    1716           6 :   (ip->nti)[strlen (ip->nti)] = '\0';
    1717           6 :   strcpy (ntin, op->nti);
    1718           6 :   strncpy (ip->nto, ntout, sizeof (ntout) - 1);
    1719           6 :   (ip->nto)[strlen (ip->nto)] = '\0';
    1720           6 :   strcpy (ntout, op->nto);
    1721           6 :   ip->mapflg = mapflag;
    1722           6 :   mapflag = op->mapflg;
    1723             : 
    1724           6 :   free (ip->mi);
    1725           6 :   ip->mi = mapin;
    1726           6 :   mapin = op->mi;
    1727           6 :   op->mi = 0;
    1728             : 
    1729           6 :   free (ip->mo);
    1730           6 :   ip->mo = mapout;
    1731           6 :   mapout = op->mo;
    1732           6 :   op->mo = 0;
    1733             : 
    1734           6 :   signal (SIGINT, oldintr);
    1735           6 :   if (abrtflag)
    1736             :     {
    1737           0 :       abrtflag = 0;
    1738           0 :       (*oldintr) (SIGINT);
    1739             :     }
    1740             : }
    1741             : 
    1742             : void
    1743           0 : abortpt (int sig _GL_UNUSED_PARAMETER)
    1744             : {
    1745             : 
    1746           0 :   printf ("\n");
    1747           0 :   fflush (stdout);
    1748           0 :   ptabflg++;
    1749           0 :   mflag = 0;
    1750           0 :   abrtflag = 0;
    1751           0 :   longjmp (ptabort, 1);
    1752             : }
    1753             : 
    1754             : void
    1755           0 : proxtrans (char *cmd, char *local, char *remote)
    1756             : {
    1757             :   sighandler_t oldintr;
    1758           0 :   int secndflag = 0, prox_type, nfnd;
    1759             :   char *cmd2;
    1760             :   fd_set mask;
    1761             : 
    1762           0 :   if (strcmp (cmd, "RETR"))
    1763           0 :     cmd2 = "RETR";
    1764             :   else
    1765           0 :     cmd2 = runique ? "STOU" : "STOR";
    1766           0 :   if ((prox_type = type) == 0)
    1767             :     {
    1768           0 :       if (unix_server && unix_proxy)
    1769           0 :         prox_type = TYPE_I;
    1770             :       else
    1771           0 :         prox_type = TYPE_A;
    1772             :     }
    1773           0 :   if (curtype != prox_type)
    1774           0 :     changetype (prox_type, 1);
    1775           0 :   if (command ("PASV") != COMPLETE)
    1776             :     {
    1777           0 :       printf ("proxy server does not support third party transfers.\n");
    1778           0 :       return;
    1779             :     }
    1780           0 :   pswitch (0);
    1781           0 :   if (!connected)
    1782             :     {
    1783           0 :       printf ("No primary connection\n");
    1784           0 :       pswitch (1);
    1785           0 :       code = -1;
    1786           0 :       return;
    1787             :     }
    1788           0 :   if (curtype != prox_type)
    1789           0 :     changetype (prox_type, 1);
    1790           0 :   if (command ("PORT %s", pasv) != COMPLETE)
    1791             :     {
    1792           0 :       pswitch (1);
    1793           0 :       return;
    1794             :     }
    1795           0 :   if (setjmp (ptabort))
    1796           0 :     goto abort;
    1797           0 :   oldintr = signal (SIGINT, abortpt);
    1798           0 :   if (command ("%s %s", cmd, remote) != PRELIM)
    1799             :     {
    1800           0 :       signal (SIGINT, oldintr);
    1801           0 :       pswitch (1);
    1802           0 :       return;
    1803             :     }
    1804           0 :   sleep (2);
    1805           0 :   pswitch (1);
    1806           0 :   secndflag++;
    1807           0 :   if (command ("%s %s", cmd2, local) != PRELIM)
    1808           0 :     goto abort;
    1809           0 :   ptflag++;
    1810           0 :   getreply (0);
    1811           0 :   pswitch (0);
    1812           0 :   getreply (0);
    1813           0 :   signal (SIGINT, oldintr);
    1814           0 :   pswitch (1);
    1815           0 :   ptflag = 0;
    1816           0 :   printf ("local: %s remote: %s\n", local, remote);
    1817           0 :   return;
    1818             : abort:
    1819           0 :   signal (SIGINT, SIG_IGN);
    1820           0 :   ptflag = 0;
    1821           0 :   if (strcmp (cmd, "RETR") && !proxy)
    1822           0 :     pswitch (1);
    1823           0 :   else if (!strcmp (cmd, "RETR") && proxy)
    1824           0 :     pswitch (0);
    1825           0 :   if (!cpend && !secndflag)
    1826             :     {                           /* only here if cmd = "STOR" (proxy=1) */
    1827           0 :       if (command ("%s %s", cmd2, local) != PRELIM)
    1828             :         {
    1829           0 :           pswitch (0);
    1830           0 :           if (cpend)
    1831           0 :             abort_remote ((FILE *) NULL);
    1832             :         }
    1833           0 :       pswitch (1);
    1834           0 :       if (ptabflg)
    1835           0 :         code = -1;
    1836           0 :       signal (SIGINT, oldintr);
    1837           0 :       return;
    1838             :     }
    1839           0 :   if (cpend)
    1840           0 :     abort_remote ((FILE *) NULL);
    1841           0 :   pswitch (!proxy);
    1842           0 :   if (!cpend && !secndflag)
    1843             :     {                           /* only if cmd = "RETR" (proxy=1) */
    1844           0 :       if (command ("%s %s", cmd2, local) != PRELIM)
    1845             :         {
    1846           0 :           pswitch (0);
    1847           0 :           if (cpend)
    1848           0 :             abort_remote ((FILE *) NULL);
    1849           0 :           pswitch (1);
    1850           0 :           if (ptabflg)
    1851           0 :             code = -1;
    1852           0 :           signal (SIGINT, oldintr);
    1853           0 :           return;
    1854             :         }
    1855             :     }
    1856           0 :   if (cpend)
    1857           0 :     abort_remote ((FILE *) NULL);
    1858           0 :   pswitch (!proxy);
    1859           0 :   if (cpend)
    1860             :     {
    1861           0 :       FD_ZERO (&mask);
    1862           0 :       FD_SET (fileno (cin), &mask);
    1863           0 :       if ((nfnd = empty (&mask, 10)) <= 0)
    1864             :         {
    1865           0 :           if (nfnd < 0)
    1866             :             {
    1867           0 :               error (0, errno, "abort");
    1868             :             }
    1869           0 :           if (ptabflg)
    1870           0 :             code = -1;
    1871           0 :           lostpeer (0);
    1872             :         }
    1873           0 :       getreply (0);
    1874           0 :       getreply (0);
    1875             :     }
    1876           0 :   if (proxy)
    1877           0 :     pswitch (0);
    1878           0 :   pswitch (1);
    1879           0 :   if (ptabflg)
    1880           0 :     code = -1;
    1881           0 :   signal (SIGINT, oldintr);
    1882             : }
    1883             : 
    1884             : void
    1885           0 : reset (int argc _GL_UNUSED_PARAMETER, char **argv _GL_UNUSED_PARAMETER)
    1886             : {
    1887             :   fd_set mask;
    1888           0 :   int nfnd = 1;
    1889             : 
    1890           0 :   FD_ZERO (&mask);
    1891           0 :   while (nfnd > 0)
    1892             :     {
    1893           0 :       FD_SET (fileno (cin), &mask);
    1894           0 :       if ((nfnd = empty (&mask, 0)) < 0)
    1895             :         {
    1896           0 :           error (0, errno, "reset");
    1897           0 :           code = -1;
    1898           0 :           lostpeer (0);
    1899             :         }
    1900           0 :       else if (nfnd)
    1901             :         {
    1902           0 :           getreply (0);
    1903             :         }
    1904             :     }
    1905           0 : }
    1906             : 
    1907             : char *
    1908           0 : gunique (char *local)
    1909             : {
    1910             :   static char *new = 0;
    1911             :   char *cp;
    1912           0 :   int count = 0;
    1913           0 :   char ext = '1';
    1914             : 
    1915           0 :   free (new);
    1916           0 :   new = malloc (strlen (local) + 1 + 3 + 1);    /* '.' + 100 + '\0' */
    1917           0 :   if (!new)
    1918             :     {
    1919           0 :       printf ("gunique: malloc failed.\n");
    1920           0 :       return 0;
    1921             :     }
    1922           0 :   strcpy (new, local);
    1923             : 
    1924           0 :   cp = new + strlen (new);
    1925           0 :   *cp++ = '.';
    1926             :   for (;;)
    1927             :     {
    1928             :       struct stat st;
    1929             : 
    1930           0 :       if (++count == 100)
    1931             :         {
    1932           0 :           printf ("runique: can't find unique file name.\n");
    1933           0 :           return ((char *) 0);
    1934             :         }
    1935           0 :       *cp++ = ext;
    1936           0 :       *cp = '\0';
    1937           0 :       if (ext == '9')
    1938           0 :         ext = '0';
    1939             :       else
    1940           0 :         ext++;
    1941             : 
    1942           0 :       if (stat (new, &st) != 0)
    1943             :         {
    1944           0 :           if (errno == ENOENT)
    1945           0 :             return new;
    1946             :           else
    1947           0 :             return 0;
    1948             :         }
    1949             : 
    1950           0 :       if (ext != '0')
    1951           0 :         cp--;
    1952           0 :       else if (*(cp - 2) == '.')
    1953           0 :         *(cp - 1) = '1';
    1954             :       else
    1955             :         {
    1956           0 :           *(cp - 2) = *(cp - 2) + 1;
    1957           0 :           cp--;
    1958             :         }
    1959           0 :     }
    1960             : }
    1961             : 
    1962             : void
    1963           0 : abort_remote (FILE *din)
    1964             : {
    1965             :   char buf[BUFSIZ];
    1966             :   int nfnd;
    1967             :   fd_set mask;
    1968             : 
    1969             :   /*
    1970             :    * send IAC in urgent mode instead of DM because 4.3BSD places oob mark
    1971             :    * after urgent byte rather than before as is protocol now
    1972             :    */
    1973           0 :   sprintf (buf, "%c%c%c", IAC, IP, IAC);
    1974           0 :   if (send (fileno (cout), buf, 3, MSG_OOB) != 3)
    1975           0 :     error (0, errno, "abort");
    1976           0 :   fprintf (cout, "%cABOR\r\n", DM);
    1977           0 :   fflush (cout);
    1978           0 :   FD_ZERO (&mask);
    1979           0 :   FD_SET (fileno (cin), &mask);
    1980           0 :   if (din)
    1981             :     {
    1982           0 :       FD_SET (fileno (din), &mask);
    1983             :     }
    1984           0 :   if ((nfnd = empty (&mask, 10)) <= 0)
    1985             :     {
    1986           0 :       if (nfnd < 0)
    1987             :         {
    1988           0 :           error (0, errno, "abort");
    1989             :         }
    1990           0 :       if (ptabflg)
    1991           0 :         code = -1;
    1992           0 :       lostpeer (0);
    1993             :     }
    1994           0 :   if (din && FD_ISSET (fileno (din), &mask))
    1995             :     {
    1996           0 :       while (read (fileno (din), buf, sizeof (buf)) > 0)
    1997             :         /* LOOP */ ;
    1998             :     }
    1999           0 :   if (getreply (0) == ERROR && code == 552)
    2000             :     {
    2001             :       /* 552 needed for nic style abort */
    2002           0 :       getreply (0);
    2003             :     }
    2004           0 :   getreply (0);
    2005           0 : }

Generated by: LCOV version 1.11