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