\section{FTP client}\label{sec:ftp}
\begin{description}
\item[Used files:] ftp.scm
\item[Name of the package:] ftp
\end{description}

\subsection{What users want to know}
This module lets you transfer files between networked machines from
the Scheme Shell, using the File Transfer Protocol as described in
RFC~959. The protocol specifies the behaviour of a server machine,
which runs an ftp daemon (not implemented by this module), and of
clients (that's us) which request services from the server.

Some of the procedures in this module extract useful information from
the server's reply, such as the size of a file, or the name of the
directory we have moved to. These procedures return either the
extracted information, or \sharpf{} to indicate failure. Other
procedures return a ``status'', which is either the server's reply as
a string, or \sharpf{} to signify failure.

The server's response is always checked. If the server's response
doesn't match the expected code from the server, an catchable
\ex{ftp:error} is raised.  

\FIXME{The source says you can look at pop3.scm to find out how to
catch the ftp:error raised by some procedures this. We have not had
a look there, yet.}

\subsubsection*{Entry points }

\defun{ftp:connect} {host \ovar{logfile}} {connection}
\begin{desc}
  Open a command connection with the remote machine \semvar{host}.
  Optionally start logging the conversation with the server to
  \semvar{logfile}, which will be appended to if it already exists,
  and created otherwise. Beware, the \semvar{logfile} contains
  passwords in clear text (it is created with permissions
  \ex{og-rxw})!
\end{desc}

\defun{ftp:login} {connection \ovar{login \ovar{passwd}}} {status}
\begin{desc}
  Log in to the remote host. If a \semvar{login} and \semvar{password}
  are not provided, they are first searched for in the user's
  \~/.netrc file, or default to user ``anonymous'' and password
  ``user@host''
\end{desc}

\defun{ftp:type} {connection type} {status}
\begin{desc}
  Change the transfer mode for future data connections. This may be
  either \ex{'ascii }or \ex{'text}, respectively, for transfering text
  files, or \ex{'binary} for transfering binary files. If
  \semvar{type} is a string it is sent verbatim to the server.
\end{desc}

\defun{ftp:rename} {connection oldname newname} {status}
\begin{desc}
  Change the name of \semvar{oldname} on the remote host to
  \semvar{newname} (assuming sufficient permissions). \semvar{oldname}
  and \semvar{newname} are strings; if prefixed with "/" they are
  taken relative to the server's root, and otherwise they are relative
  to the current directory. Note that in the case of anonymous ftp
  (user ``anonymous'' or ``ftp''), the server root is different from
  the root of the servers's filesystem.
\end{desc}

\defun{ftp:delete} {connection file} {status}
\begin{desc}
  Delete \semvar{file} from the remote host (assuming the user has
  appropriate permissions).
\end{desc}

\defun{ftp:cd} {connection dir} {status}
\begin{desc}
  Change the current directory on the server.
\end{desc}

\defun{ftp:cdup} {connection} {status}
\begin{desc}
  Move to the parent directory on the server.
\end{desc}

\defun{ftp:pwd} {connection} {string}
\begin{desc}
  Return the current directory on the remote host, as a string.
\end{desc}

\defun{ftp:ls} {connection} {status}
\begin{desc}
  Provide a listing of the current directory's contents, in short
  format, \ie as a list of filenames.
\end{desc}

\defun{ftp:dir} {connection} {status}
\begin{desc}
  Provide a listing of the current directory's contents, in long
  format. Most servers (\Unix, MS Windows, MacOS) use a standard
  format with one file per line, with the file size and other
  information, but other servers (VMS, \ldots) use their own format.
\end{desc}

\defun{ftp:get} {connection remote-file \ovar{local-file}} {status $|$ string}
\begin{desc}
  Download \semvar{remote-file} from the FTP server. If
  \semvar{local-file} is a string, save the data to
  \semvar{local-file} on the local host; otherwise save to a local
  file named \semvar{remote-file}.  \semvar{remote-file} and
  \semvar{local-file} may be absolute file names (with a leading `/'),
  or relative to the current directory. If \semvar{local-file} is
  \sharpt, output data to \ex{(current-output-port)}, and if it is
  \sharpf{} return the data as a string.
\end{desc}

\defun{ftp:put} {connection local-file \ovar{remote-file}} {status}
\begin{desc}
  Upload \semvar{local-file} to the FTP server. If
  \semvar{remote-file} is specified, then save the data to
  \semvar{remote-file} on the remote host; otherwise save to a remote
  file named \semvar{local-file}.  \semvar{local-file} and
  \semvar{remote-file} may be absolute file names (with a leading
  `/'), or relative to the current directory.
\end{desc}

\defun{ftp:append}{connection local-file \ovar{remote-file}}{status}
\begin{desc}
  Does the same as \ex{ftp:get}, but appends the data to the remote
  file, if it exists.
\end{desc}

\defun{ftp:rmdir} {connection dir} {status}
\begin{desc}
  Remove the directory \semvar{dir} from the remote host (assuming
  sufficient permissions).
\end{desc}

\defun{ftp:mkdir} {connection dir} {status}
\begin{desc}
  Create a new directory named \semvar{dir} on the remote host
  (assuming sufficient permissions).
\end{desc}

\defun{ftp:modification-time} {connection file} {date}
\begin{desc}
  Request the time of the last modification of \semvar{file} on the
  remote host, and on success return a Scsh date record. This command
  is not part of RFC~959 and is not implemented by all servers, but is
  useful for mirroring.
\end{desc}

\defun{ftp:size} {connection file} {integer}
\begin{desc}
  Return the size of \semvar{file} in bytes.
\end{desc}

\defun{ftp:abort} {connection} {status}
\begin{desc}
  Abort the current data transfer. Not particularly useful with this
  im\-ple\-men\-ta\-tion since the data transfer commands only return
  once the transfer is complete.
\end{desc}

\defun{ftp:quit} {connection} {status}
\begin{desc}
  Close the connection to the remote host. The \semvar{connection}
  object is useless after a quit command.
\end{desc}

\defun{ftp:quot}{connection command}{status}
\begin{desc}
  Send a \semvar{command} verbatim to the remote server and wait for a
  response.
\end{desc}


\subsubsection*{Unimplemented}

The following rfc959 commands are not implemented:

\begin{tabular}{ll}
\ex{ACCT} & account; this is ignored by most servers) \\
\ex{SMNT} & structure mount, for mounting another filesystem \\
\ex{REIN} & reinitialize connection \\
\ex{LOGOUT} & quit without interrupting ongoing transfers \\
\ex{STRU} & file structure \\
\ex{ALLO} & allocate space on server \\
\end{tabular}

\subsection{What programmers want to know}

\subsection*{Overview}
Communication is initiated by the client. The server responds to each
request with a three digit status code and an explanatory message, and
occasionally with data (which is sent via a separate, one-off
channel). The client starts by opening a command connection to a well
known port on the server machine. Messages send to the server are of
the form
  \codex{CMD [ <space> arg ] <CR> <LF>}
Replies from the server are of the form
  \codex{xyz <space> Informative message <CR> <LF>}
where xyz is a three digit code which indicates whether the operation
succeeded or not, whether the server is waiting for more data, etc.
The server may also send multiline messages of the form

\begin{code}
xyz- <space> Start of multiline message <CR> <LF>
[ <space>+ More information ]* <CR> <LF>
xyz <space> End of multiline message <CR> <LF>%
\end{code}

For further informations have a look at the source file.

This module has no support for sites behind a firewall. It shouldn't
be very tricky; it only requires using passive mode. Might want to add
something like the \ex{/usr/bin/ftp} command \ex{restrict}, which
implements data port range restrictions.


\subsubsection*{Portablitity}

Items of the following list are necessary in order to use this module:
\begin{itemize}
\item The netrc.scm module for parsing ~/.netrc files.
\item Scsh socket code
\item Scsh records
\item Receive for multiple values
\item \scm{} signals/handlers
\end{itemize}


\subsubsection*{Related work}

\begin{itemize}
\item RFC~959 describes the FTP protocol; see \newline
  \ex{http://www.cis.ohio-state.edu/htbin/rfc/rfc959.html}
\item \ex{/anonymous@sunsite.unc.edu:/pub/Linux/libs/ftplib.tar.gz} is
  a library similar to this one, written in C, by Thomas Pfau
\item \ex{FTP.pm} is a Perl module with similar functionality
  (available from \ex{http://www.perl.com/CPAN})
\item Emacs gets transparent remote file access from \ex{ange-ftp.el}
  by Ange Norman. However, it cheats by using \ex{/usr/bin/ftp}.
\item Siod (a small-footprint Scheme implementation by George Carette)
  comes with a file \ex{ftp.scm }with a small subset of these
  functions defined.
\end{itemize}

\subsubsection*{TODO}
\begin{itemize}
\item Handle passive mode and firewalls.
\item Unix-specific commands such as \ex{SITE UMASK}, \ex{SITE CHMOD},
  \ex{SITE IDLE}, \ex{SITE HELP}.
\item Object-based interface? (like SICP message passing).
\item Improved error handling.
\item A lot of the calls to format could be replaced by calls to
  string-join. Maybe format is easier to read?
\item The \ex{ftp:rename} command should have an optional argument
  \ex{:rename} which defaults to \sharpf, which would make us upload
  to a temporary name and rename at the end of the upload. This
  atomicity is important for ftp or http servers which are serving a
  load, and to avoid problems with "no space on device".
\item Automatic relogin a la \ex{ang-ftp}.
\end{itemize}

