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