]> sjero.net Git - wget/blobdiff - src/ftp-basic.c
[svn] Removed ftpparse dependencies. New parser for VMS listings. MacOS
[wget] / src / ftp-basic.c
index 98f0a9e60d823f2418e5e6aa90731370e8812683..84813af112950f85820049c1a6af777d48f47a8c 100644 (file)
@@ -1,5 +1,5 @@
 /* Basic FTP routines.
-   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.
 
@@ -41,13 +41,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "rbuf.h"
 #include "connect.h"
 #include "host.h"
-
-#ifndef errno
-extern int errno;
-#endif
-#ifndef h_errno
-extern int h_errno;
-#endif
+#include "ftp.h"
 
 char ftp_last_respline[128];
 
@@ -66,33 +60,33 @@ ftp_response (struct rbuf *rbuf, char **line)
   do
     {
       for (i = 0; 1; i++)
-       {
-         int res;
-         if (i > bufsize - 1)
-           *line = (char *)xrealloc (*line, (bufsize <<= 1));
-         res = RBUF_READCHAR (rbuf, *line + i);
-         /* RES is number of bytes read.  */
-         if (res == 1)
-           {
-             if ((*line)[i] == '\n')
-               {
-                 (*line)[i] = '\0';
-                 /* Get rid of \r.  */
-                 if (i > 0 && (*line)[i - 1] == '\r')
-                   (*line)[i - 1] = '\0';
-                 break;
-               }
-           }
-         else
-           return FTPRERR;
-       }
+        {
+          int res;
+          if (i > bufsize - 1)
+            *line = (char *)xrealloc (*line, (bufsize <<= 1));
+          res = RBUF_READCHAR (rbuf, *line + i);
+          /* RES is number of bytes read.  */
+          if (res == 1)
+            {
+              if ((*line)[i] == '\n')
+                {
+                  (*line)[i] = '\0';
+                  /* Get rid of \r.  */
+                  if (i > 0 && (*line)[i - 1] == '\r')
+                    (*line)[i - 1] = '\0';
+                  break;
+                }
+            }
+          else
+            return FTPRERR;
+        }
       if (opt.server_response)
-       logprintf (LOG_ALWAYS, "%s\n", *line);
+        logprintf (LOG_ALWAYS, "%s\n", *line);
       else
-       DEBUGP (("%s\n", *line));
+        DEBUGP (("%s\n", *line));
     }
   while (!(i >= 3 && ISDIGIT (**line) && ISDIGIT ((*line)[1]) &&
-          ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
+           ISDIGIT ((*line)[2]) && (*line)[3] == ' '));
   strncpy (ftp_last_respline, *line, sizeof (ftp_last_respline));
   ftp_last_respline[sizeof (ftp_last_respline) - 1] = '\0';
   return FTPOK;
@@ -105,16 +99,16 @@ static char *
 ftp_request (const char *command, const char *value)
 {
   char *res = (char *)xmalloc (strlen (command)
-                              + (value ? (1 + strlen (value)) : 0)
-                              + 2 + 1);
+                               + (value ? (1 + strlen (value)) : 0)
+                               + 2 + 1);
   sprintf (res, "%s%s%s\r\n", command, value ? " " : "", value ? value : "");
   if (opt.server_response)
     {
       /* Hack: don't print out password.  */
       if (strncmp (res, "PASS", 4) != 0)
-       logprintf (LOG_ALWAYS, "--> %s\n", res);
+        logprintf (LOG_ALWAYS, "--> %s\n", res);
       else
-       logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
+        logputs (LOG_ALWAYS, "--> PASS Turtle Power!\n");
     }
   else
     DEBUGP (("\n--> %s\n", res));
@@ -138,41 +132,41 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPSRVERR;
     }
-  free (respline);
+  xfree (respline);
   /* Send USER username.  */
   request = ftp_request ("USER", acc);
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   /* An unprobable possibility of logging without a password.  */
   if (*respline == '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPOK;
     }
   /* Else, only response 3 is appropriate.  */
   if (*respline != '3')
     {
-      free (respline);
+      xfree (respline);
       return FTPLOGREFUSED;
     }
 #ifdef USE_OPIE
