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