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