@@ -185,57 +179,57 @@ ftp_login (struct rbuf *rbuf, const char *acc, const char *pass)
 
     for (i = 0; i < ARRAY_SIZE (skey_head); i++)
       {
-       if (strncasecmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
-         break;
+        if (strncasecmp (skey_head[i], respline, strlen (skey_head[i])) == 0)
+          break;
       }
     if (i < ARRAY_SIZE (skey_head))
       {
-       const char *cp;
-       int skey_sequence = 0;
-
-       for (cp = respline + strlen (skey_head[i]);
-            '0' <= *cp && *cp <= '9';
-            cp++)
-         {
-           skey_sequence = skey_sequence * 10 + *cp - '0';
-         }
-       if (*cp == ' ')
-         cp++;
-       else
-         {
-         bad:
-           free (respline);
-           return FTPLOGREFUSED;
-         }
-       if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
-         goto bad;
-       pass = cp;
+        const char *cp;
+        int skey_sequence = 0;
+
+        for (cp = respline + strlen (skey_head[i]);
+             '0' <= *cp && *cp <= '9';
+             cp++)
+          {
+            skey_sequence = skey_sequence * 10 + *cp - '0';
+          }
+        if (*cp == ' ')
+          cp++;
+        else
+          {
+          bad:
+            xfree (respline);
+            return FTPLOGREFUSED;
+          }
+        if ((cp = calculate_skey_response (skey_sequence, cp, pass)) == 0)
+          goto bad;
+        pass = cp;
       }
   }
 #endif /* USE_OPIE */
-  free (respline);
+  xfree (respline);
   /* Send PASS password.  */
   request = ftp_request ("PASS", pass);
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPLOGINC;
     }
-  free (respline);
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }
@@ -264,30 +258,30 @@ ftp_port (struct rbuf *rbuf)
   /* Construct the argument of PORT (of the form a,b,c,d,e,f).  */
   bytes = (char *)alloca (6 * 4 + 1);
   sprintf (bytes, "%d,%d,%d,%d,%d,%d", in_addr[0], in_addr[1],
-         in_addr[2], in_addr[3], (unsigned) (port & 0xff00) >> 8,
-         port & 0xff);
+          in_addr[2], in_addr[3], (unsigned) (port & 0xff00) >> 8,
+          port & 0xff);
   /* Send PORT request.  */
   request = ftp_request ("PORT", bytes);
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPPORTERR;
     }
-  free (respline);
+  xfree (respline);
   return FTPOK;
 }
 
@@ -307,20 +301,20 @@ ftp_pasv (struct rbuf *rbuf, unsigned char *addr)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get the server response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPNOPASV;
     }
   /* Parse the request.  */
@@ -332,17 +326,17 @@ ftp_pasv (struct rbuf *rbuf, unsigned char *addr)
     {
       addr[i] = 0;
       for (; ISDIGIT (*s); s++)
-       addr[i] = (*s - '0') + 10 * addr[i];
+        addr[i] = (*s - '0') + 10 * addr[i];
       if (*s == ',')
-       s++;
+        s++;
       else if (i < 5)
-       {
-         /* When on the last number, anything can be a terminator.  */
-         free (respline);
-         return FTPINVPASV;
-       }
+        {
+          /* When on the last number, anything can be a terminator.  */
+          xfree (respline);
+          return FTPINVPASV;
+        }
     }
-  free (respline);
+  xfree (respline);
   return FTPOK;
 }
 
@@ -363,23 +357,23 @@ ftp_type (struct rbuf *rbuf, int type)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPUNKNOWNTYPE;
     }
-  free (respline);
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }
@@ -398,28 +392,28 @@ ftp_cwd (struct rbuf *rbuf, const char *dir)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline == '5')
     {
-      free (respline);
+      xfree (respline);
       return FTPNSFOD;
     }
   if (*respline != '2')
     {
-      free (respline);
+      xfree (respline);
       return FTPRERR;
     }
