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