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