/* File Transfer Protocol support.
- Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
This file is part of Wget.
#include "rbuf.h"
#include "retr.h"
#include "ftp.h"
-#include "html.h"
#include "connect.h"
#include "host.h"
#include "fnmatch.h"
extern char ftp_last_respline[];
+/* #### Global variables?? These two should be members of struct
+ ccon! */
+
+static enum stype host_type=ST_UNIX;
+static char *pwd;
+
/* Look for regexp "( *[0-9]+ *byte" (literal parenthesis) anywhere in
the string S, and return the number converted to long, if found, 0
otherwise. */
search_netrc (u->host, (const char **)&user, (const char **)&passwd, 1);
user = user ? user : opt.ftp_acc;
if (!opt.ftp_pass)
- opt.ftp_pass = xstrdup (ftp_getaddress ());
+ opt.ftp_pass = ftp_getaddress ();
passwd = passwd ? passwd : opt.ftp_pass;
assert (user && passwd);
exit (1);
break;
}
- /* Third: Set type to Image (binary). */
+ /* Third: Get the system type */
+ if (!opt.server_response)
+ logprintf (LOG_VERBOSE, "==> SYST ... ");
+ err = ftp_syst (&con->rbuf, &host_type);
+ /* FTPRERR */
+ switch (err)
+ {
+ case FTPRERR:
+ logputs (LOG_VERBOSE, "\n");
+ logputs (LOG_NOTQUIET, _("\
+Error in server response, closing control connection.\n"));
+ CLOSE (csock);
+ rbuf_uninitialize (&con->rbuf);
+ return err;
+ break;
+ case FTPSRVERR:
+ logputs (LOG_VERBOSE, "\n");
+ logputs (LOG_NOTQUIET,
+ _("Server error, can't determine system type.\n"));
+ break;
+ case FTPOK:
+ /* Everything is OK. */
+ break;
+ default:
+ abort ();
+ break;
+ }
+ if (!opt.server_response)
+ logputs (LOG_VERBOSE, _("done. "));
+
+ /* Fourth: Find the initial ftp directory */
+
+ if (!opt.server_response)
+ logprintf (LOG_VERBOSE, "==> PWD ... ");
+ err = ftp_pwd(&con->rbuf, &pwd);
+ /* FTPRERR */
+ switch (err)
+ {
+ case FTPRERR || FTPSRVERR :
+ logputs (LOG_VERBOSE, "\n");
+ logputs (LOG_NOTQUIET, _("\
+Error in server response, closing control connection.\n"));
+ CLOSE (csock);
+ rbuf_uninitialize (&con->rbuf);
+ return err;
+ break;
+ case FTPOK:
+ /* Everything is OK. */
+ break;
+ default:
+ abort ();
+ break;
+ }
+ if (!opt.server_response)
+ logputs (LOG_VERBOSE, _("done.\n"));
+
+ /* Fifth: Set the FTP type. */
if (!opt.server_response)
logprintf (LOG_VERBOSE, "==> TYPE %c ... ", TOUPPER (u->ftp_type));
err = ftp_type (&con->rbuf, TOUPPER (u->ftp_type));
logputs (LOG_VERBOSE, _("==> CWD not needed.\n"));
else
{
- /* Change working directory. */
- if (!opt.server_response)
- logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
- err = ftp_cwd (&con->rbuf, u->dir);
+ /* Change working directory. If the FTP host runs VMS and
+ the path specified is absolute, we will have to convert
+ it to VMS style as VMS does not like leading slashes */
+ DEBUGP (("changing working directory\n"));
+ if (*(u->dir) == '/')
+ {
+ int pwd_len = strlen (pwd);
+ char *result = (char *)alloca (strlen (u->dir) + pwd_len + 10);
+ *result = '\0';
+ switch (host_type)
+ {
+ case ST_VMS:
+ {
+ char *tmp_dir, *tmpp;
+ STRDUP_ALLOCA (tmp_dir, u->dir);
+ for (tmpp = tmp_dir; *tmpp; tmpp++)
+ if (*tmpp=='/')
+ *tmpp = '.';
+ strcpy (result, pwd);
+ /* pwd ends with ']', we have to get rid of it */
+ result[pwd_len - 1]= '\0';
+ strcat (result, tmp_dir);
+ strcat (result, "]");
+ }
+ break;
+ case ST_UNIX:
+ case ST_WINNT:
+ /* pwd_len == 1 means pwd = "/", but u->dir begins with '/'
+ already */
+ if (pwd_len > 1)
+ strcpy (result, pwd);
+ strcat (result, u->dir);
+ /* These look like debugging messages to me. */
+#if 0
+ logprintf (LOG_VERBOSE, "\npwd=\"%s\"", pwd);
+ logprintf (LOG_VERBOSE, "\nu->dir=\"%s\"", u->dir);
+#endif
+ break;
+ default:
+ abort ();
+ break;
+ }
+ if (!opt.server_response)
+ logprintf (LOG_VERBOSE, "==> CWD %s ... ", result);
+ err = ftp_cwd (&con->rbuf, result);
+ }
+ else
+ {
+ if (!opt.server_response)
+ logprintf (LOG_VERBOSE, "==> CWD %s ... ", u->dir);
+ err = ftp_cwd (&con->rbuf, u->dir);
+ }
/* FTPRERR, WRITEFAILED, FTPNSFOD */
switch (err)
{
}
reset_timer ();
/* Get the contents of the document. */
- res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf);
+ res = get_contents (dtsock, fp, len, restval, expected_bytes, &con->rbuf, 0);
con->dltime = elapsed_time ();
tms = time_str (NULL);
tmrate = rate (*len - restval, con->dltime);
rbuf_discard (&con->rbuf);
if (err != FTPOK)
{
- free (respline);
+ xfree (respline);
/* The control connection is decidedly closed. Print the time
only if it hasn't already been printed. */
if (res != -1)
become apparent later. */
if (*respline != '2')
{
- free (respline);
+ xfree (respline);
if (res != -1)
logprintf (LOG_NOTQUIET, "%s (%s) - ", tms, tmrate);
logputs (LOG_NOTQUIET, _("Data transfer aborted.\n"));
return FTPRETRINT;
}
- free (respline);
+ xfree (respline);
if (res == -1)
{
while ((line = read_whole_line (fp)))
{
logprintf (LOG_ALWAYS, "%s\n", line);
- free (line);
+ xfree (line);
}
fclose (fp);
}
#ifdef WINDOWS
ws_changetitle (hurl, 1);
#endif
- free (hurl);
+ xfree (hurl);
}
/* Send getftp the proper length, if fileinfo was provided. */
if (f)
char *hurl = str_url (u->proxy ? u->proxy : u, 1);
logprintf (LOG_NONVERBOSE, "%s URL: %s [%ld] -> \"%s\" [%d]\n",
tms, hurl, len, locf, count);
- free (hurl);
+ xfree (hurl);
}
if ((con->cmd & DO_LIST))
err = ftp_loop_internal (u, NULL, con);
u->local = olocal;
if (err == RETROK)
- f = ftp_parse_ls (list_filename);
+ f = ftp_parse_ls (list_filename, host_type);
else
f = NULL;
if (opt.remove_listing)
else
logprintf (LOG_VERBOSE, _("Removed `%s'.\n"), list_filename);
}
- free (list_filename);
+ xfree (list_filename);
con->cmd &= ~DO_LIST;
return f;
}
}
else if (local_size != f->size)
{
- logprintf (LOG_VERBOSE, _("\
+ if (host_type == ST_VMS)
+ {
+ logprintf (LOG_VERBOSE, _("\
+Cannot compare sizes, remote system is VMS.\n"));
+ dlthis = 0;
+ }
+ else
+ {
+ logprintf (LOG_VERBOSE, _("\
The sizes do not match (local %ld) -- retrieving.\n"), local_size);
+ }
}
}
} /* opt.timestamping && f->type == FT_PLAINFILE */
else
DEBUGP (("Unrecognized permissions for %s.\n", u->local));
- free (u->local);
+ xfree (u->local);
u->local = olocal;
u->file = ofile;
/* Break on fatals. */
_("Wrote HTML-ized index to `%s'.\n"),
filename);
}
- free (filename);
+ xfree (filename);
}
freefileinfo (f);
}
/* If a connection was left, quench it. */
if (rbuf_initialized_p (&con.rbuf))
CLOSE (RBUF_FD (&con.rbuf));
+ FREE_MAYBE (pwd);
+ pwd = NULL;
return res;
}
struct fileinfo *prev = f->prev;
struct fileinfo *next = f->next;
- free (f->name);
+ xfree (f->name);
FREE_MAYBE (f->linkto);
- free (f);
+ xfree (f);
if (next)
next->prev = prev;
while (f)
{
struct fileinfo *next = f->next;
- free (f->name);
+ xfree (f->name);
if (f->linkto)
- free (f->linkto);
- free (f);
+ xfree (f->linkto);
+ xfree (f);
f = next;
}
}