-  free (respline);
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }
@@ -438,23 +432,23 @@ ftp_rest (struct rbuf *rbuf, long offset)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline != '3')
     {
-      free (respline);
+      xfree (respline);
       return FTPRESTFAIL;
     }
-  free (respline);
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }
@@ -472,28 +466,28 @@ ftp_retr (struct rbuf *rbuf, const char *file)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate response.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline == '5')
     {
-      free (respline);
+      xfree (respline);
       return FTPNSFOD;
     }
   if (*respline != '1')
     {
-      free (respline);
+      xfree (respline);
       return FTPRERR;
     }
-  free (respline);
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }
@@ -512,28 +506,129 @@ ftp_list (struct rbuf *rbuf, const char *file)
   nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
   if (nwritten < 0)
     {
-      free (request);
+      xfree (request);
       return WRITEFAILED;
     }
-  free (request);
+  xfree (request);
   /* Get appropriate respone.  */
   err = ftp_response (rbuf, &respline);
   if (err != FTPOK)
     {
-      free (respline);
+      xfree (respline);
       return err;
     }
   if (*respline == '5')
     {
-      free (respline);
+      xfree (respline);
       return FTPNSFOD;
     }
   if (*respline != '1')
     {
-      free (respline);
+      xfree (respline);
       return FTPRERR;
     }
-  free (respline);
+  xfree (respline);
+  /* All OK.  */
+  return FTPOK;
+}
+
+/* Sends the SYST command to the server. */
+uerr_t
+ftp_syst (struct rbuf *rbuf, enum stype *server_type)
+{
+  char *request, *respline;
+  int nwritten;
+  uerr_t err;
+
+  /* Send SYST request.  */
+  request = ftp_request ("SYST", NULL);
+  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  if (nwritten < 0)
+    {
+      xfree (request);
+      return WRITEFAILED;
+    }
+  xfree (request);
+  /* Get appropriate response.  */
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+    {
+      xfree (respline);
+      return err;
+    }
+  if (*respline == '5')
+    {
+      xfree (respline);
+      return FTPSRVERR;
+    }
+
+  /* Skip the number (215, but 200 (!!!) in case of VMS) */
+  strtok (respline, " ");
+  
+  /* Which system type has been reported (we are interested just in the
+     first word of the server response)?  */
+  request = strtok (NULL, " ");
+
+  if (!strcasecmp (request, "VMS"))
+    *server_type = ST_VMS;
+  else
+    if (!strcasecmp (request, "UNIX"))
+      *server_type = ST_UNIX;
+    else
+      if (!strcasecmp (request, "WINDOWS_NT"))
+        *server_type = ST_WINNT;
+      else
+        if (!strcasecmp (request, "MACOS"))
+          *server_type = ST_MACOS;
+        else
+          *server_type = ST_OTHER;
+
+  xfree (respline);
+  /* All OK.  */
+  return FTPOK;
+}
+
+/* Sends the PWD command to the server. */
+uerr_t
+ftp_pwd (struct rbuf *rbuf, char **pwd)
+{
+  char *request, *respline;
+  int nwritten;
+  uerr_t err;
+
+  /* Send PWD request.  */
+  request = ftp_request ("PWD", NULL);
+  nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+  if (nwritten < 0)
+    {
+      xfree (request);
+      return WRITEFAILED;
+    }
+  xfree (request);
+  /* Get appropriate response.  */
+  err = ftp_response (rbuf, &respline);
+  if (err != FTPOK)
+    {
+      xfree (respline);
+      return err;
+    }
+  if (*respline == '5')
+    {
+      xfree (respline);
+      return FTPSRVERR;
+    }
+
+  /* Skip the number (257), leading citation mark, trailing citation mark
+     and everything following it. */
+  strtok (respline, "\"");
+  request = strtok (NULL, "\"");
+  
+  /* Has the `pwd' been already allocated?  Free! */
+  FREE_MAYBE (*pwd);
+
+  *pwd = xstrdup (request);
+
+  xfree (respline);
   /* All OK.  */
   return FTPOK;
 }