]> sjero.net Git - wget/blob - src/ftp.c
9077c674c4b243477754e304553698711a20e3dd
[wget] / src / ftp.c
1 /* File Transfer Protocol support.
2    Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of Wget.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #ifdef HAVE_STRING_H
25 # include <string.h>
26 #else
27 # include <strings.h>
28 #endif
29 #include <ctype.h>
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
37 #include "wget.h"
38 #include "utils.h"
39 #include "url.h"
40 #include "rbuf.h"
41 #include "retr.h"
42 #include "ftp.h"
43 #include "html.h"
44 #include "connect.h"
45 #include "host.h"
46 #include "fnmatch.h"
47 #include "netrc.h"
48
49 #ifndef errno
50 extern int errno;
51 #endif
52 #ifndef h_errno
53 extern int h_errno;
54 #endif
55
56 /* File where the "ls -al" listing will be saved.  */
57 #define LIST_FILENAME ".listing"
58
59 extern char ftp_last_respline[];
60
61 /* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
62    the string S, and return the number converted to long, if found, 0
63    otherwise.  */
64 static long
65 ftp_expected_bytes (const char *s)
66 {
67   long res;
68
69   while (1)
70     {
71       while (*s && *s != '(')
72         ++s;
73       if (!*s)
74         return 0;
75       for (++s; *s && ISSPACE (*s); s++);
76       if (!*s)
77         return 0;
78       if (!ISDIGIT (*s))
79         continue;
80       res = 0;
81       do
82         {
83           res = (*s - '0') + 10 * res;
84           ++s;
85         }
86       while (*s && ISDIGIT (*s));
87       if (!*s)
88         return 0;
89       while (*s && ISSPACE (*s))
90         ++s;
91       if (!*s)
92         return 0;
93       if (tolower (*s) != 'b')
94         continue;
95       if (strncasecmp (s, "byte", 4))
96         continue;
97       else
98         break;
99     }
100   return res;
101 }
102
103 /* Retrieves a file with denoted parameters through opening an FTP
104    connection to the server.  It always closes the data connection,
105    and closes the control connection in case of error.  */
106 static uerr_t
107 getftp (const struct urlinfo *u, long *len, long restval, ccon *con)
108 {
109   int csock, dtsock, res;
110   uerr_t err;
111   FILE *fp;
112   char *user, *passwd, *respline;
113   char *tms, *tmrate;
114   unsigned char pasv_addr[6];
115   int cmd = con->cmd;
116   int passive_mode_open = 0;
117   long expected_bytes = 0L;
118
119   assert (con != NULL);
120   assert (u->local != NULL);
121   /* Debug-check of the sanity of the request by making sure that LIST
122      and RETR are never both requested (since we can handle only one
123      at a time.  */
124   assert (!((cmd & DO_LIST) && (cmd & DO_RETR)));
125   /* Make sure that at least *something* is requested.  */
126   assert ((cmd & (DO_LIST | DO_CWD | DO_RETR | DO_LOGIN)) != 0);
127
128   user = u->user;
129   passwd = u->passwd;
130   search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
131   user = user ? user : opt.ftp_acc;
132   if (!opt.ftp_pass)
133     opt.ftp_pass = xstrdup (ftp_getaddress ());
134   passwd = passwd ? passwd : opt.ftp_pass;
135   assert (user && passwd);
136
137   dtsock = -1;
138   con->dltime = 0;
139
140   if (!(cmd & DO_LOGIN))
141     csock = RBUF_FD (&con->rbuf);
142   else                          /* cmd & DO_LOGIN */
143     {
144       /* Login to the server: */
145
146       /* First: Establish the control connection.  */
147       logprintf (LOG_VERBOSE, _("Connecting to %s:%hu... "), u->host, u->port);
148       err = make_connection (&csock, u->host, u->port);
149       if (cmd & LEAVE_PENDING)
150         rbuf_initialize (&con->rbuf, csock);
151       else
152         rbuf_uninitialize (&con->rbuf);
153       switch (err)
154         {
155           /* Do not close the socket in first several cases, since it
156              wasn't created at all.  */
157         case HOSTERR:
158           logputs (LOG_VERBOSE, "\n");
159           logprintf (LOG_NOTQUIET, "%s: %s\n", u->host, herrmsg (h_errno));
160           return HOSTERR;
161           break;
162         case CONSOCKERR:
163           logputs (LOG_VERBOSE, "\n");
164           logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
165           return CONSOCKERR;
166           break;
167         case CONREFUSED:
168           logputs (LOG_VERBOSE, "\n");
169           logprintf (LOG_NOTQUIET, _("Connection to %s:%hu refused.\n"),
170                      u->host, u->port);
171           CLOSE (csock);
172           rbuf_uninitialize (&con->rbuf);
173           return CONREFUSED;
174         case CONERROR:
175           logputs (LOG_VERBOSE, "\n");
176           logprintf (LOG_NOTQUIET, "connect: %s\n", strerror (errno));
177           CLOSE (csock);
178           rbuf_uninitialize (&con->rbuf);
179           return CONERROR;
180           break;
181         default:
182           DO_NOTHING;
183           /* #### Hmm?  */
184         }
185       /* Since this is a new connection, we may safely discard
186          anything left in the buffer.  */
187       rbuf_discard (&con->rbuf);
188
189       /* Second: Login with proper USER/PASS sequence.  */
190       logputs (LOG_VERBOSE, _("connected!\n"));
191       logprintf (LOG_VERBOSE, _("Logging in as %s ... "), user);
192       if (opt.server_response)
193         logputs (LOG_ALWAYS, "\n");
194       err = ftp_login (&con->rbuf, user, passwd);
195       /* FTPRERR, FTPSRVERR, WRITEFAILED, FTPLOGREFUSED, FTPLOGINC */
196       switch (err)
197         {
198         case FTPRERR:
199           logputs (LOG_VERBOSE, "\n");
200           logputs (LOG_NOTQUIET, _("\
201 Error in server response, closing control connection.\n"));
202           CLOSE (csock);
203           rbuf_uninitialize (&con->rbuf);
204           return err;
205           break;
206         case FTPSRVERR:
207           logputs (LOG_VERBOSE, "\n");
208           logputs (LOG_NOTQUIET, _("Error in server greeting.\n"));
209           CLOSE (csock);
210           rbuf_uninitialize (&con->rbuf);
211           return err;
212           break;
213         case WRITEFAILED:
214           logputs (LOG_VERBOSE, "\n");
215           logputs (LOG_NOTQUIET,
216                    _("Write failed, closing control connection.\n"));
217           CLOSE (csock);
218           rbuf_uninitialize (&con->rbuf);
219           return err;
220           break;
221         case FTPLOGREFUSED:
222           logputs (LOG_VERBOSE, "\n");
223           logputs (LOG_NOTQUIET, _("The server refuses login.\n"));
224           CLOSE (csock);
225           rbuf_uninitialize (&con->rbuf);
226           return FTPLOGREFUSED;
227           break;
228         case FTPLOGINC:
229           logputs (LOG_VERBOSE, "\n");
230           logputs (LOG_NOTQUIET, _("Login incorrect.\n"));
231           CLOSE (csock);
232           rbuf_uninitialize (&con->rbuf);
233           return FTPLOGINC;
234           break;
235         case FTPOK:
236           if (!opt.server_response)
237             logputs (LOG_VERBOSE, _("Logged in!\n"));
238           break;
239         default:
240           abort ();
241           exit (1);
242           break;
243         }
244       /* Third: Set type to Image (binary).  */
245       if (!opt.server_response)
246         logprintf (LOG_VERBOSE, "==> TYPE %c ... ", toupper (u->ftp_type));
247       err = ftp_type (&con->rbuf, toupper (u->ftp_type));
248       /* FTPRERR, WRITEFAILED, FTPUNKNOWNTYPE */
249       switch (err)
250         {
251         case FTPRERR:
252           logputs (LOG_VERBOSE, "\n");
253           logputs (LOG_NOTQUIET, _("\
254 Error in server response, closing control connection.\n"));
255           CLOSE (csock);
256           rbuf_uninitialize (&con->rbuf);
257           return err;
258           break;
259         case WRITEFAILED:
260           logputs (LOG_VERBOSE, "\n");
261           logputs (LOG_NOTQUIET,
262                    _("Write failed, closing control connection.\n"));
263           CLOSE (csock);
264           rbuf_uninitialize (&con->rbuf);
265           return err;
266           break;
267         case FTPUNKNOWNTYPE:
268           logputs (LOG_VERBOSE, "\n");
269           logprintf (LOG_NOTQUIET,
270                      _("Unknown type `%c', closing control connection.\n"),
271                      toupper (u->ftp_type));
272           CLOSE (csock);
273           rbuf_uninitialize (&con->rbuf);
274           return err;
275         case FTPOK:
276           /* Everything is OK.  */
277           break;
278         default:
279           abort ();
280           break;
281         }
282       if (!opt.server_response)
283         logputs (LOG_VERBOSE, _("done.  "));
284     } /* do login */
285
286   if (cmd & DO_CWD)
287     {
288       if (!*u->dir)
289         logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
290       else
291         {
292           /* Change working directory.  */
293           if (!opt.server_response)
294             logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
295           err = ftp_cwd (&con->rbuf, u->dir);
296           /* FTPRERR, WRITEFAILED, FTPNSFOD */
297           switch (err)
298             {
299             case FTPRERR:
300               logputs (LOG_VERBOSE, "\n");
301               logputs (LOG_NOTQUIET, _("\
302 Error in server response, closing control connection.\n"));
303               CLOSE (csock);
304               rbuf_uninitialize (&con->rbuf);
305               return err;
306               break;
307             case WRITEFAILED:
308               logputs (LOG_VERBOSE, "\n");
309               logputs (LOG_NOTQUIET,
310                        _("Write failed, closing control connection.\n"));
311               CLOSE (csock);
312               rbuf_uninitialize (&con->rbuf);
313               return err;
314               break;
315             case FTPNSFOD:
316               logputs (LOG_VERBOSE, "\n");
317               logprintf (LOG_NOTQUIET, _("No such directory `%s'.\n\n"),
318                          u->dir);
319               CLOSE (csock);
320               rbuf_uninitialize (&con->rbuf);
321               return err;
322               break;
323             case FTPOK:
324               /* fine and dandy */
325               break;
326             default:
327               abort ();
328               break;
329             }
330           if (!opt.server_response)
331             logputs (LOG_VERBOSE, _("done.\n"));
332         }
333     }
334   else /* do not CWD */
335     logputs (LOG_VERBOSE, _("==> CWD not required.\n"));
336
337   /* If anything is to be retrieved, PORT (or PASV) must be sent.  */
338   if (cmd & (DO_LIST | DO_RETR))
339     {
340       if (opt.ftp_pasv)
341         {
342           char thost[256];
343           unsigned short tport;
344
345           if (!opt.server_response)
346             logputs (LOG_VERBOSE, "==> PASV ... ");
347           err = ftp_pasv (&con->rbuf, pasv_addr);
348           /* FTPRERR, WRITEFAILED, FTPNOPASV, FTPINVPASV */
349           switch (err)
350             {
351             case FTPRERR:
352               logputs (LOG_VERBOSE, "\n");
353               logputs (LOG_NOTQUIET, _("\
354 Error in server response, closing control connection.\n"));
355               CLOSE (csock);
356               rbuf_uninitialize (&con->rbuf);
357               return err;
358               break;
359             case WRITEFAILED:
360               logputs (LOG_VERBOSE, "\n");
361               logputs (LOG_NOTQUIET,
362                        _("Write failed, closing control connection.\n"));
363               CLOSE (csock);
364               rbuf_uninitialize (&con->rbuf);
365               return err;
366               break;
367             case FTPNOPASV:
368               logputs (LOG_VERBOSE, "\n");
369               logputs (LOG_NOTQUIET, _("Cannot initiate PASV transfer.\n"));
370               break;
371             case FTPINVPASV:
372               logputs (LOG_VERBOSE, "\n");
373               logputs (LOG_NOTQUIET, _("Cannot parse PASV response.\n"));
374               break;
375             case FTPOK:
376               /* fine and dandy */
377               break;
378             default:
379               abort ();
380               break;
381             }
382           if (err==FTPOK)
383             {
384               sprintf (thost, "%d.%d.%d.%d",
385                        pasv_addr[0], pasv_addr[1], pasv_addr[2], pasv_addr[3]);
386               tport = (pasv_addr[4] << 8) + pasv_addr[5];
387               DEBUGP ((_("Will try connecting to %s:%hu.\n"), thost, tport));
388               err = make_connection (&dtsock, thost, tport);
389               switch (err)
390                 {
391                   /* Do not close the socket in first several cases,
392                      since it wasn't created at all.  */
393                 case HOSTERR:
394                   logputs (LOG_VERBOSE, "\n");
395                   logprintf (LOG_NOTQUIET, "%s: %s\n", thost,
396                              herrmsg (h_errno));
397                   CLOSE (csock);
398                   rbuf_uninitialize (&con->rbuf);
399                   return HOSTERR;
400                   break;
401                 case CONSOCKERR:
402                   logputs (LOG_VERBOSE, "\n");
403                   logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
404                   CLOSE (csock);
405                   rbuf_uninitialize (&con->rbuf);
406                   return CONSOCKERR;
407                   break;
408                 case CONREFUSED:
409                   logputs (LOG_VERBOSE, "\n");
410                   logprintf (LOG_NOTQUIET,
411                              _("Connection to %s:%hu refused.\n"),
412                              thost, tport);
413                   CLOSE (csock);
414                   rbuf_uninitialize (&con->rbuf);
415                   closeport (dtsock);
416                   return CONREFUSED;
417                 case CONERROR:
418                   logputs (LOG_VERBOSE, "\n");
419                   logprintf (LOG_NOTQUIET, "connect: %s\n",
420                              strerror (errno));
421                   CLOSE (csock);
422                   rbuf_uninitialize (&con->rbuf);
423                   closeport (dtsock);
424                   return CONERROR;
425                   break;
426                 default:
427                   /* #### What?!  */
428                   DO_NOTHING;
429                 }
430               passive_mode_open= 1;  /* Flag to avoid accept port */
431               if (!opt.server_response)
432                 logputs (LOG_VERBOSE, _("done.    "));
433             } /* err==FTP_OK */
434         }
435
436       if (!passive_mode_open)   /* Try to use a port command if PASV failed */
437         {
438           if (!opt.server_response)
439             logputs (LOG_VERBOSE, "==> PORT ... ");
440           err = ftp_port (&con->rbuf);
441           /* FTPRERR, WRITEFAILED, bindport (CONSOCKERR, CONPORTERR, BINDERR,
442              LISTENERR), HOSTERR, FTPPORTERR */
443           switch (err)
444             {
445             case FTPRERR:
446               logputs (LOG_VERBOSE, "\n");
447               logputs (LOG_NOTQUIET, _("\
448 Error in server response, closing control connection.\n"));
449               CLOSE (csock);
450               closeport (dtsock);
451               rbuf_uninitialize (&con->rbuf);
452               return err;
453               break;
454             case WRITEFAILED:
455               logputs (LOG_VERBOSE, "\n");
456               logputs (LOG_NOTQUIET,
457                        _("Write failed, closing control connection.\n"));
458               CLOSE (csock);
459               closeport (dtsock);
460               rbuf_uninitialize (&con->rbuf);
461               return err;
462               break;
463             case CONSOCKERR:
464               logputs (LOG_VERBOSE, "\n");
465               logprintf (LOG_NOTQUIET, "socket: %s\n", strerror (errno));
466               CLOSE (csock);
467               closeport (dtsock);
468               rbuf_uninitialize (&con->rbuf);
469               return err;
470               break;
471             case CONPORTERR: case BINDERR: case LISTENERR:
472               /* What now?  These problems are local...  */
473               logputs (LOG_VERBOSE, "\n");
474               logprintf (LOG_NOTQUIET, _("Bind error (%s).\n"),
475                          strerror (errno));
476               closeport (dtsock);
477               return err;
478               break;
479             case HOSTERR:
480               logputs (LOG_VERBOSE, "\n");
481               logprintf (LOG_NOTQUIET, "%s: %s\n", u->host,
482                          herrmsg (h_errno));
483               CLOSE (csock);
484               closeport (dtsock);
485               rbuf_uninitialize (&con->rbuf);
486               return HOSTERR;
487               break;
488             case FTPPORTERR:
489               logputs (LOG_VERBOSE, "\n");
490               logputs (LOG_NOTQUIET, _("Invalid PORT.\n"));
491               CLOSE (csock);
492               closeport (dtsock);
493               rbuf_uninitialize (&con->rbuf);
494               return err;
495               break;
496             case FTPOK:
497               /* fine and dandy */
498               break;
499             default:
500               abort ();
501               break;
502             } /* port switch */
503           if (!opt.server_response)
504             logputs (LOG_VERBOSE, _("done.    "));
505         } /* dtsock == -1 */
506     } /* cmd & (DO_LIST | DO_RETR) */
507
508   /* Restart if needed.  */
509   if (restval && (cmd & DO_RETR))
510     {
511       if (!opt.server_response)
512         logprintf (LOG_VERBOSE, "==> REST %ld ... ", restval);
513       err = ftp_rest (&con->rbuf, restval);
514
515       /* FTPRERR, WRITEFAILED, FTPRESTFAIL */
516       switch (err)
517         {
518         case FTPRERR:
519           logputs (LOG_VERBOSE, "\n");
520           logputs (LOG_NOTQUIET, _("\
521 Error in server response, closing control connection.\n"));
522           CLOSE (csock);
523           closeport (dtsock);
524           rbuf_uninitialize (&con->rbuf);
525           return err;
526           break;
527         case WRITEFAILED:
528           logputs (LOG_VERBOSE, "\n");
529           logputs (LOG_NOTQUIET,
530                    _("Write failed, closing control connection.\n"));
531           CLOSE (csock);
532           closeport (dtsock);
533           rbuf_uninitialize (&con->rbuf);
534           return err;
535           break;
536         case FTPRESTFAIL:
537           logputs (LOG_VERBOSE, _("\nREST failed, starting from scratch.\n"));
538           restval = 0L;
539           break;
540         case FTPOK:
541           /* fine and dandy */
542           break;
543         default:
544           abort ();
545           break;
546         }
547       if (err != FTPRESTFAIL && !opt.server_response)
548         logputs (LOG_VERBOSE, _("done.    "));
549     } /* restval && cmd & DO_RETR */
550
551   if (cmd & DO_RETR)
552     {
553       if (opt.verbose)
554         {
555           if (!opt.server_response)
556             {
557               if (restval)
558                 logputs (LOG_VERBOSE, "\n");
559               logprintf (LOG_VERBOSE, "==> RETR %s ... ", u->file);
560             }
561         }
562       err = ftp_retr (&con->rbuf, u->file);
563       /* FTPRERR, WRITEFAILED, FTPNSFOD */
564       switch (err)
565         {
566         case FTPRERR:
567           logputs (LOG_VERBOSE, "\n");
568           logputs (LOG_NOTQUIET, _("\
569 Error in server response, closing control connection.\n"));
570           CLOSE (csock);
571           closeport (dtsock);
572           rbuf_uninitialize (&con->rbuf);
573           return err;
574           break;
575         case WRITEFAILED:
576           logputs (LOG_VERBOSE, "\n");
577           logputs (LOG_NOTQUIET,
578                    _("Write failed, closing control connection.\n"));
579           CLOSE (csock);
580           closeport (dtsock);
581           rbuf_uninitialize (&con->rbuf);
582           return err;
583           break;
584         case FTPNSFOD:
585           logputs (LOG_VERBOSE, "\n");
586           logprintf (LOG_NOTQUIET, _("No such file `%s'.\n\n"), u->file);
587           closeport (dtsock);
588           return err;
589           break;
590         case FTPOK:
591           /* fine and dandy */
592           break;
593         default:
594           abort ();
595           break;
596         }
597
598       if (!opt.server_response)
599         logputs (LOG_VERBOSE, _("done.\n"));
600       expected_bytes = ftp_expected_bytes (ftp_last_respline);
601     } /* do retrieve */
602
603   if (cmd & DO_LIST)
604     {
605       if (!opt.server_response)
606         logputs (LOG_VERBOSE, "==> LIST ... ");
607       /* As Maciej W. Rozycki (macro@ds2.pg.gda.pl) says, `LIST'
608          without arguments is better than `LIST .'; confirmed by
609          RFC959.  */
610       err = ftp_list (&con->rbuf, NULL);
611       /* FTPRERR, WRITEFAILED */
612       switch (err)
613         {
614         case FTPRERR:
615           logputs (LOG_VERBOSE, "\n");
616           logputs (LOG_NOTQUIET, _("\
617 Error in server response, closing control connection.\n"));
618           CLOSE (csock);
619           closeport (dtsock);
620           rbuf_uninitialize (&con->rbuf);
621           return err;
622           break;
623         case WRITEFAILED:
624           logputs (LOG_VERBOSE, "\n");
625           logputs (LOG_NOTQUIET,
626                    _("Write failed, closing control connection.\n"));
627           CLOSE (csock);
628           closeport (dtsock);
629           rbuf_uninitialize (&con->rbuf);
630           return err;
631           break;
632         case FTPNSFOD:
633           logputs (LOG_VERBOSE, "\n");
634           logprintf (LOG_NOTQUIET, _("No such file or directory `%s'.\n\n"),
635                      ".");
636           closeport (dtsock);
637           return err;
638           break;
639         case FTPOK:
640           /* fine and dandy */
641           break;
642         default:
643           abort ();
644           break;
645         }
646       if (!opt.server_response)
647         logputs (LOG_VERBOSE, _("done.\n"));
648       expected_bytes = ftp_expected_bytes (ftp_last_respline);
649     } /* cmd & DO_LIST */
650
651   /* If no transmission was required, then everything is OK.  */
652   if (!(cmd & (DO_LIST | DO_RETR)))
653     return RETRFINISHED;
654
655   if (!passive_mode_open)  /* we are not using pasive mode so we need
656                               to accept */
657     {
658       /* Open the data transmission socket by calling acceptport().  */
659       err = acceptport (&dtsock);
660       /* Possible errors: ACCEPTERR.  */
661       if (err == ACCEPTERR)
662         {
663           logprintf (LOG_NOTQUIET, "accept: %s\n", strerror (errno));
664           return err;
665         }
666     }
667
668   /* Open the file -- if opt.dfp is set, use it instead.  */
669   if (!opt.dfp || con->cmd & DO_LIST)
670     {
671       mkalldirs (u->local);
672       if (opt.backups)
673         rotate_backups (u->local);
674       /* #### Is this correct? */
675       chmod (u->local, 0600);
676
677       fp = fopen (u->local, restval ? "ab" : "wb");
678       if (!fp)
679         {
680           logprintf (LOG_NOTQUIET, "%s: %s\n", u->local, strerror (errno));
681           CLOSE (csock);
682           rbuf_uninitialize (&con->rbuf);
683           closeport (dtsock);
684           return FOPENERR;
685         }
686     }
687   else
688     fp = opt.dfp;
689
690   if (*len)
691     {
692       logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
693       if (restval)
694         logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
695       logputs (LOG_VERBOSE, "\n");
696     }
697   else if (expected_bytes)
698     {
699       logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
700       if (restval)
701         logprintf (LOG_VERBOSE, _(" [%s to go]"),
702                    legible (expected_bytes - restval));
703       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
704     }
705   reset_timer ();
706   /* Get the contents of the document.  */
707   res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf);
708   con->dltime = elapsed_time ();
709   tms = time_str (NULL);
710   tmrate = rate (*len - restval, con->dltime);
711   /* Close data connection socket.  */
712   closeport (dtsock);
713   /* Close the local file.  */
714   if (!opt.dfp || con->cmd & DO_LIST)
715     fclose (fp);
716   else
717     fflush (fp);
718   /* If get_contents couldn't write to fp, bail out.  */
719   if (res == -2)
720     {
721       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
722                  u->local, strerror (errno));
723       CLOSE (csock);
724       rbuf_uninitialize (&con->rbuf);
725       return FWRITEERR;
726     }
727   else if (res == -1)
728     {
729       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
730                  tms, tmrate, strerror (errno));
731       if (opt.server_response)
732         logputs (LOG_ALWAYS, "\n");
733     }
734
735   /* Get the server to tell us if everything is retrieved.  */
736   err = ftp_response (&con->rbuf, &respline);
737   /* ...and empty the buffer.  */
738   rbuf_discard (&con->rbuf);
739   if (err != FTPOK)
740     {
741       free (respline);
742       /* The control connection is decidedly closed.  Print the time
743          only if it hasn't already been printed.  */
744       if (res != -1)
745         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
746       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
747       /* If there is an error on the control connection, close it, but
748          return FTPRETRINT, since there is a possibility that the
749          whole file was retrieved nevertheless (but that is for
750          ftp_loop_internal to decide).  */
751       CLOSE (csock);
752       rbuf_uninitialize (&con->rbuf);
753       return FTPRETRINT;
754     } /* err != FTPOK */
755   /* If retrieval failed for any reason, return FTPRETRINT, but do not
756      close socket, since the control connection is still alive.  If
757      there is something wrong with the control connection, it will
758      become apparent later.  */
759   if (*respline != '2')
760     {
761       free (respline);
762       if (res != -1)
763         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
764       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
765       return FTPRETRINT;
766     }
767   free (respline);
768
769   if (res == -1)
770     {
771       /* What now?  The data connection was erroneous, whereas the
772          response says everything is OK.  We shall play it safe.  */
773       return FTPRETRINT;
774     }
775
776   if (!(cmd & LEAVE_PENDING))
777     {
778       /* I should probably send 'QUIT' and check for a reply, but this
779          is faster.  #### Is it OK, though?  */
780       CLOSE (csock);
781       rbuf_uninitialize (&con->rbuf);
782     }
783   /* If it was a listing, and opt.server_response is true,
784      print it out.  */
785   if (opt.server_response && (con->cmd & DO_LIST))
786     {
787       mkalldirs (u->local);
788       fp = fopen (u->local, "r");
789       if (!fp)
790         logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
791       else
792         {
793           char *line;
794           /* The lines are being read with read_whole_line because of
795              no-buffering on opt.lfile.  */
796           while ((line = read_whole_line (fp)))
797             {
798               logprintf (LOG_ALWAYS, "%s\n", line);
799               free (line);
800             }
801           fclose (fp);
802         }
803     } /* con->cmd & DO_LIST && server_response */
804
805   return RETRFINISHED;
806 }
807
808 /* A one-file FTP loop.  This is the part where FTP retrieval is
809    retried, and retried, and retried, and...
810
811    This loop either gets commands from con, or (if ON_YOUR_OWN is
812    set), makes them up to retrieve the file given by the URL.  */
813 static uerr_t
814 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
815 {
816   static int first_retrieval = 1;
817
818   int count, orig_lp;
819   long restval, len;
820   char *tms, *tmrate, *locf;
821   uerr_t err;
822   struct stat st;
823
824   if (!u->local)
825     u->local = url_filename (u);
826
827   if (opt.noclobber && file_exists_p (u->local))
828     {
829       logprintf (LOG_VERBOSE,
830                  _("File `%s' already there, not retrieving.\n"), u->local);
831       /* If the file is there, we suppose it's retrieved OK.  */
832       return RETROK;
833     }
834
835   /* Remove it if it's a link.  */
836   remove_link (u->local);
837   if (!opt.output_document)
838     locf = u->local;
839   else
840     locf = opt.output_document;
841
842   count = 0;
843
844   if (con->st & ON_YOUR_OWN)
845     con->st = ON_YOUR_OWN;
846
847   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
848
849   /* THE loop.  */
850   do
851     {
852       /* Increment the pass counter.  */
853       ++count;
854       /* Wait before the retrieval (unless this is the very first
855          retrieval).  */
856       if (!first_retrieval && opt.wait)
857         sleep (opt.wait);
858       if (first_retrieval)
859         first_retrieval = 0;
860       if (con->st & ON_YOUR_OWN)
861         {
862           con->cmd = 0;
863           con->cmd |= (DO_RETR | LEAVE_PENDING);
864           if (rbuf_initialized_p (&con->rbuf))
865             con->cmd &= ~ (DO_LOGIN | DO_CWD);
866           else
867             con->cmd |= (DO_LOGIN | DO_CWD);
868         }
869       else /* not on your own */
870         {
871           if (rbuf_initialized_p (&con->rbuf))
872             con->cmd &= ~DO_LOGIN;
873           else
874             con->cmd |= DO_LOGIN;
875           if (con->st & DONE_CWD)
876             con->cmd &= ~DO_CWD;
877           else
878             con->cmd |= DO_CWD;
879         }
880       /* Assume no restarting.  */
881       restval = 0L;
882       if ((count > 1 || opt.always_rest)
883           && !(con->cmd & DO_LIST)
884           && file_exists_p (u->local))
885         if (stat (u->local, &st) == 0)
886           restval = st.st_size;
887       /* Get the current time string.  */
888       tms = time_str (NULL);
889       /* Print fetch message, if opt.verbose.  */
890       if (opt.verbose)
891         {
892           char *hurl = str_url (u->proxy ? u->proxy : u, 1);
893           char tmp[15];
894           strcpy (tmp, "        ");
895           if (count > 1)
896             sprintf (tmp, _("(try:%2d)"), count);
897           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
898                      tms, hurl, tmp, locf);
899 #ifdef WINDOWS
900           ws_changetitle (hurl, 1);
901 #endif
902           free (hurl);
903         }
904       /* Send getftp the proper length, if fileinfo was provided.  */
905       if (f)
906         len = f->size;
907       else
908         len = 0;
909       err = getftp (u, &len, restval, con);
910       /* Time?  */
911       tms = time_str (NULL);
912       tmrate = rate (len - restval, con->dltime);
913
914       if (!rbuf_initialized_p (&con->rbuf))
915         con->st &= ~DONE_CWD;
916       else
917         con->st |= DONE_CWD;
918
919       switch (err)
920         {
921         case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
922         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV:
923           /* Fatal errors, give up.  */
924           return err;
925           break;
926         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
927         case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
928         case BINDERR: case LISTENERR: case ACCEPTERR:
929         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
930           printwhat (count, opt.ntry);
931           /* non-fatal errors */
932           continue;
933           break;
934         case FTPRETRINT:
935           /* If the control connection was closed, the retrieval
936              will be considered OK if f->size == len.  */
937           if (!f || len != f->size)
938             {
939               printwhat (count, opt.ntry);
940               continue;
941             }
942           break;
943         case RETRFINISHED:
944           /* Great!  */
945           break;
946         default:
947           /* Not as great.  */
948           abort ();
949         }
950
951       /* If we get out of the switch above without continue'ing, we've
952          successfully downloaded a file.  Remember this fact. */
953       downloaded_file(ADD_FILE, locf);
954
955       if (con->st & ON_YOUR_OWN)
956         {
957           CLOSE (RBUF_FD (&con->rbuf));
958           rbuf_uninitialize (&con->rbuf);
959         }
960       logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
961                  tms, tmrate, locf, len);
962       logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
963                  tms, u->url, len, locf, count);
964       /* Do not count listings among the downloaded stuff, since they
965          will get deleted anyway.  */
966       if (!(con->cmd & DO_LIST))
967         {
968           ++opt.numurls;
969           opt.downloaded += len;
970         }
971       /* Restore the original leave-pendingness.  */
972       if (orig_lp)
973         con->cmd |= LEAVE_PENDING;
974       else
975         con->cmd &= ~LEAVE_PENDING;
976       return RETROK;
977     } while (!opt.ntry || (count < opt.ntry));
978
979   if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
980     {
981       CLOSE (RBUF_FD (&con->rbuf));
982       rbuf_uninitialize (&con->rbuf);
983     }
984   return TRYLIMEXC;
985 }
986
987 /* Return the directory listing in a reusable format.  The directory
988    is specifed in u->dir.  */
989 static struct fileinfo *
990 ftp_get_listing (struct urlinfo *u, ccon *con)
991 {
992   struct fileinfo *f;
993   uerr_t err;
994   char *olocal = u->local;
995   char *list_filename, *ofile;
996
997   con->st &= ~ON_YOUR_OWN;
998   con->cmd |= (DO_LIST | LEAVE_PENDING);
999   con->cmd &= ~DO_RETR;
1000   /* Get the listing filename.  */
1001   ofile = u->file;
1002   u->file = LIST_FILENAME;
1003   list_filename = url_filename (u);
1004   u->file = ofile;
1005   u->local = list_filename;
1006   DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1007   err = ftp_loop_internal (u, NULL, con);
1008   u->local = olocal;
1009   if (err == RETROK)
1010     f = ftp_parse_ls (list_filename);
1011   else
1012     f = NULL;
1013   if (opt.remove_listing)
1014     {
1015       if (unlink (list_filename))
1016         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1017       else
1018         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1019     }
1020   free (list_filename);
1021   con->cmd &= ~DO_LIST;
1022   return f;
1023 }
1024
1025 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1026                                          ccon *));
1027 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1028 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1029                                             struct fileinfo **));
1030 static void freefileinfo PARAMS ((struct fileinfo *f));
1031
1032 /* Retrieve a list of files given in struct fileinfo linked list.  If
1033    a file is a symbolic link, do not retrieve it, but rather try to
1034    set up a similar link on the local disk, if the symlinks are
1035    supported.
1036
1037    If opt.recursive is set, after all files have been retrieved,
1038    ftp_retrieve_dirs will be called to retrieve the directories.  */
1039 static uerr_t
1040 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1041 {
1042   static int depth = 0;
1043   uerr_t err;
1044   char *olocal, *ofile;
1045   struct fileinfo *orig;
1046   long local_size;
1047   time_t tml;
1048   int dlthis;
1049
1050   /* Increase the depth.  */
1051   ++depth;
1052   if (opt.reclevel && depth > opt.reclevel)
1053     {
1054       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1055                depth, opt.reclevel));
1056       --depth;
1057       return RECLEVELEXC;
1058     }
1059
1060   assert (f != NULL);
1061   orig = f;
1062
1063   con->st &= ~ON_YOUR_OWN;
1064   if (!(con->st & DONE_CWD))
1065     con->cmd |= DO_CWD;
1066   else
1067     con->cmd &= ~DO_CWD;
1068   con->cmd |= (DO_RETR | LEAVE_PENDING);
1069
1070   if (!rbuf_initialized_p (&con->rbuf))
1071     con->cmd |= DO_LOGIN;
1072   else
1073     con->cmd &= ~DO_LOGIN;
1074
1075   err = RETROK;                 /* in case it's not used */
1076
1077   while (f)
1078     {
1079       if (opt.quota && opt.downloaded > opt.quota)
1080         {
1081           --depth;
1082           return QUOTEXC;
1083         }
1084       olocal = u->local;
1085       ofile = u->file;
1086       u->file = f->name;
1087       u->local = url_filename (u);
1088       err = RETROK;
1089
1090       dlthis = 1;
1091       if (opt.timestamping && f->type == FT_PLAINFILE)
1092         {
1093           struct stat st;
1094           /* If conversion of HTML files retrieved via FTP is ever implemented,
1095              we'll need to stat() <file>.orig here when -K has been specified.
1096              I'm not implementing it now since files on an FTP server are much
1097              more likely than files on an HTTP server to legitimately have a
1098              .orig suffix. */
1099           if (!stat (u->local, &st))
1100             {
1101               /* Else, get it from the file.  */
1102               local_size = st.st_size;
1103               tml = st.st_mtime;
1104               if (local_size == f->size && tml >= f->tstamp)
1105                 {
1106                   logprintf (LOG_VERBOSE, _("\
1107 Server file no newer than local file `%s' -- not retrieving.\n\n"), u->local);
1108                   dlthis = 0;
1109                 }
1110               else if (local_size != f->size)
1111                 {
1112                   logprintf (LOG_VERBOSE, _("\
1113 The sizes do not match (local %ld) -- retrieving.\n"), local_size);
1114                 }
1115             }
1116         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1117       switch (f->type)
1118         {
1119         case FT_SYMLINK:
1120           /* If opt.retr_symlinks is defined, we treat symlinks as
1121              if they were normal files.  There is currently no way
1122              to distinguish whether they might be directories, and
1123              follow them.  */
1124           if (!opt.retr_symlinks)
1125             {
1126 #ifdef HAVE_SYMLINK
1127               if (!f->linkto)
1128                 logputs (LOG_NOTQUIET,
1129                          _("Invalid name of the symlink, skipping.\n"));
1130               else
1131                 {
1132                   struct stat st;
1133                   /* Check whether we already have the correct
1134                      symbolic link.  */
1135                   int rc = lstat (u->local, &st);
1136                   if (rc == 0)
1137                     {
1138                       size_t len = strlen (f->linkto) + 1;
1139                       if (S_ISLNK (st.st_mode))
1140                         {
1141                           char *link_target = (char *)alloca (len);
1142                           size_t n = readlink (u->local, link_target, len);
1143                           if ((n == len - 1)
1144                               && (memcmp (link_target, f->linkto, n) == 0))
1145                             {
1146                               logprintf (LOG_VERBOSE, _("\
1147 Already have correct symlink %s -> %s\n\n"),
1148                                          u->local, f->linkto);
1149                               dlthis = 0;
1150                               break;
1151                             }
1152                         }
1153                     }
1154                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1155                              u->local, f->linkto);
1156                   /* Unlink before creating symlink!  */
1157                   unlink (u->local);
1158                   if (symlink (f->linkto, u->local) == -1)
1159                     logprintf (LOG_NOTQUIET, "symlink: %s\n",
1160                                strerror (errno));
1161                   logputs (LOG_VERBOSE, "\n");
1162                 } /* have f->linkto */
1163 #else  /* not HAVE_SYMLINK */
1164               logprintf (LOG_NOTQUIET,
1165                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1166                          u->local);
1167 #endif /* not HAVE_SYMLINK */
1168             }
1169           else                /* opt.retr_symlinks */
1170             {
1171               if (dlthis)
1172                 err = ftp_loop_internal (u, f, con);
1173             } /* opt.retr_symlinks */
1174           break;
1175         case FT_DIRECTORY:
1176           if (!opt.recursive)
1177             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1178                        f->name);
1179           break;
1180         case FT_PLAINFILE:
1181           /* Call the retrieve loop.  */
1182           if (dlthis)
1183             err = ftp_loop_internal (u, f, con);
1184           break;
1185         case FT_UNKNOWN:
1186           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1187                      f->name);
1188           break;
1189         }       /* switch */
1190
1191       /* Set the time-stamp information to the local file.  Symlinks
1192          are not to be stamped because it sets the stamp on the
1193          original.  :( */
1194       if (!opt.dfp
1195           && !(f->type == FT_SYMLINK && !opt.retr_symlinks)
1196           && f->tstamp != -1
1197           && dlthis
1198           && file_exists_p (u->local))
1199         {
1200           touch (u->local, f->tstamp);
1201         }
1202       else if (f->tstamp == -1)
1203         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1204
1205       if (f->perms && dlthis)
1206         chmod (u->local, f->perms);
1207       else
1208         DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1209
1210       free (u->local);
1211       u->local = olocal;
1212       u->file = ofile;
1213       /* Break on fatals.  */
1214       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1215         break;
1216       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1217       f = f->next;
1218     } /* while */
1219   /* We do not want to call ftp_retrieve_dirs here */
1220   if (opt.recursive && !(opt.reclevel && depth >= opt.reclevel))
1221     err = ftp_retrieve_dirs (u, orig, con);
1222   else if (opt.recursive)
1223     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1224              depth, opt.reclevel));
1225   --depth;
1226   return err;
1227 }
1228
1229 /* Retrieve the directories given in a file list.  This function works
1230    by simply going through the linked list and calling
1231    ftp_retrieve_glob on each directory entry.  The function knows
1232    about excluded directories.  */
1233 static uerr_t
1234 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1235 {
1236   char *odir;
1237   char *current_container = NULL;
1238   int current_length = 0;
1239
1240   for (; f; f = f->next)
1241     {
1242       int len;
1243
1244       if (opt.quota && opt.downloaded > opt.quota)
1245         break;
1246       if (f->type != FT_DIRECTORY)
1247         continue;
1248       odir = u->dir;
1249       len = 1 + strlen (u->dir) + 1 + strlen (f->name) + 1;
1250       /* Allocate u->dir off stack, but reallocate only if a larger
1251          string is needed.  */
1252       if (len > current_length)
1253         current_container = (char *)alloca (len);
1254       u->dir = current_container;
1255       /* When retrieving recursively, all directories must be
1256          absolute.  This restriction will (hopefully!) be lifted in
1257          the future.  */
1258       sprintf (u->dir, "/%s%s%s", odir + (*odir == '/'),
1259               (!*odir || (*odir == '/' && !* (odir + 1))) ? "" : "/", f->name);
1260       if (!accdir (u->dir, ALLABS))
1261         {
1262           logprintf (LOG_VERBOSE, _("\
1263 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1264           u->dir = odir;
1265           continue;
1266         }
1267       con->st &= ~DONE_CWD;
1268       ftp_retrieve_glob (u, con, GETALL);
1269       /* Set the time-stamp?  */
1270       u->dir = odir;
1271     }
1272   if (opt.quota && opt.downloaded > opt.quota)
1273     return QUOTEXC;
1274   else
1275     return RETROK;
1276 }
1277
1278
1279 /* A near-top-level function to retrieve the files in a directory.
1280    The function calls ftp_get_listing, to get a linked list of files.
1281    Then it weeds out the file names that do not match the pattern.
1282    ftp_retrieve_list is called with this updated list as an argument.
1283
1284    If the argument ACTION is GETONE, just download the file (but first
1285    get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1286    use globbing; if it's GETALL, download the whole directory.  */
1287 static uerr_t
1288 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1289 {
1290   struct fileinfo *orig, *start;
1291   uerr_t res;
1292
1293   con->cmd |= LEAVE_PENDING;
1294
1295   orig = ftp_get_listing (u, con);
1296   start = orig;
1297   /* First: weed out that do not conform the global rules given in
1298      opt.accepts and opt.rejects.  */
1299   if (opt.accepts || opt.rejects)
1300     {
1301       struct fileinfo *f = orig;
1302
1303       while (f)
1304         {
1305           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1306             {
1307               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1308               f = delelement (f, &start);
1309             }
1310           else
1311             f = f->next;
1312         }
1313     }
1314   /* Now weed out the files that do not match our globbing pattern.
1315      If we are dealing with a globbing pattern, that is.  */
1316   if (*u->file && (action == GLOBALL || action == GETONE))
1317     {
1318       int matchres = 0;
1319       struct fileinfo *f = start;
1320
1321       while (f)
1322         {
1323           matchres = fnmatch (u->file, f->name, 0);
1324           if (matchres == -1)
1325             {
1326               logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1327                          strerror (errno));
1328               break;
1329             }
1330           if (matchres == FNM_NOMATCH)
1331             f = delelement (f, &start); /* delete the element from the list */
1332           else
1333             f = f->next;        /* leave the element in the list */
1334         }
1335       if (matchres == -1)
1336         {
1337           freefileinfo (start);
1338           return RETRBADPATTERN;
1339         }
1340     }
1341   res = RETROK;
1342   if (start)
1343     {
1344       /* Just get everything.  */
1345       ftp_retrieve_list (u, start, con);
1346     }
1347   else if (!start)
1348     {
1349       if (action == GLOBALL)
1350         {
1351           /* No luck.  */
1352           /* #### This message SUCKS.  We should see what was the
1353              reason that nothing was retrieved.  */
1354           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1355         }
1356       else /* GETONE or GETALL */
1357         {
1358           /* Let's try retrieving it anyway.  */
1359           con->st |= ON_YOUR_OWN;
1360           res = ftp_loop_internal (u, NULL, con);
1361           return res;
1362         }
1363     }
1364   freefileinfo (start);
1365   if (opt.quota && opt.downloaded > opt.quota)
1366     return QUOTEXC;
1367   else
1368     /* #### Should we return `res' here?  */
1369     return RETROK;
1370 }
1371
1372 /* The wrapper that calls an appropriate routine according to contents
1373    of URL.  Inherently, its capabilities are limited on what can be
1374    encoded into a URL.  */
1375 uerr_t
1376 ftp_loop (struct urlinfo *u, int *dt)
1377 {
1378   ccon con;                     /* FTP connection */
1379   uerr_t res;
1380
1381   *dt = 0;
1382
1383   rbuf_uninitialize (&con.rbuf);
1384   con.st = ON_YOUR_OWN;
1385   res = RETROK;                 /* in case it's not used */
1386
1387   /* If the file name is empty, the user probably wants a directory
1388      index.  We'll provide one, properly HTML-ized.  Unless
1389      opt.htmlify is 0, of course.  :-) */
1390   if (!*u->file && !opt.recursive)
1391     {
1392       struct fileinfo *f = ftp_get_listing (u, &con);
1393
1394       if (f)
1395         {
1396           if (opt.htmlify)
1397             {
1398               char *filename = (opt.output_document
1399                                 ? xstrdup (opt.output_document)
1400                                 : (u->local ? xstrdup (u->local)
1401                                    : url_filename (u)));
1402               res = ftp_index (filename, u, f);
1403               if (res == FTPOK && opt.verbose)
1404                 {
1405                   if (!opt.output_document)
1406                     {
1407                       struct stat st;
1408                       long sz;
1409                       if (stat (filename, &st) == 0)
1410                         sz = st.st_size;
1411                       else
1412                         sz = -1;
1413                       logprintf (LOG_NOTQUIET,
1414                                  _("Wrote HTML-ized index to `%s' [%ld].\n"),
1415                                  filename, sz);
1416                     }
1417                   else
1418                     logprintf (LOG_NOTQUIET,
1419                                _("Wrote HTML-ized index to `%s'.\n"),
1420                                filename);
1421                 }
1422               free (filename);
1423             }
1424           freefileinfo (f);
1425         }
1426     }
1427   else
1428     {
1429       int wild = has_wildcards_p (u->file);
1430       if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1431         {
1432           /* ftp_retrieve_glob is a catch-all function that gets called
1433              if we need globbing, time-stamping or recursion.  Its
1434              third argument is just what we really need.  */
1435           ftp_retrieve_glob (u, &con,
1436                              (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1437         }
1438       else
1439         res = ftp_loop_internal (u, NULL, &con);
1440     }
1441   if (res == FTPOK)
1442     res = RETROK;
1443   if (res == RETROK)
1444     *dt |= RETROKF;
1445   /* If a connection was left, quench it.  */
1446   if (rbuf_initialized_p (&con.rbuf))
1447     CLOSE (RBUF_FD (&con.rbuf));
1448   return res;
1449 }
1450
1451 /* Delete an element from the fileinfo linked list.  Returns the
1452    address of the next element, or NULL if the list is exhausted.  It
1453    can modify the start of the list.  */
1454 static struct fileinfo *
1455 delelement (struct fileinfo *f, struct fileinfo **start)
1456 {
1457   struct fileinfo *prev = f->prev;
1458   struct fileinfo *next = f->next;
1459
1460   free (f->name);
1461   FREE_MAYBE (f->linkto);
1462   free (f);
1463
1464   if (next)
1465     next->prev = prev;
1466   if (prev)
1467     prev->next = next;
1468   else
1469     *start = next;
1470   return next;
1471 }
1472
1473 /* Free the fileinfo linked list of files.  */
1474 static void
1475 freefileinfo (struct fileinfo *f)
1476 {
1477   while (f)
1478     {
1479       struct fileinfo *next = f->next;
1480       free (f->name);
1481       if (f->linkto)
1482         free (f->linkto);
1483       free (f);
1484       f = next;
1485     }
1486 }