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