Comment change.
[bpt/emacs.git] / lisp / ange-ftp.el
index 4906827..f0d5ca8 100644 (file)
 ;;; ange-ftp.el --- transparent FTP support for GNU Emacs
 
-;;; Copyright (C) 1989,90,91,92,93,94  Free Software Foundation, Inc.
-;;;
+;; Copyright (C) 1989,90,91,92,93,94,95,96  Free Software Foundation, Inc.
+
 ;; Author: Andy Norman (ange@hplb.hpl.hp.com)
+;; Maintainer: FSF
 ;; Keywords: comm
-;;;
-;;; This program is free software; you can redistribute it and/or modify
-;;; it under the terms of the GNU General Public License as published by
-;;; the Free Software Foundation; either version 2, or (at your option)
-;;; any later version.
-;;;
-;;; This program is distributed in the hope that it will be useful,
-;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;;; GNU General Public License for more details.
-;;;
-;;; A copy of the GNU General Public License can be obtained from this
-;;; program's author (send electronic mail to ange@hplb.hpl.hp.com) or from
-;;; the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
-;;; 02139, USA.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
-;;;
-;;; This package attempts to make accessing files and directories using FTP
-;;; from within GNU Emacs as simple and transparent as possible.  A subset of
-;;; the common file-handling routines are extended to interact with FTP.
-
-;;; Usage:
-;;;
-;;; Some of the common GNU Emacs file-handling operations have been made
-;;; FTP-smart.  If one of these routines is given a filename that matches
-;;; '/user@host:name' then it will spawn an FTP process connecting to machine
-;;; 'host' as account 'user' and perform its operation on the file 'name'.
-;;;
-;;; For example: if find-file is given a filename of:
-;;;
-;;;   /ange@anorman:/tmp/notes
-;;;
-;;; then ange-ftp spawns an FTP process, connect to the host 'anorman' as
-;;; user 'ange', get the file '/tmp/notes' and pop up a buffer containing the
-;;; contents of that file as if it were on the local filesystem.  If ange-ftp
-;;; needs a password to connect then it reads one in the echo area.
-
-;;; Extended filename syntax:
-;;;
-;;; The default extended filename syntax is '/user@host:name', where the
-;;; 'user@' part may be omitted.  This syntax can be customised to a certain
-;;; extent by changing ange-ftp-name-format.  There are limitations.
-;;;
-;;; If the user part is omitted then ange-ftp generates a default user
-;;; instead whose value depends on the variable ange-ftp-default-user.
-
-;;; Passwords:
-;;;
-;;; A password is required for each host/user pair.  Ange-ftp reads passwords
-;;; as needed.  You can also specify a password with ange-ftp-set-passwd, or
-;;; in a *valid* ~/.netrc file.
-
-;;; Passwords for user "anonymous":
-;;;
-;;; Passwords for the user "anonymous" (or "ftp") are handled
-;;; specially.  The variable `ange-ftp-generate-anonymous-password'
-;;; controls what happens: if the value of this variable is a string,
-;;; then this is used as the password; if non-nil (the default), then
-;;; a password is created from the name of the user and the hostname
-;;; of the machine on which GNU Emacs is running; if nil then the user
-;;; is prompted for a password as normal.
-
-;;; "Dumb" UNIX hosts:
-;;;
-;;; The FTP servers on some UNIX machines have problems if the 'ls' command is
-;;; used.
-;;;
-;;; The routine ange-ftp-add-dumb-unix-host can be called to tell ange-ftp to
-;;; limit itself to the DIR command and not 'ls' for a given UNIX host.  Note
-;;; that this change will take effect for the current GNU Emacs session only.
-;;; See below for a discussion of non-UNIX hosts.  If a large number of
-;;; machines with similar hostnames have this problem then it is easier to set
-;;; the value of ange-ftp-dumb-unix-host-regexp in your .emacs file. ange-ftp
-;;; is unable to automatically recognize dumb unix hosts.
-
-;;; File name completion:
-;;;
-;;; Full file-name completion is supported on UNIX, VMS, CMS, and MTS hosts.
-;;; To do filename completion, ange-ftp needs a listing from the remote host.
-;;; Therefore, for very slow connections, it might not save any time.
-
-;;; FTP processes:
-;;;
-;;; When ange-ftp starts up an FTP process, it leaves it running for speed
-;;; purposes.  Some FTP servers will close the connection after a period of
-;;; time, but ange-ftp should be able to quietly reconnect the next time that
-;;; the process is needed.
-;;;
-;;; Killing the "*ftp user@host*" buffer also kills the ftp process.
-;;; This should not cause ange-ftp any grief.
-
-;;; Binary file transfers:
-;;;
-;;; By default ange-ftp transfers files in ASCII mode.  If a file being
-;;; transferred matches the value of ange-ftp-binary-file-name-regexp then
-;;; binary mode is used for that transfer.
-
-;;; Account passwords:
-;;;
-;;; Some FTP servers require an additional password which is sent by the
-;;; ACCOUNT command.  ange-ftp partially supports this by allowing the user to
-;;; specify an account password by either calling ange-ftp-set-account, or by
-;;; specifying an account token in the .netrc file.  If the account password
-;;; is set by either of these methods then ange-ftp will issue an ACCOUNT
-;;; command upon starting the FTP process.
-
-;;; Preloading:
-;;;
-;;; ange-ftp can be preloaded, but must be put in the site-init.el file and
-;;; not the site-load.el file in order for the documentation strings for the
-;;; functions being overloaded to be available.
-
-;;; Status reports:
-;;;
-;;; Most ange-ftp commands that talk to the FTP process output a status
-;;; message on what they are doing.  In addition, ange-ftp can take advantage
-;;; of the FTP client's HASH command to display the status of transferring
-;;; files and listing directories.  See the documentation for the variables
-;;; ange-ftp-{ascii,binary}-hash-mark-size, ange-ftp-send-hash and
-;;; ange-ftp-process-verbose for more details.
-
-;;; Gateways:
-;;;
-;;; Sometimes it is necessary for the FTP process to be run on a different
-;;; machine than the machine running GNU Emacs.  This can happen when the
-;;; local machine has restrictions on what hosts it can access.
-;;;
-;;; ange-ftp has support for running the ftp process on a different (gateway)
-;;; machine.  The way it works is as follows:
-;;;
-;;; 1) Set the variable 'ange-ftp-gateway-host' to the name of a machine
-;;;    that doesn't have the access restrictions.
-;;;
-;;; 2) Set the variable 'ange-ftp-local-host-regexp' to a regular expression
-;;;    that matches hosts that can be contacted from running a local ftp
-;;;    process, but fails to match hosts that can't be accessed locally.  For
-;;;    example:
-;;;
-;;;    "\\.hp\\.com$\\|^[^.]*$"
-;;;
-;;;    will match all hosts that are in the .hp.com domain, or don't have an
-;;;    explicit domain in their name, but will fail to match hosts with
-;;;    explicit domains or that are specified by their ip address.
-;;;
-;;; 3) Using NFS and symlinks, make sure that there is a shared directory with
-;;;    the *same* name between the local machine and the gateway machine.
-;;;    This directory is necessary for temporary files created by ange-ftp.
-;;;
-;;; 4) Set the variable 'ange-ftp-gateway-tmp-name-template' to the name of
-;;;    this directory plus an identifying filename prefix.  For example:
-;;;
-;;;    "/nfs/hplose/ange/ange-ftp"
-;;;
-;;;    where /nfs/hplose/ange is a directory that is shared between the
-;;;    gateway machine and the local machine.
-;;;
-;;; The simplest way of getting a ftp process running on the gateway machine
-;;; is if you can spawn a remote shell using either 'rsh' or 'remsh'.  If you
-;;; can't do this for some reason such as security then points 7 onwards will
-;;; discuss an alternative approach.
-;;;
-;;; 5) Set the variable ange-ftp-gateway-program to the name of the remote
-;;;    shell process such as 'remsh' or 'rsh' if the default isn't correct.
-;;;
-;;; 6) Set the variable ange-ftp-gateway-program-interactive to nil if it
-;;;    isn't already.  This tells ange-ftp that you are using a remote shell
-;;;    rather than logging in using telnet or rlogin.
-;;;
-;;; That should be all you need to allow ange-ftp to spawn a ftp process on
-;;; the gateway machine.  If you have to use telnet or rlogin to get to the
-;;; gateway machine then follow the instructions below.
-;;;
-;;; 7) Set the variable ange-ftp-gateway-program to the name of the program
-;;;    that lets you log onto the gateway machine.  This may be something like
-;;;    telnet or rlogin.
-;;;
-;;; 8) Set the variable ange-ftp-gateway-prompt-pattern to a regular
-;;;    expression that matches the prompt you get when you login to the
-;;;    gateway machine.  Be very specific here; this regexp must not match
-;;;    *anything* in your login banner except this prompt.
-;;;    shell-prompt-pattern is far too general as it appears to match some
-;;;    login banners from Sun machines.  For example:
-;;;
-;;;    "^$*$ *"
-;;;
-;;; 9) Set the variable ange-ftp-gateway-program-interactive to 't' to let
-;;;    ange-ftp know that it has to "hand-hold" the login to the gateway
-;;;    machine.
-;;;
-;;; 10) Set the variable ange-ftp-gateway-setup-term-command to a UNIX command
-;;;     that will put the pty connected to the gateway machine into a
-;;;     no-echoing mode, and will strip off carriage-returns from output from
-;;;     the gateway machine.  For example:
-;;;
-;;;     "stty -onlcr -echo"
-;;;
-;;;     will work on HP-UX machines, whereas:
-;;;
-;;;     "stty -echo nl"
-;;;
-;;;     appears to work for some Sun machines.
-;;;
-;;; That's all there is to it.
-
-;;; Smart gateways:
-;;;
-;;; If you have a "smart" ftp program that allows you to issue commands like
-;;; "USER foo@bar" which do nice proxy things, then look at the variables
-;;; ange-ftp-smart-gateway and ange-ftp-smart-gateway-port.
-
-;;; Tips for using ange-ftp:
-;;;
-;;; 1. For dired to work on a host which marks symlinks with a trailing @ in
-;;;    an ls -alF listing, you need to (setq dired-ls-F-marks-symlinks t).
-;;;    Most UNIX systems do not do this, but ULTRIX does. If you think that
-;;;    there is a chance you might connect to an ULTRIX machine (such as
-;;;    prep.ai.mit.edu), then set this variable accordingly.  This will have
-;;;    the side effect that dired will have problems with symlinks whose names
-;;;    end in an @.  If you get yourself into this situation then editing
-;;;    dired's ls-switches to remove "F", will temporarily fix things.
-;;;
-;;; 2. If you know that you are connecting to a certain non-UNIX machine
-;;;    frequently, and ange-ftp seems to be unable to guess its host-type,
-;;;    then setting the appropriate host-type regexp
-;;;    (ange-ftp-vms-host-regexp, ange-ftp-mts-host-regexp, or
-;;;    ange-ftp-cms-host-regexp) accordingly should help. Also, please report
-;;;    ange-ftp's inability to recognize the host-type as a bug.
-;;;
-;;; 3. For slow connections, you might get "listing unreadable" error
-;;;    messages, or get an empty buffer for a file that you know has something
-;;;    in it. The solution is to increase the value of ange-ftp-retry-time.
-;;;    Its default value is 5 which is plenty for reasonable connections.
-;;;    However, for some transatlantic connections I set this to 20.
-;;;
-;;; 4. Beware of compressing files on non-UNIX hosts. Ange-ftp will do it by
-;;;    copying the file to the local machine, compressing it there, and then
-;;;    sending it back. Binary file transfers between machines of different
-;;;    architectures can be a risky business. Test things out first on some
-;;;    test files. See "Bugs" below. Also, note that ange-ftp copies files by
-;;;    moving them through the local machine. Again, be careful when doing
-;;;    this with binary files on non-Unix machines.
-;;;
-;;; 5. Beware that dired over ftp will use your setting of dired-no-confirm
-;;;    (list of dired commands for which confirmation is not asked).  You
-;;;    might want to reconsider your setting of this variable, because you
-;;;    might want confirmation for more commands on remote direds than on
-;;;    local direds. For example, I strongly recommend that you not include
-;;;    compress and uncompress in this list. If there is enough demand it
-;;;    might be a good idea to have an alist ange-ftp-dired-no-confirm of
-;;;    pairs ( TYPE . LIST ), where TYPE is an operating system type and LIST
-;;;    is a list of commands for which confirmation would be suppressed.  Then
-;;;    remote dired listings would take their (buffer-local) value of
-;;;    dired-no-confirm from this alist. Who votes for this?
-
-;;; ---------------------------------------------------------------------
-;;; Non-UNIX support:
-;;; ---------------------------------------------------------------------
-
-;;; VMS support:
-;;;
-;;; Ange-ftp has full support for VMS hosts.  It
-;;; should be able to automatically recognize any VMS machine. However, if it
-;;; fails to do this, you can use the command ange-ftp-add-vms-host.  As well,
-;;; you can set the variable ange-ftp-vms-host-regexp in your .emacs file. We
-;;; would be grateful if you would report any failures to automatically
-;;; recognize a VMS host as a bug.
-;;;
-;;; Filename Syntax:
-;;;
-;;; For ease of *implementation*, the user enters the VMS filename syntax in a
-;;; UNIX-y way.  For example:
-;;;  PUB$:[ANONYMOUS.SDSCPUB.NEXT]README.TXT;1
-;;; would be entered as:
-;;;  /PUB$$:/ANONYMOUS/SDSCPUB/NEXT/README.TXT;1
-;;; i.e. to log in as anonymous on ymir.claremont.edu and grab the file:
-;;;  [.CSV.POLICY]RULES.MEM
-;;; you would type:
-;;;  C-x C-f /anonymous@ymir.claremont.edu:CSV/POLICY/RULES.MEM
-;;;
-;;; A legal VMS filename is of the form: FILE.TYPE;##
-;;; where FILE can be up to 39 characters
-;;;       TYPE can be up to 39 characters
-;;;       ## is a version number (an integer between 1 and 32,767)
-;;; Valid characters in FILE and TYPE are A-Z 0-9 _ - $
-;;; $ cannot begin a filename, and - cannot be used as the first or last
-;;; character.
-;;;
-;;; Tips:
-;;; 1. Although VMS is not case sensitive, EMACS running under UNIX is.
-;;;    Therefore, to access a VMS file, you must enter the filename with upper
-;;;    case letters.
-;;; 2. To access the latest version of file under VMS, you use the filename
-;;;    without the ";" and version number. You should always edit the latest
-;;;    version of a file. If you want to edit an earlier version, copy it to a
-;;;    new file first. This has nothing to do with ange-ftp, but is simply
-;;;    good VMS operating practice. Therefore, to edit FILE.TXT;3 (say 3 is
-;;;    latest version), do C-x C-f /ymir.claremont.edu:FILE.TXT. If you
-;;;    inadvertently do C-x C-f /ymir.claremont.edu:FILE.TXT;3, you will find
-;;;    that VMS will not allow you to save the file because it will refuse to
-;;;    overwrite FILE.TXT;3, but instead will want to create FILE.TXT;4, and
-;;;    attach the buffer to this file. To get out of this situation, M-x
-;;;    write-file /ymir.claremont.edu:FILE.TXT will attach the buffer to
-;;;    latest version of the file. For this reason, in dired "f"
-;;;    (dired-find-file), always loads the file sans version, whereas "v",
-;;;    (dired-view-file), always loads the explicit version number. The
-;;;    reasoning being that it reasonable to view old versions of a file, but
-;;;    not to edit them.
-;;; 3. EMACS has a feature in which it does environment variable substitution
-;;;    in filenames. Therefore, to enter a $ in a filename, you must quote it
-;;;    by typing $$.
-
-;;; MTS support:
-;;;
-;;; Ange-ftp has full support for hosts running
-;;; the Michigan terminal system.  It should be able to automatically
-;;; recognize any MTS machine. However, if it fails to do this, you can use
-;;; the command ange-ftp-add-mts-host.  As well, you can set the variable
-;;; ange-ftp-mts-host-regexp in your .emacs file. We would be grateful if you
-;;; would report any failures to automatically recognize a MTS host as a bug.
-;;;
-;;; Filename syntax:
-;;; 
-;;; MTS filenames are entered in a UNIX-y way. For example, if your account
-;;; was YYYY, the file FILE in the account XXXX: on mtsg.ubc.ca would be
-;;; entered as
-;;;   /YYYY@mtsg.ubc.ca:/XXXX:/FILE
-;;; In other words, MTS accounts are treated as UNIX directories. Of course,
-;;; to access a file in another account, you must have access permission for
-;;; it.  If FILE were in your own account, then you could enter it in a
-;;; relative name fashion as
-;;;   /YYYY@mtsg.ubc.ca:FILE
-;;; MTS filenames can be up to 12 characters. Like UNIX, the structure of the
-;;; filename does not contain a TYPE (i.e. it can have as many "."'s as you
-;;; like.) MTS filenames are always in upper case, and hence be sure to enter
-;;; them as such! MTS is not case sensitive, but an EMACS running under UNIX
-;;; is.
-
-;;; CMS support:
-;;; 
-;;; Ange-ftp has full support for hosts running
-;;; CMS.  It should be able to automatically recognize any CMS machine.
-;;; However, if it fails to do this, you can use the command
-;;; ange-ftp-add-cms-host.  As well, you can set the variable
-;;; ange-ftp-cms-host-regexp in your .emacs file. We would be grateful if you
-;;; would report any failures to automatically recognize a CMS host as a bug.
-;;; 
-;;; Filename syntax:
-;;;
-;;; CMS filenames are entered in a UNIX-y way. In otherwords, minidisks are
-;;; treated as UNIX directories. For example to access the file READ.ME in
-;;; minidisk *.311 on cuvmb.cc.columbia.edu, you would enter
-;;;   /anonymous@cuvmb.cc.columbia.edu:/*.311/READ.ME
-;;; If *.301 is the default minidisk for this account, you could access
-;;; FOO.BAR on this minidisk as
-;;;   /anonymous@cuvmb.cc.columbia.edu:FOO.BAR
-;;; CMS filenames are of the form FILE.TYPE, where both FILE and TYPE can be
-;;; up to 8 characters. Again, beware that CMS filenames are always upper
-;;; case, and hence must be entered as such.
-;;;
-;;; Tips:
-;;; 1. CMS machines, with the exception of anonymous accounts, nearly always
-;;;    need an account password. To have ange-ftp send an account password,
-;;;    you can either include it in your .netrc file, or use
-;;;    ange-ftp-set-account.
-;;; 2. Ange-ftp cannot send "write passwords" for a minidisk. Hopefully, we
-;;;    can fix this.
-;;;
-;;; ------------------------------------------------------------------
-;;; Bugs:
-;;; ------------------------------------------------------------------
-;;; 
-;;; 1. Umask problems:
-;;;    Be warned that files created by using ange-ftp will take account of the
-;;;    umask of the ftp daemon process rather than the umask of the creating
-;;;    user.  This is particularly important when logging in as the root user.
-;;;    The way that I tighten up the ftp daemon's umask under HP-UX is to make
-;;;    sure that the umask is changed to 027 before I spawn /etc/inetd.  I
-;;;    suspect that there is something similar on other systems.
-;;;
-;;; 2. Some combinations of FTP clients and servers break and get out of sync
-;;;    when asked to list a non-existent directory.  Some of the ai.mit.edu
-;;;    machines cause this problem for some FTP clients. Using
-;;;    ange-ftp-kill-ftp-process can restart the ftp process, which
-;;;    should get things back in synch.
-;;;
-;;; 3. Ange-ftp does not check to make sure that when creating a new file,
-;;;    you provide a valid filename for the remote operating system.
-;;;    If you do not, then the remote FTP server will most likely
-;;;    translate your filename in some way. This may cause ange-ftp to
-;;;    get confused about what exactly is the name of the file. The
-;;;    most common causes of this are using lower case filenames on systems
-;;;    which support only upper case, and using filenames which are too
-;;;    long.
-;;;
-;;; 4. Null (blank) passwords confuse both ange-ftp and some FTP daemons.
-;;;
-;;; 5. Ange-ftp likes to use pty's to talk to its FTP processes.  If GNU Emacs
-;;;    for some reason creates a FTP process that only talks via pipes then
-;;;    ange-ftp won't be getting the information it requires at the time that
-;;;    it wants it since pipes flush at different times to pty's.  One
-;;;    disgusting way around this problem is to talk to the FTP process via
-;;;    rlogin which does the 'right' things with pty's.
-;;;
-;;; 6. For CMS support, we send too many cd's. Since cd's are cheap, I haven't
-;;;    worried about this too much. Eventually, we should have some caching
-;;;    of the current minidisk.
-;;;    
-;;; 7. Some CMS machines do not assign a default minidisk when you ftp them as
-;;;    anonymous. It is then necessary to guess a valid minidisk name, and cd
-;;;    to it. This is (understandably) beyond ange-ftp.
-;;;
-;;; 8. Remote to remote copying of files on non-Unix machines can be risky.
-;;;    Depending on the variable ange-ftp-binary-file-name-regexp, ange-ftp
-;;;    will use binary mode for the copy. Between systems of different
-;;;    architecture, this still may not be enough to guarantee the integrity
-;;;    of binary files. Binary file transfers from VMS machines are
-;;;    particularly problematical. Should ange-ftp-binary-file-name-regexp be
-;;;    an alist of OS type, regexp pairs?
-;;;
-;;; 9. The code to do compression of files over ftp is not as careful as it
-;;;    should be. It deletes the old remote version of the file, before
-;;;    actually checking if the local to remote transfer of the compressed
-;;;    file succeeds. Of course to delete the original version of the file
-;;;    after transferring the compressed version back is also dangerous,
-;;;    because some OS's have severe restrictions on the length of filenames,
-;;;    and when the compressed version is copied back the "-Z" or ".Z" may be
-;;;    truncated. Then, ange-ftp would delete the only remaining version of
-;;;    the file.  Maybe ange-ftp should make backups when it compresses files
-;;;    (of course, the backup "~" could also be truncated off, sigh...).
-;;;    Suggestions?
-;;;
-
-;;; 10. If a dir listing is attempted for an empty directory on (at least
-;;;     some) VMS hosts, an ftp error is given. This is really an ftp bug, and
-;;;     I don't know how to get ange-ftp work to around it.
-;;;
-;;; 11. Bombs on filenames that start with a space. Deals well with filenames
-;;;     containing spaces, but beware that the remote ftpd may not like them
-;;;     much.
-;;;
-;;; 12. The dired support for non-Unix-like systems does not currently work.
-;;;     It needs to be reimplemented by modifying the parse-...-listing
-;;;    functions to convert the directory listing to ls -l format.
-;;; 
-;;; 13. The famous @ bug. As mentioned above in TIPS, ULTRIX marks symlinks
-;;;     with a trailing @ in a ls -alF listing. In order to account for this
-;;;     ange-ftp looks to chop trailing @'s off of symlink names when it is
-;;;     parsing a listing with the F switch. This will cause ange-ftp to
-;;;     incorrectly get the name of a symlink on a non-ULTRIX host if its name
-;;;     ends in an @. ange-ftp will correct itself if you take F out of the
-;;;     dired ls switches (C-u s will allow you to edit the switches). The
-;;;     dired buffer will be automatically reverted, which will allow ange-ftp
-;;;     to fix its files hashtable.  A cookie to anyone who can think of a
-;;;     fast, sure-fire way to recognize ULTRIX over ftp.
-
-;;; If you find any bugs or problems with this package, PLEASE either e-mail
-;;; the above author, or send a message to the ange-ftp-lovers mailing list
-;;; below.  Ideas and constructive comments are especially welcome.
-
-;;; ange-ftp-lovers:
-;;;
-;;; ange-ftp has its own mailing list modestly called ange-ftp-lovers.  All
-;;; users of ange-ftp are welcome to subscribe (see below) and to discuss
-;;; aspects of ange-ftp.  New versions of ange-ftp are posted periodically to
-;;; the mailing list.
-;;;
-;;; To [un]subscribe to ange-ftp-lovers, or to report mailer problems with the
-;;; list, please mail one of the following addresses:
-;;;
-;;;     ange-ftp-lovers-request@anorman.hpl.hp.com
-;;; or
-;;;     ange-ftp-lovers-request%anorman.hpl.hp.com@hplb.hpl.hp.com
-;;;
-;;; Please don't forget the -request part.
-;;;
-;;; For mail to be posted directly to ange-ftp-lovers, send to one of the
-;;; following addresses:
-;;; 
-;;;     ange-ftp-lovers@anorman.hpl.hp.com
-;;; or
-;;;     ange-ftp-lovers%anorman.hpl.hp.com@hplb.hpl.hp.com
-;;;
-;;; Alternatively, there is a mailing list that only gets announcements of new
-;;; ange-ftp releases.  This is called ange-ftp-lovers-announce, and can be
-;;; subscribed to by e-mailing to the -request address as above.  Please make
-;;; it clear in the request which mailing list you wish to join.
-
-;;; The latest version of ange-ftp can usually be obtained via anonymous ftp
-;;; from:
-;;;     alpha.gnu.ai.mit.edu:ange-ftp/ange-ftp.tar.Z
-;;; or:
-;;;     ugle.unit.no:/pub/gnu/emacs-lisp/ange-ftp.tar.Z
-;;; or:
-;;;   archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/ange-ftp.tar.Z
-
-;;; The archives for ange-ftp-lovers can be found via anonymous ftp under:
-;;;
-;;;     ftp.reed.edu:pub/mailing-lists/ange-ftp/
+
+;; This package attempts to make accessing files and directories using FTP
+;; from within GNU Emacs as simple and transparent as possible.  A subset of
+;; the common file-handling routines are extended to interact with FTP.
+
+;; Usage:
+;;
+;; Some of the common GNU Emacs file-handling operations have been made
+;; FTP-smart.  If one of these routines is given a filename that matches
+;; '/user@host:name' then it will spawn an FTP process connecting to machine
+;; 'host' as account 'user' and perform its operation on the file 'name'.
+;;
+;; For example: if find-file is given a filename of:
+;;
+;;   /ange@anorman:/tmp/notes
+;;
+;; then ange-ftp spawns an FTP process, connect to the host 'anorman' as
+;; user 'ange', get the file '/tmp/notes' and pop up a buffer containing the
+;; contents of that file as if it were on the local filesystem.  If ange-ftp
+;; needs a password to connect then it reads one in the echo area.
+
+;; Extended filename syntax:
+;;
+;; The default extended filename syntax is '/user@host:name', where the
+;; 'user@' part may be omitted.  This syntax can be customised to a certain
+;; extent by changing ange-ftp-name-format.  There are limitations.
+;;
+;; If the user part is omitted then ange-ftp generates a default user
+;; instead whose value depends on the variable ange-ftp-default-user.
+
+;; Passwords:
+;;
+;; A password is required for each host/user pair.  Ange-ftp reads passwords
+;; as needed.  You can also specify a password with ange-ftp-set-passwd, or
+;; in a *valid* ~/.netrc file.
+
+;; Passwords for user "anonymous":
+;;
+;; Passwords for the user "anonymous" (or "ftp") are handled
+;; specially.  The variable `ange-ftp-generate-anonymous-password'
+;; controls what happens: if the value of this variable is a string,
+;; then this is used as the password; if non-nil (the default), then
+;; the value of `user-mail-address' is used; if nil then the user
+;; is prompted for a password as normal.
+
+;; "Dumb" UNIX hosts:
+;;
+;; The FTP servers on some UNIX machines have problems if the 'ls' command is
+;; used.
+;;
+;; The routine ange-ftp-add-dumb-unix-host can be called to tell ange-ftp to
+;; limit itself to the DIR command and not 'ls' for a given UNIX host.  Note
+;; that this change will take effect for the current GNU Emacs session only.
+;; See below for a discussion of non-UNIX hosts.  If a large number of
+;; machines with similar hostnames have this problem then it is easier to set
+;; the value of ange-ftp-dumb-unix-host-regexp in your .emacs file. ange-ftp
+;; is unable to automatically recognize dumb unix hosts.
+
+;; File name completion:
+;;
+;; Full file-name completion is supported on UNIX, VMS, CMS, and MTS hosts.
+;; To do filename completion, ange-ftp needs a listing from the remote host.
+;; Therefore, for very slow connections, it might not save any time.
+
+;; FTP processes:
+;;
+;; When ange-ftp starts up an FTP process, it leaves it running for speed
+;; purposes.  Some FTP servers will close the connection after a period of
+;; time, but ange-ftp should be able to quietly reconnect the next time that
+;; the process is needed.
+;;
+;; Killing the "*ftp user@host*" buffer also kills the ftp process.
+;; This should not cause ange-ftp any grief.
+
+;; Binary file transfers:
+;;
+;; By default ange-ftp transfers files in ASCII mode.  If a file being
+;; transferred matches the value of ange-ftp-binary-file-name-regexp then
+;; binary mode is used for that transfer.
+
+;; Account passwords:
+;;
+;; Some FTP servers require an additional password which is sent by the
+;; ACCOUNT command.  ange-ftp partially supports this by allowing the user to
+;; specify an account password by either calling ange-ftp-set-account, or by
+;; specifying an account token in the .netrc file.  If the account password
+;; is set by either of these methods then ange-ftp will issue an ACCOUNT
+;; command upon starting the FTP process.
+
+;; Preloading:
+;;
+;; ange-ftp can be preloaded, but must be put in the site-init.el file and
+;; not the site-load.el file in order for the documentation strings for the
+;; functions being overloaded to be available.
+
+;; Status reports:
+;;
+;; Most ange-ftp commands that talk to the FTP process output a status
+;; message on what they are doing.  In addition, ange-ftp can take advantage
+;; of the FTP client's HASH command to display the status of transferring
+;; files and listing directories.  See the documentation for the variables
+;; ange-ftp-{ascii,binary}-hash-mark-size, ange-ftp-send-hash and
+;; ange-ftp-process-verbose for more details.
+
+;; Gateways:
+;;
+;; Sometimes it is necessary for the FTP process to be run on a different
+;; machine than the machine running GNU Emacs.  This can happen when the
+;; local machine has restrictions on what hosts it can access.
+;;
+;; ange-ftp has support for running the ftp process on a different (gateway)
+;; machine.  The way it works is as follows:
+;;
+;; 1) Set the variable 'ange-ftp-gateway-host' to the name of a machine
+;;    that doesn't have the access restrictions.
+;;
+;; 2) Set the variable 'ange-ftp-local-host-regexp' to a regular expression
+;;    that matches hosts that can be contacted from running a local ftp
+;;    process, but fails to match hosts that can't be accessed locally.  For
+;;    example:
+;;
+;;    "\\.hp\\.com$\\|^[^.]*$"
+;;
+;;    will match all hosts that are in the .hp.com domain, or don't have an
+;;    explicit domain in their name, but will fail to match hosts with
+;;    explicit domains or that are specified by their ip address.
+;;
+;; 3) Using NFS and symlinks, make sure that there is a shared directory with
+;;    the *same* name between the local machine and the gateway machine.
+;;    This directory is necessary for temporary files created by ange-ftp.
+;;
+;; 4) Set the variable 'ange-ftp-gateway-tmp-name-template' to the name of
+;;    this directory plus an identifying filename prefix.  For example:
+;;
+;;    "/nfs/hplose/ange/ange-ftp"
+;;
+;;    where /nfs/hplose/ange is a directory that is shared between the
+;;    gateway machine and the local machine.
+;;
+;; The simplest way of getting a ftp process running on the gateway machine
+;; is if you can spawn a remote shell using either 'rsh' or 'remsh'.  If you
+;; can't do this for some reason such as security then points 7 onwards will
+;; discuss an alternative approach.
+;;
+;; 5) Set the variable ange-ftp-gateway-program to the name of the remote
+;;    shell process such as 'remsh' or 'rsh' if the default isn't correct.
+;;
+;; 6) Set the variable ange-ftp-gateway-program-interactive to nil if it
+;;    isn't already.  This tells ange-ftp that you are using a remote shell
+;;    rather than logging in using telnet or rlogin.
+;;
+;; That should be all you need to allow ange-ftp to spawn a ftp process on
+;; the gateway machine.  If you have to use telnet or rlogin to get to the
+;; gateway machine then follow the instructions below.
+;;
+;; 7) Set the variable ange-ftp-gateway-program to the name of the program
+;;    that lets you log onto the gateway machine.  This may be something like
+;;    telnet or rlogin.
+;;
+;; 8) Set the variable ange-ftp-gateway-prompt-pattern to a regular
+;;    expression that matches the prompt you get when you login to the
+;;    gateway machine.  Be very specific here; this regexp must not match
+;;    *anything* in your login banner except this prompt.
+;;    shell-prompt-pattern is far too general as it appears to match some
+;;    login banners from Sun machines.  For example:
+;;
+;;    "^$*$ *"
+;;
+;; 9) Set the variable ange-ftp-gateway-program-interactive to 't' to let
+;;    ange-ftp know that it has to "hand-hold" the login to the gateway
+;;    machine.
+;;
+;; 10) Set the variable ange-ftp-gateway-setup-term-command to a UNIX command
+;;     that will put the pty connected to the gateway machine into a
+;;     no-echoing mode, and will strip off carriage-returns from output from
+;;     the gateway machine.  For example:
+;;
+;;     "stty -onlcr -echo"
+;;
+;;     will work on HP-UX machines, whereas:
+;;
+;;     "stty -echo nl"
+;;
+;;     appears to work for some Sun machines.
+;;
+;; That's all there is to it.
+
+;; Smart gateways:
+;;
+;; If you have a "smart" ftp program that allows you to issue commands like
+;; "USER foo@bar" which do nice proxy things, then look at the variables
+;; ange-ftp-smart-gateway and ange-ftp-smart-gateway-port.
+;;
+;; Otherwise, if there is an alternate ftp program that implements proxy in
+;; a transparent way (i.e. w/o specifying the proxy host), that will
+;; connect you directly to the desired destination host:
+;; Set ange-ftp-gateway-ftp-program-name to that program's name.
+;; Set ange-ftp-local-host-regexp to a value as stated earlier on.
+;; Leave ange-ftp-gateway-host set to nil.
+;; Set ange-ftp-smart-gateway to t.
+
+;; Tips for using ange-ftp:
+;;
+;; 1. For dired to work on a host which marks symlinks with a trailing @ in
+;;    an ls -alF listing, you need to (setq dired-ls-F-marks-symlinks t).
+;;    Most UNIX systems do not do this, but ULTRIX does. If you think that
+;;    there is a chance you might connect to an ULTRIX machine (such as
+;;    prep.ai.mit.edu), then set this variable accordingly.  This will have
+;;    the side effect that dired will have problems with symlinks whose names
+;;    end in an @.  If you get yourself into this situation then editing
+;;    dired's ls-switches to remove "F", will temporarily fix things.
+;;
+;; 2. If you know that you are connecting to a certain non-UNIX machine
+;;    frequently, and ange-ftp seems to be unable to guess its host-type,
+;;    then setting the appropriate host-type regexp
+;;    (ange-ftp-vms-host-regexp, ange-ftp-mts-host-regexp, or
+;;    ange-ftp-cms-host-regexp) accordingly should help. Also, please report
+;;    ange-ftp's inability to recognize the host-type as a bug.
+;;
+;; 3. For slow connections, you might get "listing unreadable" error
+;;    messages, or get an empty buffer for a file that you know has something
+;;    in it. The solution is to increase the value of ange-ftp-retry-time.
+;;    Its default value is 5 which is plenty for reasonable connections.
+;;    However, for some transatlantic connections I set this to 20.
+;;
+;; 4. Beware of compressing files on non-UNIX hosts. Ange-ftp will do it by
+;;    copying the file to the local machine, compressing it there, and then
+;;    sending it back. Binary file transfers between machines of different
+;;    architectures can be a risky business. Test things out first on some
+;;    test files. See "Bugs" below. Also, note that ange-ftp copies files by
+;;    moving them through the local machine. Again, be careful when doing
+;;    this with binary files on non-Unix machines.
+;;
+;; 5. Beware that dired over ftp will use your setting of dired-no-confirm
+;;    (list of dired commands for which confirmation is not asked).  You
+;;    might want to reconsider your setting of this variable, because you
+;;    might want confirmation for more commands on remote direds than on
+;;    local direds. For example, I strongly recommend that you not include
+;;    compress and uncompress in this list. If there is enough demand it
+;;    might be a good idea to have an alist ange-ftp-dired-no-confirm of
+;;    pairs ( TYPE . LIST ), where TYPE is an operating system type and LIST
+;;    is a list of commands for which confirmation would be suppressed.  Then
+;;    remote dired listings would take their (buffer-local) value of
+;;    dired-no-confirm from this alist. Who votes for this?
+
+;; ---------------------------------------------------------------------
+;; Non-UNIX support:
+;; ---------------------------------------------------------------------
+
+;; VMS support:
+;;
+;; Ange-ftp has full support for VMS hosts.  It
+;; should be able to automatically recognize any VMS machine. However, if it
+;; fails to do this, you can use the command ange-ftp-add-vms-host.  As well,
+;; you can set the variable ange-ftp-vms-host-regexp in your .emacs file. We
+;; would be grateful if you would report any failures to automatically
+;; recognize a VMS host as a bug.
+;;
+;; Filename Syntax:
+;;
+;; For ease of *implementation*, the user enters the VMS filename syntax in a
+;; UNIX-y way.  For example:
+;;  PUB$:[ANONYMOUS.SDSCPUB.NEXT]README.TXT;1
+;; would be entered as:
+;;  /PUB$$:/ANONYMOUS/SDSCPUB/NEXT/README.TXT;1
+;; i.e. to log in as anonymous on ymir.claremont.edu and grab the file:
+;;  [.CSV.POLICY]RULES.MEM
+;; you would type:
+;;  C-x C-f /anonymous@ymir.claremont.edu:CSV/POLICY/RULES.MEM
+;;
+;; A legal VMS filename is of the form: FILE.TYPE;##
+;; where FILE can be up to 39 characters
+;;       TYPE can be up to 39 characters
+;;       ## is a version number (an integer between 1 and 32,767)
+;; Valid characters in FILE and TYPE are A-Z 0-9 _ - $
+;; $ cannot begin a filename, and - cannot be used as the first or last
+;; character.
+;;
+;; Tips:
+;; 1. Although VMS is not case sensitive, EMACS running under UNIX is.
+;;    Therefore, to access a VMS file, you must enter the filename with upper
+;;    case letters.
+;; 2. To access the latest version of file under VMS, you use the filename
+;;    without the ";" and version number. You should always edit the latest
+;;    version of a file. If you want to edit an earlier version, copy it to a
+;;    new file first. This has nothing to do with ange-ftp, but is simply
+;;    good VMS operating practice. Therefore, to edit FILE.TXT;3 (say 3 is
+;;    latest version), do C-x C-f /ymir.claremont.edu:FILE.TXT. If you
+;;    inadvertently do C-x C-f /ymir.claremont.edu:FILE.TXT;3, you will find
+;;    that VMS will not allow you to save the file because it will refuse to
+;;    overwrite FILE.TXT;3, but instead will want to create FILE.TXT;4, and
+;;    attach the buffer to this file. To get out of this situation, M-x
+;;    write-file /ymir.claremont.edu:FILE.TXT will attach the buffer to
+;;    latest version of the file. For this reason, in dired "f"
+;;    (dired-find-file), always loads the file sans version, whereas "v",
+;;    (dired-view-file), always loads the explicit version number. The
+;;    reasoning being that it reasonable to view old versions of a file, but
+;;    not to edit them.
+;; 3. EMACS has a feature in which it does environment variable substitution
+;;    in filenames. Therefore, to enter a $ in a filename, you must quote it
+;;    by typing $$.
+
+;; MTS support:
+;;
+;; Ange-ftp has full support for hosts running
+;; the Michigan terminal system.  It should be able to automatically
+;; recognize any MTS machine. However, if it fails to do this, you can use
+;; the command ange-ftp-add-mts-host.  As well, you can set the variable
+;; ange-ftp-mts-host-regexp in your .emacs file. We would be grateful if you
+;; would report any failures to automatically recognize a MTS host as a bug.
+;;
+;; Filename syntax:
+;; 
+;; MTS filenames are entered in a UNIX-y way. For example, if your account
+;; was YYYY, the file FILE in the account XXXX: on mtsg.ubc.ca would be
+;; entered as
+;;   /YYYY@mtsg.ubc.ca:/XXXX:/FILE
+;; In other words, MTS accounts are treated as UNIX directories. Of course,
+;; to access a file in another account, you must have access permission for
+;; it.  If FILE were in your own account, then you could enter it in a
+;; relative name fashion as
+;;   /YYYY@mtsg.ubc.ca:FILE
+;; MTS filenames can be up to 12 characters. Like UNIX, the structure of the
+;; filename does not contain a TYPE (i.e. it can have as many "."'s as you
+;; like.) MTS filenames are always in upper case, and hence be sure to enter
+;; them as such! MTS is not case sensitive, but an EMACS running under UNIX
+;; is.
+
+;; CMS support:
+;; 
+;; Ange-ftp has full support for hosts running
+;; CMS.  It should be able to automatically recognize any CMS machine.
+;; However, if it fails to do this, you can use the command
+;; ange-ftp-add-cms-host.  As well, you can set the variable
+;; ange-ftp-cms-host-regexp in your .emacs file. We would be grateful if you
+;; would report any failures to automatically recognize a CMS host as a bug.
+;; 
+;; Filename syntax:
+;;
+;; CMS filenames are entered in a UNIX-y way. In otherwords, minidisks are
+;; treated as UNIX directories. For example to access the file READ.ME in
+;; minidisk *.311 on cuvmb.cc.columbia.edu, you would enter
+;;   /anonymous@cuvmb.cc.columbia.edu:/*.311/READ.ME
+;; If *.301 is the default minidisk for this account, you could access
+;; FOO.BAR on this minidisk as
+;;   /anonymous@cuvmb.cc.columbia.edu:FOO.BAR
+;; CMS filenames are of the form FILE.TYPE, where both FILE and TYPE can be
+;; up to 8 characters. Again, beware that CMS filenames are always upper
+;; case, and hence must be entered as such.
+;;
+;; Tips:
+;; 1. CMS machines, with the exception of anonymous accounts, nearly always
+;;    need an account password. To have ange-ftp send an account password,
+;;    you can either include it in your .netrc file, or use
+;;    ange-ftp-set-account.
+;; 2. Ange-ftp cannot send "write passwords" for a minidisk. Hopefully, we
+;;    can fix this.
+;;
+;; ------------------------------------------------------------------
+;; Bugs:
+;; ------------------------------------------------------------------
+;; 
+;; 1. Umask problems:
+;;    Be warned that files created by using ange-ftp will take account of the
+;;    umask of the ftp daemon process rather than the umask of the creating
+;;    user.  This is particularly important when logging in as the root user.
+;;    The way that I tighten up the ftp daemon's umask under HP-UX is to make
+;;    sure that the umask is changed to 027 before I spawn /etc/inetd.  I
+;;    suspect that there is something similar on other systems.
+;;
+;; 2. Some combinations of FTP clients and servers break and get out of sync
+;;    when asked to list a non-existent directory.  Some of the ai.mit.edu
+;;    machines cause this problem for some FTP clients. Using
+;;    ange-ftp-kill-ftp-process can restart the ftp process, which
+;;    should get things back in sync.
+;;
+;; 3. Ange-ftp does not check to make sure that when creating a new file,
+;;    you provide a valid filename for the remote operating system.
+;;    If you do not, then the remote FTP server will most likely
+;;    translate your filename in some way. This may cause ange-ftp to
+;;    get confused about what exactly is the name of the file. The
+;;    most common causes of this are using lower case filenames on systems
+;;    which support only upper case, and using filenames which are too
+;;    long.
+;;
+;; 4. Null (blank) passwords confuse both ange-ftp and some FTP daemons.
+;;
+;; 5. Ange-ftp likes to use pty's to talk to its FTP processes.  If GNU Emacs
+;;    for some reason creates a FTP process that only talks via pipes then
+;;    ange-ftp won't be getting the information it requires at the time that
+;;    it wants it since pipes flush at different times to pty's.  One
+;;    disgusting way around this problem is to talk to the FTP process via
+;;    rlogin which does the 'right' things with pty's.
+;;
+;; 6. For CMS support, we send too many cd's. Since cd's are cheap, I haven't
+;;    worried about this too much. Eventually, we should have some caching
+;;    of the current minidisk.
+;;    
+;; 7. Some CMS machines do not assign a default minidisk when you ftp them as
+;;    anonymous. It is then necessary to guess a valid minidisk name, and cd
+;;    to it. This is (understandably) beyond ange-ftp.
+;;
+;; 8. Remote to remote copying of files on non-Unix machines can be risky.
+;;    Depending on the variable ange-ftp-binary-file-name-regexp, ange-ftp
+;;    will use binary mode for the copy. Between systems of different
+;;    architecture, this still may not be enough to guarantee the integrity
+;;    of binary files. Binary file transfers from VMS machines are
+;;    particularly problematical. Should ange-ftp-binary-file-name-regexp be
+;;    an alist of OS type, regexp pairs?
+;;
+;; 9. The code to do compression of files over ftp is not as careful as it
+;;    should be. It deletes the old remote version of the file, before
+;;    actually checking if the local to remote transfer of the compressed
+;;    file succeeds. Of course to delete the original version of the file
+;;    after transferring the compressed version back is also dangerous,
+;;    because some OS's have severe restrictions on the length of filenames,
+;;    and when the compressed version is copied back the "-Z" or ".Z" may be
+;;    truncated. Then, ange-ftp would delete the only remaining version of
+;;    the file.  Maybe ange-ftp should make backups when it compresses files
+;;    (of course, the backup "~" could also be truncated off, sigh...).
+;;    Suggestions?
+;;
+;; 10. If a dir listing is attempted for an empty directory on (at least
+;;     some) VMS hosts, an ftp error is given. This is really an ftp bug, and
+;;     I don't know how to get ange-ftp work to around it.
+;;
+;; 11. Bombs on filenames that start with a space. Deals well with filenames
+;;     containing spaces, but beware that the remote ftpd may not like them
+;;     much.
+;;
+;; 12. The dired support for non-Unix-like systems does not currently work.
+;;     It needs to be reimplemented by modifying the parse-...-listing
+;;     functions to convert the directory listing to ls -l format.
+;; 
+;; 13. The famous @ bug. As mentioned above in TIPS, ULTRIX marks symlinks
+;;     with a trailing @ in a ls -alF listing. In order to account for this
+;;     ange-ftp looks to chop trailing @'s off of symlink names when it is
+;;     parsing a listing with the F switch. This will cause ange-ftp to
+;;     incorrectly get the name of a symlink on a non-ULTRIX host if its name
+;;     ends in an @. ange-ftp will correct itself if you take F out of the
+;;     dired ls switches (C-u s will allow you to edit the switches). The
+;;     dired buffer will be automatically reverted, which will allow ange-ftp
+;;     to fix its files hashtable.  A cookie to anyone who can think of a
+;;     fast, sure-fire way to recognize ULTRIX over ftp.
+
+;; If you find any bugs or problems with this package, PLEASE either e-mail
+;; the above author, or send a message to the ange-ftp-lovers mailing list
+;; below.  Ideas and constructive comments are especially welcome.
+
+;; ange-ftp-lovers:
+;;
+;; ange-ftp has its own mailing list modestly called ange-ftp-lovers.  All
+;; users of ange-ftp are welcome to subscribe (see below) and to discuss
+;; aspects of ange-ftp.  New versions of ange-ftp are posted periodically to
+;; the mailing list.
+;;
+;; To [un]subscribe to ange-ftp-lovers, or to report mailer problems with the
+;; list, please mail one of the following addresses:
+;;
+;;     ange-ftp-lovers-request@anorman.hpl.hp.com
+;; or
+;;     ange-ftp-lovers-request%anorman.hpl.hp.com@hplb.hpl.hp.com
+;;
+;; Please don't forget the -request part.
+;;
+;; For mail to be posted directly to ange-ftp-lovers, send to one of the
+;; following addresses:
+;; 
+;;     ange-ftp-lovers@anorman.hpl.hp.com
+;; or
+;;     ange-ftp-lovers%anorman.hpl.hp.com@hplb.hpl.hp.com
+;;
+;; Alternatively, there is a mailing list that only gets announcements of new
+;; ange-ftp releases.  This is called ange-ftp-lovers-announce, and can be
+;; subscribed to by e-mailing to the -request address as above.  Please make
+;; it clear in the request which mailing list you wish to join.
+
+;; The latest version of ange-ftp can usually be obtained via anonymous ftp
+;; from:
+;;     alpha.gnu.ai.mit.edu:ange-ftp/ange-ftp.tar.Z
+;; or:
+;;     ugle.unit.no:/pub/gnu/emacs-lisp/ange-ftp.tar.Z
+;; or:
+;;   archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/packages/ange-ftp.tar.Z
+
+;; The archives for ange-ftp-lovers can be found via anonymous ftp under:
+;;
+;;     ftp.reed.edu:pub/mailing-lists/ange-ftp/
 \f
-;;; -----------------------------------------------------------
-;;; Technical information on this package:
-;;; -----------------------------------------------------------
-
-;;; ange-ftp works by putting a handler on file-name-handler-alist
-;;; which is called by many primitives, and a few non-primitives,
-;;; whenever they see a file name of the appropriate sort.
-
-;;; Checklist for adding non-UNIX support for TYPE
-;;; 
-;;; The following functions may need TYPE versions:
-;;; (not all functions will be needed for every OS)
-;;;
-;;; ange-ftp-fix-name-for-TYPE
-;;; ange-ftp-fix-dir-name-for-TYPE
-;;; ange-ftp-TYPE-host
-;;; ange-ftp-TYPE-add-host
-;;; ange-ftp-parse-TYPE-listing
-;;; ange-ftp-TYPE-delete-file-entry
-;;; ange-ftp-TYPE-add-file-entry
-;;; ange-ftp-TYPE-file-name-as-directory
-;;; ange-ftp-TYPE-make-compressed-filename
-;;; ange-ftp-TYPE-file-name-sans-versions
-;;;
-;;; Variables:
-;;;
-;;; ange-ftp-TYPE-host-regexp
-;;; May need to add TYPE to ange-ftp-dumb-host-types
-;;;
-;;; Check the following functions for OS dependent coding:
-;;;
-;;; ange-ftp-host-type
-;;; ange-ftp-guess-host-type
-;;; ange-ftp-allow-child-lookup
-
-;;; Host type conventions:
-;;;
-;;; The function ange-ftp-host-type and the variable ange-ftp-dired-host-type
-;;; (mostly) follow the following conventions for remote host types.  At
-;;; least, I think that future code should try to follow these conventions,
-;;; and the current code should eventually be made compliant.
-;;;
-;;; nil = local host type, whatever that is (probably unix).
-;;;       Think nil as in "not a remote host". This value is used by
-;;;       ange-ftp-dired-host-type for local buffers.
-;;;
-;;; t = a remote host of unknown type. Think t is in true, it's remote.
-;;;     Currently, 'unix is used as the default remote host type.
-;;;     Maybe we should use t.
-;;;
-;;; 'type = a remote host of TYPE type.
-;;;
-;;; 'type:list = a remote host of TYPE type, using a specialized ftp listing
-;;;              program called list. This is currently only used for Unix
-;;;              dl (descriptive listings), when ange-ftp-dired-host-type
-;;;              is set to 'unix:dl.
-
-;;; Bug report codes:
-;;;
-;;; Because of their naive faith in this code, there are certain situations
-;;; which the writers of this program believe could never happen. However,
-;;; being realists they have put calls to `error' in the program at these
-;;; points. These errors provide a code, which is an integer, greater than 1.
-;;; To aid debugging.  the error codes, and the functions in which they reside
-;;; are listed below.
-;;; 
-;;; 1: See ange-ftp-ls
-;;;
+;; -----------------------------------------------------------
+;; Technical information on this package:
+;; -----------------------------------------------------------
+
+;; ange-ftp works by putting a handler on file-name-handler-alist
+;; which is called by many primitives, and a few non-primitives,
+;; whenever they see a file name of the appropriate sort.
+
+;; Checklist for adding non-UNIX support for TYPE
+;; 
+;; The following functions may need TYPE versions:
+;; (not all functions will be needed for every OS)
+;;
+;; ange-ftp-fix-name-for-TYPE
+;; ange-ftp-fix-dir-name-for-TYPE
+;; ange-ftp-TYPE-host
+;; ange-ftp-TYPE-add-host
+;; ange-ftp-parse-TYPE-listing
+;; ange-ftp-TYPE-delete-file-entry
+;; ange-ftp-TYPE-add-file-entry
+;; ange-ftp-TYPE-file-name-as-directory
+;; ange-ftp-TYPE-make-compressed-filename
+;; ange-ftp-TYPE-file-name-sans-versions
+;;
+;; Variables:
+;;
+;; ange-ftp-TYPE-host-regexp
+;; May need to add TYPE to ange-ftp-dumb-host-types
+;;
+;; Check the following functions for OS dependent coding:
+;;
+;; ange-ftp-host-type
+;; ange-ftp-guess-host-type
+;; ange-ftp-allow-child-lookup
+
+;; Host type conventions:
+;;
+;; The function ange-ftp-host-type and the variable ange-ftp-dired-host-type
+;; (mostly) follow the following conventions for remote host types.  At
+;; least, I think that future code should try to follow these conventions,
+;; and the current code should eventually be made compliant.
+;;
+;; nil = local host type, whatever that is (probably unix).
+;;       Think nil as in "not a remote host". This value is used by
+;;       ange-ftp-dired-host-type for local buffers.
+;;
+;; t = a remote host of unknown type. Think t is in true, it's remote.
+;;     Currently, 'unix is used as the default remote host type.
+;;     Maybe we should use t.
+;;
+;; 'type = a remote host of TYPE type.
+;;
+;; 'type:list = a remote host of TYPE type, using a specialized ftp listing
+;;              program called list. This is currently only used for Unix
+;;              dl (descriptive listings), when ange-ftp-dired-host-type
+;;              is set to 'unix:dl.
+
+;; Bug report codes:
+;;
+;; Because of their naive faith in this code, there are certain situations
+;; which the writers of this program believe could never happen. However,
+;; being realists they have put calls to `error' in the program at these
+;; points. These errors provide a code, which is an integer, greater than 1.
+;; To aid debugging.  the error codes, and the functions in which they reside
+;; are listed below.
+;; 
+;; 1: See ange-ftp-ls
+;;
 \f
-;;; -----------------------------------------------------------
-;;; Hall of fame:
-;;; -----------------------------------------------------------
-;;; 
-;;; Thanks to Roland McGrath for improving the filename syntax handling,
-;;; for suggesting many enhancements and for numerous cleanups to the code.
-;;;
-;;; Thanks to Jamie Zawinski for bugfixes and for ideas such as gateways.
-;;;
-;;; Thanks to Ken Laprade for improved .netrc parsing, password reading, and
-;;; dired / shell auto-loading.
-;;;
-;;; Thanks to Sebastian Kremer for dired support and for many ideas and
-;;; bugfixes.
-;;;
-;;; Thanks to Joe Wells for bugfixes, the original non-UNIX system support,
-;;; VOS support, and hostname completion.
-;;;
-;;; Thanks to Nakagawa Takayuki for many good ideas, filename-completion, help
-;;; with file-name expansion, efficiency worries, stylistic concerns and many
-;;; bugfixes.
-;;;
-;;; Thanks to Sandy Rutherford who re-wrote most of ange-ftp to support VMS,
-;;; MTS, CMS and UNIX-dls.  Sandy also added dired-support for non-UNIX OS and
-;;; auto-recognition of the host type.
-;;;
-;;; Thanks to Dave Smith who wrote the info file for ange-ftp.
-;;;
-;;; Finally, thanks to Keith Waclena, Mark D. Baushke, Terence Kelleher, Ping
-;;; Zhou, Edward Vielmetti, Jack Repenning, Mike Balenger, Todd Kaufmann,
-;;; Kjetil Svarstad, Tom Wurgler, Linus Tolke, Niko Makila, Carl Edman, Bill
-;;; Trost, Dave Brennan, Dan Jacobson, Andy Scott, Steve Anderson, Sanjay
-;;; Mathur, the folks on the ange-ftp-lovers mailing list and many others
-;;; whose names I've forgotten who have helped to debug and fix problems with
-;;; ange-ftp.el.
+;; -----------------------------------------------------------
+;; Hall of fame:
+;; -----------------------------------------------------------
+;; 
+;; Thanks to Roland McGrath for improving the filename syntax handling,
+;; for suggesting many enhancements and for numerous cleanups to the code.
+;;
+;; Thanks to Jamie Zawinski for bugfixes and for ideas such as gateways.
+;;
+;; Thanks to Ken Laprade for improved .netrc parsing, password reading, and
+;; dired / shell auto-loading.
+;;
+;; Thanks to Sebastian Kremer for dired support and for many ideas and
+;; bugfixes.
+;;
+;; Thanks to Joe Wells for bugfixes, the original non-UNIX system support,
+;; VOS support, and hostname completion.
+;;
+;; Thanks to Nakagawa Takayuki for many good ideas, filename-completion, help
+;; with file-name expansion, efficiency worries, stylistic concerns and many
+;; bugfixes.
+;;
+;; Thanks to Sandy Rutherford who re-wrote most of ange-ftp to support VMS,
+;; MTS, CMS and UNIX-dls.  Sandy also added dired-support for non-UNIX OS and
+;; auto-recognition of the host type.
+;;
+;; Thanks to Dave Smith who wrote the info file for ange-ftp.
+;;
+;; Finally, thanks to Keith Waclena, Mark D. Baushke, Terence Kelleher, Ping
+;; Zhou, Edward Vielmetti, Jack Repenning, Mike Balenger, Todd Kaufmann,
+;; Kjetil Svarstad, Tom Wurgler, Linus Tolke, Niko Makila, Carl Edman, Bill
+;; Trost, Dave Brennan, Dan Jacobson, Andy Scott, Steve Anderson, Sanjay
+;; Mathur, the folks on the ange-ftp-lovers mailing list and many others
+;; whose names I've forgotten who have helped to debug and fix problems with
+;; ange-ftp.el.
 \f
-
 ;;; Code:
+
 (require 'comint)
 
 ;;;; ------------------------------------------------------------
 ;;;; ------------------------------------------------------------
 
 (defvar ange-ftp-name-format
-  '("^/\\(\\([^@/:]*\\)@\\)?\\([^@/:]*\\):\\(.*\\)" . (3 2 4))
+  '("^/\\(\\([^@/:]*\\)@\\)?\\([^@/:]*[^@/:.]\\):\\(.*\\)" . (3 2 4))
   "*Format of a fully expanded remote file name.
 This is a list of the form \(REGEXP HOST USER NAME\),
 where REGEXP is a regular expression matching
@@ -646,6 +655,7 @@ parenthesized expressions in REGEXP for the components (in that order).")
 (defvar ange-ftp-skip-msgs
   (concat "^200 \\(PORT\\|Port\\) \\|^331 \\|^150 \\|^350 \\|^[0-9]+ bytes \\|"
          "^Connected \\|^$\\|^Remote system\\|^Using\\|^ \\|Password:\\|"
+         "^Data connection \\|"
          "^local:\\|^Trying\\|^125 \\|^550-\\|^221 .*oodbye")
   "*Regular expression matching ftp messages that can be ignored.")
 
@@ -680,20 +690,38 @@ cross-mounted.")
   "*If non-nil avoid checking permissions on the .netrc file.")
 
 (defvar ange-ftp-default-user nil
-  "*User name to use when none is specied in a file name.
-If nil, then the name under which the user is logged in is used.
-If non-nil but not a string, the user is prompted for the name.")
+  "*User name to use when none is specified in a file name.
+If non-nil but not a string, you are prompted for the name.
+If nil, the value of `ange-ftp-netrc-default-user' is used.
+If that is nil too, then your login name is used.
+
+Once a connection to a given host has been initiated, the user name
+and password information for that host are cached and re-used by
+ange-ftp.  Use `ange-ftp-set-user' to change the cached values,
+since setting `ange-ftp-default-user' directly does not affect
+the cached information.")  
+
+(defvar ange-ftp-netrc-default-user nil
+  "Alternate default user name to use when none is specified.
+This variable is set from the `default' command in your `.netrc' file,
+if there is one.")
 
 (defvar ange-ftp-default-password nil
-  "*Password to use when the user is the same as ange-ftp-default-user.")
+  "*Password to use when the user name equals `ange-ftp-default-user'.")
 
 (defvar ange-ftp-default-account nil
-  "*Account password to use when the user is the same as ange-ftp-default-user.")
+  "*Account to use when the user name equals `ange-ftp-default-user'.")
+
+(defvar ange-ftp-netrc-default-password nil
+  "*Password to use when the user name equals `ange-ftp-netrc-default-user'.")
+
+(defvar ange-ftp-netrc-default-account nil
+  "*Account to use when the user name equals `ange-ftp-netrc-default-user'.")
 
 (defvar ange-ftp-generate-anonymous-password t
-  "*If t, use a password of user@host when logging in as the anonymous user.
-If a string then use that as the password.
-If nil then prompt the user for a password.")
+  "*If t, use value of `user-mail-address' as password for anonymous ftp.
+If a string, then use that string as the password.
+If nil, prompt the user for a password.")
 
 (defvar ange-ftp-dumb-unix-host-regexp nil
   "*If non-nil, regexp matching hosts on which `dir' command lists directory.")
@@ -711,15 +739,15 @@ If nil then prompt the user for a password.")
 (defvar ange-ftp-local-host-regexp ".*"
   "*Regexp selecting hosts which can be reached directly with ftp.
 For other hosts the FTP process is started on \`ange-ftp-gateway-host\'
-instead.")
+instead, and/or reached via \`ange-ftp-gateway-ftp-program-name\'.")
 
 (defvar ange-ftp-gateway-program-interactive nil
   "*If non-nil then the gateway program should  give a shell prompt.
 Both telnet and rlogin do something like this.")
 
-(defvar ange-ftp-gateway-program (if (eq system-type 'hpux) "remsh" "rsh")
+(defvar ange-ftp-gateway-program remote-shell-program
   "*Name of program to spawn a shell on the gateway machine.
-Valid candidates are rsh (remsh on hp-ux), telnet and rlogin.  See
+Valid candidates are rsh (remsh on some systems), telnet and rlogin.  See
 also the gateway variable above.")
 
 (defvar ange-ftp-gateway-prompt-pattern "^[^#$%>;\n]*[#$%>;] *"
@@ -738,8 +766,9 @@ This command should stop the terminal from echoing each command, and
 arrange to strip out trailing ^M characters.")
 
 (defvar ange-ftp-smart-gateway nil
-  "*Non-nil means the ftp gateway is smart.
-Don't bother telnetting, etc., just issue a user@host command instead.")
+  "*Non-nil means the ftp gateway and/or the gateway ftp program is smart.
+Don't bother telnetting, etc., already connected to desired host transparently,
+or just issue a user@host command in case \`ange-ftp-gateway-host\' is non-nil.")
 
 (defvar ange-ftp-smart-gateway-port "21"
   "*Port on gateway machine to use when smart gateway is in operation.")
@@ -765,7 +794,7 @@ outputs a suitable response to the HASH command.")
   "*Name of FTP program to run.")
 
 (defvar ange-ftp-gateway-ftp-program-name "ftp"
-  "*Name of FTP program to run on gateway machine.
+  "*Name of FTP program to run when accessing non-local hosts.
 Some AT&T folks claim to use something called `pftp' here.")
 
 (defvar ange-ftp-ftp-program-args '("-i" "-n" "-g" "-v")
@@ -851,8 +880,6 @@ SIZE, if supplied, should be a prime number."
 ;;;; Internal variables.
 ;;;; ------------------------------------------------------------
 
-(defconst ange-ftp-version "$Revision: 1.54 $")
-
 (defvar ange-ftp-data-buffer-name " *ftp data*"
   "Buffer name to hold directory listing data received from ftp process.")
 
@@ -911,24 +938,6 @@ SIZE, if supplied, should be a prime number."
 (put 'ftp-error 'error-conditions '(ftp-error file-error error))
 ;; (put 'ftp-error 'error-message "FTP error")
 \f
-;;; ------------------------------------------------------------
-;;; Match-data support (stolen from Kyle I think)
-;;; ------------------------------------------------------------
-
-(defmacro ange-ftp-save-match-data (&rest body)
-  "Execute the BODY forms, restoring the global value of the match data.
-Also makes matching case-sensitive within BODY."
-  (let ((original (make-symbol "match-data"))
-       case-fold-search)
-    (list
-     'let (list (list original '(match-data)))
-     (list 'unwind-protect
-           (cons 'progn body)
-           (list 'store-match-data original)))))
-
-(put 'ange-ftp-save-match-data 'lisp-indent-hook 0)
-(put 'ange-ftp-save-match-data 'edebug-form-hook '(&rest form))
-\f
 ;;; ------------------------------------------------------------
 ;;; Enhanced message support.
 ;;; ------------------------------------------------------------
@@ -938,15 +947,18 @@ Also makes matching case-sensitive within BODY."
 Args are as in `message': a format string, plus arguments to be formatted."
   (let ((msg (apply (function format) fmt args))
        (max (window-width (minibuffer-window))))
-    (if (>= (length msg) max)
-       (setq msg (concat "> " (substring msg (- 3 max)))))
-    (message "%s" msg)))
+    (if noninteractive
+       msg
+      (if (>= (length msg) max)
+         ;; Take just the last MAX - 3 chars of the string.
+         (setq msg (concat "> " (substring msg (- 3 max)))))
+      (message "%s" msg))))
 
 (defun ange-ftp-abbreviate-filename (file &optional new)
   "Abbreviate the file name FILE relative to the default-directory.
 If the optional parameter NEW is given and the non-directory parts match,
 only return the directory part of FILE."
-  (ange-ftp-save-match-data
+  (save-match-data
     (if (and default-directory
             (string-match (concat "^"
                                   (regexp-quote default-directory)
@@ -982,6 +994,7 @@ only return the directory part of FILE."
                         (let ((enable-recursive-minibuffers t))
                           (read-string (format "User for %s: " host)
                                        (user-login-name))))
+                       (ange-ftp-netrc-default-user)
                        ;; Default to the user's login name.
                        (t
                         (user-login-name))))
@@ -1039,7 +1052,7 @@ Optional DEFAULT is password to start with."
                 (if (ange-ftp-lookup-passwd host user)
                     (throw 'found-one host))))
      ange-ftp-user-hashtable)
-    (ange-ftp-save-match-data
+    (save-match-data
       (ange-ftp-map-hashtable
        (function
        (lambda (key value)
@@ -1059,12 +1072,18 @@ Optional DEFAULT is password to start with."
   ;; defaults.
   (cond ((ange-ftp-lookup-passwd host user))
        
-       ;; see if default user and password set from the .netrc file.
+       ;; See if default user and password set.
        ((and (stringp ange-ftp-default-user)
              ange-ftp-default-password
              (string-equal user ange-ftp-default-user))
         ange-ftp-default-password)
        
+       ;; See if default user and password set from .netrc file.
+       ((and (stringp ange-ftp-netrc-default-user)
+             ange-ftp-netrc-default-password
+             (string-equal user ange-ftp-netrc-default-user))
+        ange-ftp-netrc-default-password)
+       
        ;; anonymous ftp password is handled specially since there is an
        ;; unwritten rule about how that is used on the Internet.
        ((and (or (string-equal user "anonymous")
@@ -1072,7 +1091,7 @@ Optional DEFAULT is password to start with."
              ange-ftp-generate-anonymous-password)
         (if (stringp ange-ftp-generate-anonymous-password)
             ange-ftp-generate-anonymous-password
-          (concat (user-login-name) "@" (system-name))))
+          user-mail-address))
        
        ;; see if same user has logged in to other hosts; if so then prompt
        ;; with the password that was used there.
@@ -1118,7 +1137,10 @@ Optional DEFAULT is password to start with."
                               ange-ftp-account-hashtable)
       (and (stringp ange-ftp-default-user)
           (string-equal user ange-ftp-default-user)
-          ange-ftp-default-account)))
+          ange-ftp-default-account)
+      (and (stringp ange-ftp-netrc-default-user)
+          (string-equal user ange-ftp-netrc-default-user)
+          ange-ftp-netrc-default-account)))
 \f
 ;;;; ------------------------------------------------------------
 ;;;; ~/.netrc support
@@ -1157,12 +1179,22 @@ Optional DEFAULT is password to start with."
 ;; record the information found.
 
 (defun ange-ftp-parse-netrc-group ()
-  (beginning-of-line)
   (let ((start (point))
-       (end (progn (re-search-forward "machine\\|default"
-                                      (point-max) 'end 2) (point)))
+       (end (save-excursion
+              (if (looking-at "machine\\>")
+                  ;; Skip `machine' and the machine name that follows.
+                  (progn
+                    (skip-chars-forward "^ \t\n")
+                    (skip-chars-forward " \t\n")
+                    (skip-chars-forward "^ \t\n"))
+                ;; Skip `default'.
+                (skip-chars-forward "^ \t\n"))
+              ;; Find start of the next `machine' or `default'
+              ;; or the end of the buffer.
+              (if (re-search-forward "machine\\>\\|default\\>" nil t)
+                  (match-beginning 0)
+                (point-max))))
        machine login password account)
-    (goto-char start)
     (setq machine  (ange-ftp-parse-netrc-token "machine"  end)
          login    (ange-ftp-parse-netrc-token "login"    end)
          password (ange-ftp-parse-netrc-token "password" end)
@@ -1182,11 +1214,11 @@ Optional DEFAULT is password to start with."
                  password (ange-ftp-parse-netrc-token "password" end)
                  account  (ange-ftp-parse-netrc-token "account"  end))
            (and login
-                (setq ange-ftp-default-user login))
+                (setq ange-ftp-netrc-default-user login))
            (and password
-                (setq ange-ftp-default-password password))
+                (setq ange-ftp-netrc-default-password password))
            (and account
-                (setq ange-ftp-default-account account)))))
+                (setq ange-ftp-netrc-default-account account)))))
     (goto-char end)))
 
 ;; Read in ~/.netrc, if one exists.  If ~/.netrc file exists and has
