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