]> sjero.net Git - wget/blob - src/ftp.c
mass change: update copyright years.
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3    2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
4    Inc.
5
6 This file is part of GNU Wget.
7
8 GNU Wget 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
11 (at your option) any later version.
12
13 GNU Wget is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Wget.  If not, see <http://www.gnu.org/licenses/>.
20
21 Additional permission under GNU GPL version 3 section 7
22
23 If you modify this program, or any covered work, by linking or
24 combining it with the OpenSSL project's OpenSSL library (or a
25 modified version of that library), containing parts covered by the
26 terms of the OpenSSL or SSLeay licenses, the Free Software Foundation
27 grants you additional permission to convey the resulting work.
28 Corresponding Source for a non-source form of such a combination
29 shall include the source code for the parts of OpenSSL used as well
30 as that of the covered work.  */
31
32 #include "wget.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <strings.h>
38 #include <unistd.h>
39 #include <assert.h>
40 #include <errno.h>
41 #include <time.h>
42
43 #include "utils.h"
44 #include "url.h"
45 #include "retr.h"
46 #include "ftp.h"
47 #include "connect.h"
48 #include "host.h"
49 #include "netrc.h"
50 #include "convert.h"            /* for downloaded_file */
51 #include "recur.h"              /* for INFINITE_RECURSION */
52
53 #ifdef __VMS
54 # include "vms.h"
55 #endif /* def __VMS */
56
57
58 /* File where the "ls -al" listing will be saved.  */
59 #ifdef MSDOS
60 #define LIST_FILENAME "_listing"
61 #else
62 #define LIST_FILENAME ".listing"
63 #endif
64
65 typedef struct
66 {
67   int st;                       /* connection status */
68   int cmd;                      /* command code */
69   int csock;                    /* control connection socket */
70   double dltime;                /* time of the download in msecs */
71   enum stype rs;                /* remote system reported by ftp server */
72   char *id;                     /* initial directory */
73   char *target;                 /* target file name */
74   struct url *proxy;            /* FTWK-style proxy */
75 } ccon;
76
77 extern int numurls;
78
79 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
80    the string S, and return the number converted to wgint, if found, 0
81    otherwise.  */
82 static wgint
83 ftp_expected_bytes (const char *s)
84 {
85   wgint res;
86
87   while (1)
88     {
89       while (*s && *s != '(')
90         ++s;
91       if (!*s)
92         return 0;
93       ++s;                      /* skip the '(' */
94       res = str_to_wgint (s, (char **) &s, 10);
95       if (!*s)
96         return 0;
97       while (*s && c_isspace (*s))
98         ++s;
99       if (!*s)
100         return 0;
101       if (c_tolower (*s) != 'b')
102         continue;
103       if (strncasecmp (s, "byte", 4))
104         continue;
105       else
106         break;
107     }
108   return res;
109 }
110
111 #ifdef ENABLE_IPV6
112 /*
113  * This function sets up a passive data connection with the FTP server.
114  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
115  */
116 static uerr_t
117 ftp_do_pasv (int csock, ip_address *addr, int *port)
118 {
119   uerr_t err;
120
121   /* We need to determine the address family and need to call
122      getpeername, so while we're at it, store the address to ADDR.
123      ftp_pasv and ftp_lpsv can simply override it.  */
124   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
125     abort ();
126
127   /* If our control connection is over IPv6, then we first try EPSV and then
128    * LPSV if the former is not supported. If the control connection is over
129    * IPv4, we simply issue the good old PASV request. */
130   switch (addr->family)
131     {
132     case AF_INET:
133       if (!opt.server_response)
134         logputs (LOG_VERBOSE, "==> PASV ... ");
135       err = ftp_pasv (csock, addr, port);
136       break;
137     case AF_INET6:
138       if (!opt.server_response)
139         logputs (LOG_VERBOSE, "==> EPSV ... ");
140       err = ftp_epsv (csock, addr, port);
141
142       /* If EPSV is not supported try LPSV */
143       if (err == FTPNOPASV)
144         {
145           if (!opt.server_response)
146             logputs (LOG_VERBOSE, "==> LPSV ... ");
147           err = ftp_lpsv (csock, addr, port);
148         }
149       break;
150     default:
151       abort ();
152     }
153
154   return err;
155 }
156
157 /*
158  * This function sets up an active data connection with the FTP server.
159  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
160  */
161 static uerr_t
162 ftp_do_port (int csock, int *local_sock)
163 {
164   uerr_t err;
165   ip_address cip;
166
167   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
168     abort ();
169
170   /* If our control connection is over IPv6, then we first try EPRT and then
171    * LPRT if the former is not supported. If the control connection is over
172    * IPv4, we simply issue the good old PORT request. */
173   switch (cip.family)
174     {
175     case AF_INET:
176       if (!opt.server_response)
177         logputs (LOG_VERBOSE, "==> PORT ... ");
178       err = ftp_port (csock, local_sock);
179       break;
180     case AF_INET6:
181       if (!opt.server_response)
182         logputs (LOG_VERBOSE, "==> EPRT ... ");
183       err = ftp_eprt (csock, local_sock);
184
185       /* If EPRT is not supported try LPRT */
186       if (err == FTPPORTERR)
187         {
188           if (!opt.server_response)
189             logputs (LOG_VERBOSE, "==> LPRT ... ");
190           err = ftp_lprt (csock, local_sock);
191         }
192       break;
193     default:
194       abort ();
195     }
196   return err;
197 }
198 #else
199
200 static uerr_t
201 ftp_do_pasv (int csock, ip_address *addr, int *port)
202 {
203   if (!opt.server_response)
204     logputs (LOG_VERBOSE, "==> PASV ... ");
205   return ftp_pasv (csock, addr, port);
206 }
207
208 static uerr_t
209 ftp_do_port (int csock, int *local_sock)
210 {
211   if (!opt.server_response)
212     logputs (LOG_VERBOSE, "==> PORT ... ");
213   return ftp_port (csock, local_sock);
214 }
215 #endif
216
217 static void
218 print_length (wgint size, wgint start, bool authoritative)
219 {
220   logprintf (LOG_VERBOSE, _("Length: %s"), number_to_static_string (size));
221   if (size >= 1024)
222     logprintf (LOG_VERBOSE, " (%s)", human_readable (size));
223   if (start > 0)
224     {
225       if (size - start >= 1024)
226         logprintf (LOG_VERBOSE, _(", %s (%s) remaining"),
227                    number_to_static_string (size - start),
228                    human_readable (size - start));
229       else
230         logprintf (LOG_VERBOSE, _(", %s remaining"),
231                    number_to_static_string (size - start));
232     }
233   logputs (LOG_VERBOSE, !authoritative ? _(" (unauthoritative)\n") : "\n");
234 }
235
236 static uerr_t ftp_get_listing (struct url *, ccon *, struct fileinfo **);
237
238 /* Retrieves a file with denoted parameters through opening an FTP
239    connection to the server.  It always closes the data connection,
240    and closes the control connection in case of error.  */
241 static uerr_t
242 getftp (struct url *u, wgint passed_expected_bytes, wgint *qtyread,
243         wgint restval, ccon *con, int count)
244 {
245   int csock, dtsock, local_sock, res;
246   uerr_t err = RETROK;          /* appease the compiler */
247   FILE *fp;
248   char *user, *passwd, *respline;
249   char *tms;
250   const char *tmrate;
251   int cmd = con->cmd;
252   bool pasv_mode_open = false;
253   wgint expected_bytes = 0;
254   bool got_expected_bytes = false;
255   bool rest_failed = false;
256   int flags;
257   wgint rd_size;
258   char type_char;
259
260   assert (con != NULL);
261   assert (con->target != NULL);
262
263   /* Debug-check of the sanity of the request by making sure that LIST
264      and RETR are never both requested (since we can handle only one
265      at a time.  */
266   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
267   /* Make sure that at least *something* is requested.  */
268   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
269
270   *qtyread = restval;
271
272   user = u->user;
273   passwd = u->passwd;
274   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
275   user = user ? user : (opt.ftp_user ? opt.ftp_user : opt.user);
276   if (!user) user = "anonymous";
277   passwd = passwd ? passwd : (opt.ftp_passwd ? opt.ftp_passwd : opt.passwd);
278   if (!passwd) passwd = "-wget@";
279
280   dtsock = -1;
281   local_sock = -1;
282   con->dltime = 0;
283
284   if (!(cmd & DO_LOGIN))
285     csock = con->csock;
286   else                          /* cmd & DO_LOGIN */
287     {
288       char    *host = con->proxy ? con->proxy->host : u->host;
289       int      port = con->proxy ? con->proxy->port : u->port;
290       char *logname = user;
291
292       if (con->proxy)
293         {
294           /* If proxy is in use, log in as username@target-site. */
295           logname = concat_strings (user, "@", u->host, (char *) 0);
296         }
297
298       /* Login to the server: */
299
300       /* First: Establish the control connection.  */
301
302       csock = connect_to_host (host, port);
303       if (csock == E_HOST)
304         return HOSTERR;
305       else if (csock < 0)
306         return (retryable_socket_connect_error (errno)
307                 ? CONERROR : CONIMPOSSIBLE);
308
309       if (cmd & LEAVE_PENDING)
310         con->csock = csock;
311       else
312         con->csock = -1;
313
314       /* Second: Login with proper USER/PASS sequence.  */
315       logprintf (LOG_VERBOSE, _("Logging in as %s ... "),
316                  quotearg_style (escape_quoting_style, user));
317       if (opt.server_response)
318         logputs (LOG_ALWAYS, "\n");
319       err = ftp_login (csock, logname, passwd);
320
321       if (con->proxy)
322         xfree (logname);
323
324       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
325       switch (err)
326         {
327         case FTPRERR:
328           logputs (LOG_VERBOSE, "\n");
329           logputs (LOG_NOTQUIET, _("\
330 Error in server response, closing control connection.\n"));
331           fd_close (csock);
332           con->csock = -1;
333           return err;
334         case FTPSRVERR:
335           logputs (LOG_VERBOSE, "\n");
336           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
337           fd_close (csock);
338           con->csock = -1;
339           return err;
340         case WRITEFAILED:
341           logputs (LOG_VERBOSE, "\n");
342           logputs (LOG_NOTQUIET,
343                    _("Write failed, closing control connection.\n"));
344           fd_close (csock);
345           con->csock = -1;
346           return err;
347         case FTPLOGREFUSED:
348           logputs (LOG_VERBOSE, "\n");
349           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
350           fd_close (csock);
351           con->csock = -1;
352           return FTPLOGREFUSED;
353         case FTPLOGINC:
354           logputs (LOG_VERBOSE, "\n");
355           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
356           fd_close (csock);
357           con->csock = -1;
358           return FTPLOGINC;
359         case FTPOK:
360           if (!opt.server_response)
361             logputs (LOG_VERBOSE, _("Logged in!\n"));
362           break;
363         default:
364           abort ();
365         }
366       /* Third: Get the system type */
367       if (!opt.server_response)
368         logprintf (LOG_VERBOSE, "==> SYST ... ");
369       err = ftp_syst (csock, &con->rs);
370       /* FTPRERR */
371       switch (err)
372         {
373         case FTPRERR:
374           logputs (LOG_VERBOSE, "\n");
375           logputs (LOG_NOTQUIET, _("\
376 Error in server response, closing control connection.\n"));
377           fd_close (csock);
378           con->csock = -1;
379           return err;
380         case FTPSRVERR:
381           logputs (LOG_VERBOSE, "\n");
382           logputs (LOG_NOTQUIET,
383                    _("Server error, can't determine system type.\n"));
384           break;
385         case FTPOK:
386           /* Everything is OK.  */
387           break;
388         default:
389           abort ();
390         }
391       if (!opt.server_response && err != FTPSRVERR)
392         logputs (LOG_VERBOSE, _("done.    "));
393
394       /* Fourth: Find the initial ftp directory */
395
396       if (!opt.server_response)
397         logprintf (LOG_VERBOSE, "==> PWD ... ");
398       err = ftp_pwd (csock, &con->id);
399       /* FTPRERR */
400       switch (err)
401         {
402         case FTPRERR:
403           logputs (LOG_VERBOSE, "\n");
404           logputs (LOG_NOTQUIET, _("\
405 Error in server response, closing control connection.\n"));
406           fd_close (csock);
407           con->csock = -1;
408           return err;
409         case FTPSRVERR :
410           /* PWD unsupported -- assume "/". */
411           xfree_null (con->id);
412           con->id = xstrdup ("/");
413           break;
414         case FTPOK:
415           /* Everything is OK.  */
416           break;
417         default:
418           abort ();
419         }
420
421 #if 0
422       /* 2004-09-17 SMS.
423          Don't help me out.  Please.
424          A reasonably recent VMS FTP server will cope just fine with
425          UNIX file specifications.  This code just spoils things.
426          Discarding the device name, for example, is not a wise move.
427          This code was disabled but left in as an example of what not
428          to do.
429       */
430
431       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
432          Convert it to "/INITIAL/FOLDER" */
433       if (con->rs == ST_VMS)
434         {
435           char *path = strchr (con->id, '[');
436           char *pathend = path ? strchr (path + 1, ']') : NULL;
437           if (!path || !pathend)
438             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
439           else
440             {
441               char *idir = con->id;
442               DEBUGP (("Preprocessing the initial VMS directory\n"));
443               DEBUGP (("  old = '%s'\n", con->id));
444               /* We do the conversion in-place by copying the stuff
445                  between [ and ] to the beginning, and changing dots
446                  to slashes at the same time.  */
447               *idir++ = '/';
448               for (++path; path < pathend; path++, idir++)
449                 *idir = *path == '.' ? '/' : *path;
450               *idir = '\0';
451               DEBUGP (("  new = '%s'\n\n", con->id));
452             }
453         }
454 #endif /* 0 */
455
456       if (!opt.server_response)
457         logputs (LOG_VERBOSE, _("done.\n"));
458
459       /* Fifth: Set the FTP type.  */
460       type_char = ftp_process_type (u->params);
461       if (!opt.server_response)
462         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
463       err = ftp_type (csock, type_char);
464       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
465       switch (err)
466         {
467         case FTPRERR:
468           logputs (LOG_VERBOSE, "\n");
469           logputs (LOG_NOTQUIET, _("\
470 Error in server response, closing control connection.\n"));
471           fd_close (csock);
472           con->csock = -1;
473           return err;
474         case WRITEFAILED:
475           logputs (LOG_VERBOSE, "\n");
476           logputs (LOG_NOTQUIET,
477                    _("Write failed, closing control connection.\n"));
478           fd_close (csock);
479           con->csock = -1;
480           return err;
481         case FTPUNKNOWNTYPE:
482           logputs (LOG_VERBOSE, "\n");
483           logprintf (LOG_NOTQUIET,
484                      _("Unknown type `%c', closing control connection.\n"),
485                      type_char);
486           fd_close (csock);
487           con->csock = -1;
488           return err;
489         case FTPOK:
490           /* Everything is OK.  */
491           break;
492         default:
493           abort ();
494         }
495       if (!opt.server_response)
496         logputs (LOG_VERBOSE, _("done.  "));
497     } /* do login */
498
499   if (cmd & DO_CWD)
500     {
501       if (!*u->dir)
502         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
503       else
504         {
505           char *targ = NULL;
506           int cwd_count;
507           int cwd_end;
508           int cwd_start;
509
510           char *target = u->dir;
511
512           DEBUGP (("changing working directory\n"));
513
514           /* Change working directory.  To change to a non-absolute
515              Unix directory, we need to prepend initial directory
516              (con->id) to it.  Absolute directories "just work".
517
518              A relative directory is one that does not begin with '/'
519              and, on non-Unix OS'es, one that doesn't begin with
520              "[a-z]:".
521
522              This is not done for OS400, which doesn't use
523              "/"-delimited directories, nor does it support directory
524              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
525              in "bar", not in "foo/bar", as would be customary
526              elsewhere.  */
527
528             /* 2004-09-20 SMS.
529                Why is this wise even on UNIX?  It certainly fouls VMS.
530                See below for a more reliable, more universal method.
531             */
532
533             /* 2008-04-22 MJC.
534                I'm not crazy about it either. I'm informed it's useful
535                for misconfigured servers that have some dirs in the path
536                with +x but -r, but this method is not RFC-conformant. I
537                understand the need to deal with crappy server
538                configurations, but it's far better to use the canonical
539                method first, and fall back to kludges second.
540             */
541
542           if (target[0] != '/'
543               && !(con->rs != ST_UNIX
544                    && c_isalpha (target[0])
545                    && target[1] == ':')
546               && (con->rs != ST_OS400)
547               && (con->rs != ST_VMS))
548             {
549               int idlen = strlen (con->id);
550               char *ntarget, *p;
551
552               /* Strip trailing slash(es) from con->id. */
553               while (idlen > 0 && con->id[idlen - 1] == '/')
554                 --idlen;
555               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
556               memcpy (p, con->id, idlen);
557               p += idlen;
558               *p++ = '/';
559               strcpy (p, target);
560
561               DEBUGP (("Prepended initial PWD to relative path:\n"));
562               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
563                        con->id, target, ntarget));
564               target = ntarget;
565             }
566
567 #if 0
568           /* 2004-09-17 SMS.
569              Don't help me out.  Please.
570              A reasonably recent VMS FTP server will cope just fine with
571              UNIX file specifications.  This code just spoils things.
572              Discarding the device name, for example, is not a wise
573              move.
574              This code was disabled but left in as an example of what
575              not to do.
576           */
577
578           /* If the FTP host runs VMS, we will have to convert the absolute
579              directory path in UNIX notation to absolute directory path in
580              VMS notation as VMS FTP servers do not like UNIX notation of
581              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
582
583           if (con->rs == ST_VMS)
584             {
585               char *tmpp;
586               char *ntarget = (char *)alloca (strlen (target) + 2);
587               /* We use a converted initial dir, so directories in
588                  TARGET will be separated with slashes, something like
589                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
590                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
591               strcpy (ntarget, target);
592               assert (*ntarget == '/');
593               *ntarget = '[';
594               for (tmpp = ntarget + 1; *tmpp; tmpp++)
595                 if (*tmpp == '/')
596                   *tmpp = '.';
597               *tmpp++ = ']';
598               *tmpp = '\0';
599               DEBUGP (("Changed file name to VMS syntax:\n"));
600               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
601               target = ntarget;
602             }
603 #endif /* 0 */
604
605           /* 2004-09-20 SMS.
606              A relative directory is relative to the initial directory.
607              Thus, what _is_ useful on VMS (and probably elsewhere) is
608              to CWD to the initial directory (ideally, whatever the
609              server reports, _exactly_, NOT badly UNIX-ixed), and then
610              CWD to the (new) relative directory.  This should probably
611              be restructured as a function, called once or twice, but
612              I'm lazy enough to take the badly indented loop short-cut
613              for now.
614           */
615
616           /* Decide on one pass (absolute) or two (relative).
617              The VMS restriction may be relaxed when the squirrely code
618              above is reformed.
619           */
620           if ((con->rs == ST_VMS) && (target[0] != '/'))
621             {
622               cwd_start = 0;
623               DEBUGP (("Using two-step CWD for relative path.\n"));
624             }
625           else
626             {
627               /* Go straight to the target. */
628               cwd_start = 1;
629             }
630
631           /* At least one VMS FTP server (TCPware V5.6-2) can switch to
632              a UNIX emulation mode when given a UNIX-like directory
633              specification (like "a/b/c").  If allowed to continue this
634              way, LIST interpretation will be confused, because the
635              system type (SYST response) will not be re-checked, and
636              future UNIX-format directory listings (for multiple URLs or
637              "-r") will be horribly misinterpreted.
638
639              The cheap and nasty work-around is to do a "CWD []" after a
640              UNIX-like directory specification is used.  (A single-level
641              directory is harmless.)  This puts the TCPware server back
642              into VMS mode, and does no harm on other servers.
643
644              Unlike the rest of this block, this particular behavior
645              _is_ VMS-specific, so it gets its own VMS test.
646           */
647           if ((con->rs == ST_VMS) && (strchr( target, '/') != NULL))
648             {
649               cwd_end = 3;
650               DEBUGP (("Using extra \"CWD []\" step for VMS server.\n"));
651             }
652           else
653             {
654               cwd_end = 2;
655             }
656
657           /* 2004-09-20 SMS. */
658           /* Sorry about the deviant indenting.  Laziness. */
659
660           for (cwd_count = cwd_start; cwd_count < cwd_end; cwd_count++)
661         {
662           switch (cwd_count)
663             {
664               case 0:
665                 /* Step one (optional): Go to the initial directory,
666                    exactly as reported by the server.
667                 */
668                 targ = con->id;
669                 break;
670
671               case 1:
672                 /* Step two: Go to the target directory.  (Absolute or
673                    relative will work now.)
674                 */
675                 targ = target;
676                 break;
677
678               case 2:
679                 /* Step three (optional): "CWD []" to restore server
680                    VMS-ness.
681                 */
682                 targ = "[]";
683                 break;
684
685               default:
686                 /* Can't happen. */
687                 assert (1);
688             }
689
690           if (!opt.server_response)
691             logprintf (LOG_VERBOSE, "==> CWD (%d) %s ... ", cwd_count,
692                        quotearg_style (escape_quoting_style, target));
693           err = ftp_cwd (csock, targ);
694           /* FTPRERR, WRITEFAILED, FTPNSFOD */
695           switch (err)
696             {
697             case FTPRERR:
698               logputs (LOG_VERBOSE, "\n");
699               logputs (LOG_NOTQUIET, _("\
700 Error in server response, closing control connection.\n"));
701               fd_close (csock);
702               con->csock = -1;
703               return err;
704             case WRITEFAILED:
705               logputs (LOG_VERBOSE, "\n");
706               logputs (LOG_NOTQUIET,
707                        _("Write failed, closing control connection.\n"));
708               fd_close (csock);
709               con->csock = -1;
710               return err;
711             case FTPNSFOD:
712               logputs (LOG_VERBOSE, "\n");
713               logprintf (LOG_NOTQUIET, _("No such directory %s.\n\n"),
714                          quote (u->dir));
715               fd_close (csock);
716               con->csock = -1;
717               return err;
718             case FTPOK:
719               break;
720             default:
721               abort ();
722             }
723           if (!opt.server_response)
724             logputs (LOG_VERBOSE, _("done.\n"));
725
726         } /* for */
727
728           /* 2004-09-20 SMS. */
729           /* End of deviant indenting. */
730
731         } /* else */
732     }
733   else /* do not CWD */
734     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
735
736   if ((cmd & DO_RETR) && passed_expected_bytes == 0)
737     {
738       if (opt.verbose)
739         {
740           if (!opt.server_response)
741             logprintf (LOG_VERBOSE, "==> SIZE %s ... ",
742                        quotearg_style (escape_quoting_style, u->file));
743         }
744
745       err = ftp_size (csock, u->file, &expected_bytes);
746       /* FTPRERR */
747       switch (err)
748         {
749         case FTPRERR:
750         case FTPSRVERR:
751           logputs (LOG_VERBOSE, "\n");
752           logputs (LOG_NOTQUIET, _("\
753 Error in server response, closing control connection.\n"));
754           fd_close (csock);
755           con->csock = -1;
756           return err;
757         case FTPOK:
758           got_expected_bytes = true;
759           /* Everything is OK.  */
760           break;
761         default:
762           abort ();
763         }
764         if (!opt.server_response)
765           logprintf (LOG_VERBOSE, expected_bytes ? "%s\n" : _("done.\n"),
766                      number_to_static_string (expected_bytes));
767     }
768
769   if (cmd & DO_RETR && restval > 0 && restval == expected_bytes)
770     {
771       /* Server confirms that file has length restval. We should stop now.
772          Some servers (f.e. NcFTPd) return error when receive REST 0 */
773       logputs (LOG_VERBOSE, _("File has already been retrieved.\n"));
774       fd_close (csock);
775       con->csock = -1;
776       return RETRFINISHED;
777     }
778
779   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
780   if (cmd & (DO_LIST | DO_RETR))
781     {
782       if (opt.ftp_pasv)
783         {
784           ip_address passive_addr;
785           int        passive_port;
786           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
787           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
788           switch (err)
789             {
790             case FTPRERR:
791               logputs (LOG_VERBOSE, "\n");
792               logputs (LOG_NOTQUIET, _("\
793 Error in server response, closing control connection.\n"));
794               fd_close (csock);
795               con->csock = -1;
796               return err;
797             case WRITEFAILED:
798               logputs (LOG_VERBOSE, "\n");
799               logputs (LOG_NOTQUIET,
800                        _("Write failed, closing control connection.\n"));
801               fd_close (csock);
802               con->csock = -1;
803               return err;
804             case FTPNOPASV:
805               logputs (LOG_VERBOSE, "\n");
806               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
807               break;
808             case FTPINVPASV:
809               logputs (LOG_VERBOSE, "\n");
810               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
811               break;
812             case FTPOK:
813               break;
814             default:
815               abort ();
816             }   /* switch (err) */
817           if (err==FTPOK)
818             {
819               DEBUGP (("trying to connect to %s port %d\n",
820                       print_address (&passive_addr), passive_port));
821               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
822               if (dtsock < 0)
823                 {
824                   int save_errno = errno;
825                   fd_close (csock);
826                   con->csock = -1;
827                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
828                              print_address (&passive_addr), passive_port,
829                              strerror (save_errno));
830                   return (retryable_socket_connect_error (save_errno)
831                           ? CONERROR : CONIMPOSSIBLE);
832                 }
833
834               pasv_mode_open = true;  /* Flag to avoid accept port */
835               if (!opt.server_response)
836                 logputs (LOG_VERBOSE, _("done.    "));
837             } /* err==FTP_OK */
838         }
839
840       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
841         {
842           err = ftp_do_port (csock, &local_sock);
843           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
844              FTPPORTERR */
845           switch (err)
846             {
847             case FTPRERR:
848               logputs (LOG_VERBOSE, "\n");
849               logputs (LOG_NOTQUIET, _("\
850 Error in server response, closing control connection.\n"));
851               fd_close (csock);
852               con->csock = -1;
853               fd_close (dtsock);
854               fd_close (local_sock);
855               return err;
856             case WRITEFAILED:
857               logputs (LOG_VERBOSE, "\n");
858               logputs (LOG_NOTQUIET,
859                        _("Write failed, closing control connection.\n"));
860               fd_close (csock);
861               con->csock = -1;
862               fd_close (dtsock);
863               fd_close (local_sock);
864               return err;
865             case CONSOCKERR:
866               logputs (LOG_VERBOSE, "\n");
867               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
868               fd_close (csock);
869               con->csock = -1;
870               fd_close (dtsock);
871               fd_close (local_sock);
872               return err;
873             case FTPSYSERR:
874               logputs (LOG_VERBOSE, "\n");
875               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
876                          strerror (errno));
877               fd_close (dtsock);
878               return err;
879             case FTPPORTERR:
880               logputs (LOG_VERBOSE, "\n");
881               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
882               fd_close (csock);
883               con->csock = -1;
884               fd_close (dtsock);
885               fd_close (local_sock);
886               return err;
887             case FTPOK:
888               break;
889             default:
890               abort ();
891             } /* port switch */
892           if (!opt.server_response)
893             logputs (LOG_VERBOSE, _("done.    "));
894         } /* dtsock == -1 */
895     } /* cmd & (DO_LIST | DO_RETR) */
896
897   /* Restart if needed.  */
898   if (restval && (cmd & DO_RETR))
899     {
900       if (!opt.server_response)
901         logprintf (LOG_VERBOSE, "==> REST %s ... ",
902                    number_to_static_string (restval));
903       err = ftp_rest (csock, restval);
904
905       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
906       switch (err)
907         {
908         case FTPRERR:
909           logputs (LOG_VERBOSE, "\n");
910           logputs (LOG_NOTQUIET, _("\
911 Error in server response, closing control connection.\n"));
912           fd_close (csock);
913           con->csock = -1;
914           fd_close (dtsock);
915           fd_close (local_sock);
916           return err;
917         case WRITEFAILED:
918           logputs (LOG_VERBOSE, "\n");
919           logputs (LOG_NOTQUIET,
920                    _("Write failed, closing control connection.\n"));
921           fd_close (csock);
922           con->csock = -1;
923           fd_close (dtsock);
924           fd_close (local_sock);
925           return err;
926         case FTPRESTFAIL:
927           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
928           rest_failed = true;
929           break;
930         case FTPOK:
931           break;
932         default:
933           abort ();
934         }
935       if (err != FTPRESTFAIL && !opt.server_response)
936         logputs (LOG_VERBOSE, _("done.    "));
937     } /* restval && cmd & DO_RETR */
938
939   if (cmd & DO_RETR)
940     {
941       /* If we're in spider mode, don't really retrieve anything except
942          the directory listing and verify whether the given "file" exists.  */
943       if (opt.spider)
944         {
945           bool exists = false;
946           uerr_t res;
947           struct fileinfo *f;
948           res = ftp_get_listing (u, con, &f);
949           /* Set the DO_RETR command flag again, because it gets unset when
950              calling ftp_get_listing() and would otherwise cause an assertion
951              failure earlier on when this function gets repeatedly called
952              (e.g., when recursing).  */
953           con->cmd |= DO_RETR;
954           if (res == RETROK)
955             {
956               while (f)
957                 {
958                   if (!strcmp (f->name, u->file))
959                     {
960                       exists = true;
961                       break;
962                     }
963                   f = f->next;
964                 }
965               if (exists)
966                 {
967                   logputs (LOG_VERBOSE, "\n");
968                   logprintf (LOG_NOTQUIET, _("File %s exists.\n"),
969                              quote (u->file));
970                 }
971               else
972                 {
973                   logputs (LOG_VERBOSE, "\n");
974                   logprintf (LOG_NOTQUIET, _("No such file %s.\n"),
975                              quote (u->file));
976                 }
977             }
978           fd_close (csock);
979           con->csock = -1;
980           fd_close (dtsock);
981           fd_close (local_sock);
982           return RETRFINISHED;
983         }
984
985       if (opt.verbose)
986         {
987           if (!opt.server_response)
988             {
989               if (restval)
990                 logputs (LOG_VERBOSE, "\n");
991               logprintf (LOG_VERBOSE, "==> RETR %s ... ",
992                          quotearg_style (escape_quoting_style, u->file));
993             }
994         }
995
996       err = ftp_retr (csock, u->file);
997       /* FTPRERR, WRITEFAILED, FTPNSFOD */
998       switch (err)
999         {
1000         case FTPRERR:
1001           logputs (LOG_VERBOSE, "\n");
1002           logputs (LOG_NOTQUIET, _("\
1003 Error in server response, closing control connection.\n"));
1004           fd_close (csock);
1005           con->csock = -1;
1006           fd_close (dtsock);
1007           fd_close (local_sock);
1008           return err;
1009         case WRITEFAILED:
1010           logputs (LOG_VERBOSE, "\n");
1011           logputs (LOG_NOTQUIET,
1012                    _("Write failed, closing control connection.\n"));
1013           fd_close (csock);
1014           con->csock = -1;
1015           fd_close (dtsock);
1016           fd_close (local_sock);
1017           return err;
1018         case FTPNSFOD:
1019           logputs (LOG_VERBOSE, "\n");
1020           logprintf (LOG_NOTQUIET, _("No such file %s.\n\n"),
1021                      quote (u->file));
1022           fd_close (dtsock);
1023           fd_close (local_sock);
1024           return err;
1025         case FTPOK:
1026           break;
1027         default:
1028           abort ();
1029         }
1030
1031       if (!opt.server_response)
1032         logputs (LOG_VERBOSE, _("done.\n"));
1033
1034       if (! got_expected_bytes)
1035         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1036     } /* do retrieve */
1037
1038   if (cmd & DO_LIST)
1039     {
1040       if (!opt.server_response)
1041         logputs (LOG_VERBOSE, "==> LIST ... ");
1042       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
1043          without arguments is better than `LIST .'; confirmed by
1044          RFC959.  */
1045       err = ftp_list (csock, NULL, con->rs);
1046       /* FTPRERR, WRITEFAILED */
1047       switch (err)
1048         {
1049         case FTPRERR:
1050           logputs (LOG_VERBOSE, "\n");
1051           logputs (LOG_NOTQUIET, _("\
1052 Error in server response, closing control connection.\n"));
1053           fd_close (csock);
1054           con->csock = -1;
1055           fd_close (dtsock);
1056           fd_close (local_sock);
1057           return err;
1058         case WRITEFAILED:
1059           logputs (LOG_VERBOSE, "\n");
1060           logputs (LOG_NOTQUIET,
1061                    _("Write failed, closing control connection.\n"));
1062           fd_close (csock);
1063           con->csock = -1;
1064           fd_close (dtsock);
1065           fd_close (local_sock);
1066           return err;
1067         case FTPNSFOD:
1068           logputs (LOG_VERBOSE, "\n");
1069           logprintf (LOG_NOTQUIET, _("No such file or directory %s.\n\n"),
1070                      quote ("."));
1071           fd_close (dtsock);
1072           fd_close (local_sock);
1073           return err;
1074         case FTPOK:
1075           break;
1076         default:
1077           abort ();
1078         }
1079       if (!opt.server_response)
1080         logputs (LOG_VERBOSE, _("done.\n"));
1081
1082       if (! got_expected_bytes)
1083         expected_bytes = ftp_expected_bytes (ftp_last_respline);
1084     } /* cmd & DO_LIST */
1085
1086   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
1087     return RETRFINISHED;
1088
1089   /* Some FTP servers return the total length of file after REST
1090      command, others just return the remaining size. */
1091   if (passed_expected_bytes && restval && expected_bytes
1092       && (expected_bytes == passed_expected_bytes - restval))
1093     {
1094       DEBUGP (("Lying FTP server found, adjusting.\n"));
1095       expected_bytes = passed_expected_bytes;
1096     }
1097
1098   /* If no transmission was required, then everything is OK.  */
1099   if (!pasv_mode_open)  /* we are not using pasive mode so we need
1100                               to accept */
1101     {
1102       /* Wait for the server to connect to the address we're waiting
1103          at.  */
1104       dtsock = accept_connection (local_sock);
1105       if (dtsock < 0)
1106         {
1107           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
1108           return CONERROR;
1109         }
1110     }
1111
1112   /* Open the file -- if output_stream is set, use it instead.  */
1113
1114   /* 2005-04-17 SMS.
1115      Note that having the output_stream ("-O") file opened in main()
1116      (main.c) rather limits the ability in VMS to open the file
1117      differently for ASCII versus binary FTP here.  (Of course, doing it
1118      there allows a open failure to be detected immediately, without first
1119      connecting to the server.)
1120   */
1121   if (!output_stream || con->cmd & DO_LIST)
1122     {
1123 /* On VMS, alter the name as required. */
1124 #ifdef __VMS
1125       char *targ;
1126
1127       targ = ods_conform (con->target);
1128       if (targ != con->target)
1129         {
1130           xfree (con->target);
1131           con->target = targ;
1132         }
1133 #endif /* def __VMS */
1134
1135       mkalldirs (con->target);
1136       if (opt.backups)
1137         rotate_backups (con->target);
1138
1139 /* 2005-04-15 SMS.
1140    For VMS, define common fopen() optional arguments, and a handy macro
1141    for use as a variable "binary" flag.
1142    Elsewhere, define a constant "binary" flag.
1143    Isn't it nice to have distinct text and binary file types?
1144 */
1145 # define BIN_TYPE_TRANSFER (type_char != 'A')
1146 #ifdef __VMS
1147 # define FOPEN_OPT_ARGS "fop=sqo", "acc", acc_cb, &open_id
1148 # define FOPEN_OPT_ARGS_BIN "ctx=bin,stm", "rfm=fix", "mrs=512" FOPEN_OPT_ARGS
1149 # define BIN_TYPE_FILE (BIN_TYPE_TRANSFER && (opt.ftp_stmlf == 0))
1150 #else /* def __VMS */
1151 # define BIN_TYPE_FILE 1
1152 #endif /* def __VMS [else] */
1153
1154       if (restval && !(con->cmd & DO_LIST))
1155         {
1156 #ifdef __VMS
1157           int open_id;
1158
1159           if (BIN_TYPE_FILE)
1160             {
1161               open_id = 3;
1162               fp = fopen (con->target, "ab", FOPEN_OPT_ARGS_BIN);
1163             }
1164           else
1165             {
1166               open_id = 4;
1167               fp = fopen (con->target, "a", FOPEN_OPT_ARGS);
1168             }
1169 #else /* def __VMS */
1170           fp = fopen (con->target, "ab");
1171 #endif /* def __VMS [else] */
1172         }
1173       else if (opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct
1174                || opt.output_document || count > 0)
1175         {         
1176           if (opt.unlink && file_exists_p (con->target))
1177             {
1178               int res = unlink (con->target);
1179               if (res < 0)
1180                 {
1181                   logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1182                              strerror (errno));
1183                   fd_close (csock);
1184                   con->csock = -1;
1185                   fd_close (dtsock);
1186                   fd_close (local_sock);
1187                   return UNLINKERR;
1188                 }
1189             }
1190
1191 #ifdef __VMS
1192           int open_id;
1193
1194           if (BIN_TYPE_FILE)
1195             {
1196               open_id = 5;
1197               fp = fopen (con->target, "wb", FOPEN_OPT_ARGS_BIN);
1198             }
1199           else
1200             {
1201               open_id = 6;
1202               fp = fopen (con->target, "w", FOPEN_OPT_ARGS);
1203             }
1204 #else /* def __VMS */
1205           fp = fopen (con->target, "wb");
1206 #endif /* def __VMS [else] */
1207         }
1208       else
1209         {
1210           fp = fopen_excl (con->target, true);
1211           if (!fp && errno == EEXIST)
1212             {
1213               /* We cannot just invent a new name and use it (which is
1214                  what functions like unique_create typically do)
1215                  because we told the user we'd use this name.
1216                  Instead, return and retry the download.  */
1217               logprintf (LOG_NOTQUIET, _("%s has sprung into existence.\n"),
1218                          con->target);
1219               fd_close (csock);
1220               con->csock = -1;
1221               fd_close (dtsock);
1222               fd_close (local_sock);
1223               return FOPEN_EXCL_ERR;
1224             }
1225         }
1226       if (!fp)
1227         {
1228           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
1229           fd_close (csock);
1230           con->csock = -1;
1231           fd_close (dtsock);
1232           fd_close (local_sock);
1233           return FOPENERR;
1234         }
1235     }
1236   else
1237     fp = output_stream;
1238
1239   if (passed_expected_bytes)
1240     {
1241       print_length (passed_expected_bytes, restval, true);
1242       expected_bytes = passed_expected_bytes;
1243         /* for fd_read_body's progress bar */
1244     }
1245   else if (expected_bytes)
1246     print_length (expected_bytes, restval, false);
1247
1248   /* Get the contents of the document.  */
1249   flags = 0;
1250   if (restval && rest_failed)
1251     flags |= rb_skip_startpos;
1252   rd_size = 0;
1253   res = fd_read_body (dtsock, fp,
1254                       expected_bytes ? expected_bytes - restval : 0,
1255                       restval, &rd_size, qtyread, &con->dltime, flags);
1256
1257   tms = datetime_str (time (NULL));
1258   tmrate = retr_rate (rd_size, con->dltime);
1259   total_download_time += con->dltime;
1260
1261   fd_close (local_sock);
1262   /* Close the local file.  */
1263   if (!output_stream || con->cmd & DO_LIST)
1264     fclose (fp);
1265
1266   /* If fd_read_body couldn't write to fp, bail out.  */
1267   if (res == -2)
1268     {
1269       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1270                  con->target, strerror (errno));
1271       fd_close (csock);
1272       con->csock = -1;
1273       fd_close (dtsock);
1274       return FWRITEERR;
1275     }
1276   else if (res == -1)
1277     {
1278       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1279                  tms, tmrate, fd_errstr (dtsock));
1280       if (opt.server_response)
1281         logputs (LOG_ALWAYS, "\n");
1282     }
1283   fd_close (dtsock);
1284
1285   /* Get the server to tell us if everything is retrieved.  */
1286   err = ftp_response (csock, &respline);
1287   if (err != FTPOK)
1288     {
1289       /* The control connection is decidedly closed.  Print the time
1290          only if it hasn't already been printed.  */
1291       if (res != -1)
1292         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1293       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1294       /* If there is an error on the control connection, close it, but
1295          return FTPRETRINT, since there is a possibility that the
1296          whole file was retrieved nevertheless (but that is for
1297          ftp_loop_internal to decide).  */
1298       fd_close (csock);
1299       con->csock = -1;
1300       return FTPRETRINT;
1301     } /* err != FTPOK */
1302   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1303      close socket, since the control connection is still alive.  If
1304      there is something wrong with the control connection, it will
1305      become apparent later.  */
1306   if (*respline != '2')
1307     {
1308       xfree (respline);
1309       if (res != -1)
1310         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1311       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1312       return FTPRETRINT;
1313     }
1314   xfree (respline);
1315
1316   if (res == -1)
1317     {
1318       /* What now?  The data connection was erroneous, whereas the
1319          response says everything is OK.  We shall play it safe.  */
1320       return FTPRETRINT;
1321     }
1322
1323   if (!(cmd & LEAVE_PENDING))
1324     {
1325       /* Closing the socket is faster than sending 'QUIT' and the
1326          effect is the same.  */
1327       fd_close (csock);
1328       con->csock = -1;
1329     }
1330   /* If it was a listing, and opt.server_response is true,
1331      print it out.  */
1332   if (opt.server_response && (con->cmd & DO_LIST))
1333     {
1334 /* 2005-02-25 SMS.
1335    Much of this work may already have been done, but repeating it should
1336    do no damage beyond wasting time.
1337 */
1338 /* On VMS, alter the name as required. */
1339 #ifdef __VMS
1340       char *targ;
1341
1342       targ = ods_conform( con->target);
1343       if (targ != con->target)
1344         {
1345           xfree( con->target);
1346           con->target = targ;
1347         }
1348 #endif /* def __VMS */
1349
1350       mkalldirs (con->target);
1351       fp = fopen (con->target, "r");
1352       if (!fp)
1353         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1354       else
1355         {
1356           char *line;
1357           /* The lines are being read with read_whole_line because of
1358              no-buffering on opt.lfile.  */
1359           while ((line = read_whole_line (fp)) != NULL)
1360             {
1361               char *p = strchr (line, '\0');
1362               while (p > line && (p[-1] == '\n' || p[-1] == '\r'))
1363                 *--p = '\0';
1364               logprintf (LOG_ALWAYS, "%s\n",
1365                          quotearg_style (escape_quoting_style, line));
1366               xfree (line);
1367             }
1368           fclose (fp);
1369         }
1370     } /* con->cmd & DO_LIST && server_response */
1371
1372   return RETRFINISHED;
1373 }
1374
1375 /* A one-file FTP loop.  This is the part where FTP retrieval is
1376    retried, and retried, and retried, and...
1377
1378    This loop either gets commands from con, or (if ON_YOUR_OWN is
1379    set), makes them up to retrieve the file given by the URL.  */
1380 static uerr_t
1381 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con, char **local_file)
1382 {
1383   int count, orig_lp;
1384   wgint restval, len = 0, qtyread = 0;
1385   char *tms, *locf;
1386   const char *tmrate = NULL;
1387   uerr_t err;
1388   struct_stat st;
1389
1390   /* Get the target, and set the name for the message accordingly. */
1391   if ((f == NULL) && (con->target))
1392     {
1393       /* Explicit file (like ".listing"). */
1394       locf = con->target;
1395     }
1396   else
1397     {
1398       /* URL-derived file.  Consider "-O file" name. */
1399       con->target = url_file_name (u, NULL);
1400       if (!opt.output_document)
1401         locf = con->target;
1402       else
1403         locf = opt.output_document;
1404     }
1405
1406   /* If the output_document was given, then this check was already done and
1407      the file didn't exist. Hence the !opt.output_document */
1408   if (opt.noclobber && !opt.output_document && file_exists_p (con->target))
1409     {
1410       logprintf (LOG_VERBOSE,
1411                  _("File %s already there; not retrieving.\n"), quote (con->target));
1412       /* If the file is there, we suppose it's retrieved OK.  */
1413       return RETROK;
1414     }
1415
1416   /* Remove it if it's a link.  */
1417   remove_link (con->target);
1418
1419   count = 0;
1420
1421   if (con->st & ON_YOUR_OWN)
1422     con->st = ON_YOUR_OWN;
1423
1424   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1425
1426   /* THE loop.  */
1427   do
1428     {
1429       /* Increment the pass counter.  */
1430       ++count;
1431       sleep_between_retrievals (count);
1432       if (con->st & ON_YOUR_OWN)
1433         {
1434           con->cmd = 0;
1435           con->cmd |= (DO_RETR | LEAVE_PENDING);
1436           if (con->csock != -1)
1437             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1438           else
1439             con->cmd |= (DO_LOGIN | DO_CWD);
1440         }
1441       else /* not on your own */
1442         {
1443           if (con->csock != -1)
1444             con->cmd &= ~DO_LOGIN;
1445           else
1446             con->cmd |= DO_LOGIN;
1447           if (con->st & DONE_CWD)
1448             con->cmd &= ~DO_CWD;
1449           else
1450             con->cmd |= DO_CWD;
1451         }
1452
1453       /* Decide whether or not to restart.  */
1454       if (con->cmd & DO_LIST)
1455         restval = 0;
1456       else if (opt.always_rest
1457           && stat (locf, &st) == 0
1458           && S_ISREG (st.st_mode))
1459         /* When -c is used, continue from on-disk size.  (Can't use
1460            hstat.len even if count>1 because we don't want a failed
1461            first attempt to clobber existing data.)  */
1462         restval = st.st_size;
1463       else if (count > 1)
1464         restval = qtyread;          /* start where the previous run left off */
1465       else
1466         restval = 0;
1467
1468       /* Get the current time string.  */
1469       tms = datetime_str (time (NULL));
1470       /* Print fetch message, if opt.verbose.  */
1471       if (opt.verbose)
1472         {
1473           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1474           char tmp[256];
1475           strcpy (tmp, "        ");
1476           if (count > 1)
1477             sprintf (tmp, _("(try:%2d)"), count);
1478           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => %s\n",
1479                      tms, hurl, tmp, quote (locf));
1480 #ifdef WINDOWS
1481           ws_changetitle (hurl);
1482 #endif
1483           xfree (hurl);
1484         }
1485       /* Send getftp the proper length, if fileinfo was provided.  */
1486       if (f && f->type != FT_SYMLINK)
1487         len = f->size;
1488       else
1489         len = 0;
1490       err = getftp (u, len, &qtyread, restval, con, count);
1491
1492       if (con->csock == -1)
1493         con->st &= ~DONE_CWD;
1494       else
1495         con->st |= DONE_CWD;
1496
1497       switch (err)
1498         {
1499         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1500         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1501         case UNLINKERR:
1502           /* Fatal errors, give up.  */
1503           return err;
1504         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1505         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1506         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1507         case FOPEN_EXCL_ERR:
1508           printwhat (count, opt.ntry);
1509           /* non-fatal errors */
1510           if (err == FOPEN_EXCL_ERR)
1511             {
1512               /* Re-determine the file name. */
1513               xfree_null (con->target);
1514               con->target = url_file_name (u, NULL);
1515               locf = con->target;
1516             }
1517           continue;
1518         case FTPRETRINT:
1519           /* If the control connection was closed, the retrieval
1520              will be considered OK if f->size == len.  */
1521           if (!f || qtyread != f->size)
1522             {
1523               printwhat (count, opt.ntry);
1524               continue;
1525             }
1526           break;
1527         case RETRFINISHED:
1528           /* Great!  */
1529           break;
1530         default:
1531           /* Not as great.  */
1532           abort ();
1533         }
1534       tms = datetime_str (time (NULL));
1535       if (!opt.spider)
1536         tmrate = retr_rate (qtyread - restval, con->dltime);
1537
1538       /* If we get out of the switch above without continue'ing, we've
1539          successfully downloaded a file.  Remember this fact. */
1540       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1541
1542       if (con->st & ON_YOUR_OWN)
1543         {
1544           fd_close (con->csock);
1545           con->csock = -1;
1546         }
1547       if (!opt.spider)
1548         {
1549           bool write_to_stdout = (opt.output_document && HYPHENP (opt.output_document));
1550
1551           logprintf (LOG_VERBOSE,
1552                      write_to_stdout
1553                      ? _("%s (%s) - written to stdout %s[%s]\n\n")
1554                      : _("%s (%s) - %s saved [%s]\n\n"),
1555                      tms, tmrate,
1556                      write_to_stdout ? "" : quote (locf),
1557                      number_to_static_string (qtyread));
1558         }
1559       if (!opt.verbose && !opt.quiet)
1560         {
1561           /* Need to hide the password from the URL.  The `if' is here
1562              so that we don't do the needless allocation every
1563              time. */
1564           char *hurl = url_string (u, URL_AUTH_HIDE_PASSWD);
1565           logprintf (LOG_NONVERBOSE, "%s URL: %s [%s] -> \"%s\" [%d]\n",
1566                      tms, hurl, number_to_static_string (qtyread), locf, count);
1567           xfree (hurl);
1568         }
1569
1570       if ((con->cmd & DO_LIST))
1571         /* This is a directory listing file. */
1572         {
1573           if (!opt.remove_listing)
1574             /* --dont-remove-listing was specified, so do count this towards the
1575                number of bytes and files downloaded. */
1576             {
1577               total_downloaded_bytes += qtyread;
1578               numurls++;
1579             }
1580
1581           /* Deletion of listing files is not controlled by --delete-after, but
1582              by the more specific option --dont-remove-listing, and the code
1583              to do this deletion is in another function. */
1584         }
1585       else if (!opt.spider)
1586         /* This is not a directory listing file. */
1587         {
1588           /* Unlike directory listing files, don't pretend normal files weren't
1589              downloaded if they're going to be deleted.  People seeding proxies,
1590              for instance, may want to know how many bytes and files they've
1591              downloaded through it. */
1592           total_downloaded_bytes += qtyread;
1593           numurls++;
1594
1595           if (opt.delete_after && !input_file_url (opt.input_filename))
1596             {
1597               DEBUGP (("\
1598 Removing file due to --delete-after in ftp_loop_internal():\n"));
1599               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1600               if (unlink (locf))
1601                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1602             }
1603         }
1604
1605       /* Restore the original leave-pendingness.  */
1606       if (orig_lp)
1607         con->cmd |= LEAVE_PENDING;
1608       else
1609         con->cmd &= ~LEAVE_PENDING;
1610
1611       if (local_file)
1612         *local_file = xstrdup (locf);
1613
1614       return RETROK;
1615     } while (!opt.ntry || (count < opt.ntry));
1616
1617   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1618     {
1619       fd_close (con->csock);
1620       con->csock = -1;
1621     }
1622   return TRYLIMEXC;
1623 }
1624
1625 /* Return the directory listing in a reusable format.  The directory
1626    is specifed in u->dir.  */
1627 static uerr_t
1628 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1629 {
1630   uerr_t err;
1631   char *uf;                     /* url file name */
1632   char *lf;                     /* list file name */
1633   char *old_target = con->target;
1634
1635   con->st &= ~ON_YOUR_OWN;
1636   con->cmd |= (DO_LIST | LEAVE_PENDING);
1637   con->cmd &= ~DO_RETR;
1638
1639   /* Find the listing file name.  We do it by taking the file name of
1640      the URL and replacing the last component with the listing file
1641      name.  */
1642   uf = url_file_name (u, NULL);
1643   lf = file_merge (uf, LIST_FILENAME);
1644   xfree (uf);
1645   DEBUGP ((_("Using %s as listing tmp file.\n"), quote (lf)));
1646
1647   con->target = xstrdup (lf);
1648   xfree (lf);
1649   err = ftp_loop_internal (u, NULL, con, NULL);
1650   lf = xstrdup (con->target);
1651   xfree (con->target);
1652   con->target = old_target;
1653
1654   if (err == RETROK)
1655     {
1656       *f = ftp_parse_ls (lf, con->rs);
1657       if (opt.remove_listing)
1658         {
1659           if (unlink (lf))
1660             logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1661           else
1662             logprintf (LOG_VERBOSE, _("Removed %s.\n"), quote (lf));
1663         }
1664     }
1665   else
1666     *f = NULL;
1667   xfree (lf);
1668   con->cmd &= ~DO_LIST;
1669   return err;
1670 }
1671
1672 static uerr_t ftp_retrieve_dirs (struct url *, struct fileinfo *, ccon *);
1673 static uerr_t ftp_retrieve_glob (struct url *, ccon *, int);
1674 static struct fileinfo *delelement (struct fileinfo *, struct fileinfo **);
1675 static void freefileinfo (struct fileinfo *f);
1676
1677 /* Retrieve a list of files given in struct fileinfo linked list.  If
1678    a file is a symbolic link, do not retrieve it, but rather try to
1679    set up a similar link on the local disk, if the symlinks are
1680    supported.
1681
1682    If opt.recursive is set, after all files have been retrieved,
1683    ftp_retrieve_dirs will be called to retrieve the directories.  */
1684 static uerr_t
1685 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1686 {
1687   static int depth = 0;
1688   uerr_t err;
1689   struct fileinfo *orig;
1690   wgint local_size;
1691   time_t tml;
1692   bool dlthis; /* Download this (file). */
1693   const char *actual_target = NULL;
1694
1695   /* Increase the depth.  */
1696   ++depth;
1697   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1698     {
1699       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1700                depth, opt.reclevel));
1701       --depth;
1702       return RECLEVELEXC;
1703     }
1704
1705   assert (f != NULL);
1706   orig = f;
1707
1708   con->st &= ~ON_YOUR_OWN;
1709   if (!(con->st & DONE_CWD))
1710     con->cmd |= DO_CWD;
1711   else
1712     con->cmd &= ~DO_CWD;
1713   con->cmd |= (DO_RETR | LEAVE_PENDING);
1714
1715   if (con->csock < 0)
1716     con->cmd |= DO_LOGIN;
1717   else
1718     con->cmd &= ~DO_LOGIN;
1719
1720   err = RETROK;                 /* in case it's not used */
1721
1722   while (f)
1723     {
1724       char *old_target, *ofile;
1725
1726       if (opt.quota && total_downloaded_bytes > opt.quota)
1727         {
1728           --depth;
1729           return QUOTEXC;
1730         }
1731       old_target = con->target;
1732
1733       ofile = xstrdup (u->file);
1734       url_set_file (u, f->name);
1735
1736       con->target = url_file_name (u, NULL);
1737       err = RETROK;
1738
1739       dlthis = true;
1740       if (opt.timestamping && f->type == FT_PLAINFILE)
1741         {
1742           struct_stat st;
1743           /* If conversion of HTML files retrieved via FTP is ever implemented,
1744              we'll need to stat() <file>.orig here when -K has been specified.
1745              I'm not implementing it now since files on an FTP server are much
1746              more likely than files on an HTTP server to legitimately have a
1747              .orig suffix. */
1748           if (!stat (con->target, &st))
1749             {
1750               bool eq_size;
1751               bool cor_val;
1752               /* Else, get it from the file.  */
1753               local_size = st.st_size;
1754               tml = st.st_mtime;
1755 #ifdef WINDOWS
1756               /* Modification time granularity is 2 seconds for Windows, so
1757                  increase local time by 1 second for later comparison. */
1758               tml++;
1759 #endif
1760               /* Compare file sizes only for servers that tell us correct
1761                  values. Assume sizes being equal for servers that lie
1762                  about file size.  */
1763               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1764               eq_size = cor_val ? (local_size == f->size) : true;
1765               if (f->tstamp <= tml && eq_size)
1766                 {
1767                   /* Remote file is older, file sizes can be compared and
1768                      are both equal. */
1769                   logprintf (LOG_VERBOSE, _("\
1770 Remote file no newer than local file %s -- not retrieving.\n"), quote (con->target));
1771                   dlthis = false;
1772                 }
1773               else if (eq_size)
1774                 {
1775                   /* Remote file is newer or sizes cannot be matched */
1776                   logprintf (LOG_VERBOSE, _("\
1777 Remote file is newer than local file %s -- retrieving.\n\n"),
1778                              quote (con->target));
1779                 }
1780               else
1781                 {
1782                   /* Sizes do not match */
1783                   logprintf (LOG_VERBOSE, _("\
1784 The sizes do not match (local %s) -- retrieving.\n\n"),
1785                              number_to_static_string (local_size));
1786                 }
1787             }
1788         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1789       switch (f->type)
1790         {
1791         case FT_SYMLINK:
1792           /* If opt.retr_symlinks is defined, we treat symlinks as
1793              if they were normal files.  There is currently no way
1794              to distinguish whether they might be directories, and
1795              follow them.  */
1796           if (!opt.retr_symlinks)
1797             {
1798 #ifdef HAVE_SYMLINK
1799               if (!f->linkto)
1800                 logputs (LOG_NOTQUIET,
1801                          _("Invalid name of the symlink, skipping.\n"));
1802               else
1803                 {
1804                   struct_stat st;
1805                   /* Check whether we already have the correct
1806                      symbolic link.  */
1807                   int rc = lstat (con->target, &st);
1808                   if (rc == 0)
1809                     {
1810                       size_t len = strlen (f->linkto) + 1;
1811                       if (S_ISLNK (st.st_mode))
1812                         {
1813                           char *link_target = (char *)alloca (len);
1814                           size_t n = readlink (con->target, link_target, len);
1815                           if ((n == len - 1)
1816                               && (memcmp (link_target, f->linkto, n) == 0))
1817                             {
1818                               logprintf (LOG_VERBOSE, _("\
1819 Already have correct symlink %s -> %s\n\n"),
1820                                          quote (con->target),
1821                                          quote (f->linkto));
1822                               dlthis = false;
1823                               break;
1824                             }
1825                         }
1826                     }
1827                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1828                              quote (con->target), quote (f->linkto));
1829                   /* Unlink before creating symlink!  */
1830                   unlink (con->target);
1831                   if (symlink (f->linkto, con->target) == -1)
1832                     logprintf (LOG_NOTQUIET, "symlink: %s\n", strerror (errno));
1833                   logputs (LOG_VERBOSE, "\n");
1834                 } /* have f->linkto */
1835 #else  /* not HAVE_SYMLINK */
1836               logprintf (LOG_NOTQUIET,
1837                          _("Symlinks not supported, skipping symlink %s.\n"),
1838                          quote (con->target));
1839 #endif /* not HAVE_SYMLINK */
1840             }
1841           else                /* opt.retr_symlinks */
1842             {
1843               if (dlthis)
1844                 err = ftp_loop_internal (u, f, con, NULL);
1845             } /* opt.retr_symlinks */
1846           break;
1847         case FT_DIRECTORY:
1848           if (!opt.recursive)
1849             logprintf (LOG_NOTQUIET, _("Skipping directory %s.\n"),
1850                        quote (f->name));
1851           break;
1852         case FT_PLAINFILE:
1853           /* Call the retrieve loop.  */
1854           if (dlthis)
1855             err = ftp_loop_internal (u, f, con, NULL);
1856           break;
1857         case FT_UNKNOWN:
1858           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1859                      quote (f->name));
1860           break;
1861         }       /* switch */
1862
1863
1864       /* 2004-12-15 SMS.
1865        * Set permissions _before_ setting the times, as setting the
1866        * permissions changes the modified-time, at least on VMS.
1867        * Also, use the opt.output_document name here, too, as
1868        * appropriate.  (Do the test once, and save the result.)
1869        */
1870
1871       set_local_file (&actual_target, con->target);
1872
1873       /* If downloading a plain file, set valid (non-zero) permissions. */
1874       if (dlthis && (actual_target != NULL) && (f->type == FT_PLAINFILE))
1875         {
1876           if (f->perms)
1877             chmod (actual_target, f->perms);
1878           else
1879             DEBUGP (("Unrecognized permissions for %s.\n", actual_target));
1880         }
1881
1882       /* Set the time-stamp information to the local file.  Symlinks
1883          are not to be stamped because it sets the stamp on the
1884          original.  :( */
1885       if (actual_target != NULL)
1886         {
1887           if (opt.useservertimestamps
1888               && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1889               && f->tstamp != -1
1890               && dlthis
1891               && file_exists_p (con->target))
1892             {
1893               touch (actual_target, f->tstamp);
1894             }
1895           else if (f->tstamp == -1)
1896             logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"),
1897                        actual_target);
1898         }
1899
1900       xfree (con->target);
1901       con->target = old_target;
1902
1903       url_set_file (u, ofile);
1904       xfree (ofile);
1905
1906       /* Break on fatals.  */
1907       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1908         break;
1909       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1910       f = f->next;
1911     }
1912
1913   /* We do not want to call ftp_retrieve_dirs here */
1914   if (opt.recursive &&
1915       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1916     err = ftp_retrieve_dirs (u, orig, con);
1917   else if (opt.recursive)
1918     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1919              depth, opt.reclevel));
1920   --depth;
1921   return err;
1922 }
1923
1924 /* Retrieve the directories given in a file list.  This function works
1925    by simply going through the linked list and calling
1926    ftp_retrieve_glob on each directory entry.  The function knows
1927    about excluded directories.  */
1928 static uerr_t
1929 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1930 {
1931   char *container = NULL;
1932   int container_size = 0;
1933
1934   for (; f; f = f->next)
1935     {
1936       int size;
1937       char *odir, *newdir;
1938
1939       if (opt.quota && total_downloaded_bytes > opt.quota)
1940         break;
1941       if (f->type != FT_DIRECTORY)
1942         continue;
1943
1944       /* Allocate u->dir off stack, but reallocate only if a larger
1945          string is needed.  It's a pity there's no "realloca" for an
1946          item on the bottom of the stack.  */
1947       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1948       if (size > container_size)
1949         container = (char *)alloca (size);
1950       newdir = container;
1951
1952       odir = u->dir;
1953       if (*odir == '\0'
1954           || (*odir == '/' && *(odir + 1) == '\0'))
1955         /* If ODIR is empty or just "/", simply append f->name to
1956            ODIR.  (In the former case, to preserve u->dir being
1957            relative; in the latter case, to avoid double slash.)  */
1958         sprintf (newdir, "%s%s", odir, f->name);
1959       else
1960         /* Else, use a separator. */
1961         sprintf (newdir, "%s/%s", odir, f->name);
1962
1963       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1964       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1965                odir, f->name, newdir));
1966       if (!accdir (newdir))
1967         {
1968           logprintf (LOG_VERBOSE, _("\
1969 Not descending to %s as it is excluded/not-included.\n"),
1970                      quote (newdir));
1971           continue;
1972         }
1973
1974       con->st &= ~DONE_CWD;
1975
1976       odir = xstrdup (u->dir);  /* because url_set_dir will free
1977                                    u->dir. */
1978       url_set_dir (u, newdir);
1979       ftp_retrieve_glob (u, con, GLOB_GETALL);
1980       url_set_dir (u, odir);
1981       xfree (odir);
1982
1983       /* Set the time-stamp?  */
1984     }
1985
1986   if (opt.quota && total_downloaded_bytes > opt.quota)
1987     return QUOTEXC;
1988   else
1989     return RETROK;
1990 }
1991
1992 /* Return true if S has a leading '/'  or contains '../' */
1993 static bool
1994 has_insecure_name_p (const char *s)
1995 {
1996   if (*s == '/')
1997     return true;
1998
1999   if (strstr (s, "../") != 0)
2000     return true;
2001
2002   return false;
2003 }
2004
2005 /* A near-top-level function to retrieve the files in a directory.
2006    The function calls ftp_get_listing, to get a linked list of files.
2007    Then it weeds out the file names that do not match the pattern.
2008    ftp_retrieve_list is called with this updated list as an argument.
2009
2010    If the argument ACTION is GLOB_GETONE, just download the file (but
2011    first get the listing, so that the time-stamp is heeded); if it's
2012    GLOB_GLOBALL, use globbing; if it's GLOB_GETALL, download the whole
2013    directory.  */
2014 static uerr_t
2015 ftp_retrieve_glob (struct url *u, ccon *con, int action)
2016 {
2017   struct fileinfo *f, *start;
2018   uerr_t res;
2019
2020   con->cmd |= LEAVE_PENDING;
2021
2022   res = ftp_get_listing (u, con, &start);
2023   if (res != RETROK)
2024     return res;
2025   /* First: weed out that do not conform the global rules given in
2026      opt.accepts and opt.rejects.  */
2027   if (opt.accepts || opt.rejects)
2028     {
2029       f = start;
2030       while (f)
2031         {
2032           if (f->type != FT_DIRECTORY && !acceptable (f->name))
2033             {
2034               logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2035                          quote (f->name));
2036               f = delelement (f, &start);
2037             }
2038           else
2039             f = f->next;
2040         }
2041     }
2042   /* Remove all files with possible harmful names */
2043   f = start;
2044   while (f)
2045     {
2046       if (has_insecure_name_p (f->name))
2047         {
2048           logprintf (LOG_VERBOSE, _("Rejecting %s.\n"),
2049                      quote (f->name));
2050           f = delelement (f, &start);
2051         }
2052       else
2053         f = f->next;
2054     }
2055   /* Now weed out the files that do not match our globbing pattern.
2056      If we are dealing with a globbing pattern, that is.  */
2057   if (*u->file)
2058     {
2059       if (action == GLOB_GLOBALL)
2060         {
2061           int (*matcher) (const char *, const char *, int)
2062             = opt.ignore_case ? fnmatch_nocase : fnmatch;
2063           int matchres = 0;
2064
2065           f = start;
2066           while (f)
2067             {
2068               matchres = matcher (u->file, f->name, 0);
2069               if (matchres == -1)
2070                 {
2071                   logprintf (LOG_NOTQUIET, _("Error matching %s against %s: %s\n"),
2072                              u->file, quotearg_style (escape_quoting_style, f->name),
2073                              strerror (errno));
2074                   break;
2075                 }
2076               if (matchres == FNM_NOMATCH)
2077                 f = delelement (f, &start); /* delete the element from the list */
2078               else
2079                 f = f->next;        /* leave the element in the list */
2080             }
2081           if (matchres == -1)
2082             {
2083               freefileinfo (start);
2084               return RETRBADPATTERN;
2085             }
2086         }
2087       else if (action == GLOB_GETONE)
2088         {
2089 #ifdef __VMS
2090           /* 2009-09-09 SMS.
2091            * Odd-ball compiler ("HP C V7.3-009 on OpenVMS Alpha V7.3-2")
2092            * bug causes spurious %CC-E-BADCONDIT complaint with this
2093            * "?:" statement.  (Different linkage attributes for strcmp()
2094            * and strcasecmp().)  Converting to "if" changes the
2095            * complaint to %CC-W-PTRMISMATCH on "cmp = strcmp;".  Adding
2096            * the senseless type cast clears the complaint, and looks
2097            * harmless.
2098            */
2099           int (*cmp) (const char *, const char *)
2100             = opt.ignore_case ? strcasecmp : (int (*)())strcmp;
2101 #else /* def __VMS */
2102           int (*cmp) (const char *, const char *)
2103             = opt.ignore_case ? strcasecmp : strcmp;
2104 #endif /* def __VMS [else] */
2105           f = start;
2106           while (f)
2107             {
2108               if (0 != cmp(u->file, f->name))
2109                 f = delelement (f, &start);
2110               else
2111                 f = f->next;
2112             }
2113         }
2114     }
2115   if (start)
2116     {
2117       /* Just get everything.  */
2118       ftp_retrieve_list (u, start, con);
2119     }
2120   else
2121     {
2122       if (action == GLOB_GLOBALL)
2123         {
2124           /* No luck.  */
2125           /* #### This message SUCKS.  We should see what was the
2126              reason that nothing was retrieved.  */
2127           logprintf (LOG_VERBOSE, _("No matches on pattern %s.\n"),
2128                      quote (u->file));
2129         }
2130       else if (action == GLOB_GETONE) /* GLOB_GETONE or GLOB_GETALL */
2131         {
2132           /* Let's try retrieving it anyway.  */
2133           con->st |= ON_YOUR_OWN;
2134           res = ftp_loop_internal (u, NULL, con, NULL);
2135           return res;
2136         }
2137
2138       /* If action == GLOB_GETALL, and the file list is empty, there's
2139          no point in trying to download anything or in complaining about
2140          it.  (An empty directory should not cause complaints.)
2141       */
2142     }
2143   freefileinfo (start);
2144   if (opt.quota && total_downloaded_bytes > opt.quota)
2145     return QUOTEXC;
2146   else
2147     /* #### Should we return `res' here?  */
2148     return RETROK;
2149 }
2150
2151 /* The wrapper that calls an appropriate routine according to contents
2152    of URL.  Inherently, its capabilities are limited on what can be
2153    encoded into a URL.  */
2154 uerr_t
2155 ftp_loop (struct url *u, char **local_file, int *dt, struct url *proxy,
2156           bool recursive, bool glob)
2157 {
2158   ccon con;                     /* FTP connection */
2159   uerr_t res;
2160
2161   *dt = 0;
2162
2163   xzero (con);
2164
2165   con.csock = -1;
2166   con.st = ON_YOUR_OWN;
2167   con.rs = ST_UNIX;
2168   con.id = NULL;
2169   con.proxy = proxy;
2170
2171   /* If the file name is empty, the user probably wants a directory
2172      index.  We'll provide one, properly HTML-ized.  Unless
2173      opt.htmlify is 0, of course.  :-) */
2174   if (!*u->file && !recursive)
2175     {
2176       struct fileinfo *f;
2177       res = ftp_get_listing (u, &con, &f);
2178
2179       if (res == RETROK)
2180         {
2181           if (opt.htmlify && !opt.spider)
2182             {
2183               char *filename = (opt.output_document
2184                                 ? xstrdup (opt.output_document)
2185                                 : (con.target ? xstrdup (con.target)
2186                                    : url_file_name (u, NULL)));
2187               res = ftp_index (filename, u, f);
2188               if (res == FTPOK && opt.verbose)
2189                 {
2190                   if (!opt.output_document)
2191                     {
2192                       struct_stat st;
2193                       wgint sz;
2194                       if (stat (filename, &st) == 0)
2195                         sz = st.st_size;
2196                       else
2197                         sz = -1;
2198                       logprintf (LOG_NOTQUIET,
2199                                  _("Wrote HTML-ized index to %s [%s].\n"),
2200                                  quote (filename), number_to_static_string (sz));
2201                     }
2202                   else
2203                     logprintf (LOG_NOTQUIET,
2204                                _("Wrote HTML-ized index to %s.\n"),
2205                                quote (filename));
2206                 }
2207               xfree (filename);
2208             }
2209           freefileinfo (f);
2210         }
2211     }
2212   else
2213     {
2214       bool ispattern = false;
2215       if (glob)
2216         {
2217           /* Treat the URL as a pattern if the file name part of the
2218              URL path contains wildcards.  (Don't check for u->file
2219              because it is unescaped and therefore doesn't leave users
2220              the option to escape literal '*' as %2A.)  */
2221           char *file_part = strrchr (u->path, '/');
2222           if (!file_part)
2223             file_part = u->path;
2224           ispattern = has_wildcards_p (file_part);
2225         }
2226       if (ispattern || recursive || opt.timestamping)
2227         {
2228           /* ftp_retrieve_glob is a catch-all function that gets called
2229              if we need globbing, time-stamping or recursion.  Its
2230              third argument is just what we really need.  */
2231           res = ftp_retrieve_glob (u, &con,
2232                                    ispattern ? GLOB_GLOBALL : GLOB_GETONE);
2233         }
2234       else
2235         res = ftp_loop_internal (u, NULL, &con, local_file);
2236     }
2237   if (res == FTPOK)
2238     res = RETROK;
2239   if (res == RETROK)
2240     *dt |= RETROKF;
2241   /* If a connection was left, quench it.  */
2242   if (con.csock != -1)
2243     fd_close (con.csock);
2244   xfree_null (con.id);
2245   con.id = NULL;
2246   xfree_null (con.target);
2247   con.target = NULL;
2248   return res;
2249 }
2250
2251 /* Delete an element from the fileinfo linked list.  Returns the
2252    address of the next element, or NULL if the list is exhausted.  It
2253    can modify the start of the list.  */
2254 static struct fileinfo *
2255 delelement (struct fileinfo *f, struct fileinfo **start)
2256 {
2257   struct fileinfo *prev = f->prev;
2258   struct fileinfo *next = f->next;
2259
2260   xfree (f->name);
2261   xfree_null (f->linkto);
2262   xfree (f);
2263
2264   if (next)
2265     next->prev = prev;
2266   if (prev)
2267     prev->next = next;
2268   else
2269     *start = next;
2270   return next;
2271 }
2272
2273 /* Free the fileinfo linked list of files.  */
2274 static void
2275 freefileinfo (struct fileinfo *f)
2276 {
2277   while (f)
2278     {
2279       struct fileinfo *next = f->next;
2280       xfree (f->name);
2281       if (f->linkto)
2282         xfree (f->linkto);
2283       xfree (f);
2284       f = next;
2285     }
2286 }