+
+/* 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;
+}
+
+/* Sends the SIZE command to the server, and returns the value in 'size'.
+ * If an error occurs, size is set to zero. */
+uerr_t
+ftp_size (struct rbuf *rbuf, const char *file, long int *size)
+{
+ char *request, *respline;
+ int nwritten;
+ uerr_t err;
+
+ /* Send PWD request. */
+ request = ftp_request ("SIZE", file);
+ nwritten = iwrite (RBUF_FD (rbuf), request, strlen (request));
+ if (nwritten < 0)
+ {
+ xfree (request);
+ *size = 0;
+ return WRITEFAILED;
+ }
+ xfree (request);
+ /* Get appropriate response. */
+ err = ftp_response (rbuf, &respline);
+ if (err != FTPOK)
+ {
+ xfree (respline);
+ *size = 0;
+ return err;
+ }
+ if (*respline == '5')
+ {
+ /*
+ * Probably means SIZE isn't supported on this server.
+ * Error is nonfatal since SIZE isn't in RFC 959
+ */
+ xfree (respline);
+ *size = 0;
+ return FTPOK;
+ }
+
+ errno = 0;
+ *size = strtol (respline + 4, NULL, 0);
+ if (errno)
+ {
+ /*
+ * Couldn't parse the response for some reason. On the (few)
+ * tests I've done, the response is 213 <SIZE> with nothing else -
+ * maybe something a bit more resilient is necessary. It's not a
+ * fatal error, however.
+ */
+ xfree (respline);
+ *size = 0;
+ return FTPOK;
+ }
+
+ xfree (respline);
+ /* All OK. */
+ return FTPOK;
+}
+
+/* If URL's params are of the form "type=X", return character X.
+ Otherwise, return 'I' (the default type). */
+char
+ftp_process_type (const char *params)
+{
+ if (params
+ && 0 == strncasecmp (params, "type=", 5)
+ && params[5] != '\0')
+ return TOUPPER (params[5]);
+ else
+ return 'I';
+}