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