\section{FTP client}\label{sec:ftp} \begin{description} \item[Used files:] ftp.scm, ftp-obsolete.scm \item[Name of the package:] ftp, ftp-obsolete \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, a 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} \defun{ftp-error?}{thing}{boolean} \begin{desc} Returns \sharpt, if \semvar{thing} is a \ex{ftp-error} object, otherwise \sharpf. \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 [ arg ] } Replies from the server are of the form \codex{xyz Informative message } 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- Start of multiline message [ + More information ]* xyz End of multiline message % \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*{Obsolete procedures} Names in further versions of \ex{ftp} contained a colon (`\ex{:}') after the prefix `\ex{ftp-}'. This is now changed to a hyphen ('\ex{-}'), accordingly to SUnet's philosophy. If you need the old names, use the \ex{ftp\=obsolete}-package that maps the names to the new ones. \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}