]> sjero.net Git - wget/blob - src/ftp.c
[svn] Make sure opt.dfp is rewound only on the first retrieval.
[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       extern int global_download_count;
818       fp = opt.dfp;
819
820       /* Rewind the output document if the download starts over and if
821          this is the first download.  See gethttp() for a longer
822          explanation.  */
823       if (!restval && global_download_count == 0)
824         {
825           /* This will silently fail for streams that don't correspond
826              to regular files, but that's OK.  */
827           rewind (fp);
828           clearerr (fp);
829         }
830     }
831
832   if (*len)
833     {
834       logprintf (LOG_VERBOSE, _("Length: %s"), legible (*len));
835       if (restval)
836         logprintf (LOG_VERBOSE, _(" [%s to go]"), legible (*len - restval));
837       logputs (LOG_VERBOSE, "\n");
838     }
839   else if (expected_bytes)
840     {
841       logprintf (LOG_VERBOSE, _("Length: %s"), legible (expected_bytes));
842       if (restval)
843         logprintf (LOG_VERBOSE, _(" [%s to go]"),
844                    legible (expected_bytes - restval));
845       logputs (LOG_VERBOSE, _(" (unauthoritative)\n"));
846     }
847   reset_timer ();
848   /* Get the contents of the document.  */
849   res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
850   con->dltime = elapsed_time ();
851   tms = time_str (NULL);
852   tmrate = rate (*len - restval, con->dltime, 0);
853   /* Close data connection socket.  */
854   closeport (dtsock);
855   /* Close the local file.  */
856   {
857     /* Close or flush the file.  We have to be careful to check for
858        error here.  Checking the result of fwrite() is not enough --
859        errors could go unnoticed!  */
860     int flush_res;
861     if (!opt.dfp || con->cmd & DO_LIST)
862       flush_res = fclose (fp);
863     else
864       flush_res = fflush (fp);
865     if (flush_res == EOF)
866       res = -2;
867   }
868   /* If get_contents couldn't write to fp, bail out.  */
869   if (res == -2)
870     {
871       logprintf (LOG_NOTQUIET, _("%s: %s, closing control connection.\n"),
872                  u->local, strerror (errno));
873       CLOSE (csock);
874       rbuf_uninitialize (&con->rbuf);
875       return FWRITEERR;
876     }
877   else if (res == -1)
878     {
879       logprintf (LOG_NOTQUIET, _("%s (%s) - Data connection: %s; "),
880                  tms, tmrate, strerror (errno));
881       if (opt.server_response)
882         logputs (LOG_ALWAYS, "\n");
883     }
884
885   /* Get the server to tell us if everything is retrieved.  */
886   err = ftp_response (&con->rbuf, &respline);
887   /* ...and empty the buffer.  */
888   rbuf_discard (&con->rbuf);
889   if (err != FTPOK)
890     {
891       xfree (respline);
892       /* The control connection is decidedly closed.  Print the time
893          only if it hasn't already been printed.  */
894       if (res != -1)
895         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
896       logputs (LOG_NOTQUIET, _("Control connection closed.\n"));
897       /* If there is an error on the control connection, close it, but
898          return FTPRETRINT, since there is a possibility that the
899          whole file was retrieved nevertheless (but that is for
900          ftp_loop_internal to decide).  */
901       CLOSE (csock);
902       rbuf_uninitialize (&con->rbuf);
903       return FTPRETRINT;
904     } /* err != FTPOK */
905   /* If retrieval failed for any reason, return FTPRETRINT, but do not
906      close socket, since the control connection is still alive.  If
907      there is something wrong with the control connection, it will
908      become apparent later.  */
909   if (*respline != '2')
910     {
911       xfree (respline);
912       if (res != -1)
913         logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
914       logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
915       return FTPRETRINT;
916     }
917   xfree (respline);
918
919   if (res == -1)
920     {
921       /* What now?  The data connection was erroneous, whereas the
922          response says everything is OK.  We shall play it safe.  */
923       return FTPRETRINT;
924     }
925
926   if (!(cmd & LEAVE_PENDING))
927     {
928       /* I should probably send 'QUIT' and check for a reply, but this
929          is faster.  #### Is it OK, though?  */
930       CLOSE (csock);
931       rbuf_uninitialize (&con->rbuf);
932     }
933   /* If it was a listing, and opt.server_response is true,
934      print it out.  */
935   if (opt.server_response && (con->cmd & DO_LIST))
936     {
937       mkalldirs (u->local);
938       fp = fopen (u->local, "r");
939       if (!fp)
940         logprintf (LOG_ALWAYS, "%s: %s\n", u->local, strerror (errno));
941       else
942         {
943           char *line;
944           /* The lines are being read with read_whole_line because of
945              no-buffering on opt.lfile.  */
946           while ((line = read_whole_line (fp)))
947             {
948               logprintf (LOG_ALWAYS, "%s\n", line);
949               xfree (line);
950             }
951           fclose (fp);
952         }
953     } /* con->cmd & DO_LIST && server_response */
954
955   return RETRFINISHED;
956 }
957
958 /* A one-file FTP loop.  This is the part where FTP retrieval is
959    retried, and retried, and retried, and...
960
961    This loop either gets commands from con, or (if ON_YOUR_OWN is
962    set), makes them up to retrieve the file given by the URL.  */
963 static uerr_t
964 ftp_loop_internal (struct urlinfo *u, struct fileinfo *f, ccon *con)
965 {
966   int count, orig_lp, no_truncate;
967   long restval, len;
968   char *tms, *tmrate, *locf;
969   uerr_t err;
970   struct stat st;
971
972   if (!u->local)
973     u->local = url_filename (u);
974
975   if (opt.noclobber && file_exists_p (u->local))
976     {
977       logprintf (LOG_VERBOSE,
978                  _("File `%s' already there, not retrieving.\n"), u->local);
979       /* If the file is there, we suppose it's retrieved OK.  */
980       return RETROK;
981     }
982
983   /* Remove it if it's a link.  */
984   remove_link (u->local);
985   if (!opt.output_document)
986     locf = u->local;
987   else
988     locf = opt.output_document;
989
990   count = 0;
991
992   if (con->st & ON_YOUR_OWN)
993     con->st = ON_YOUR_OWN;
994
995   orig_lp = con->cmd & LEAVE_PENDING ? 1 : 0;
996
997   /* In `-c' is used, check whether the file we're writing to exists
998      before we've done anything.  If so, we'll refuse to truncate it
999      if the server doesn't support continued downloads.  */
1000   no_truncate = 0;
1001   if (opt.always_rest)
1002     no_truncate = file_exists_p (locf);
1003
1004   /* THE loop.  */
1005   do
1006     {
1007       /* Increment the pass counter.  */
1008       ++count;
1009       sleep_between_retrievals (count);
1010       if (con->st & ON_YOUR_OWN)
1011         {
1012           con->cmd = 0;
1013           con->cmd |= (DO_RETR | LEAVE_PENDING);
1014           if (rbuf_initialized_p (&con->rbuf))
1015             con->cmd &= ~ (DO_LOGIN | DO_CWD);
1016           else
1017             con->cmd |= (DO_LOGIN | DO_CWD);
1018         }
1019       else /* not on your own */
1020         {
1021           if (rbuf_initialized_p (&con->rbuf))
1022             con->cmd &= ~DO_LOGIN;
1023           else
1024             con->cmd |= DO_LOGIN;
1025           if (con->st & DONE_CWD)
1026             con->cmd &= ~DO_CWD;
1027           else
1028             con->cmd |= DO_CWD;
1029         }
1030       if (no_truncate)
1031         con->cmd |= NO_TRUNCATE;
1032       /* Assume no restarting.  */
1033       restval = 0L;
1034       if ((count > 1 || opt.always_rest)
1035           && !(con->cmd & DO_LIST)
1036           && file_exists_p (u->local))
1037         if (stat (u->local, &st) == 0)
1038           restval = st.st_size;
1039       /* Get the current time string.  */
1040       tms = time_str (NULL);
1041       /* Print fetch message, if opt.verbose.  */
1042       if (opt.verbose)
1043         {
1044           char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1045           char tmp[15];
1046           strcpy (tmp, "        ");
1047           if (count > 1)
1048             sprintf (tmp, _("(try:%2d)"), count);
1049           logprintf (LOG_VERBOSE, "--%s--  %s\n  %s => `%s'\n",
1050                      tms, hurl, tmp, locf);
1051 #ifdef WINDOWS
1052           ws_changetitle (hurl, 1);
1053 #endif
1054           xfree (hurl);
1055         }
1056       /* Send getftp the proper length, if fileinfo was provided.  */
1057       if (f)
1058         len = f->size;
1059       else
1060         len = 0;
1061       err = getftp (u, &len, restval, con);
1062       /* Time?  */
1063       tms = time_str (NULL);
1064       tmrate = rate (len - restval, con->dltime, 0);
1065
1066       if (!rbuf_initialized_p (&con->rbuf))
1067         con->st &= ~DONE_CWD;
1068       else
1069         con->st |= DONE_CWD;
1070
1071       switch (err)
1072         {
1073         case HOSTERR: case CONREFUSED: case FWRITEERR: case FOPENERR:
1074         case FTPNSFOD: case FTPLOGINC: case FTPNOPASV: case CONTNOTSUPPORTED:
1075           /* Fatal errors, give up.  */
1076           return err;
1077           break;
1078         case CONSOCKERR: case CONERROR: case FTPSRVERR: case FTPRERR:
1079         case WRITEFAILED: case FTPUNKNOWNTYPE: case CONPORTERR:
1080         case BINDERR: case LISTENERR: case ACCEPTERR:
1081         case FTPPORTERR: case FTPLOGREFUSED: case FTPINVPASV:
1082           printwhat (count, opt.ntry);
1083           /* non-fatal errors */
1084           continue;
1085           break;
1086         case FTPRETRINT:
1087           /* If the control connection was closed, the retrieval
1088              will be considered OK if f->size == len.  */
1089           if (!f || len != f->size)
1090             {
1091               printwhat (count, opt.ntry);
1092               continue;
1093             }
1094           break;
1095         case RETRFINISHED:
1096           /* Great!  */
1097           break;
1098         default:
1099           /* Not as great.  */
1100           abort ();
1101         }
1102
1103       /* If we get out of the switch above without continue'ing, we've
1104          successfully downloaded a file.  Remember this fact. */
1105       downloaded_file(FILE_DOWNLOADED_NORMALLY, locf);
1106
1107       if (con->st & ON_YOUR_OWN)
1108         {
1109           CLOSE (RBUF_FD (&con->rbuf));
1110           rbuf_uninitialize (&con->rbuf);
1111         }
1112       logprintf (LOG_VERBOSE, _("%s (%s) - `%s' saved [%ld]\n\n"),
1113                  tms, tmrate, locf, len);
1114       if (!opt.verbose && !opt.quiet)
1115         {
1116           /* Need to hide the password from the URL.  The `if' is here
1117              so that we don't do the needless allocation every
1118              time. */
1119           char *hurl = str_url (u->proxy ? u->proxy : u, 1);
1120           logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
1121                      tms, hurl, len, locf, count);
1122           xfree (hurl);
1123         }
1124
1125       if ((con->cmd & DO_LIST))
1126         /* This is a directory listing file. */
1127         {
1128           if (!opt.remove_listing)
1129             /* --dont-remove-listing was specified, so do count this towards the
1130                number of bytes and files downloaded. */
1131             {
1132               downloaded_increase (len);
1133               opt.numurls++;
1134             }
1135
1136           /* Deletion of listing files is not controlled by --delete-after, but
1137              by the more specific option --dont-remove-listing, and the code
1138              to do this deletion is in another function. */
1139         }
1140       else
1141         /* This is not a directory listing file. */
1142         {
1143           /* Unlike directory listing files, don't pretend normal files weren't
1144              downloaded if they're going to be deleted.  People seeding proxies,
1145              for instance, may want to know how many bytes and files they've
1146              downloaded through it. */
1147           downloaded_increase (len);
1148           opt.numurls++;
1149
1150           if (opt.delete_after)
1151             {
1152               DEBUGP (("Removing file due to --delete-after in"
1153                        " ftp_loop_internal():\n"));
1154               logprintf (LOG_VERBOSE, _("Removing %s.\n"), locf);
1155               if (unlink (locf))
1156                 logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1157             }
1158         }
1159       
1160       /* Restore the original leave-pendingness.  */
1161       if (orig_lp)
1162         con->cmd |= LEAVE_PENDING;
1163       else
1164         con->cmd &= ~LEAVE_PENDING;
1165       return RETROK;
1166     } while (!opt.ntry || (count < opt.ntry));
1167
1168   if (rbuf_initialized_p (&con->rbuf) && (con->st & ON_YOUR_OWN))
1169     {
1170       CLOSE (RBUF_FD (&con->rbuf));
1171       rbuf_uninitialize (&con->rbuf);
1172     }
1173   return TRYLIMEXC;
1174 }
1175
1176 /* Return the directory listing in a reusable format.  The directory
1177    is specifed in u->dir.  */
1178 uerr_t
1179 ftp_get_listing (struct urlinfo *u, ccon *con, struct fileinfo **f)
1180 {
1181   uerr_t err;
1182   char *olocal = u->local;
1183   char *list_filename, *ofile;
1184
1185   con->st &= ~ON_YOUR_OWN;
1186   con->cmd |= (DO_LIST | LEAVE_PENDING);
1187   con->cmd &= ~DO_RETR;
1188   /* Get the listing filename.  */
1189   ofile = u->file;
1190   u->file = LIST_FILENAME;
1191   list_filename = url_filename (u);
1192   u->file = ofile;
1193   u->local = list_filename;
1194   DEBUGP ((_("Using `%s' as listing tmp file.\n"), list_filename));
1195   err = ftp_loop_internal (u, NULL, con);
1196   u->local = olocal;
1197   if (err == RETROK)
1198     *f = ftp_parse_ls (list_filename, con->rs);
1199   else
1200     *f = NULL;
1201   if (opt.remove_listing)
1202     {
1203       if (unlink (list_filename))
1204         logprintf (LOG_NOTQUIET, "unlink: %s\n", strerror (errno));
1205       else
1206         logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
1207     }
1208   xfree (list_filename);
1209   con->cmd &= ~DO_LIST;
1210   return err;
1211 }
1212
1213 static uerr_t ftp_retrieve_dirs PARAMS ((struct urlinfo *, struct fileinfo *,
1214                                          ccon *));
1215 static uerr_t ftp_retrieve_glob PARAMS ((struct urlinfo *, ccon *, int));
1216 static struct fileinfo *delelement PARAMS ((struct fileinfo *,
1217                                             struct fileinfo **));
1218 static void freefileinfo PARAMS ((struct fileinfo *f));
1219
1220 /* Retrieve a list of files given in struct fileinfo linked list.  If
1221    a file is a symbolic link, do not retrieve it, but rather try to
1222    set up a similar link on the local disk, if the symlinks are
1223    supported.
1224
1225    If opt.recursive is set, after all files have been retrieved,
1226    ftp_retrieve_dirs will be called to retrieve the directories.  */
1227 static uerr_t
1228 ftp_retrieve_list (struct urlinfo *u, struct fileinfo *f, ccon *con)
1229 {
1230   static int depth = 0;
1231   uerr_t err;
1232   char *olocal, *ofile;
1233   struct fileinfo *orig;
1234   long local_size;
1235   time_t tml;
1236   int dlthis;
1237
1238   /* Increase the depth.  */
1239   ++depth;
1240   if (opt.reclevel != INFINITE_RECURSION && depth > opt.reclevel)
1241     {
1242       DEBUGP ((_("Recursion depth %d exceeded max. depth %d.\n"),
1243                depth, opt.reclevel));
1244       --depth;
1245       return RECLEVELEXC;
1246     }
1247
1248   assert (f != NULL);
1249   orig = f;
1250
1251   con->st &= ~ON_YOUR_OWN;
1252   if (!(con->st & DONE_CWD))
1253     con->cmd |= DO_CWD;
1254   else
1255     con->cmd &= ~DO_CWD;
1256   con->cmd |= (DO_RETR | LEAVE_PENDING);
1257
1258   if (!rbuf_initialized_p (&con->rbuf))
1259     con->cmd |= DO_LOGIN;
1260   else
1261     con->cmd &= ~DO_LOGIN;
1262
1263   err = RETROK;                 /* in case it's not used */
1264
1265   while (f)
1266     {
1267       if (downloaded_exceeds_quota ())
1268         {
1269           --depth;
1270           return QUOTEXC;
1271         }
1272       olocal = u->local;
1273       ofile = u->file;
1274       u->file = f->name;
1275       u->local = url_filename (u);
1276       err = RETROK;
1277
1278       dlthis = 1;
1279       if (opt.timestamping && f->type == FT_PLAINFILE)
1280         {
1281           struct stat st;
1282           /* If conversion of HTML files retrieved via FTP is ever implemented,
1283              we'll need to stat() <file>.orig here when -K has been specified.
1284              I'm not implementing it now since files on an FTP server are much
1285              more likely than files on an HTTP server to legitimately have a
1286              .orig suffix. */
1287           if (!stat (u->local, &st))
1288             {
1289               int eq_size;
1290               int cor_val;
1291               /* Else, get it from the file.  */
1292               local_size = st.st_size;
1293               tml = st.st_mtime;
1294               /* Compare file sizes only for servers that tell us correct
1295                  values. Assumme sizes being equal for servers that lie
1296                  about file size.  */
1297               cor_val = (con->rs == ST_UNIX || con->rs == ST_WINNT);
1298               eq_size = cor_val ? (local_size == f->size) : 1 ;
1299               if (f->tstamp <= tml && eq_size)
1300                 {
1301                   /* Remote file is older, file sizes can be compared and
1302                      are both equal. */
1303                   logprintf (LOG_VERBOSE, _("\
1304 Remote file no newer than local file `%s' -- not retrieving.\n"), u->local);
1305                   dlthis = 0;
1306                 }
1307               else if (eq_size)
1308                 {
1309                   /* Remote file is newer or sizes cannot be matched */
1310                   logprintf (LOG_VERBOSE, _("\
1311 Remote file is newer than local file `%s' -- retrieving.\n\n"),
1312                              u->local);
1313                 }
1314               else
1315                 {
1316                   /* Sizes do not match */
1317                   logprintf (LOG_VERBOSE, _("\
1318 The sizes do not match (local %ld) -- retrieving.\n\n"), local_size);
1319                 }
1320             }
1321         }       /* opt.timestamping && f->type == FT_PLAINFILE */
1322       switch (f->type)
1323         {
1324         case FT_SYMLINK:
1325           /* If opt.retr_symlinks is defined, we treat symlinks as
1326              if they were normal files.  There is currently no way
1327              to distinguish whether they might be directories, and
1328              follow them.  */
1329           if (!opt.retr_symlinks)
1330             {
1331 #ifdef HAVE_SYMLINK
1332               if (!f->linkto)
1333                 logputs (LOG_NOTQUIET,
1334                          _("Invalid name of the symlink, skipping.\n"));
1335               else
1336                 {
1337                   struct stat st;
1338                   /* Check whether we already have the correct
1339                      symbolic link.  */
1340                   int rc = lstat (u->local, &st);
1341                   if (rc == 0)
1342                     {
1343                       size_t len = strlen (f->linkto) + 1;
1344                       if (S_ISLNK (st.st_mode))
1345                         {
1346                           char *link_target = (char *)alloca (len);
1347                           size_t n = readlink (u->local, link_target, len);
1348                           if ((n == len - 1)
1349                               && (memcmp (link_target, f->linkto, n) == 0))
1350                             {
1351                               logprintf (LOG_VERBOSE, _("\
1352 Already have correct symlink %s -> %s\n\n"),
1353                                          u->local, f->linkto);
1354                               dlthis = 0;
1355                               break;
1356                             }
1357                         }
1358                     }
1359                   logprintf (LOG_VERBOSE, _("Creating symlink %s -> %s\n"),
1360                              u->local, f->linkto);
1361                   /* Unlink before creating symlink!  */
1362                   unlink (u->local);
1363                   if (symlink (f->linkto, u->local) == -1)
1364                     logprintf (LOG_NOTQUIET, "symlink: %s\n",
1365                                strerror (errno));
1366                   logputs (LOG_VERBOSE, "\n");
1367                 } /* have f->linkto */
1368 #else  /* not HAVE_SYMLINK */
1369               logprintf (LOG_NOTQUIET,
1370                          _("Symlinks not supported, skipping symlink `%s'.\n"),
1371                          u->local);
1372 #endif /* not HAVE_SYMLINK */
1373             }
1374           else                /* opt.retr_symlinks */
1375             {
1376               if (dlthis)
1377                 err = ftp_loop_internal (u, f, con);
1378             } /* opt.retr_symlinks */
1379           break;
1380         case FT_DIRECTORY:
1381           if (!opt.recursive)
1382             logprintf (LOG_NOTQUIET, _("Skipping directory `%s'.\n"),
1383                        f->name);
1384           break;
1385         case FT_PLAINFILE:
1386           /* Call the retrieve loop.  */
1387           if (dlthis)
1388             err = ftp_loop_internal (u, f, con);
1389           break;
1390         case FT_UNKNOWN:
1391           logprintf (LOG_NOTQUIET, _("%s: unknown/unsupported file type.\n"),
1392                      f->name);
1393           break;
1394         }       /* switch */
1395
1396       /* Set the time-stamp information to the local file.  Symlinks
1397          are not to be stamped because it sets the stamp on the
1398          original.  :( */
1399       if (!(f->type == FT_SYMLINK && !opt.retr_symlinks)
1400           && f->tstamp != -1
1401           && dlthis
1402           && file_exists_p (u->local))
1403         {
1404           /* #### This code repeats in http.c and ftp.c.  Move it to a
1405              function!  */
1406           const char *fl = NULL;
1407           if (opt.output_document)
1408             {
1409               if (opt.od_known_regular)
1410                 fl = opt.output_document;
1411             }
1412           else
1413             fl = u->local;
1414           if (fl)
1415             touch (fl, f->tstamp);
1416         }
1417       else if (f->tstamp == -1)
1418         logprintf (LOG_NOTQUIET, _("%s: corrupt time-stamp.\n"), u->local);
1419
1420       if (f->perms && f->type == FT_PLAINFILE && dlthis)
1421         chmod (u->local, f->perms);
1422       else
1423         DEBUGP (("Unrecognized permissions for %s.\n", u->local));
1424
1425       xfree (u->local);
1426       u->local = olocal;
1427       u->file = ofile;
1428       /* Break on fatals.  */
1429       if (err == QUOTEXC || err == HOSTERR || err == FWRITEERR)
1430         break;
1431       con->cmd &= ~ (DO_CWD | DO_LOGIN);
1432       f = f->next;
1433     } /* while */
1434   /* We do not want to call ftp_retrieve_dirs here */
1435   if (opt.recursive &&
1436       !(opt.reclevel != INFINITE_RECURSION && depth >= opt.reclevel))
1437     err = ftp_retrieve_dirs (u, orig, con);
1438   else if (opt.recursive)
1439     DEBUGP ((_("Will not retrieve dirs since depth is %d (max %d).\n"),
1440              depth, opt.reclevel));
1441   --depth;
1442   return err;
1443 }
1444
1445 /* Retrieve the directories given in a file list.  This function works
1446    by simply going through the linked list and calling
1447    ftp_retrieve_glob on each directory entry.  The function knows
1448    about excluded directories.  */
1449 static uerr_t
1450 ftp_retrieve_dirs (struct urlinfo *u, struct fileinfo *f, ccon *con)
1451 {
1452   char *odir;
1453   char *current_container = NULL;
1454   int current_length = 0;
1455
1456   for (; f; f = f->next)
1457     {
1458       int len;
1459
1460       if (downloaded_exceeds_quota ())
1461         break;
1462       if (f->type != FT_DIRECTORY)
1463         continue;
1464       odir = u->dir;
1465       len = 1 + strlen (u->dir) + 1 + strlen (f->name) + 1;
1466       /* Allocate u->dir off stack, but reallocate only if a larger
1467          string is needed.  */
1468       if (len > current_length)
1469         current_container = (char *)alloca (len);
1470       u->dir = current_container;
1471       sprintf (u->dir, "/%s%s%s", odir + (*odir == '/'),
1472               (!*odir || (*odir == '/' && !* (odir + 1))) ? "" : "/", f->name);
1473       if (!accdir (u->dir, ALLABS))
1474         {
1475           logprintf (LOG_VERBOSE, _("\
1476 Not descending to `%s' as it is excluded/not-included.\n"), u->dir);
1477           u->dir = odir;
1478           continue;
1479         }
1480       con->st &= ~DONE_CWD;
1481       ftp_retrieve_glob (u, con, GETALL);
1482       /* Set the time-stamp?  */
1483       u->dir = odir;
1484     }
1485   if (opt.quota && opt.downloaded > opt.quota)
1486     return QUOTEXC;
1487   else
1488     return RETROK;
1489 }
1490
1491
1492 /* A near-top-level function to retrieve the files in a directory.
1493    The function calls ftp_get_listing, to get a linked list of files.
1494    Then it weeds out the file names that do not match the pattern.
1495    ftp_retrieve_list is called with this updated list as an argument.
1496
1497    If the argument ACTION is GETONE, just download the file (but first
1498    get the listing, so that the time-stamp is heeded); if it's GLOBALL,
1499    use globbing; if it's GETALL, download the whole directory.  */
1500 static uerr_t
1501 ftp_retrieve_glob (struct urlinfo *u, ccon *con, int action)
1502 {
1503   struct fileinfo *orig, *start;
1504   uerr_t res;
1505
1506   con->cmd |= LEAVE_PENDING;
1507
1508   res = ftp_get_listing (u, con, &orig);
1509   if (res != RETROK)
1510     return res;
1511   start = orig;
1512   /* First: weed out that do not conform the global rules given in
1513      opt.accepts and opt.rejects.  */
1514   if (opt.accepts || opt.rejects)
1515     {
1516       struct fileinfo *f = orig;
1517
1518       while (f)
1519         {
1520           if (f->type != FT_DIRECTORY && !acceptable (f->name))
1521             {
1522               logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name);
1523               f = delelement (f, &start);
1524             }
1525           else
1526             f = f->next;
1527         }
1528     }
1529   /* Now weed out the files that do not match our globbing pattern.
1530      If we are dealing with a globbing pattern, that is.  */
1531   if (*u->file && (action == GLOBALL || action == GETONE))
1532     {
1533       int matchres = 0;
1534       struct fileinfo *f = start;
1535
1536       while (f)
1537         {
1538           matchres = fnmatch (u->file, f->name, 0);
1539           if (matchres == -1)
1540             {
1541               logprintf (LOG_NOTQUIET, "%s: %s\n", u->local,
1542                          strerror (errno));
1543               break;
1544             }
1545           if (matchres == FNM_NOMATCH)
1546             f = delelement (f, &start); /* delete the element from the list */
1547           else
1548             f = f->next;        /* leave the element in the list */
1549         }
1550       if (matchres == -1)
1551         {
1552           freefileinfo (start);
1553           return RETRBADPATTERN;
1554         }
1555     }
1556   res = RETROK;
1557   if (start)
1558     {
1559       /* Just get everything.  */
1560       ftp_retrieve_list (u, start, con);
1561     }
1562   else if (!start)
1563     {
1564       if (action == GLOBALL)
1565         {
1566           /* No luck.  */
1567           /* #### This message SUCKS.  We should see what was the
1568              reason that nothing was retrieved.  */
1569           logprintf (LOG_VERBOSE, _("No matches on pattern `%s'.\n"), u->file);
1570         }
1571       else /* GETONE or GETALL */
1572         {
1573           /* Let's try retrieving it anyway.  */
1574           con->st |= ON_YOUR_OWN;
1575           res = ftp_loop_internal (u, NULL, con);
1576           return res;
1577         }
1578     }
1579   freefileinfo (start);
1580   if (downloaded_exceeds_quota ())
1581     return QUOTEXC;
1582   else
1583     /* #### Should we return `res' here?  */
1584     return RETROK;
1585 }
1586
1587 /* The wrapper that calls an appropriate routine according to contents
1588    of URL.  Inherently, its capabilities are limited on what can be
1589    encoded into a URL.  */
1590 uerr_t
1591 ftp_loop (struct urlinfo *u, int *dt)
1592 {
1593   ccon con;                     /* FTP connection */
1594   uerr_t res;
1595
1596   *dt = 0;
1597
1598   memset (&con, 0, sizeof (con));
1599
1600   rbuf_uninitialize (&con.rbuf);
1601   con.st = ON_YOUR_OWN;
1602   con.rs = ST_UNIX;
1603   con.id = NULL;
1604   res = RETROK;                 /* in case it's not used */
1605
1606   /* If the file name is empty, the user probably wants a directory
1607      index.  We'll provide one, properly HTML-ized.  Unless
1608      opt.htmlify is 0, of course.  :-) */
1609   if (!*u->file && !opt.recursive)
1610     {
1611       struct fileinfo *f;
1612       res = ftp_get_listing (u, &con, &f);
1613
1614       if (res == RETROK)
1615         {
1616           if (opt.htmlify)
1617             {
1618               char *filename = (opt.output_document
1619                                 ? xstrdup (opt.output_document)
1620                                 : (u->local ? xstrdup (u->local)
1621                                    : url_filename (u)));
1622               res = ftp_index (filename, u, f);
1623               if (res == FTPOK && opt.verbose)
1624                 {
1625                   if (!opt.output_document)
1626                     {
1627                       struct stat st;
1628                       long sz;
1629                       if (stat (filename, &st) == 0)
1630                         sz = st.st_size;
1631                       else
1632                         sz = -1;
1633                       logprintf (LOG_NOTQUIET,
1634                                  _("Wrote HTML-ized index to `%s' [%ld].\n"),
1635                                  filename, sz);
1636                     }
1637                   else
1638                     logprintf (LOG_NOTQUIET,
1639                                _("Wrote HTML-ized index to `%s'.\n"),
1640                                filename);
1641                 }
1642               xfree (filename);
1643             }
1644           freefileinfo (f);
1645         }
1646     }
1647   else
1648     {
1649       int wild = has_wildcards_p (u->file);
1650       if ((opt.ftp_glob && wild) || opt.recursive || opt.timestamping)
1651         {
1652           /* ftp_retrieve_glob is a catch-all function that gets called
1653              if we need globbing, time-stamping or recursion.  Its
1654              third argument is just what we really need.  */
1655           ftp_retrieve_glob (u, &con,
1656                              (opt.ftp_glob && wild) ? GLOBALL : GETONE);
1657         }
1658       else
1659         res = ftp_loop_internal (u, NULL, &con);
1660     }
1661   if (res == FTPOK)
1662     res = RETROK;
1663   if (res == RETROK)
1664     *dt |= RETROKF;
1665   /* If a connection was left, quench it.  */
1666   if (rbuf_initialized_p (&con.rbuf))
1667     CLOSE (RBUF_FD (&con.rbuf));
1668   FREE_MAYBE (con.id);
1669   con.id = NULL;
1670   return res;
1671 }
1672
1673 /* Delete an element from the fileinfo linked list.  Returns the
1674    address of the next element, or NULL if the list is exhausted.  It
1675    can modify the start of the list.  */
1676 static struct fileinfo *
1677 delelement (struct fileinfo *f, struct fileinfo **start)
1678 {
1679   struct fileinfo *prev = f->prev;
1680   struct fileinfo *next = f->next;
1681
1682   xfree (f->name);
1683   FREE_MAYBE (f->linkto);
1684   xfree (f);
1685
1686   if (next)
1687     next->prev = prev;
1688   if (prev)
1689     prev->next = next;
1690   else
1691     *start = next;
1692   return next;
1693 }
1694
1695 /* Free the fileinfo linked list of files.  */
1696 static void
1697 freefileinfo (struct fileinfo *f)
1698 {
1699   while (f)
1700     {
1701       struct fileinfo *next = f->next;
1702       xfree (f->name);
1703       if (f->linkto)
1704         xfree (f->linkto);
1705       xfree (f);
1706       f = next;
1707     }
1708 }