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