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