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