@@ -1197,12 +1229,14 @@ Optional DEFAULT is password to start with."
   ;; We set this before actually doing it to avoid the possibility
   ;; of an infinite loop if ange-ftp-netrc-filename is an FTP file.
   (interactive)
-  (let* ((file (ange-ftp-chase-symlinks
-               (ange-ftp-real-expand-file-name ange-ftp-netrc-filename)))
-        (attr (ange-ftp-real-file-attributes file)))
+  (let (file attr)
+    (let ((default-directory "/"))
+      (setq file (ange-ftp-chase-symlinks
+                 (ange-ftp-real-expand-file-name ange-ftp-netrc-filename)))
+      (setq attr (ange-ftp-real-file-attributes file)))
     (if (and attr                      ; file exists.
             (not (equal (nth 5 attr) ange-ftp-netrc-modtime))) ; file changed
-       (ange-ftp-save-match-data
+       (save-match-data
          (if (or ange-ftp-disable-netrc-security-check
                  (and (eq (nth 2 attr) (user-uid)) ; Same uids.
                       (string-match ".r..------" (nth 8 attr))))
@@ -1219,6 +1253,7 @@ Optional DEFAULT is password to start with."
                (mapcar 'funcall find-file-hooks)
                (setq buffer-file-name nil)
                (goto-char (point-min))
+               (skip-chars-forward " \t\n")
                (while (not (eobp))
                  (ange-ftp-parse-netrc-group))
                (kill-buffer (current-buffer)))
@@ -1232,7 +1267,7 @@ Optional DEFAULT is password to start with."
 
 (defun ange-ftp-generate-root-prefixes ()
   (ange-ftp-parse-netrc)
-  (ange-ftp-save-match-data
+  (save-match-data
     (let (res)
       (ange-ftp-map-hashtable
        (function
@@ -1270,8 +1305,8 @@ Optional DEFAULT is password to start with."
       ange-ftp-ftp-name-res
     (setq ange-ftp-ftp-name-arg name
          ange-ftp-ftp-name-res
-         (ange-ftp-save-match-data
-           (if (string-match (car ange-ftp-name-format) name)
+         (save-match-data
+           (if (posix-string-match (car ange-ftp-name-format) name)
                (let* ((ns (cdr ange-ftp-name-format))
                       (host (ange-ftp-ftp-name-component 0 ns name))
                       (user (ange-ftp-ftp-name-component 1 ns name))
@@ -1284,8 +1319,8 @@ Optional DEFAULT is password to start with."
 ;; Take a FULLNAME that matches according to ange-ftp-name-format and
 ;; replace the name component with NAME.
 (defun ange-ftp-replace-name-component (fullname name)
-  (ange-ftp-save-match-data
-    (if (string-match (car ange-ftp-name-format) fullname)
+  (save-match-data
+    (if (posix-string-match (car ange-ftp-name-format) fullname)
        (let* ((ns (cdr ange-ftp-name-format))
               (elt (nth 2 ns)))
          (concat (substring fullname 0 (match-beginning elt))
@@ -1324,10 +1359,7 @@ Optional DEFAULT is password to start with."
   "Set correct modes for the current buffer if visiting a remote file."
   (if (and (stringp buffer-file-name)
           (ange-ftp-ftp-name buffer-file-name))
-      (progn
-       (make-local-variable 'make-backup-files)
-       (setq make-backup-files ange-ftp-make-backup-files)
-       (auto-save-mode ange-ftp-auto-save))))
+      (auto-save-mode ange-ftp-auto-save)))
 
 (defun ange-ftp-kill-ftp-process (buffer)
   "Kill the FTP process associated with BUFFER.
@@ -1386,12 +1418,17 @@ good, skip, fatal, or unknown."
         (setq ange-ftp-process-busy nil
               ange-ftp-process-result t
               ange-ftp-process-result-line line))
+       ;; Check this before checking for errors.
+       ;; Otherwise the last line of these three seems to be an error:
+       ;; 230-see a significant impact from the move.  For those of you who can't
+       ;; 230-use DNS to resolve hostnames and get an error message like
+       ;; 230-"ftp.stsci.edu: unknown host", the new IP address will be...
+       ((string-match ange-ftp-multi-msgs line)
+        (setq ange-ftp-process-multi-skip t))
        ((string-match ange-ftp-fatal-msgs line)
         (delete-process proc)
         (setq ange-ftp-process-busy nil
               ange-ftp-process-result-line line))
-       ((string-match ange-ftp-multi-msgs line)
-        (setq ange-ftp-process-multi-skip t))
        (ange-ftp-process-multi-skip
         t)
        (t
@@ -1415,7 +1452,8 @@ good, skip, fatal, or unknown."
        ange-ftp-hash-mark-count (+ (- (match-end 0)
                                       (match-beginning 0))
                                    ange-ftp-hash-mark-count))
-  (and ange-ftp-process-msg
+  (and ange-ftp-hash-mark-unit
+       ange-ftp-process-msg
        ange-ftp-process-verbose
        (not (eq (selected-window) (minibuffer-window)))
        (not (boundp 'search-message))  ;screws up isearch otherwise
@@ -1455,15 +1493,17 @@ good, skip, fatal, or unknown."
     ;; see if the buffer is still around... it could have been deleted.
     (if (buffer-name buffer)
        (unwind-protect
-           (ange-ftp-save-match-data
+           (progn
              (set-buffer (process-buffer proc))
              
              ;; handle hash mark printing
-             (and ange-ftp-hash-mark-unit
-                  ange-ftp-process-busy
+             (and ange-ftp-process-busy
                   (string-match "^#+$" str)
                   (setq str (ange-ftp-process-handle-hash str)))
              (comint-output-filter proc str)
+             ;; Replace STR by the result of the comint processing.
+             (setq str (buffer-substring comint-last-output-start
+                                         (process-mark proc)))
              (if ange-ftp-process-busy
                  (progn
                    (setq ange-ftp-process-string (concat ange-ftp-process-string
@@ -1512,13 +1552,12 @@ good, skip, fatal, or unknown."
 
 (defun ange-ftp-process-sentinel (proc str)
   "When ftp process changes state, nuke all file-entries in cache."
-  (ange-ftp-save-match-data
-    (let ((name (process-name proc)))
-      (if (string-match "\\*ftp \\([^@]+\\)@\\([^*]+\\)*" name)
-         (let ((user (substring name (match-beginning 1) (match-end 1)))
-               (host (substring name (match-beginning 2) (match-end 2))))
-           (ange-ftp-wipe-file-entries host user))))
-    (setq ange-ftp-ls-cache-file nil)))
+  (let ((name (process-name proc)))
+    (if (string-match "\\*ftp \\([^@]+\\)@\\([^*]+\\)\\*" name)
+       (let ((user (substring name (match-beginning 1) (match-end 1)))
+             (host (substring name (match-beginning 2) (match-end 2))))
+         (ange-ftp-wipe-file-entries host user))))
+  (setq ange-ftp-ls-cache-file nil))
 \f
 ;;;; ------------------------------------------------------------
 ;;;; Gateway support.
@@ -1529,13 +1568,13 @@ good, skip, fatal, or unknown."
   ;; yes, I know that I could simplify the following expression, but it is
   ;; clearer (to me at least) this way.
   (and (not ange-ftp-smart-gateway)
-       (ange-ftp-save-match-data
+       (save-match-data
         (not (string-match ange-ftp-local-host-regexp host)))))
 
 (defun ange-ftp-use-smart-gateway-p (host)
   "Returns whether to access this host via a smart gateway."
   (and ange-ftp-smart-gateway
-       (ange-ftp-save-match-data
+       (save-match-data
         (not (string-match ange-ftp-local-host-regexp host)))))
 
 \f
@@ -1592,27 +1631,30 @@ good, skip, fatal, or unknown."
   (setq ange-ftp-gwp-running nil))
 
 (defun ange-ftp-gwp-filter (proc str)
-  (ange-ftp-save-match-data
-    (comint-output-filter proc str)
-    (cond ((string-match "login: *$" str)
-          (send-string proc
-                       (concat
-                        (let ((ange-ftp-default-user t))
-                          (ange-ftp-get-user ange-ftp-gateway-host))
-                        "\n")))
-         ((string-match "Password: *$" str)
-          (send-string proc
-                       (concat
-                        (ange-ftp-get-passwd ange-ftp-gateway-host
-                                             (ange-ftp-get-user
-                                              ange-ftp-gateway-host))
-                        "\n")))
-         ((string-match ange-ftp-gateway-fatal-msgs str)
-          (delete-process proc)
-          (setq ange-ftp-gwp-running nil))
-         ((string-match ange-ftp-gateway-prompt-pattern str)
-          (setq ange-ftp-gwp-running nil
-                ange-ftp-gwp-status t)))))
+  (comint-output-filter proc str)
+  (save-excursion
+    (set-buffer (process-buffer proc))
+    ;; Replace STR by the result of the comint processing.
+    (setq str (buffer-substring comint-last-output-start (process-mark proc))))
+  (cond ((string-match "login: *$" str)
+        (send-string proc
+                     (concat
+                      (let ((ange-ftp-default-user t))
+                        (ange-ftp-get-user ange-ftp-gateway-host))
+                      "\n")))
+       ((string-match "Password: *$" str)
+        (send-string proc
+                     (concat
+                      (ange-ftp-get-passwd ange-ftp-gateway-host
+                                           (ange-ftp-get-user
+                                            ange-ftp-gateway-host))
+                      "\n")))
+       ((string-match ange-ftp-gateway-fatal-msgs str)
+        (delete-process proc)
+        (setq ange-ftp-gwp-running nil))
+       ((string-match ange-ftp-gateway-prompt-pattern str)
+        (setq ange-ftp-gwp-running nil
+              ange-ftp-gwp-status t))))
 
 (defun ange-ftp-gwp-start (host user name args)
   "Login to the gateway machine and fire up an ftp process."
@@ -1693,7 +1735,7 @@ been queued with no result.  CONT will still be called, however."
        (goto-char (point-max))
        (move-marker comint-last-input-start (point))
        ;; don't insert the password into the buffer on the USER command.
-       (ange-ftp-save-match-data
+       (save-match-data
          (if (string-match "^user \"[^\"]*\"" cmd)
              (insert (substring cmd 0 (match-end 0)) " Turtle Power!\n")
            (insert cmd)))
@@ -1746,7 +1788,10 @@ been queued with no result.  CONT will still be called, however."
 If HOST is only ftp-able through a gateway machine then spawn a shell
 on the gateway machine to do the ftp instead."
   (let* ((use-gateway (ange-ftp-use-gateway-p host))
-        (ftp-prog (if use-gateway 
+        (use-smart-ftp (and (not ange-ftp-gateway-host)
+                            (ange-ftp-use-smart-gateway-p host)))
+        (ftp-prog (if (or use-gateway
+                          use-smart-ftp) 
                       ange-ftp-gateway-ftp-program-name
                     ange-ftp-ftp-program-name))
         (args (append (list ftp-prog) ange-ftp-ftp-program-args))
@@ -1763,7 +1808,10 @@ on the gateway machine to do the ftp instead."
     ;; It would be nice to make process-connection-type nil,
     ;; but that doesn't work: ftp never responds.
     ;; Can anyone find a fix for that?
-    (let ((process-connection-type t))
+    (let ((process-connection-type t)
+         (process-environment process-environment))
+      ;; This tells GNU ftp not to output any fancy escape sequences.
+      (setenv "TERM" "dumb")
       (if use-gateway
          (if ange-ftp-gateway-program-interactive
              (setq proc (ange-ftp-gwp-start host user name args))
@@ -1811,6 +1859,10 @@ on the gateway machine to do the ftp instead."
     (setq ange-ftp-process-result-line "")
 
     (setq comint-prompt-regexp "^ftp> ")
+    (make-local-variable 'comint-password-prompt-regexp)
+    ;; This is a regexp that can't match anything.
+    ;; ange-ftp has its own ways of handling passwords.
+    (setq comint-password-prompt-regexp "^a\\'z")
     (make-local-variable 'paragraph-start)
     (setq paragraph-start comint-prompt-regexp)))
 
@@ -1849,9 +1901,10 @@ host specified in ``ange-ftp-gateway-host''."
 (defun ange-ftp-normal-login (host user pass account proc)
   "Connect to the FTP-server on HOST as USER using PASSWORD and ACCOUNT.
 PROC is the process to the FTP-client."
-  (let ((result (ange-ftp-raw-send-cmd
+  (let* ((nshost (ange-ftp-nslookup-host host))
+        (result (ange-ftp-raw-send-cmd
                 proc
-                (format "open %s" (ange-ftp-nslookup-host host))
+                (format "open %s" nshost)
                 (format "Opening FTP connection to %s" host))))
     (or (car result)
        (ange-ftp-error host user
@@ -1859,7 +1912,9 @@ PROC is the process to the FTP-client."
                                (cdr result))))
     (setq result (ange-ftp-raw-send-cmd
                  proc
-                 (format "user \"%s\" %s %s" user pass account)
+                 (if (ange-ftp-use-smart-gateway-p host)
+                     (format "user \"%s\"@%s %s %s" user nshost pass account)
+                   (format "user \"%s\" %s %s" user pass account))
                  (format "Logging in as user %s@%s" user host)))
     (or (car result)
        (progn
@@ -1881,7 +1936,7 @@ PROC is the process to the FTP-client."
        (let* ((status (ange-ftp-raw-send-cmd proc "hash"))
               (result (car status))
               (line (cdr status)))
-         (ange-ftp-save-match-data
+         (save-match-data
            (if (string-match ange-ftp-hash-mark-msgs line)
                (let ((size (string-to-int
                            (substring line
@@ -1909,7 +1964,8 @@ Create a new process if needed."
        (setq proc (ange-ftp-start-process host user name))
        
        ;; login to FTP server.
-       (if (ange-ftp-use-smart-gateway-p host)
+       (if (and (ange-ftp-use-smart-gateway-p host)
+                ange-ftp-gateway-host)
            (ange-ftp-smart-login host user pass account proc)
          (ange-ftp-normal-login host user pass account proc))
       
@@ -2111,7 +2167,7 @@ Works by doing a pwd and examining the directory syntax."
        (key (concat host "/" user "/~")))
     (if (eq host-type 'unix)
        ;; Note that ange-ftp-host-type returns unix as the default value.
-       (ange-ftp-save-match-data
+       (save-match-data
          (let* ((result (ange-ftp-get-pwd host user))
                 (dir (car result))
                 fix-name-func)
@@ -2186,8 +2242,8 @@ Works by doing a pwd and examining the directory syntax."
 ;; Returns whether HOST's FTP server doesn't like \'ls\' or \'dir\' commands
 ;; to take switch arguments.
 (defun ange-ftp-dumb-unix-host (host)
-  (and ange-ftp-dumb-unix-host-regexp
-       (ange-ftp-save-match-data
+  (and host ange-ftp-dumb-unix-host-regexp
+       (save-match-data
         (string-match ange-ftp-dumb-unix-host-regexp host))))
 
 (defun ange-ftp-add-dumb-unix-host (host)
@@ -2216,7 +2272,7 @@ which can parse the output from a DIR listing for a host of type TYPE.")
 ;; 
 ;; With no-error t, it returns:
 ;; an error if not an ange-ftp-name
-;; error if listing is unreable (most likely caused by a slow connection)
+;; error if listing is unreadable (most likely caused by a slow connection)
 ;; nil if ftp error (this is because although asking to list a nonexistent
 ;;                   directory on a remote unix machine usually (except
 ;;                   maybe for dumb hosts) returns an ls error, but no
@@ -2459,7 +2515,7 @@ match subdirectories as well.")
 ;; a listing, then return nil.
 
 (defun ange-ftp-parse-dired-listing (&optional switches)
-  (ange-ftp-save-match-data
+  (save-match-data
     (cond
      ((looking-at "^total [0-9]+$")
       (forward-line 1)
@@ -2499,7 +2555,7 @@ This will give an error or return nil, depending on the value of
 NO-ERROR, if a listing for DIRECTORY cannot be obtained."
   (setq directory (file-name-as-directory directory)) ;normalize
   (or (ange-ftp-get-hash-entry directory ange-ftp-files-hashtable)
-      (ange-ftp-save-match-data
+      (save-match-data
        (and (ange-ftp-ls directory
                          ;; This is an efficiency hack. We try to
                          ;; anticipate what sort of listing dired
@@ -2663,7 +2719,9 @@ this also returns nil."
        (ange-ftp-error host user (concat "BINARY failed: " (cdr result)))
       (save-excursion
        (set-buffer (process-buffer (ange-ftp-get-process host user)))
-       (setq ange-ftp-hash-mark-unit (ash ange-ftp-binary-hash-mark-size -4))))))
+       (and ange-ftp-binary-hash-mark-size
+            (setq ange-ftp-hash-mark-unit
+                  (ash ange-ftp-binary-hash-mark-size -4)))))))
 
 (defun ange-ftp-set-ascii-mode (host user)
   "Tell the ftp process for the given HOST & USER to switch to ascii mode."
@@ -2672,7 +2730,9 @@ this also returns nil."
        (ange-ftp-error host user (concat "ASCII failed: " (cdr result)))
       (save-excursion
        (set-buffer (process-buffer (ange-ftp-get-process host user)))
-       (setq ange-ftp-hash-mark-unit (ash ange-ftp-ascii-hash-mark-size -4))))))
+       (and ange-ftp-ascii-hash-mark-size
+            (setq ange-ftp-hash-mark-unit
+                  (ash ange-ftp-ascii-hash-mark-size -4)))))))
 \f
 (defun ange-ftp-cd (host user dir)
   (let ((result (ange-ftp-send-cmd host user (list 'cd dir) "Doing CD")))
@@ -2687,7 +2747,7 @@ and LINE is the relevant success or fail line from the FTP-client."
         (line (cdr result))
         dir)
     (if (car result)
-       (ange-ftp-save-match-data
+       (save-match-data
          (and (or (string-match "\"\\([^\"]*\\)\"" line)
                   (string-match " \\([^ ]+\\) " line)) ; stone-age VMS servers!
               (setq dir (substring line
@@ -2803,7 +2863,7 @@ logged in as user USER and cd'd to directory DIR."
 
 (defun ange-ftp-expand-file-name (name &optional default)
   "Documented as original."
-  (ange-ftp-save-match-data
+  (save-match-data
     (if (eq (string-to-char name) ?/)
        (while (cond ((string-match "[^:]+//" name) ;don't upset Apollo users
                      (setq name (substring name (1- (match-end 0)))))
@@ -2844,7 +2904,7 @@ system TYPE.")
   (let ((parsed (ange-ftp-ftp-name name)))
     (if parsed
        (let ((filename (nth 2 parsed)))
-         (if (ange-ftp-save-match-data
+         (if (save-match-data
                (string-match "^~[^/]*$" filename))
              name
            (ange-ftp-replace-name-component
@@ -2857,7 +2917,7 @@ system TYPE.")
   (let ((parsed (ange-ftp-ftp-name name)))
     (if parsed
        (let ((filename (nth 2 parsed)))
-         (if (ange-ftp-save-match-data
+         (if (save-match-data
                (string-match "^~[^/]*$" filename))
              ""
            (ange-ftp-real-file-name-nondirectory name)))
@@ -2877,7 +2937,7 @@ system TYPE.")
 
 ;; Returns non-nil if should transfer FILE in binary mode.
 (defun ange-ftp-binary-file (file)
-  (ange-ftp-save-match-data
+  (save-match-data
     (string-match ange-ftp-binary-file-name-regexp file)))
 
 (defun ange-ftp-write-region (start end filename &optional append visit)
@@ -2888,12 +2948,13 @@ system TYPE.")
               (user (nth 1 parsed))
               (name (ange-ftp-quote-string (nth 2 parsed)))
               (temp (ange-ftp-make-tmp-name host))
-              (binary (ange-ftp-binary-file filename))
+              (binary (or (ange-ftp-binary-file filename)
+                          (eq (ange-ftp-host-type host user) 'unix)))
               (cmd (if append 'append 'put))
               (abbr (ange-ftp-abbreviate-filename filename)))
          (unwind-protect
              (progn
-               (let ((executing-macro t)
+               (let ((executing-kbd-macro t)
                      (filename (buffer-file-name))
                      (mod-p (buffer-modified-p)))
                  (unwind-protect
@@ -2950,7 +3011,8 @@ system TYPE.")
                     (user (nth 1 parsed))
                     (name (ange-ftp-quote-string (nth 2 parsed)))
                     (temp (ange-ftp-make-tmp-name host))
-                    (binary (ange-ftp-binary-file filename))
+                    (binary (or (ange-ftp-binary-file filename)
+                                (eq (ange-ftp-host-type host user) 'unix)))
                     (abbr (ange-ftp-abbreviate-filename filename))
                     size)
                (unwind-protect
@@ -3055,7 +3117,7 @@ system TYPE.")
                     (ange-ftp-get-files directory)))
              files f)
          (setq directory (file-name-as-directory directory))
-         (ange-ftp-save-match-data
+         (save-match-data
            (while tail
              (setq f (car tail)
                    tail (cdr tail))
@@ -3230,7 +3292,9 @@ system TYPE.")
             (t-name (and t-parsed (ange-ftp-quote-string (nth 2 t-parsed))))
             (t-abbr (ange-ftp-abbreviate-filename newname filename))
             (binary (or (ange-ftp-binary-file filename)
-                        (ange-ftp-binary-file newname)))
+                        (ange-ftp-binary-file newname)
+                        (and (eq (ange-ftp-host-type f-host f-user) 'unix)
+                             (eq (ange-ftp-host-type t-host t-user) 'unix))))
             temp1
             temp2)
 
@@ -3389,8 +3453,7 @@ system TYPE.")
 ;;;; File renaming support.
 ;;;; ------------------------------------------------------------
 
-(defun ange-ftp-rename-remote-to-remote (filename newname f-parsed t-parsed
-                                                 binary)
+(defun ange-ftp-rename-remote-to-remote (filename newname f-parsed t-parsed)
   "Rename remote file FILE to remote file NEWNAME."
   (let ((f-host (nth 0 f-parsed))
        (f-user (nth 1 f-parsed))
@@ -3442,8 +3505,7 @@ system TYPE.")
   (setq filename (expand-file-name filename))
   (setq newname (expand-file-name newname))
   (let* ((f-parsed (ange-ftp-ftp-name filename))
-        (t-parsed (ange-ftp-ftp-name newname))
-        (binary (if (or f-parsed t-parsed) (ange-ftp-binary-file filename))))
+        (t-parsed (ange-ftp-ftp-name newname)))
     (if (and (or f-parsed t-parsed)
             (or (not ok-if-already-exists)
                 (numberp ok-if-already-exists)))
@@ -3454,7 +3516,7 @@ system TYPE.")
     (if f-parsed
        (if t-parsed
            (ange-ftp-rename-remote-to-remote filename newname f-parsed
-                                             t-parsed binary)
+                                             t-parsed)
          (ange-ftp-rename-remote-to-local filename newname))
       (if t-parsed
          (ange-ftp-rename-local-to-remote filename newname)
@@ -3537,7 +3599,7 @@ system TYPE.")
                                              "/"))) ; / never in filename
                               completion-ignored-extensions
                               "\\|")))
-             (ange-ftp-save-match-data
+             (save-match-data
                (or (ange-ftp-file-name-completion-1
                     file tbl ange-ftp-this-dir
                     (function ange-ftp-file-entry-not-ignored-p))
@@ -3660,8 +3722,7 @@ system TYPE.")
   (let* ((fn1 (expand-file-name file))
         (pa1 (ange-ftp-ftp-name fn1)))
     (if pa1
-       (let* ((tmp1 (ange-ftp-make-tmp-name (car pa1)))
-              (bin1 (ange-ftp-binary-file fn1)))
+       (let ((tmp1 (ange-ftp-make-tmp-name (car pa1))))
          (ange-ftp-copy-file-internal fn1 tmp1 t nil
                                       (format "Getting %s" fn1))
          tmp1))))
@@ -3675,7 +3736,8 @@ system TYPE.")
        (while (and tryfiles (not copy))
          (condition-case error
              (setq copy (ange-ftp-file-local-copy (car tryfiles)))
-           (ftp-error nil)))
+           (ftp-error nil))
+         (setq tryfiles (cdr tryfiles)))
        (if copy
            (unwind-protect
                (funcall 'load copy noerror nomessage nosuffix)
@@ -3710,7 +3772,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
                   (cdr (assq (ange-ftp-host-type (car parsed))
                              ange-ftp-make-compressed-filename-alist))))
        (let* ((decision
-               (ange-ftp-save-match-data (funcall conversion-func name)))
+               (save-match-data (funcall conversion-func name)))
               (compressing (car decision))
               (newfile (nth 1 decision)))
          (if compressing
@@ -3786,6 +3848,12 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
                (ange-ftp-copy-file-internal tmp2 nfile t nil msg2))))
       (ange-ftp-del-tmp-name tmp1)
       (ange-ftp-del-tmp-name tmp2))))
+
+(defun ange-ftp-find-backup-file-name (fn)
+  ;; Either return the ordinary backup name, etc.,
+  ;; or return nil meaning don't make a backup.
+  (if ange-ftp-make-backup-files
+      (ange-ftp-real-find-backup-file-name fn)))
 \f
 ;;; Define the handler for special file names
 ;;; that causes ange-ftp to be invoked.
@@ -3799,10 +3867,11 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 
 ;;; This regexp takes care of real ange-ftp file names (with a slash
 ;;; and colon).
+;;; Don't allow the host name to end in a period--some systems use /.:
 ;;;###autoload
-(or (assoc "^/[^/:]*[^/:]:" file-name-handler-alist)
+(or (assoc "^/[^/:]*[^/:.]:" file-name-handler-alist)
     (setq file-name-handler-alist
-         (cons '("^/[^/:]*[^/:]:" . ange-ftp-hook-function)
+         (cons '("^/[^/:]*[^/:.]:" . ange-ftp-hook-function)
                file-name-handler-alist)))
 
 ;;; This regexp recognizes and absolute filenames with only one component,
@@ -3857,6 +3926,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 (put 'dired-uncache 'ange-ftp 'ange-ftp-dired-uncache)
 (put 'dired-compress-file 'ange-ftp 'ange-ftp-dired-compress-file)
 (put 'load 'ange-ftp 'ange-ftp-load)
+(put 'find-backup-file-name 'ange-ftp 'ange-ftp-find-backup-file-name)
 
 ;; Turn off truename processing to save time.
 ;; Treat each name as its own truename.
@@ -3865,6 +3935,8 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 ;; Turn off RCS/SCCS processing to save time.
 ;; This returns nil for any file name as argument.
 (put 'vc-registered 'ange-ftp 'null)
+
+(put 'dired-call-process 'ange-ftp 'ange-ftp-dired-call-process)
 \f
 ;;; Define ways of getting at unmodified Emacs primitives,
 ;;; turning off our handler.
@@ -3936,6 +4008,8 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
   (ange-ftp-run-real-handler 'shell-command args))
 (defun ange-ftp-real-load (&rest args)
   (ange-ftp-run-real-handler 'load args))
+(defun ange-ftp-real-find-backup-file-name (&rest args)
+  (ange-ftp-run-real-handler 'find-backup-file-name args))
 \f
 ;; Here we support using dired on remote hosts.
 ;; I have turned off the support for using dired on foreign directory formats.
@@ -3978,12 +4052,6 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
     (if func (funcall func file keep-backup-version)
       (ange-ftp-real-file-name-sans-versions file keep-backup-version))))
 
-(defvar ange-ftp-remote-shell-file-name
-  (if (memq system-type '(hpux usg-unix-v)) ; hope that's right
-      "remsh"
-    "rsh")
-  "Name of command to run a remote shell, for ange-ftp.")
-
 ;;; This doesn't work yet; a new hook needs to be created.
 ;;; Maybe the new hook should be in call-process.
 (defun ange-ftp-shell-command (command)
@@ -3998,14 +4066,14 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
       (setq command
            (format  "%s %s \"%s\""     ; remsh -l USER does not work well
                                        ; on a hp-ux machine I tried
-                    ange-ftp-remote-shell-file-name host command))
+                    remote-shell-program host command))
       (ange-ftp-message "Remote command '%s' ..." command)
       ;; Cannot call ange-ftp-real-dired-run-shell-command here as it
       ;; would prepend "cd default-directory" --- which bombs because
       ;; default-directory is in ange-ftp syntax for remote file names.
       (ange-ftp-real-shell-command command))))
 
-;;; Thisis not hooked up yet.      
+;;; This is the handler for call-process.
 (defun ange-ftp-dired-call-process (program discard &rest arguments)
   ;; PROGRAM is always one of those below in the cond in dired.el.
   ;; The ARGUMENTS are (nearly) always files.
@@ -4362,7 +4430,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 ;
 ;(defun ange-ftp-vos-host (host)
 ;  (and ange-ftp-vos-host-regexp
-;       (ange-ftp-save-match-data
+;       (save-match-data
 ;       (string-match ange-ftp-vos-host-regexp host))))
 ;
 ;(defun ange-ftp-parse-vos-listing ()
@@ -4374,7 +4442,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 ;         ("^Dirs: [0-9]+\n+" t 30)))
 ;      type-regexp type-is-dir type-col file)
 ;    (goto-char (point-min))
-;    (ange-ftp-save-match-data
+;    (save-match-data
 ;      (while type-list
 ;      (setq type-regexp (car (car type-list))
 ;            type-is-dir (nth 1 (car type-list))
@@ -4405,7 +4473,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 ;; Convert NAME from UNIX-ish to VMS.  If REVERSE given then convert from VMS
 ;; to UNIX-ish.
 (defun ange-ftp-fix-name-for-vms (name &optional reverse)
-  (ange-ftp-save-match-data
+  (save-match-data
     (if reverse
        (if (string-match "^\\([^:]+:\\)?\\(\\[.*\\]\\)?\\([^][]*\\)$" name)
            (let (drive dir file)
@@ -4491,7 +4559,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
 ;; Return non-nil if HOST is running VMS.
 (defun ange-ftp-vms-host (host)
   (and ange-ftp-vms-host-regexp
-       (ange-ftp-save-match-data
+       (save-match-data
         (string-match ange-ftp-vms-host-regexp host))))
 
 ;; Because some VMS ftp servers convert filenames to lower case
@@ -4525,7 +4593,7 @@ Other orders of $ and _ seem to all work just fine.")
   (let ((tbl (ange-ftp-make-hashtable))
        file)
     (goto-char (point-min))
-    (ange-ftp-save-match-data
+    (save-match-data
       (while (setq file (ange-ftp-parse-vms-filename))
        (if (string-match "\\.\\(DIR\\|dir\\);[0-9]+" file)
            ;; deal with directories
@@ -4559,7 +4627,7 @@ Other orders of $ and _ seem to all work just fine.")
 (defun ange-ftp-vms-delete-file-entry (name &optional dir-p)
   (if dir-p
       (ange-ftp-internal-delete-file-entry name t)
-    (ange-ftp-save-match-data
+    (save-match-data
       (let ((file (ange-ftp-get-file-part name)))
        (if (string-match ";[0-9]+$" file)
            ;; In VMS you can't delete a file without an explicit       
@@ -4600,7 +4668,7 @@ Other orders of $ and _ seem to all work just fine.")
                  ange-ftp-files-hashtable)))
       (if files
          (let ((file (ange-ftp-get-file-part name)))
-           (ange-ftp-save-match-data
+           (save-match-data
              (if (string-match ";[0-9]+$" file)
                  (ange-ftp-put-hash-entry
                   (substring file 0 (match-beginning 0))
@@ -4649,7 +4717,7 @@ Other orders of $ and _ seem to all work just fine.")
 
 
 (defun ange-ftp-vms-file-name-as-directory (name)
-  (ange-ftp-save-match-data
+  (save-match-data
     (if (string-match "\\.\\(DIR\\|dir\\)\\(;[0-9]+\\)?$" name)
        (setq name (substring name 0 (match-beginning 0))))
     (ange-ftp-real-file-name-as-directory name)))
@@ -4810,8 +4878,8 @@ Other orders of $ and _ seem to all work just fine.")
 ;;       (cons '(vms . ange-ftp-dired-vms-ls-trim)
 ;;             ange-ftp-dired-ls-trim-alist))) 
 
-(defun ange-ftp-vms-sans-version (name)
-  (ange-ftp-save-match-data
+(defun ange-ftp-vms-sans-version (name &rest args)
+  (save-match-data
     (if (string-match ";[0-9]+$" name)
        (substring name 0 (match-beginning 0))
       name)))
@@ -4968,7 +5036,7 @@ Other orders of $ and _ seem to all work just fine.")
 ;; Convert NAME from UNIX-ish to MTS. If REVERSE given then convert from
 ;; MTS to UNIX-ish.
 (defun ange-ftp-fix-name-for-mts (name &optional reverse)
-  (ange-ftp-save-match-data
+  (save-match-data
     (if reverse
        (if (string-match "^\\([^:]+:\\)?\\(.*\\)$" name)
            (let (acct file)
@@ -5018,14 +5086,14 @@ Other orders of $ and _ seem to all work just fine.")
 ;; Return non-nil if HOST is running MTS.
 (defun ange-ftp-mts-host (host)
   (and ange-ftp-mts-host-regexp
-       (ange-ftp-save-match-data
+       (save-match-data
         (string-match ange-ftp-mts-host-regexp host))))
 
 ;; Parse the current buffer which is assumed to be in mts ftp dir format.
 (defun ange-ftp-parse-mts-listing ()
   (let ((tbl (ange-ftp-make-hashtable)))
     (goto-char (point-min))
-    (ange-ftp-save-match-data
+    (save-match-data
       (while (re-search-forward ange-ftp-date-regexp nil t)
        (end-of-line)
        (skip-chars-backward " ")
@@ -5131,7 +5199,7 @@ Other orders of $ and _ seem to all work just fine.")
 ;; Have I got the filename character set right?
 
 (defun ange-ftp-fix-name-for-cms (name &optional reverse)
-  (ange-ftp-save-match-data
+  (save-match-data
     (if reverse
        ;; Since we only convert output from a pwd in this direction,
        ;; we'll assume that it's a minidisk, and make it into a
@@ -5221,7 +5289,7 @@ Other orders of $ and _ seem to all work just fine.")
 ;; Return non-nil if HOST is running CMS.
 (defun ange-ftp-cms-host (host)
   (and ange-ftp-cms-host-regexp
-       (ange-ftp-save-match-data
+       (save-match-data
         (string-match ange-ftp-cms-host-regexp host))))
 
 (defun ange-ftp-add-cms-host (host)
@@ -5258,7 +5326,7 @@ Other orders of $ and _ seem to all work just fine.")
   ;; Now do the usual parsing
   (let ((tbl (ange-ftp-make-hashtable)))
     (goto-char (point-min))
-    (ange-ftp-save-match-data
+    (save-match-data
       (while
          (re-search-forward
           "^\\([-A-Z0-9$_]+\\) +\\([-A-Z0-9$_]+\\) +[VF] +[0-9]+ " nil t)