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