]> sjero.net Git - wget/blob - src/ftp.c
[svn] Set con->csock to -1 where rbuf_uninitialize was previously used.
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Wget.
6
7 GNU Wget is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GNU Wget is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Wget; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 In addition, as a special exception, the Free Software Foundation
22 gives permission to link the code of its release of Wget with the
23 OpenSSL project's "OpenSSL" library (or with modified versions of it
24 that use the same license as the "OpenSSL" library), and distribute
25 the linked executables.  You must obey the GNU General Public License
26 in all respects for all of the code used other than "OpenSSL".  If you
27 modify this file, you may extend this exception to your version of the
28 file, but you are not obligated to do so.  If you do not wish to do
29 so, delete this exception statement from your version.  */
30
31 #include <config.h>
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #else
38 # include <strings.h>
39 #endif
40 #ifdef HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif
43 #include <sys/types.h>
44 #include <assert.h>
45 #include <errno.h>
46
47 #include "wget.h"
48 #include "utils.h"
49 #include "url.h"
50 #include "retr.h"
51 #include "ftp.h"
52 #include "connect.h"
53 #include "host.h"
54 #include "netrc.h"
55 #include "convert.h"            /* for downloaded_file */
56 #include "recur.h"              /* for INFINITE_RECURSION */
57
58 #ifndef errno
59 extern int errno;
60 #endif
61
62 extern LARGE_INT total_downloaded_bytes;
63
64 /* File where the "ls -al" listing will be saved.  */
65 #define LIST_FILENAME ".listing"
66
67 extern char ftp_last_respline[];
68
69 typedef struct
70 {
71   int st;                       /* connection status */
72   int cmd;                      /* command code */
73   int csock;                    /* control connection socket */
74   double dltime;                /* time of the download in msecs */
75   enum stype rs;                /* remote system reported by ftp server */ 
76   char *id;                     /* initial directory */
77   char *target;                 /* target file name */
78   struct url *proxy;            /* FTWK-style proxy */
79 } ccon;
80
81
82 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
83    the string S, and return the number converted to long, if found, 0
84    otherwise.  */
85 static long
86 ftp_expected_bytes (const char *s)
87 {
88   long res;
89
90   while (1)
91     {
92       while (*s && *s != '(')
93         ++s;
94       if (!*s)
95         return 0;
96       for (++s; *s && ISSPACE (*s); s++);
97       if (!*s)
98         return 0;
99       if (!ISDIGIT (*s))
100         continue;
101       res = 0;
102       do
103         {
104           res = (*s - '0') + 10 * res;
105           ++s;
106         }
107       while (*s && ISDIGIT (*s));
108       if (!*s)
109         return 0;
110       while (*s && ISSPACE (*s))
111         ++s;
112       if (!*s)
113         return 0;
114       if (TOLOWER (*s) != 'b')
115         continue;
116       if (strncasecmp (s, "byte", 4))
117         continue;
118       else
119         break;
120     }
121   return res;
122 }
123
124 #ifdef ENABLE_IPV6
125 /* 
126  * This function sets up a passive data connection with the FTP server.
127  * It is merely a wrapper around ftp_epsv, ftp_lpsv and ftp_pasv.
128  */
129 static uerr_t
130 ftp_do_pasv (int csock, ip_address *addr, int *port)
131 {
132   uerr_t err;
133
134   /* We need to determine the address family and need to call
135      getpeername, so while we're at it, store the address to ADDR.
136      ftp_pasv and ftp_lpsv can simply override it.  */
137   if (!socket_ip_address (csock, addr, ENDPOINT_PEER))
138     abort ();
139
140   /* If our control connection is over IPv6, then we first try EPSV and then 
141    * LPSV if the former is not supported. If the control connection is over 
142    * IPv4, we simply issue the good old PASV request. */
143   switch (addr->type)
144     {
145     case IPV4_ADDRESS:
146       if (!opt.server_response)
147         logputs (LOG_VERBOSE, "==> PASV ... ");
148       err = ftp_pasv (csock, addr, port);
149       break;
150     case IPV6_ADDRESS:
151       if (!opt.server_response)
152         logputs (LOG_VERBOSE, "==> EPSV ... ");
153       err = ftp_epsv (csock, addr, port);
154
155       /* If EPSV is not supported try LPSV */
156       if (err == FTPNOPASV)
157         {
158           if (!opt.server_response)
159             logputs (LOG_VERBOSE, "==> LPSV ... ");
160           err = ftp_lpsv (csock, addr, port);
161         }
162       break;
163     default:
164       abort ();
165     }
166
167   return err;
168 }
169
170 /* 
171  * This function sets up an active data connection with the FTP server.
172  * It is merely a wrapper around ftp_eprt, ftp_lprt and ftp_port.
173  */
174 static uerr_t
175 ftp_do_port (int csock, int *local_sock)
176 {
177   uerr_t err;
178   ip_address cip;
179
180   if (!socket_ip_address (csock, &cip, ENDPOINT_PEER))
181     abort ();
182
183   /* If our control connection is over IPv6, then we first try EPRT and then 
184    * LPRT if the former is not supported. If the control connection is over 
185    * IPv4, we simply issue the good old PORT request. */
186   switch (cip.type)
187     {
188     case IPV4_ADDRESS:
189       if (!opt.server_response)
190         logputs (LOG_VERBOSE, "==> PORT ... ");
191       err = ftp_port (csock, local_sock);
192       break;
193     case IPV6_ADDRESS:
194       if (!opt.server_response)
195         logputs (LOG_VERBOSE, "==> EPRT ... ");
196       err = ftp_eprt (csock, local_sock);
197
198       /* If EPRT is not supported try LPRT */
199       if (err == FTPPORTERR)
200         {
201           if (!opt.server_response)
202             logputs (LOG_VERBOSE, "==> LPRT ... ");
203           err = ftp_lprt (csock, local_sock);
204         }
205       break;
206     default:
207       abort ();
208     }
209   return err;
210 }
211 #else
212
213 static uerr_t
214 ftp_do_pasv (int csock, ip_address *addr, int *port)
215 {
216   if (!opt.server_response)
217     logputs (LOG_VERBOSE, "==> PASV ... ");
218   return ftp_pasv (csock, addr, port);
219 }
220
221 static uerr_t
222 ftp_do_port (int csock, int *local_sock)
223 {
224   if (!opt.server_response)
225     logputs (LOG_VERBOSE, "==> PORT ... ");
226   return ftp_port (csock, local_sock);
227 }
228 #endif
229
230 /* Retrieves a file with denoted parameters through opening an FTP
231    connection to the server.  It always closes the data connection,
232    and closes the control connection in case of error.  */
233 static uerr_t
234 getftp (struct url *u, long *len, long restval, ccon *con)
235 {
236   int csock, dtsock, local_sock, res;
237   uerr_t err;
238   FILE *fp;
239   char *user, *passwd, *respline;
240   char *tms, *tmrate;
241   int cmd = con->cmd;
242   int pasv_mode_open = 0;
243   long expected_bytes = 0L;
244
245   assert (con != NULL);
246   assert (con->target != NULL);
247
248   /* Debug-check of the sanity of the request by making sure that LIST
249      and RETR are never both requested (since we can handle only one
250      at a time.  */
251   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
252   /* Make sure that at least *something* is requested.  */
253   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
254
255   user = u->user;
256   passwd = u->passwd;
257   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
258   user = user ? user : opt.ftp_acc;
259   passwd = passwd ? passwd : opt.ftp_pass;
260   assert (user && passwd);
261
262   dtsock = -1;
263   local_sock = -1;
264   con->dltime = 0;
265
266   if (!(cmd & DO_LOGIN))
267     csock = con->csock;
268   else                          /* cmd & DO_LOGIN */
269     {
270       char type_char;
271       char    *host = con->proxy ? con->proxy->host : u->host;
272       int      port = con->proxy ? con->proxy->port : u->port;
273       char *logname = user;
274
275       if (con->proxy)
276         {
277           /* If proxy is in use, log in as username@target-site. */
278           logname = xmalloc (strlen (user) + 1 + strlen (u->host) + 1);
279           sprintf (logname, "%s@%s", user, u->host);
280         }
281
282       /* Login to the server: */
283
284       /* First: Establish the control connection.  */
285
286       csock = connect_to_host (host, port);
287       if (csock == E_HOST)
288         return HOSTERR;
289       else if (csock < 0)
290         return (retryable_socket_connect_error (errno)
291                 ? CONERROR : CONIMPOSSIBLE);
292
293       if (cmd & LEAVE_PENDING)
294         con->csock = csock;
295       else
296         con->csock = -1;
297
298       /* Second: Login with proper USER/PASS sequence.  */
299       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
300       if (opt.server_response)
301         logputs (LOG_ALWAYS, "\n");
302       err = ftp_login (csock, logname, passwd);
303
304       if (con->proxy)
305         xfree (logname);
306
307       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
308       switch (err)
309         {
310         case FTPRERR:
311           logputs (LOG_VERBOSE, "\n");
312           logputs (LOG_NOTQUIET, _("\
313 Error in server response, closing control connection.\n"));
314           fd_close (csock);
315           con->csock = -1;
316           return err;
317           break;
318         case FTPSRVERR:
319           logputs (LOG_VERBOSE, "\n");
320           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
321           fd_close (csock);
322           con->csock = -1;
323           return err;
324           break;
325         case WRITEFAILED:
326           logputs (LOG_VERBOSE, "\n");
327           logputs (LOG_NOTQUIET,
328                    _("Write failed, closing control connection.\n"));
329           fd_close (csock);
330           con->csock = -1;
331           return err;
332           break;
333         case FTPLOGREFUSED:
334           logputs (LOG_VERBOSE, "\n");
335           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
336           fd_close (csock);
337           con->csock = -1;
338           return FTPLOGREFUSED;
339           break;
340         case FTPLOGINC:
341           logputs (LOG_VERBOSE, "\n");
342           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
343           fd_close (csock);
344           con->csock = -1;
345           return FTPLOGINC;
346           break;
347         case FTPOK:
348           if (!opt.server_response)
349             logputs (LOG_VERBOSE, _("Logged in!\n"));
350           break;
351         default:
352           abort ();
353           exit (1);
354           break;
355         }
356       /* Third: Get the system type */
357       if (!opt.server_response)
358         logprintf (LOG_VERBOSE, "==> SYST ... ");
359       err = ftp_syst (csock, &con->rs);
360       /* FTPRERR */
361       switch (err)
362         {
363         case FTPRERR:
364           logputs (LOG_VERBOSE, "\n");
365           logputs (LOG_NOTQUIET, _("\
366 Error in server response, closing control connection.\n"));
367           fd_close (csock);
368           con->csock = -1;
369           return err;
370           break;
371         case FTPSRVERR:
372           logputs (LOG_VERBOSE, "\n");
373           logputs (LOG_NOTQUIET,
374                    _("Server error, can't determine system type.\n"));
375           break;
376         case FTPOK:
377           /* Everything is OK.  */
378           break;
379         default:
380           abort ();
381           break;
382         }
383       if (!opt.server_response && err != FTPSRVERR)
384         logputs (LOG_VERBOSE, _("done.    "));
385
386       /* Fourth: Find the initial ftp directory */
387
388       if (!opt.server_response)
389         logprintf (LOG_VERBOSE, "==> PWD ... ");
390       err = ftp_pwd (csock, &con->id);
391       /* FTPRERR */
392       switch (err)
393         {
394         case FTPRERR:
395           logputs (LOG_VERBOSE, "\n");
396           logputs (LOG_NOTQUIET, _("\
397 Error in server response, closing control connection.\n"));
398           fd_close (csock);
399           con->csock = -1;
400           return err;
401           break;
402         case FTPSRVERR :
403           /* PWD unsupported -- assume "/". */
404           xfree_null (con->id);
405           con->id = xstrdup ("/");
406           break;
407         case FTPOK:
408           /* Everything is OK.  */
409           break;
410         default:
411           abort ();
412           break;
413         }
414       /* VMS will report something like "PUB$DEVICE:[INITIAL.FOLDER]".
415          Convert it to "/INITIAL/FOLDER" */ 
416       if (con->rs == ST_VMS)
417         {
418           char *path = strchr (con->id, '[');
419           char *pathend = path ? strchr (path + 1, ']') : NULL;
420           if (!path || !pathend)
421             DEBUGP (("Initial VMS directory not in the form [...]!\n"));
422           else
423             {
424               char *idir = con->id;
425               DEBUGP (("Preprocessing the initial VMS directory\n"));
426               DEBUGP (("  old = '%s'\n", con->id));
427               /* We do the conversion in-place by copying the stuff
428                  between [ and ] to the beginning, and changing dots
429                  to slashes at the same time.  */
430               *idir++ = '/';
431               for (++path; path < pathend; path++, idir++)
432                 *idir = *path == '.' ? '/' : *path;
433               *idir = '\0';
434               DEBUGP (("  new = '%s'\n\n", con->id));
435             }
436         }
437       if (!opt.server_response)
438         logputs (LOG_VERBOSE, _("done.\n"));
439
440       /* Fifth: Set the FTP type.  */
441       type_char = ftp_process_type (u->params);
442       if (!opt.server_response)
443         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", type_char);
444       err = ftp_type (csock, type_char);
445       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
446       switch (err)
447         {
448         case FTPRERR:
449           logputs (LOG_VERBOSE, "\n");
450           logputs (LOG_NOTQUIET, _("\
451 Error in server response, closing control connection.\n"));
452           fd_close (csock);
453           con->csock = -1;
454           return err;
455           break;
456         case WRITEFAILED:
457           logputs (LOG_VERBOSE, "\n");
458           logputs (LOG_NOTQUIET,
459                    _("Write failed, closing control connection.\n"));
460           fd_close (csock);
461           con->csock = -1;
462           return err;
463           break;
464         case FTPUNKNOWNTYPE:
465           logputs (LOG_VERBOSE, "\n");
466           logprintf (LOG_NOTQUIET,
467                      _("Unknown type `%c', closing control connection.\n"),
468                      type_char);
469           fd_close (csock);
470           con->csock = -1;
471           return err;
472         case FTPOK:
473           /* Everything is OK.  */
474           break;
475         default:
476           abort ();
477           break;
478         }
479       if (!opt.server_response)
480         logputs (LOG_VERBOSE, _("done.  "));
481     } /* do login */
482
483   if (cmd & DO_CWD)
484     {
485       if (!*u->dir)
486         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
487       else
488         {
489           char *target = u->dir;
490
491           DEBUGP (("changing working directory\n"));
492
493           /* Change working directory.  To change to a non-absolute
494              Unix directory, we need to prepend initial directory
495              (con->id) to it.  Absolute directories "just work".
496
497              A relative directory is one that does not begin with '/'
498              and, on non-Unix OS'es, one that doesn't begin with
499              "[a-z]:".
500
501              This is not done for OS400, which doesn't use
502              "/"-delimited directories, nor does it support directory
503              hierarchies.  "CWD foo" followed by "CWD bar" leaves us
504              in "bar", not in "foo/bar", as would be customary
505              elsewhere.  */
506
507           if (target[0] != '/'
508               && !(con->rs != ST_UNIX
509                    && ISALPHA (target[0])
510                    && target[1] == ':')
511               && con->rs != ST_OS400)
512             {
513               int idlen = strlen (con->id);
514               char *ntarget, *p;
515
516               /* Strip trailing slash(es) from con->id. */
517               while (idlen > 0 && con->id[idlen - 1] == '/')
518                 --idlen;
519               p = ntarget = (char *)alloca (idlen + 1 + strlen (u->dir) + 1);
520               memcpy (p, con->id, idlen);
521               p += idlen;
522               *p++ = '/';
523               strcpy (p, target);
524
525               DEBUGP (("Prepended initial PWD to relative path:\n"));
526               DEBUGP (("   pwd: '%s'\n   old: '%s'\n  new: '%s'\n",
527                        con->id, target, ntarget));
528               target = ntarget;
529             }
530
531           /* If the FTP host runs VMS, we will have to convert the absolute
532              directory path in UNIX notation to absolute directory path in
533              VMS notation as VMS FTP servers do not like UNIX notation of
534              absolute paths.  "VMS notation" is [dir.subdir.subsubdir]. */
535
536           if (con->rs == ST_VMS)
537             {
538               char *tmpp;
539               char *ntarget = (char *)alloca (strlen (target) + 2);
540               /* We use a converted initial dir, so directories in
541                  TARGET will be separated with slashes, something like
542                  "/INITIAL/FOLDER/DIR/SUBDIR".  Convert that to
543                  "[INITIAL.FOLDER.DIR.SUBDIR]".  */
544               strcpy (ntarget, target);
545               assert (*ntarget == '/');
546               *ntarget = '[';
547               for (tmpp = ntarget + 1; *tmpp; tmpp++)
548                 if (*tmpp == '/')
549                   *tmpp = '.';
550               *tmpp++ = ']';
551               *tmpp = '\0';
552               DEBUGP (("Changed file name to VMS syntax:\n"));
553               DEBUGP (("  Unix: '%s'\n  VMS: '%s'\n", target, ntarget));
554               target = ntarget;
555             }
556
557           if (!opt.server_response)
558             logprintf (LOG_VERBOSE, "==> CWD %s ... ", target);
559           err = ftp_cwd (csock, target);
560           /* FTPRERR, WRITEFAILED, FTPNSFOD */
561           switch (err)
562             {
563             case FTPRERR:
564               logputs (LOG_VERBOSE, "\n");
565               logputs (LOG_NOTQUIET, _("\
566 Error in server response, closing control connection.\n"));
567               fd_close (csock);
568               con->csock = -1;
569               return err;
570               break;
571             case WRITEFAILED:
572               logputs (LOG_VERBOSE, "\n");
573               logputs (LOG_NOTQUIET,
574                        _("Write failed, closing control connection.\n"));
575               fd_close (csock);
576               con->csock = -1;
577               return err;
578               break;
579             case FTPNSFOD:
580               logputs (LOG_VERBOSE, "\n");
581               logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
582                          u->dir);
583               fd_close (csock);
584               con->csock = -1;
585               return err;
586               break;
587             case FTPOK:
588               /* fine and dandy */
589               break;
590             default:
591               abort ();
592               break;
593             }
594           if (!opt.server_response)
595             logputs (LOG_VERBOSE, _("done.\n"));
596         }
597     }
598   else /* do not CWD */
599     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
600
601   if ((cmd & DO_RETR) && restval && *len == 0)
602     {
603       if (opt.verbose)
604         {
605           if (!opt.server_response)
606             logprintf (LOG_VERBOSE, "==> SIZE %s ... ", u->file);
607         }
608
609       err = ftp_size (csock, u->file, len);
610       /* FTPRERR */
611       switch (err)
612         {
613         case FTPRERR:
614         case FTPSRVERR :
615           logputs (LOG_VERBOSE, "\n");
616           logputs (LOG_NOTQUIET, _("\
617 Error in server response, closing control connection.\n"));
618           fd_close (csock);
619           con->csock = -1;
620           return err;
621           break;
622         case FTPOK:
623           /* Everything is OK.  */
624           break;
625         default:
626           abort ();
627           break;
628         }
629         if (!opt.server_response)
630           logputs (LOG_VERBOSE, _("done.\n"));
631     }
632
633   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
634   if (cmd & (DO_LIST | DO_RETR))
635     {
636       if (opt.ftp_pasv > 0)
637         {
638           ip_address passive_addr;
639           int        passive_port;
640           err = ftp_do_pasv (csock, &passive_addr, &passive_port);
641           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
642           switch (err)
643             {
644             case FTPRERR:
645               logputs (LOG_VERBOSE, "\n");
646               logputs (LOG_NOTQUIET, _("\
647 Error in server response, closing control connection.\n"));
648               fd_close (csock);
649               con->csock = -1;
650               return err;
651               break;
652             case WRITEFAILED:
653               logputs (LOG_VERBOSE, "\n");
654               logputs (LOG_NOTQUIET,
655                        _("Write failed, closing control connection.\n"));
656               fd_close (csock);
657               con->csock = -1;
658               return err;
659               break;
660             case FTPNOPASV:
661               logputs (LOG_VERBOSE, "\n");
662               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
663               break;
664             case FTPINVPASV:
665               logputs (LOG_VERBOSE, "\n");
666               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
667               break;
668             case FTPOK:
669               /* fine and dandy */
670               break;
671             default:
672               abort ();
673               break;
674             }   /* switch (err) */
675           if (err==FTPOK)
676             {
677               DEBUGP (("trying to connect to %s port %d\n", 
678                       pretty_print_address (&passive_addr),
679                       passive_port));
680               dtsock = connect_to_ip (&passive_addr, passive_port, NULL);
681               if (dtsock < 0)
682                 {
683                   int save_errno = errno;
684                   fd_close (csock);
685                   con->csock = -1;
686                   logprintf (LOG_VERBOSE, _("couldn't connect to %s port %d: %s\n"),
687                              pretty_print_address (&passive_addr), passive_port,
688                              strerror (save_errno));
689                   return (retryable_socket_connect_error (save_errno)
690                           ? CONERROR : CONIMPOSSIBLE);
691                 }
692
693               pasv_mode_open = 1;  /* Flag to avoid accept port */
694               if (!opt.server_response)
695                 logputs (LOG_VERBOSE, _("done.    "));
696             } /* err==FTP_OK */
697         }
698
699       if (!pasv_mode_open)   /* Try to use a port command if PASV failed */
700         {
701           err = ftp_do_port (csock, &local_sock);
702           /* FTPRERR, WRITEFAILED, bindport (FTPSYSERR), HOSTERR,
703              FTPPORTERR */
704           switch (err)
705             {
706             case FTPRERR:
707               logputs (LOG_VERBOSE, "\n");
708               logputs (LOG_NOTQUIET, _("\
709 Error in server response, closing control connection.\n"));
710               fd_close (csock);
711               con->csock = -1;
712               fd_close (dtsock);
713               fd_close (local_sock);
714               return err;
715               break;
716             case WRITEFAILED:
717               logputs (LOG_VERBOSE, "\n");
718               logputs (LOG_NOTQUIET,
719                        _("Write failed, closing control connection.\n"));
720               fd_close (csock);
721               con->csock = -1;
722               fd_close (dtsock);
723               fd_close (local_sock);
724               return err;
725               break;
726             case CONSOCKERR:
727               logputs (LOG_VERBOSE, "\n");
728               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
729               fd_close (csock);
730               con->csock = -1;
731               fd_close (dtsock);
732               fd_close (local_sock);
733               return err;
734               break;
735             case FTPSYSERR:
736               logputs (LOG_VERBOSE, "\n");
737               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
738                          strerror (errno));
739               fd_close (dtsock);
740               return err;
741               break;
742             case FTPPORTERR:
743               logputs (LOG_VERBOSE, "\n");
744               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
745               fd_close (csock);
746               con->csock = -1;
747               fd_close (dtsock);
748               fd_close (local_sock);
749               return err;
750               break;
751             case FTPOK:
752               /* fine and dandy */
753               break;
754             default:
755               abort ();
756               break;
757             } /* port switch */
758           if (!opt.server_response)
759             logputs (LOG_VERBOSE, _("done.    "));
760         } /* dtsock == -1 */
761     } /* cmd & (DO_LIST | DO_RETR) */
762
763   /* Restart if needed.  */
764   if (restval && (cmd & DO_RETR))
765     {
766       if (!opt.server_response)
767         logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
768       err = ftp_rest (csock, restval);
769
770       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
771       switch (err)
772         {
773         case FTPRERR:
774           logputs (LOG_VERBOSE, "\n");
775           logputs (LOG_NOTQUIET, _("\
776 Error in server response, closing control connection.\n"));
777           fd_close (csock);
778           con->csock = -1;
779           fd_close (dtsock);
780           fd_close (local_sock);
781           return err;
782           break;
783         case WRITEFAILED:
784           logputs (LOG_VERBOSE, "\n");
785           logputs (LOG_NOTQUIET,
786                    _("Write failed, closing control connection.\n"));
787           fd_close (csock);
788           con->csock = -1;
789           fd_close (dtsock);
790           fd_close (local_sock);
791           return err;
792           break;
793         case FTPRESTFAIL:
794           /* If `-c' is specified and the file already existed when
795              Wget was started, it would be a bad idea for us to start
796              downloading it from scratch, effectively truncating it.  */
797           if (opt.always_rest && (cmd & NO_TRUNCATE))
798             {
799               logprintf (LOG_NOTQUIET,
800                          _("\nREST failed; will not truncate `%s'.\n"),
801                          con->target);
802               fd_close (csock);
803               con->csock = -1;
804               fd_close (dtsock);
805               fd_close (local_sock);
806               return CONTNOTSUPPORTED;
807             }
808           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
809           restval = 0L;
810           break;
811         case FTPOK:
812           /* fine and dandy */
813           break;
814         default:
815           abort ();
816           break;
817         }
818       if (err != FTPRESTFAIL && !opt.server_response)
819         logputs (LOG_VERBOSE, _("done.    "));
820     } /* restval && cmd & DO_RETR */
821
822   if (cmd & DO_RETR)
823     {
824       /* If we're in spider mode, don't really retrieve anything.  The
825          fact that we got to this point should be proof enough that
826          the file exists, vaguely akin to HTTP's concept of a "HEAD"
827          request.  */
828       if (opt.spider)
829         {
830           fd_close (csock);
831           con->csock = -1;
832           fd_close (dtsock);
833           fd_close (local_sock);
834           return RETRFINISHED;
835         }
836
837       if (opt.verbose)
838         {
839           if (!opt.server_response)
840             {
841               if (restval)
842                 logputs (LOG_VERBOSE, "\n");
843               logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
844             }
845         }
846
847       err = ftp_retr (csock, u->file);
848       /* FTPRERR, WRITEFAILED, FTPNSFOD */
849       switch (err)
850         {
851         case FTPRERR:
852           logputs (LOG_VERBOSE, "\n");
853           logputs (LOG_NOTQUIET, _("\
854 Error in server response, closing control connection.\n"));
855           fd_close (csock);
856           con->csock = -1;
857           fd_close (dtsock);
858           fd_close (local_sock);
859           return err;
860           break;
861         case WRITEFAILED:
862           logputs (LOG_VERBOSE, "\n");
863           logputs (LOG_NOTQUIET,
864                    _("Write failed, closing control connection.\n"));
865           fd_close (csock);
866           con->csock = -1;
867           fd_close (dtsock);
868           fd_close (local_sock);
869           return err;
870           break;
871         case FTPNSFOD:
872           logputs (LOG_VERBOSE, "\n");
873           logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
874           fd_close (dtsock);
875           fd_close (local_sock);
876           return err;
877           break;
878         case FTPOK:
879           /* fine and dandy */
880           break;
881         default:
882           abort ();
883           break;
884         }
885
886       if (!opt.server_response)
887         logputs (LOG_VERBOSE, _("done.\n"));
888       expected_bytes = ftp_expected_bytes (ftp_last_respline);
889     } /* do retrieve */
890
891   if (cmd & DO_LIST)
892     {
893       if (!opt.server_response)
894         logputs (LOG_VERBOSE, "==> LIST ... ");
895       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
896          without arguments is better than `LIST .'; confirmed by
897          RFC959.  */
898       err = ftp_list (csock, NULL);
899       /* FTPRERR, WRITEFAILED */
900       switch (err)
901         {
902         case FTPRERR:
903           logputs (LOG_VERBOSE, "\n");
904           logputs (LOG_NOTQUIET, _("\
905 Error in server response, closing control connection.\n"));
906           fd_close (csock);
907           con->csock = -1;
908           fd_close (dtsock);
909           fd_close (local_sock);
910           return err;
911           break;
912         case WRITEFAILED:
913           logputs (LOG_VERBOSE, "\n");
914           logputs (LOG_NOTQUIET,
915                    _("Write failed, closing control connection.\n"));
916           fd_close (csock);
917           con->csock = -1;
918           fd_close (dtsock);
919           fd_close (local_sock);
920           return err;
921           break;
922         case FTPNSFOD:
923           logputs (LOG_VERBOSE, "\n");
924           logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
925                      ".");
926           fd_close (dtsock);
927           fd_close (local_sock);
928           return err;
929           break;
930         case FTPOK:
931           /* fine and dandy */
932           break;
933         default:
934           abort ();
935           break;
936         }
937       if (!opt.server_response)
938         logputs (LOG_VERBOSE, _("done.\n"));
939       expected_bytes = ftp_expected_bytes (ftp_last_respline);
940     } /* cmd & DO_LIST */
941
942   if (!(cmd & (DO_LIST | DO_RETR)) || (opt.spider && !(cmd & DO_LIST)))
943     return RETRFINISHED;
944
945   /* Some FTP servers return the total length of file after REST
946      command, others just return the remaining size. */
947   if (*len && restval && expected_bytes
948       && (expected_bytes == *len - restval))
949     {
950       DEBUGP (("Lying FTP server found, adjusting.\n"));
951       expected_bytes = *len;
952     }
953
954   /* If no transmission was required, then everything is OK.  */
955   if (!pasv_mode_open)  /* we are not using pasive mode so we need
956                               to accept */
957     {
958       /* Wait for the server to connect to the address we're waiting
959          at.  */
960       dtsock = accept_connection (local_sock);
961       if (dtsock < 0)
962         {
963           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
964           return err;
965         }
966     }
967
968   /* Open the file -- if opt.dfp is set, use it instead.  */
969   if (!opt.dfp || con->cmd & DO_LIST)
970     {
971       mkalldirs (con->target);
972       if (opt.backups)
973         rotate_backups (con->target);
974       /* #### Is this correct? */
975       chmod (con->target, 0600);
976
977       fp = fopen (con->target, restval ? "ab" : "wb");
978       if (!fp)
979         {
980           logprintf (LOG_NOTQUIET, "%s: %s\n", con->target, strerror (errno));
981           fd_close (csock);
982           con->csock = -1;
983           fd_close (dtsock);
984           fd_close (local_sock);
985           return FOPENERR;
986         }
987     }
988   else
989     {
990       extern int global_download_count;
991       fp = opt.dfp;
992
993       /* Rewind the output document if the download starts over and if
994          this is the first download.  See gethttp() for a longer
995          explanation.  */
996       if (!restval && global_download_count == 0 && opt.dfp != stdout)
997         {
998           /* This will silently fail for streams that don't correspond
999              to regular files, but that's OK.  */
1000           rewind (fp);
1001           /* ftruncate is needed because opt.dfp is opened in append
1002              mode if opt.always_rest is set.  */
1003           ftruncate (fileno (fp), 0);
1004           clearerr (fp);
1005         }
1006     }
1007
1008   if (*len)
1009     {
1010       logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
1011       if (restval)
1012         logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
1013       logputs (LOG_VERBOSE, "\n");
1014       expected_bytes = *len;    /* for get_contents/show_progress */
1015     }
1016   else if (expected_bytes)
1017     {
1018       logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
1019       if (restval)
1020         logprintf (LOG_VERBOSE, _(" [%s to go]"),
1021                    legible (expected_bytes - restval));
1022       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
1023     }
1024
1025   /* Get the contents of the document.  */
1026   res = fd_read_body (dtsock, fp, len, restval, expected_bytes, 0,
1027                       &con->dltime);
1028   tms = time_str (NULL);
1029   tmrate = retr_rate (*len - restval, con->dltime, 0);
1030   /* Close data connection socket.  */
1031   fd_close (dtsock);
1032   fd_close (local_sock);
1033   /* Close the local file.  */
1034   {
1035     /* Close or flush the file.  We have to be careful to check for
1036        error here.  Checking the result of fwrite() is not enough --
1037        errors could go unnoticed!  */
1038     int flush_res;
1039     if (!opt.dfp || con->cmd & DO_LIST)
1040       flush_res = fclose (fp);
1041     else
1042       flush_res = fflush (fp);
1043     if (flush_res == EOF)
1044       res = -2;
1045   }
1046
1047   /* If get_contents couldn't write to fp, bail out.  */
1048   if (res == -2)
1049     {
1050       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
1051                  con->target, strerror (errno));
1052       fd_close (csock);
1053       con->csock = -1;
1054       return FWRITEERR;
1055     }
1056   else if (res == -1)
1057     {
1058       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
1059                  tms, tmrate, strerror (errno));
1060       if (opt.server_response)
1061         logputs (LOG_ALWAYS, "\n");
1062     }
1063
1064   /* Get the server to tell us if everything is retrieved.  */
1065   err = ftp_response (csock, &respline);
1066   if (err != FTPOK)
1067     {
1068       xfree (respline);
1069       /* The control connection is decidedly closed.  Print the time
1070          only if it hasn't already been printed.  */
1071       if (res != -1)
1072         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1073       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
1074       /* If there is an error on the control connection, close it, but
1075          return FTPRETRINT, since there is a possibility that the
1076          whole file was retrieved nevertheless (but that is for
1077          ftp_loop_internal to decide).  */
1078       fd_close (csock);
1079       con->csock = -1;
1080       return FTPRETRINT;
1081     } /* err != FTPOK */
1082   /* If retrieval failed for any reason, return FTPRETRINT, but do not
1083      close socket, since the control connection is still alive.  If
1084      there is something wrong with the control connection, it will
1085      become apparent later.  */
1086   if (*respline != '2')
1087     {
1088       xfree (respline);
1089       if (res != -1)
1090         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
1091       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
1092       return FTPRETRINT;
1093     }
1094   xfree (respline);
1095
1096   if (res == -1)
1097     {
1098       /* What now?  The data connection was erroneous, whereas the
1099          response says everything is OK.  We shall play it safe.  */
1100       return FTPRETRINT;
1101     }
1102
1103   if (!(cmd & LEAVE_PENDING))
1104     {
1105       /* I should probably send 'QUIT' and check for a reply, but this
1106          is faster.  #### Is it OK, though?  */
1107       fd_close (csock);
1108       con->csock = -1;
1109     }
1110   /* If it was a listing, and opt.server_response is true,
1111      print it out.  */
1112   if (opt.server_response && (con->cmd & DO_LIST))
1113     {
1114       mkalldirs (con->target);
1115       fp = fopen (con->target, "r");
1116       if (!fp)
1117         logprintf (LOG_ALWAYS, "%s: %s\n", con->target, strerror (errno));
1118       else
1119         {
1120           char *line;
1121           /* The lines are being read with read_whole_line because of
1122              no-buffering on opt.lfile.  */
1123           while ((line = read_whole_line (fp)))
1124             {
1125               logprintf (LOG_ALWAYS, "%s\n", line);
1126               xfree (line);
1127             }
1128           fclose (fp);
1129         }
1130     } /* con->cmd & DO_LIST && server_response */
1131
1132   return RETRFINISHED;
1133 }
1134
1135 /* A one-file FTP loop.  This is the part where FTP retrieval is
1136    retried, and retried, and retried, and...
1137
1138    This loop either gets commands from con, or (if ON_YOUR_OWN is
1139    set), makes them up to retrieve the file given by the URL.  */
1140 static uerr_t
1141 ftp_loop_internal (struct url *u, struct fileinfo *f, ccon *con)
1142 {
1143   int count, orig_lp;
1144   long restval, len;
1145   char *tms, *locf;
1146   char *tmrate = NULL;
1147   uerr_t err;
1148   struct stat st;
1149
1150   if (!con->target)
1151     con->target = url_file_name (u);
1152
1153   if (opt.noclobber && file_exists_p (con->target))
1154     {
1155       logprintf (LOG_VERBOSE,
1156                  _("File `%s' already there, not retrieving.\n"), con->target);
1157       /* If the file is there, we suppose it's retrieved OK.  */
1158       return RETROK;
1159     }
1160
1161   /* Remove it if it's a link.  */
1162   remove_link (con->target);
1163   if (!opt.output_document)
1164     locf = con->target;
1165   else
1166     locf = opt.output_document;
1167
1168   count = 0;
1169
1170   if (con->st & ON_YOUR_OWN)
1171     con->st = ON_YOUR_OWN;
1172
1173   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
1174
1175   /* THE loop.  */
1176   do
1177     {
1178       /* Increment the pass counter.  */
1179       ++count;
1180       sleep_between_retrievals (count);
1181       if (con->st & ON_YOUR_OWN)
1182         {
1183           con->cmd = 0;
1184           con->cmd |= (DO_RETR | LEAVE_PENDING);
1185           if (con->csock != -1)
1186             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1187           else
1188             con->cmd |= (DO_LOGIN | DO_CWD);
1189         }
1190       else /* not on your own */
1191         {
1192           if (con->csock != -1)
1193             con->cmd &= ~DO_LOGIN;
1194           else
1195             con->cmd |= DO_LOGIN;
1196           if (con->st & DONE_CWD)
1197             con->cmd &= ~DO_CWD;
1198           else
1199             con->cmd |= DO_CWD;
1200         }
1201
1202       /* Assume no restarting.  */
1203       restval = 0L;
1204       if ((count > 1 || opt.always_rest)
1205           && !(con->cmd & DO_LIST)
1206           && file_exists_p (locf))
1207         if (stat (locf, &st) == 0 && S_ISREG (st.st_mode))
1208           restval = st.st_size;
1209
1210       /* In `-c' is used, check whether the file we're writing to
1211          exists and is of non-zero length.  If so, we'll refuse to
1212          truncate it if the server doesn't support continued
1213          downloads.  */
1214       if (opt.always_rest && restval > 0)
1215         con->cmd |= NO_TRUNCATE;
1216
1217       /* Get the current time string.  */
1218       tms = time_str (NULL);
1219       /* Print fetch message, if opt.verbose.  */
1220       if (opt.verbose)
1221         {
1222           char *hurl = url_string (u, 1);
1223           char tmp[15];
1224           strcpy (tmp, "        ");
1225           if (count > 1)
1226             sprintf (tmp, _("(try:%2d)"), count);
1227           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1228                      tms, hurl, tmp, locf);
1229 #ifdef WINDOWS
1230           ws_changetitle (hurl, 1);
1231 #endif
1232           xfree (hurl);
1233         }
1234       /* Send getftp the proper length, if fileinfo was provided.  */
1235       if (f)
1236         len = f->size;
1237       else
1238         len = 0;
1239       err = getftp (u, &len, restval, con);
1240
1241       if (con->csock != -1)
1242         con->st &= ~DONE_CWD;
1243       else
1244         con->st |= DONE_CWD;
1245
1246       switch (err)
1247         {
1248         case HOSTERR: case CONIMPOSSIBLE: case FWRITEERR: case FOPENERR:
1249         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1250           /* Fatal errors, give up.  */
1251           return err;
1252           break;
1253         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1254         case WRITEFAILED: case FTPUNKNOWNTYPE: case FTPSYSERR:
1255         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1256           printwhat (count, opt.ntry);
1257           /* non-fatal errors */
1258           continue;
1259           break;
1260         case FTPRETRINT:
1261           /* If the control connection was closed, the retrieval
1262              will be considered OK if f->size == len.  */
1263           if (!f || len != f->size)
1264             {
1265               printwhat (count, opt.ntry);
1266               continue;
1267             }
1268           break;
1269         case RETRFINISHED:
1270           /* Great!  */
1271           break;
1272         default:
1273           /* Not as great.  */
1274           abort ();
1275         }
1276       /* Time?  */
1277       tms = time_str (NULL);
1278       if (!opt.spider)
1279         tmrate = retr_rate (len - restval, con->dltime, 0);
1280
1281       /* If we get out of the switch above without continue'ing, we've
1282          successfully downloaded a file.  Remember this fact. */
1283       downloaded_file (FILE_DOWNLOADED_NORMALLY, locf);
1284
1285       if (con->st & ON_YOUR_OWN)
1286         {
1287           fd_close (con->csock);
1288           con->csock = -1;
1289         }
1290       if (!opt.spider)
1291         logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1292                    tms, tmrate, locf, len);
1293       if (!opt.verbose && !opt.quiet)
1294         {
1295           /* Need to hide the password from the URL.  The `if' is here
1296              so that we don't do the needless allocation every
1297              time. */
1298           char *hurl = url_string (u, 1);
1299           logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1300                      tms, hurl, len, locf, count);
1301           xfree (hurl);
1302         }
1303
1304       if ((con->cmd & DO_LIST))
1305         /* This is a directory listing file. */
1306         {
1307           if (!opt.remove_listing)
1308             /* --dont-remove-listing was specified, so do count this towards the
1309                number of bytes and files downloaded. */
1310             {
1311               total_downloaded_bytes += len;
1312               opt.numurls++;
1313             }
1314
1315           /* Deletion of listing files is not controlled by --delete-after, but
1316              by the more specific option --dont-remove-listing, and the code
1317              to do this deletion is in another function. */
1318         }
1319       else if (!opt.spider)
1320         /* This is not a directory listing file. */
1321         {
1322           /* Unlike directory listing files, don't pretend normal files weren't
1323              downloaded if they're going to be deleted.  People seeding proxies,
1324              for instance, may want to know how many bytes and files they've
1325              downloaded through it. */
1326           total_downloaded_bytes += len;
1327           opt.numurls++;
1328
1329           if (opt.delete_after)
1330             {
1331               DEBUGP (("Removing file due to --delete-after in"
1332                        " ftp_loop_internal():\n"));
1333               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1334               if (unlink (locf))
1335                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1336             }
1337         }
1338
1339       /* Restore the original leave-pendingness.  */
1340       if (orig_lp)
1341         con->cmd |= LEAVE_PENDING;
1342       else
1343         con->cmd &= ~LEAVE_PENDING;
1344       return RETROK;
1345     } while (!opt.ntry || (count < opt.ntry));
1346
1347   if (con->csock != -1 && (con->st & ON_YOUR_OWN))
1348     {
1349       fd_close (con->csock);
1350       con->csock = -1;
1351     }
1352   return TRYLIMEXC;
1353 }
1354
1355 /* Return the directory listing in a reusable format.  The directory
1356    is specifed in u->dir.  */
1357 uerr_t
1358 ftp_get_listing (struct url *u, ccon *con, struct fileinfo **f)
1359 {
1360   uerr_t err;
1361   char *uf;                     /* url file name */
1362   char *lf;                     /* list file name */
1363   char *old_target = con->target;
1364
1365   con->st &= ~ON_YOUR_OWN;
1366   con->cmd |= (DO_LIST | LEAVE_PENDING);
1367   con->cmd &= ~DO_RETR;
1368
1369   /* Find the listing file name.  We do it by taking the file name of
1370      the URL and replacing the last component with the listing file
1371      name.  */
1372   uf = url_file_name (u);
1373   lf = file_merge (uf, LIST_FILENAME);
1374   xfree (uf);
1375   DEBUGP ((_("Using `%s' as listing tmp file.\n"), lf));
1376
1377   con->target = lf;
1378   err = ftp_loop_internal (u, NULL, con);
1379   con->target = old_target;
1380
1381   if (err == RETROK)
1382     *f = ftp_parse_ls (lf, con->rs);
1383   else
1384     *f = NULL;
1385   if (opt.remove_listing)
1386     {
1387       if (unlink (lf))
1388         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1389       else
1390         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), lf);
1391     }
1392   xfree (lf);
1393   con->cmd &= ~DO_LIST;
1394   return err;
1395 }
1396
1397 static uerr_t ftp_retrieve_dirs PARAMS ((struct url *, struct fileinfo *,
1398                                          ccon *));
1399 static uerr_t ftp_retrieve_glob PARAMS ((struct url *, ccon *, int));
1400 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1401                                             struct fileinfo **));
1402 static void freefileinfo PARAMS ((struct fileinfo *f));
1403
1404 /* Retrieve a list of files given in struct fileinfo linked list.  If
1405    a file is a symbolic link, do not retrieve it, but rather try to
1406    set up a similar link on the local disk, if the symlinks are
1407    supported.
1408
1409    If opt.recursive is set, after all files have been retrieved,
1410    ftp_retrieve_dirs will be called to retrieve the directories.  */
1411 static uerr_t
1412 ftp_retrieve_list (struct url *u, struct fileinfo *f, ccon *con)
1413 {
1414   static int depth = 0;
1415   uerr_t err;
1416   struct fileinfo *orig;
1417   long local_size;
1418   time_t tml;
1419   int dlthis;
1420
1421   /* Increase the depth.  */
1422   ++depth;
1423   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1424     {
1425       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1426                depth, opt.reclevel));
1427       --depth;
1428       return RECLEVELEXC;
1429     }
1430
1431   assert (f != NULL);
1432   orig = f;
1433
1434   con->st &= ~ON_YOUR_OWN;
1435   if (!(con->st & DONE_CWD))
1436     con->cmd |= DO_CWD;
1437   else
1438     con->cmd &= ~DO_CWD;
1439   con->cmd |= (DO_RETR | LEAVE_PENDING);
1440
1441   if (con->csock < 0)
1442     con->cmd |= DO_LOGIN;
1443   else
1444     con->cmd &= ~DO_LOGIN;
1445
1446   err = RETROK;                 /* in case it's not used */
1447
1448   while (f)
1449     {
1450       char *old_target, *ofile;
1451
1452       if (opt.quota && total_downloaded_bytes > opt.quota)
1453         {
1454           --depth;
1455           return QUOTEXC;
1456         }
1457       old_target = con->target;
1458
1459       ofile = xstrdup (u->file);
1460       url_set_file (u, f->name);
1461
1462       con->target = url_file_name (u);
1463       err = RETROK;
1464
1465       dlthis = 1;
1466       if (opt.timestamping && f->type == FT_PLAINFILE)
1467         {
1468           struct stat st;
1469           /* If conversion of HTML files retrieved via FTP is ever implemented,
1470              we'll need to stat() <file>.orig here when -K has been specified.
1471              I'm not implementing it now since files on an FTP server are much
1472              more likely than files on an HTTP server to legitimately have a
1473              .orig suffix. */
1474           if (!stat (con->target, &st))
1475             {
1476               int eq_size;
1477               int cor_val;
1478               /* Else, get it from the file.  */
1479               local_size = st.st_size;
1480               tml = st.st_mtime;
1481 #ifdef WINDOWS
1482               /* Modification time granularity is 2 seconds for Windows, so
1483                  increase local time by 1 second for later comparison. */
1484               tml++;
1485 #endif
1486               /* Compare file sizes only for servers that tell us correct
1487                  values. Assumme sizes being equal for servers that lie
1488                  about file size.  */
1489               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1490               eq_size = cor_val ? (local_size == f->size) : 1 ;
1491               if (f->tstamp <= tml && eq_size)
1492                 {
1493                   /* Remote file is older, file sizes can be compared and
1494                      are both equal. */
1495                   logprintf (LOG_VERBOSE, _("\
1496 Remote file no newer than local file `%s' -- not retrieving.\n"), con->target);
1497                   dlthis = 0;
1498                 }
1499               else if (eq_size)
1500                 {
1501                   /* Remote file is newer or sizes cannot be matched */
1502                   logprintf (LOG_VERBOSE, _("\
1503 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1504                              con->target);
1505                 }
1506               else
1507                 {
1508                   /* Sizes do not match */
1509                   logprintf (LOG_VERBOSE, _("\
1510 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1511                 }
1512             }
1513         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1514       switch (f->type)
1515         {
1516         case FT_SYMLINK:
1517           /* If opt.retr_symlinks is defined, we treat symlinks as
1518              if they were normal files.  There is currently no way
1519              to distinguish whether they might be directories, and
1520              follow them.  */
1521           if (!opt.retr_symlinks)
1522             {
1523 #ifdef HAVE_SYMLINK
1524               if (!f->linkto)
1525                 logputs (LOG_NOTQUIET,
1526                          _("Invalid name of the symlink, skipping.\n"));
1527               else
1528                 {
1529                   struct stat st;
1530                   /* Check whether we already have the correct
1531                      symbolic link.  */
1532                   int rc = lstat (con->target, &st);
1533                   if (rc == 0)
1534                     {
1535                       size_t len = strlen (f->linkto) + 1;
1536                       if (S_ISLNK (st.st_mode))
1537                         {
1538                           char *link_target = (char *)alloca (len);
1539                           size_t n = readlink (con->target, link_target, len);
1540                           if ((n == len - 1)
1541                               && (memcmp (link_target, f->linkto, n) == 0))
1542                             {
1543                               logprintf (LOG_VERBOSE, _("\
1544 Already have correct symlink %s -> %s\n\n"),
1545                                          con->target, f->linkto);
1546                               dlthis = 0;
1547                               break;
1548                             }
1549                         }
1550                     }
1551                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1552                              con->target, f->linkto);
1553                   /* Unlink before creating symlink!  */
1554                   unlink (con->target);
1555                   if (symlink (f->linkto, con->target) == -1)
1556                     logprintf (LOG_NOTQUIET, "symlink: %s\n",
1557                                strerror (errno));
1558                   logputs (LOG_VERBOSE, "\n");
1559                 } /* have f->linkto */
1560 #else  /* not HAVE_SYMLINK */
1561               logprintf (LOG_NOTQUIET,
1562                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1563                          con->target);
1564 #endif /* not HAVE_SYMLINK */
1565             }
1566           else                /* opt.retr_symlinks */
1567             {
1568               if (dlthis)
1569                 err = ftp_loop_internal (u, f, con);
1570             } /* opt.retr_symlinks */
1571           break;
1572         case FT_DIRECTORY:
1573           if (!opt.recursive)
1574             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1575                        f->name);
1576           break;
1577         case FT_PLAINFILE:
1578           /* Call the retrieve loop.  */
1579           if (dlthis)
1580             err = ftp_loop_internal (u, f, con);
1581           break;
1582         case FT_UNKNOWN:
1583           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1584                      f->name);
1585           break;
1586         }       /* switch */
1587
1588       /* Set the time-stamp information to the local file.  Symlinks
1589          are not to be stamped because it sets the stamp on the
1590          original.  :( */
1591       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1592           && f->tstamp != -1
1593           && dlthis
1594           && file_exists_p (con->target))
1595         {
1596           /* #### This code repeats in http.c and ftp.c.  Move it to a
1597              function!  */
1598           const char *fl = NULL;
1599           if (opt.output_document)
1600             {
1601               if (opt.od_known_regular)
1602                 fl = opt.output_document;
1603             }
1604           else
1605             fl = con->target;
1606           if (fl)
1607             touch (fl, f->tstamp);
1608         }
1609       else if (f->tstamp == -1)
1610         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), con->target);
1611
1612       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1613         {
1614           if (opt.preserve_perm)
1615             chmod (con->target, f->perms);
1616         }
1617       else
1618         DEBUGP (("Unrecognized permissions for %s.\n", con->target));
1619
1620       xfree (con->target);
1621       con->target = old_target;
1622
1623       url_set_file (u, ofile);
1624       xfree (ofile);
1625
1626       /* Break on fatals.  */
1627       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1628         break;
1629       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1630       f = f->next;
1631     }
1632
1633   /* We do not want to call ftp_retrieve_dirs here */
1634   if (opt.recursive &&
1635       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1636     err = ftp_retrieve_dirs (u, orig, con);
1637   else if (opt.recursive)
1638     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1639              depth, opt.reclevel));
1640   --depth;
1641   return err;
1642 }
1643
1644 /* Retrieve the directories given in a file list.  This function works
1645    by simply going through the linked list and calling
1646    ftp_retrieve_glob on each directory entry.  The function knows
1647    about excluded directories.  */
1648 static uerr_t
1649 ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
1650 {
1651   char *container = NULL;
1652   int container_size = 0;
1653
1654   for (; f; f = f->next)
1655     {
1656       int size;
1657       char *odir, *newdir;
1658
1659       if (opt.quota && total_downloaded_bytes > opt.quota)
1660         break;
1661       if (f->type != FT_DIRECTORY)
1662         continue;
1663
1664       /* Allocate u->dir off stack, but reallocate only if a larger
1665          string is needed.  It's a pity there's no "realloca" for an
1666          item on the bottom of the stack.  */
1667       size = strlen (u->dir) + 1 + strlen (f->name) + 1;
1668       if (size > container_size)
1669         container = (char *)alloca (size);
1670       newdir = container;
1671
1672       odir = u->dir;
1673       if (*odir == '\0'
1674           || (*odir == '/' && *(odir + 1) == '\0'))
1675         /* If ODIR is empty or just "/", simply append f->name to
1676            ODIR.  (In the former case, to preserve u->dir being
1677            relative; in the latter case, to avoid double slash.)  */
1678         sprintf (newdir, "%s%s", odir, f->name);
1679       else
1680         /* Else, use a separator. */
1681         sprintf (newdir, "%s/%s", odir, f->name);
1682
1683       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
1684       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
1685                odir, f->name, newdir));
1686       if (!accdir (newdir, ALLABS))
1687         {
1688           logprintf (LOG_VERBOSE, _("\
1689 Not descending to `%s' as it is excluded/not-included.\n"), newdir);
1690           continue;
1691         }
1692
1693       con->st &= ~DONE_CWD;
1694
1695       odir = xstrdup (u->dir);  /* because url_set_dir will free
1696                                    u->dir. */
1697       url_set_dir (u, newdir);
1698       ftp_retrieve_glob (u, con, GETALL);
1699       url_set_dir (u, odir);
1700       xfree (odir);
1701
1702       /* Set the time-stamp?  */
1703     }
1704
1705   if (opt.quota && total_downloaded_bytes > opt.quota)
1706     return QUOTEXC;
1707   else
1708     return RETROK;
1709 }
1710
1711 /* Return non-zero if S has a leading '/'  or contains '../' */
1712 static int
1713 has_insecure_name_p (const char *s)
1714 {
1715   if (*s == '/')
1716     return 1;
1717
1718   if (strstr (s, "../") != 0)
1719     return 1;
1720
1721   return 0;
1722 }
1723
1724 /* A near-top-level function to retrieve the files in a directory.
1725    The function calls ftp_get_listing, to get a linked list of files.
1726    Then it weeds out the file names that do not match the pattern.
1727    ftp_retrieve_list is called with this updated list as an argument.
1728
1729    If the argument ACTION is GETONE, just download the file (but first
1730    get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1731    use globbing; if it's GETALL, download the whole directory.  */
1732 static uerr_t
1733 ftp_retrieve_glob (struct url *u, ccon *con, int action)
1734 {
1735   struct fileinfo *f, *start;
1736   uerr_t res;
1737
1738   con->cmd |= LEAVE_PENDING;
1739
1740   res = ftp_get_listing (u, con, &start);
1741   if (res != RETROK)
1742     return res;
1743   /* First: weed out that do not conform the global rules given in
1744      opt.accepts and opt.rejects.  */
1745   if (opt.accepts || opt.rejects)
1746     {
1747       f = start;
1748       while (f)
1749         {
1750           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1751             {
1752               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1753               f = delelement (f, &start);
1754             }
1755           else
1756             f = f->next;
1757         }
1758     }
1759   /* Remove all files with possible harmful names */
1760   f = start;
1761   while (f)
1762     {
1763       if (has_insecure_name_p (f->name))
1764         {
1765           logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1766           f = delelement (f, &start);
1767         }
1768       else
1769         f = f->next;
1770     }
1771   /* Now weed out the files that do not match our globbing pattern.
1772      If we are dealing with a globbing pattern, that is.  */
1773   if (*u->file && (action == GLOBALL || action == GETONE))
1774     {
1775       int matchres = 0;
1776
1777       f = start;
1778       while (f)
1779         {
1780           matchres = fnmatch (u->file, f->name, 0);
1781           if (matchres == -1)
1782             {
1783               logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
1784                          strerror (errno));
1785               break;
1786             }
1787           if (matchres == FNM_NOMATCH)
1788             f = delelement (f, &start); /* delete the element from the list */
1789           else
1790             f = f->next;        /* leave the element in the list */
1791         }
1792       if (matchres == -1)
1793         {
1794           freefileinfo (start);
1795           return RETRBADPATTERN;
1796         }
1797     }
1798   res = RETROK;
1799   if (start)
1800     {
1801       /* Just get everything.  */
1802       ftp_retrieve_list (u, start, con);
1803     }
1804   else if (!start)
1805     {
1806       if (action == GLOBALL)
1807         {
1808           /* No luck.  */
1809           /* #### This message SUCKS.  We should see what was the
1810              reason that nothing was retrieved.  */
1811           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1812         }
1813       else /* GETONE or GETALL */
1814         {
1815           /* Let's try retrieving it anyway.  */
1816           con->st |= ON_YOUR_OWN;
1817           res = ftp_loop_internal (u, NULL, con);
1818           return res;
1819         }
1820     }
1821   freefileinfo (start);
1822   if (opt.quota && total_downloaded_bytes > opt.quota)
1823     return QUOTEXC;
1824   else
1825     /* #### Should we return `res' here?  */
1826     return RETROK;
1827 }
1828
1829 /* The wrapper that calls an appropriate routine according to contents
1830    of URL.  Inherently, its capabilities are limited on what can be
1831    encoded into a URL.  */
1832 uerr_t
1833 ftp_loop (struct url *u, int *dt, struct url *proxy)
1834 {
1835   ccon con;                     /* FTP connection */
1836   uerr_t res;
1837
1838   *dt = 0;
1839
1840   memset (&con, 0, sizeof (con));
1841
1842   con.csock = -1;
1843   con.st = ON_YOUR_OWN;
1844   con.rs = ST_UNIX;
1845   con.id = NULL;
1846   con.proxy = proxy;
1847   res = RETROK;                 /* in case it's not used */
1848
1849   /* If the file name is empty, the user probably wants a directory
1850      index.  We'll provide one, properly HTML-ized.  Unless
1851      opt.htmlify is 0, of course.  :-) */
1852   if (!*u->file && !opt.recursive)
1853     {
1854       struct fileinfo *f;
1855       res = ftp_get_listing (u, &con, &f);
1856
1857       if (res == RETROK)
1858         {
1859           if (opt.htmlify && !opt.spider)
1860             {
1861               char *filename = (opt.output_document
1862                                 ? xstrdup (opt.output_document)
1863                                 : (con.target ? xstrdup (con.target)
1864                                    : url_file_name (u)));
1865               res = ftp_index (filename, u, f);
1866               if (res == FTPOK && opt.verbose)
1867                 {
1868                   if (!opt.output_document)
1869                     {
1870                       struct stat st;
1871                       long sz;
1872                       if (stat (filename, &st) == 0)
1873                         sz = st.st_size;
1874                       else
1875                         sz = -1;
1876                       logprintf (LOG_NOTQUIET,
1877                                  _("Wrote HTML-ized index to `%s' [%ld].\n"),
1878                                  filename, sz);
1879                     }
1880                   else
1881                     logprintf (LOG_NOTQUIET,
1882                                _("Wrote HTML-ized index to `%s'.\n"),
1883                                filename);
1884                 }
1885               xfree (filename);
1886             }
1887           freefileinfo (f);
1888         }
1889     }
1890   else
1891     {
1892       int wild = has_wildcards_p (u->file);
1893       if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1894         {
1895           /* ftp_retrieve_glob is a catch-all function that gets called
1896              if we need globbing, time-stamping or recursion.  Its
1897              third argument is just what we really need.  */
1898           res = ftp_retrieve_glob (u, &con,
1899                                    (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1900         }
1901       else
1902         res = ftp_loop_internal (u, NULL, &con);
1903     }
1904   if (res == FTPOK)
1905     res = RETROK;
1906   if (res == RETROK)
1907     *dt |= RETROKF;
1908   /* If a connection was left, quench it.  */
1909   if (con.csock != -1)
1910     fd_close (con.csock);
1911   xfree_null (con.id);
1912   con.id = NULL;
1913   xfree_null (con.target);
1914   con.target = NULL;
1915   return res;
1916 }
1917
1918 /* Delete an element from the fileinfo linked list.  Returns the
1919    address of the next element, or NULL if the list is exhausted.  It
1920    can modify the start of the list.  */
1921 static struct fileinfo *
1922 delelement (struct fileinfo *f, struct fileinfo **start)
1923 {
1924   struct fileinfo *prev = f->prev;
1925   struct fileinfo *next = f->next;
1926
1927   xfree (f->name);
1928   xfree_null (f->linkto);
1929   xfree (f);
1930
1931   if (next)
1932     next->prev = prev;
1933   if (prev)
1934     prev->next = next;
1935   else
1936     *start = next;
1937   return next;
1938 }
1939
1940 /* Free the fileinfo linked list of files.  */
1941 static void
1942 freefileinfo (struct fileinfo *f)
1943 {
1944   while (f)
1945     {
1946       struct fileinfo *next = f->next;
1947       xfree (f->name);
1948       if (f->linkto)
1949         xfree (f->linkto);
1950       xfree (f);
1951       f = next;
1952     }
1953 }