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