comparison lisp/ange-ftp.el @ 10244:3d95ea97eb9e

(ange-ftp-save-match-data): Macro deleted. Most callers use save-match-data. (ange-ftp-process-filter, ange-ftp-process-sentinel) (ange-ftp-gwp-filter): Don't save the match data explicitly. (ange-ftp-process-filter, ange-ftp-gwp-filter): After comint output processing, update STR.
author Richard M. Stallman <rms@gnu.org>
date Sun, 25 Dec 1994 14:35:19 +0000
parents 7e22057e9516
children 8b26137996f9
comparison
equal deleted inserted replaced
10243:ea9dda158056 10244:3d95ea97eb9e
917 ;; New error symbols. 917 ;; New error symbols.
918 (put 'ftp-error 'error-conditions '(ftp-error file-error error)) 918 (put 'ftp-error 'error-conditions '(ftp-error file-error error))
919 ;; (put 'ftp-error 'error-message "FTP error") 919 ;; (put 'ftp-error 'error-message "FTP error")
920 920
921 ;;; ------------------------------------------------------------ 921 ;;; ------------------------------------------------------------
922 ;;; Match-data support (stolen from Kyle I think)
923 ;;; ------------------------------------------------------------
924
925 (defmacro ange-ftp-save-match-data (&rest body)
926 "Execute the BODY forms, restoring the global value of the match data.
927 Also makes matching case-sensitive within BODY."
928 (let ((original (make-symbol "match-data"))
929 case-fold-search)
930 (list
931 'let (list (list original '(match-data)))
932 (list 'unwind-protect
933 (cons 'progn body)
934 (list 'store-match-data original)))))
935
936 (put 'ange-ftp-save-match-data 'lisp-indent-hook 0)
937 (put 'ange-ftp-save-match-data 'edebug-form-hook '(&rest form))
938
939 ;;; ------------------------------------------------------------
940 ;;; Enhanced message support. 922 ;;; Enhanced message support.
941 ;;; ------------------------------------------------------------ 923 ;;; ------------------------------------------------------------
942 924
943 (defun ange-ftp-message (fmt &rest args) 925 (defun ange-ftp-message (fmt &rest args)
944 "Display message in echo area, but indicate if truncated. 926 "Display message in echo area, but indicate if truncated.
951 933
952 (defun ange-ftp-abbreviate-filename (file &optional new) 934 (defun ange-ftp-abbreviate-filename (file &optional new)
953 "Abbreviate the file name FILE relative to the default-directory. 935 "Abbreviate the file name FILE relative to the default-directory.
954 If the optional parameter NEW is given and the non-directory parts match, 936 If the optional parameter NEW is given and the non-directory parts match,
955 only return the directory part of FILE." 937 only return the directory part of FILE."
956 (ange-ftp-save-match-data 938 (save-match-data
957 (if (and default-directory 939 (if (and default-directory
958 (string-match (concat "^" 940 (string-match (concat "^"
959 (regexp-quote default-directory) 941 (regexp-quote default-directory)
960 ".") file)) 942 ".") file))
961 (setq file (substring file (1- (match-end 0))))) 943 (setq file (substring file (1- (match-end 0)))))
1044 (ange-ftp-map-hashtable 1026 (ange-ftp-map-hashtable
1045 (function (lambda (host val) 1027 (function (lambda (host val)
1046 (if (ange-ftp-lookup-passwd host user) 1028 (if (ange-ftp-lookup-passwd host user)
1047 (throw 'found-one host)))) 1029 (throw 'found-one host))))
1048 ange-ftp-user-hashtable) 1030 ange-ftp-user-hashtable)
1049 (ange-ftp-save-match-data 1031 (save-match-data
1050 (ange-ftp-map-hashtable 1032 (ange-ftp-map-hashtable
1051 (function 1033 (function
1052 (lambda (key value) 1034 (lambda (key value)
1053 (if (string-match "^[^/]*\\(/\\).*$" key) 1035 (if (string-match "^[^/]*\\(/\\).*$" key)
1054 (let ((host (substring key 0 (match-beginning 1)))) 1036 (let ((host (substring key 0 (match-beginning 1))))
1217 (let* ((file (ange-ftp-chase-symlinks 1199 (let* ((file (ange-ftp-chase-symlinks
1218 (ange-ftp-real-expand-file-name ange-ftp-netrc-filename))) 1200 (ange-ftp-real-expand-file-name ange-ftp-netrc-filename)))
1219 (attr (ange-ftp-real-file-attributes file))) 1201 (attr (ange-ftp-real-file-attributes file)))
1220 (if (and attr ; file exists. 1202 (if (and attr ; file exists.
1221 (not (equal (nth 5 attr) ange-ftp-netrc-modtime))) ; file changed 1203 (not (equal (nth 5 attr) ange-ftp-netrc-modtime))) ; file changed
1222 (ange-ftp-save-match-data 1204 (save-match-data
1223 (if (or ange-ftp-disable-netrc-security-check 1205 (if (or ange-ftp-disable-netrc-security-check
1224 (and (eq (nth 2 attr) (user-uid)) ; Same uids. 1206 (and (eq (nth 2 attr) (user-uid)) ; Same uids.
1225 (string-match ".r..------" (nth 8 attr)))) 1207 (string-match ".r..------" (nth 8 attr))))
1226 (save-excursion 1208 (save-excursion
1227 ;; we are cheating a bit here. I'm trying to do the equivalent 1209 ;; we are cheating a bit here. I'm trying to do the equivalent
1248 ;; Return a list of prefixes of the form 'user@host:' to be used when 1230 ;; Return a list of prefixes of the form 'user@host:' to be used when
1249 ;; completion is done in the root directory. 1231 ;; completion is done in the root directory.
1250 1232
1251 (defun ange-ftp-generate-root-prefixes () 1233 (defun ange-ftp-generate-root-prefixes ()
1252 (ange-ftp-parse-netrc) 1234 (ange-ftp-parse-netrc)
1253 (ange-ftp-save-match-data 1235 (save-match-data
1254 (let (res) 1236 (let (res)
1255 (ange-ftp-map-hashtable 1237 (ange-ftp-map-hashtable
1256 (function 1238 (function
1257 (lambda (key value) 1239 (lambda (key value)
1258 (if (string-match "^[^/]*\\(/\\).*$" key) 1240 (if (string-match "^[^/]*\\(/\\).*$" key)
1286 (defun ange-ftp-ftp-name (name) 1268 (defun ange-ftp-ftp-name (name)
1287 (if (string-equal name ange-ftp-ftp-name-arg) 1269 (if (string-equal name ange-ftp-ftp-name-arg)
1288 ange-ftp-ftp-name-res 1270 ange-ftp-ftp-name-res
1289 (setq ange-ftp-ftp-name-arg name 1271 (setq ange-ftp-ftp-name-arg name
1290 ange-ftp-ftp-name-res 1272 ange-ftp-ftp-name-res
1291 (ange-ftp-save-match-data 1273 (save-match-data
1292 (if (string-match (car ange-ftp-name-format) name) 1274 (if (string-match (car ange-ftp-name-format) name)
1293 (let* ((ns (cdr ange-ftp-name-format)) 1275 (let* ((ns (cdr ange-ftp-name-format))
1294 (host (ange-ftp-ftp-name-component 0 ns name)) 1276 (host (ange-ftp-ftp-name-component 0 ns name))
1295 (user (ange-ftp-ftp-name-component 1 ns name)) 1277 (user (ange-ftp-ftp-name-component 1 ns name))
1296 (name (ange-ftp-ftp-name-component 2 ns name))) 1278 (name (ange-ftp-ftp-name-component 2 ns name)))
1300 nil))))) 1282 nil)))))
1301 1283
1302 ;; Take a FULLNAME that matches according to ange-ftp-name-format and 1284 ;; Take a FULLNAME that matches according to ange-ftp-name-format and
1303 ;; replace the name component with NAME. 1285 ;; replace the name component with NAME.
1304 (defun ange-ftp-replace-name-component (fullname name) 1286 (defun ange-ftp-replace-name-component (fullname name)
1305 (ange-ftp-save-match-data 1287 (save-match-data
1306 (if (string-match (car ange-ftp-name-format) fullname) 1288 (if (string-match (car ange-ftp-name-format) fullname)
1307 (let* ((ns (cdr ange-ftp-name-format)) 1289 (let* ((ns (cdr ange-ftp-name-format))
1308 (elt (nth 2 ns))) 1290 (elt (nth 2 ns)))
1309 (concat (substring fullname 0 (match-beginning elt)) 1291 (concat (substring fullname 0 (match-beginning elt))
1310 name 1292 name
1476 (old-buffer (current-buffer))) 1458 (old-buffer (current-buffer)))
1477 1459
1478 ;; see if the buffer is still around... it could have been deleted. 1460 ;; see if the buffer is still around... it could have been deleted.
1479 (if (buffer-name buffer) 1461 (if (buffer-name buffer)
1480 (unwind-protect 1462 (unwind-protect
1481 (ange-ftp-save-match-data 1463 (progn
1482 (set-buffer (process-buffer proc)) 1464 (set-buffer (process-buffer proc))
1483 1465
1484 ;; handle hash mark printing 1466 ;; handle hash mark printing
1485 (and ange-ftp-hash-mark-unit 1467 (and ange-ftp-hash-mark-unit
1486 ange-ftp-process-busy 1468 ange-ftp-process-busy
1487 (string-match "^#+$" str) 1469 (string-match "^#+$" str)
1488 (setq str (ange-ftp-process-handle-hash str))) 1470 (setq str (ange-ftp-process-handle-hash str)))
1489 (comint-output-filter proc str) 1471 (comint-output-filter proc str)
1472 ;; Replace STR by the result of the comint processing.
1473 (setq str (buffer-substring comint-last-output-start
1474 (process-mark proc)))
1490 (if ange-ftp-process-busy 1475 (if ange-ftp-process-busy
1491 (progn 1476 (progn
1492 (setq ange-ftp-process-string (concat ange-ftp-process-string 1477 (setq ange-ftp-process-string (concat ange-ftp-process-string
1493 str)) 1478 str))
1494 1479
1533 ange-ftp-process-result-line)))))) 1518 ange-ftp-process-result-line))))))
1534 (set-buffer old-buffer))))) 1519 (set-buffer old-buffer)))))
1535 1520
1536 (defun ange-ftp-process-sentinel (proc str) 1521 (defun ange-ftp-process-sentinel (proc str)
1537 "When ftp process changes state, nuke all file-entries in cache." 1522 "When ftp process changes state, nuke all file-entries in cache."
1538 (ange-ftp-save-match-data 1523 (let ((name (process-name proc)))
1539 (let ((name (process-name proc))) 1524 (if (string-match "\\*ftp \\([^@]+\\)@\\([^*]+\\)*" name)
1540 (if (string-match "\\*ftp \\([^@]+\\)@\\([^*]+\\)*" name) 1525 (let ((user (substring name (match-beginning 1) (match-end 1)))
1541 (let ((user (substring name (match-beginning 1) (match-end 1))) 1526 (host (substring name (match-beginning 2) (match-end 2))))
1542 (host (substring name (match-beginning 2) (match-end 2)))) 1527 (ange-ftp-wipe-file-entries host user))))
1543 (ange-ftp-wipe-file-entries host user)))) 1528 (setq ange-ftp-ls-cache-file nil))
1544 (setq ange-ftp-ls-cache-file nil)))
1545 1529
1546 ;;;; ------------------------------------------------------------ 1530 ;;;; ------------------------------------------------------------
1547 ;;;; Gateway support. 1531 ;;;; Gateway support.
1548 ;;;; ------------------------------------------------------------ 1532 ;;;; ------------------------------------------------------------
1549 1533
1550 (defun ange-ftp-use-gateway-p (host) 1534 (defun ange-ftp-use-gateway-p (host)
1551 "Returns whether to access this host via a normal (non-smart) gateway." 1535 "Returns whether to access this host via a normal (non-smart) gateway."
1552 ;; yes, I know that I could simplify the following expression, but it is 1536 ;; yes, I know that I could simplify the following expression, but it is
1553 ;; clearer (to me at least) this way. 1537 ;; clearer (to me at least) this way.
1554 (and (not ange-ftp-smart-gateway) 1538 (and (not ange-ftp-smart-gateway)
1555 (ange-ftp-save-match-data 1539 (save-match-data
1556 (not (string-match ange-ftp-local-host-regexp host))))) 1540 (not (string-match ange-ftp-local-host-regexp host)))))
1557 1541
1558 (defun ange-ftp-use-smart-gateway-p (host) 1542 (defun ange-ftp-use-smart-gateway-p (host)
1559 "Returns whether to access this host via a smart gateway." 1543 "Returns whether to access this host via a smart gateway."
1560 (and ange-ftp-smart-gateway 1544 (and ange-ftp-smart-gateway
1561 (ange-ftp-save-match-data 1545 (save-match-data
1562 (not (string-match ange-ftp-local-host-regexp host))))) 1546 (not (string-match ange-ftp-local-host-regexp host)))))
1563 1547
1564 1548
1565 ;;; ------------------------------------------------------------ 1549 ;;; ------------------------------------------------------------
1566 ;;; Temporary file location and deletion... 1550 ;;; Temporary file location and deletion...
1613 1597
1614 (defun ange-ftp-gwp-sentinel (proc str) 1598 (defun ange-ftp-gwp-sentinel (proc str)
1615 (setq ange-ftp-gwp-running nil)) 1599 (setq ange-ftp-gwp-running nil))
1616 1600
1617 (defun ange-ftp-gwp-filter (proc str) 1601 (defun ange-ftp-gwp-filter (proc str)
1618 (ange-ftp-save-match-data 1602 (comint-output-filter proc str)
1619 (comint-output-filter proc str) 1603 ;; Replace STR by the result of the comint processing.
1620 (cond ((string-match "login: *$" str) 1604 (setq str (buffer-substring comint-last-output-start (process-mark proc)))
1621 (send-string proc 1605 (cond ((string-match "login: *$" str)
1622 (concat 1606 (send-string proc
1623 (let ((ange-ftp-default-user t)) 1607 (concat
1624 (ange-ftp-get-user ange-ftp-gateway-host)) 1608 (let ((ange-ftp-default-user t))
1625 "\n"))) 1609 (ange-ftp-get-user ange-ftp-gateway-host))
1626 ((string-match "Password: *$" str) 1610 "\n")))
1627 (send-string proc 1611 ((string-match "Password: *$" str)
1628 (concat 1612 (send-string proc
1629 (ange-ftp-get-passwd ange-ftp-gateway-host 1613 (concat
1630 (ange-ftp-get-user 1614 (ange-ftp-get-passwd ange-ftp-gateway-host
1631 ange-ftp-gateway-host)) 1615 (ange-ftp-get-user
1632 "\n"))) 1616 ange-ftp-gateway-host))
1633 ((string-match ange-ftp-gateway-fatal-msgs str) 1617 "\n")))
1634 (delete-process proc) 1618 ((string-match ange-ftp-gateway-fatal-msgs str)
1635 (setq ange-ftp-gwp-running nil)) 1619 (delete-process proc)
1636 ((string-match ange-ftp-gateway-prompt-pattern str) 1620 (setq ange-ftp-gwp-running nil))
1637 (setq ange-ftp-gwp-running nil 1621 ((string-match ange-ftp-gateway-prompt-pattern str)
1638 ange-ftp-gwp-status t))))) 1622 (setq ange-ftp-gwp-running nil
1623 ange-ftp-gwp-status t))))
1639 1624
1640 (defun ange-ftp-gwp-start (host user name args) 1625 (defun ange-ftp-gwp-start (host user name args)
1641 "Login to the gateway machine and fire up an ftp process." 1626 "Login to the gateway machine and fire up an ftp process."
1642 (let* ((gw-user (ange-ftp-get-user ange-ftp-gateway-host)) 1627 (let* ((gw-user (ange-ftp-get-user ange-ftp-gateway-host))
1643 ;; It would be nice to make process-connection-type nil, 1628 ;; It would be nice to make process-connection-type nil,
1714 cmd (concat cmd "\n")) 1699 cmd (concat cmd "\n"))
1715 (and msg ange-ftp-process-verbose (ange-ftp-message "%s..." msg)) 1700 (and msg ange-ftp-process-verbose (ange-ftp-message "%s..." msg))
1716 (goto-char (point-max)) 1701 (goto-char (point-max))
1717 (move-marker comint-last-input-start (point)) 1702 (move-marker comint-last-input-start (point))
1718 ;; don't insert the password into the buffer on the USER command. 1703 ;; don't insert the password into the buffer on the USER command.
1719 (ange-ftp-save-match-data 1704 (save-match-data
1720 (if (string-match "^user \"[^\"]*\"" cmd) 1705 (if (string-match "^user \"[^\"]*\"" cmd)
1721 (insert (substring cmd 0 (match-end 0)) " Turtle Power!\n") 1706 (insert (substring cmd 0 (match-end 0)) " Turtle Power!\n")
1722 (insert cmd))) 1707 (insert cmd)))
1723 (move-marker comint-last-input-end (point)) 1708 (move-marker comint-last-input-end (point))
1724 (send-string proc cmd) 1709 (send-string proc cmd)
1905 (save-excursion 1890 (save-excursion
1906 (set-buffer (process-buffer proc)) 1891 (set-buffer (process-buffer proc))
1907 (let* ((status (ange-ftp-raw-send-cmd proc "hash")) 1892 (let* ((status (ange-ftp-raw-send-cmd proc "hash"))
1908 (result (car status)) 1893 (result (car status))
1909 (line (cdr status))) 1894 (line (cdr status)))
1910 (ange-ftp-save-match-data 1895 (save-match-data
1911 (if (string-match ange-ftp-hash-mark-msgs line) 1896 (if (string-match ange-ftp-hash-mark-msgs line)
1912 (let ((size (string-to-int 1897 (let ((size (string-to-int
1913 (substring line 1898 (substring line
1914 (match-beginning 1) 1899 (match-beginning 1)
1915 (match-end 1))))) 1900 (match-end 1)))))
2136 Works by doing a pwd and examining the directory syntax." 2121 Works by doing a pwd and examining the directory syntax."
2137 (let ((host-type (ange-ftp-host-type host)) 2122 (let ((host-type (ange-ftp-host-type host))
2138 (key (concat host "/" user "/~"))) 2123 (key (concat host "/" user "/~")))
2139 (if (eq host-type 'unix) 2124 (if (eq host-type 'unix)
2140 ;; Note that ange-ftp-host-type returns unix as the default value. 2125 ;; Note that ange-ftp-host-type returns unix as the default value.
2141 (ange-ftp-save-match-data 2126 (save-match-data
2142 (let* ((result (ange-ftp-get-pwd host user)) 2127 (let* ((result (ange-ftp-get-pwd host user))
2143 (dir (car result)) 2128 (dir (car result))
2144 fix-name-func) 2129 fix-name-func)
2145 (cond ((null dir) 2130 (cond ((null dir)
2146 (message "Warning! Unable to get home directory") 2131 (message "Warning! Unable to get home directory")
2212 2197
2213 ;; Returns whether HOST's FTP server doesn't like \'ls\' or \'dir\' commands 2198 ;; Returns whether HOST's FTP server doesn't like \'ls\' or \'dir\' commands
2214 ;; to take switch arguments. 2199 ;; to take switch arguments.
2215 (defun ange-ftp-dumb-unix-host (host) 2200 (defun ange-ftp-dumb-unix-host (host)
2216 (and ange-ftp-dumb-unix-host-regexp 2201 (and ange-ftp-dumb-unix-host-regexp
2217 (ange-ftp-save-match-data 2202 (save-match-data
2218 (string-match ange-ftp-dumb-unix-host-regexp host)))) 2203 (string-match ange-ftp-dumb-unix-host-regexp host))))
2219 2204
2220 (defun ange-ftp-add-dumb-unix-host (host) 2205 (defun ange-ftp-add-dumb-unix-host (host)
2221 "Interactively adds a given HOST to ange-ftp-dumb-unix-host-regexp." 2206 "Interactively adds a given HOST to ange-ftp-dumb-unix-host-regexp."
2222 (interactive 2207 (interactive
2484 ;; Parse the current buffer which is assumed to be in a dired-like listing 2469 ;; Parse the current buffer which is assumed to be in a dired-like listing
2485 ;; format, and return a hashtable as the result. If the listing is not really 2470 ;; format, and return a hashtable as the result. If the listing is not really
2486 ;; a listing, then return nil. 2471 ;; a listing, then return nil.
2487 2472
2488 (defun ange-ftp-parse-dired-listing (&optional switches) 2473 (defun ange-ftp-parse-dired-listing (&optional switches)
2489 (ange-ftp-save-match-data 2474 (save-match-data
2490 (cond 2475 (cond
2491 ((looking-at "^total [0-9]+$") 2476 ((looking-at "^total [0-9]+$")
2492 (forward-line 1) 2477 (forward-line 1)
2493 ;; Some systems put in a blank line here. 2478 ;; Some systems put in a blank line here.
2494 (if (eolp) (forward-line 1)) 2479 (if (eolp) (forward-line 1))
2524 "Given a given DIRECTORY, return a hashtable of file entries. 2509 "Given a given DIRECTORY, return a hashtable of file entries.
2525 This will give an error or return nil, depending on the value of 2510 This will give an error or return nil, depending on the value of
2526 NO-ERROR, if a listing for DIRECTORY cannot be obtained." 2511 NO-ERROR, if a listing for DIRECTORY cannot be obtained."
2527 (setq directory (file-name-as-directory directory)) ;normalize 2512 (setq directory (file-name-as-directory directory)) ;normalize
2528 (or (ange-ftp-get-hash-entry directory ange-ftp-files-hashtable) 2513 (or (ange-ftp-get-hash-entry directory ange-ftp-files-hashtable)
2529 (ange-ftp-save-match-data 2514 (save-match-data
2530 (and (ange-ftp-ls directory 2515 (and (ange-ftp-ls directory
2531 ;; This is an efficiency hack. We try to 2516 ;; This is an efficiency hack. We try to
2532 ;; anticipate what sort of listing dired 2517 ;; anticipate what sort of listing dired
2533 ;; might want, and cache just such a listing. 2518 ;; might want, and cache just such a listing.
2534 (if (and (boundp 'dired-actual-switches) 2519 (if (and (boundp 'dired-actual-switches)
2716 and LINE is the relevant success or fail line from the FTP-client." 2701 and LINE is the relevant success or fail line from the FTP-client."
2717 (let* ((result (ange-ftp-send-cmd host user '(pwd) "Getting PWD")) 2702 (let* ((result (ange-ftp-send-cmd host user '(pwd) "Getting PWD"))
2718 (line (cdr result)) 2703 (line (cdr result))
2719 dir) 2704 dir)
2720 (if (car result) 2705 (if (car result)
2721 (ange-ftp-save-match-data 2706 (save-match-data
2722 (and (or (string-match "\"\\([^\"]*\\)\"" line) 2707 (and (or (string-match "\"\\([^\"]*\\)\"" line)
2723 (string-match " \\([^ ]+\\) " line)) ; stone-age VMS servers! 2708 (string-match " \\([^ ]+\\) " line)) ; stone-age VMS servers!
2724 (setq dir (substring line 2709 (setq dir (substring line
2725 (match-beginning 1) 2710 (match-beginning 1)
2726 (match-end 1)))))) 2711 (match-end 1))))))
2832 (ange-ftp-real-file-name-nondirectory n) 2817 (ange-ftp-real-file-name-nondirectory n)
2833 (ange-ftp-real-file-name-directory n)))))) 2818 (ange-ftp-real-file-name-directory n))))))
2834 2819
2835 (defun ange-ftp-expand-file-name (name &optional default) 2820 (defun ange-ftp-expand-file-name (name &optional default)
2836 "Documented as original." 2821 "Documented as original."
2837 (ange-ftp-save-match-data 2822 (save-match-data
2838 (if (eq (string-to-char name) ?/) 2823 (if (eq (string-to-char name) ?/)
2839 (while (cond ((string-match "[^:]+//" name) ;don't upset Apollo users 2824 (while (cond ((string-match "[^:]+//" name) ;don't upset Apollo users
2840 (setq name (substring name (1- (match-end 0))))) 2825 (setq name (substring name (1- (match-end 0)))))
2841 ((string-match "/~" name) 2826 ((string-match "/~" name)
2842 (setq name (substring name (1- (match-end 0)))))))) 2827 (setq name (substring name (1- (match-end 0))))))))
2873 (defun ange-ftp-file-name-directory (name) 2858 (defun ange-ftp-file-name-directory (name)
2874 "Documented as original." 2859 "Documented as original."
2875 (let ((parsed (ange-ftp-ftp-name name))) 2860 (let ((parsed (ange-ftp-ftp-name name)))
2876 (if parsed 2861 (if parsed
2877 (let ((filename (nth 2 parsed))) 2862 (let ((filename (nth 2 parsed)))
2878 (if (ange-ftp-save-match-data 2863 (if (save-match-data
2879 (string-match "^~[^/]*$" filename)) 2864 (string-match "^~[^/]*$" filename))
2880 name 2865 name
2881 (ange-ftp-replace-name-component 2866 (ange-ftp-replace-name-component
2882 name 2867 name
2883 (ange-ftp-real-file-name-directory filename)))) 2868 (ange-ftp-real-file-name-directory filename))))
2886 (defun ange-ftp-file-name-nondirectory (name) 2871 (defun ange-ftp-file-name-nondirectory (name)
2887 "Documented as original." 2872 "Documented as original."
2888 (let ((parsed (ange-ftp-ftp-name name))) 2873 (let ((parsed (ange-ftp-ftp-name name)))
2889 (if parsed 2874 (if parsed
2890 (let ((filename (nth 2 parsed))) 2875 (let ((filename (nth 2 parsed)))
2891 (if (ange-ftp-save-match-data 2876 (if (save-match-data
2892 (string-match "^~[^/]*$" filename)) 2877 (string-match "^~[^/]*$" filename))
2893 "" 2878 ""
2894 (ange-ftp-real-file-name-nondirectory name))) 2879 (ange-ftp-real-file-name-nondirectory name)))
2895 (ange-ftp-real-file-name-nondirectory name)))) 2880 (ange-ftp-real-file-name-nondirectory name))))
2896 2881
2906 2891
2907 ;;; Hooks that handle Emacs primitives. 2892 ;;; Hooks that handle Emacs primitives.
2908 2893
2909 ;; Returns non-nil if should transfer FILE in binary mode. 2894 ;; Returns non-nil if should transfer FILE in binary mode.
2910 (defun ange-ftp-binary-file (file) 2895 (defun ange-ftp-binary-file (file)
2911 (ange-ftp-save-match-data 2896 (save-match-data
2912 (string-match ange-ftp-binary-file-name-regexp file))) 2897 (string-match ange-ftp-binary-file-name-regexp file)))
2913 2898
2914 (defun ange-ftp-write-region (start end filename &optional append visit) 2899 (defun ange-ftp-write-region (start end filename &optional append visit)
2915 (setq filename (expand-file-name filename)) 2900 (setq filename (expand-file-name filename))
2916 (let ((parsed (ange-ftp-ftp-name filename))) 2901 (let ((parsed (ange-ftp-ftp-name filename)))
3084 (ange-ftp-barf-if-not-directory directory) 3069 (ange-ftp-barf-if-not-directory directory)
3085 (let ((tail (ange-ftp-hash-table-keys 3070 (let ((tail (ange-ftp-hash-table-keys
3086 (ange-ftp-get-files directory))) 3071 (ange-ftp-get-files directory)))
3087 files f) 3072 files f)
3088 (setq directory (file-name-as-directory directory)) 3073 (setq directory (file-name-as-directory directory))
3089 (ange-ftp-save-match-data 3074 (save-match-data
3090 (while tail 3075 (while tail
3091 (setq f (car tail) 3076 (setq f (car tail)
3092 tail (cdr tail)) 3077 tail (cdr tail))
3093 (if (or (not match) (string-match match f)) 3078 (if (or (not match) (string-match match f))
3094 (setq files 3079 (setq files
3566 (lambda (s) (if (stringp s) 3551 (lambda (s) (if (stringp s)
3567 (concat (regexp-quote s) "$") 3552 (concat (regexp-quote s) "$")
3568 "/"))) ; / never in filename 3553 "/"))) ; / never in filename
3569 completion-ignored-extensions 3554 completion-ignored-extensions
3570 "\\|"))) 3555 "\\|")))
3571 (ange-ftp-save-match-data 3556 (save-match-data
3572 (or (ange-ftp-file-name-completion-1 3557 (or (ange-ftp-file-name-completion-1
3573 file tbl ange-ftp-this-dir 3558 file tbl ange-ftp-this-dir
3574 (function ange-ftp-file-entry-not-ignored-p)) 3559 (function ange-ftp-file-entry-not-ignored-p))
3575 (ange-ftp-file-name-completion-1 3560 (ange-ftp-file-name-completion-1
3576 file tbl ange-ftp-this-dir 3561 file tbl ange-ftp-this-dir
3739 (if (and parsed 3724 (if (and parsed
3740 (setq conversion-func 3725 (setq conversion-func
3741 (cdr (assq (ange-ftp-host-type (car parsed)) 3726 (cdr (assq (ange-ftp-host-type (car parsed))
3742 ange-ftp-make-compressed-filename-alist)))) 3727 ange-ftp-make-compressed-filename-alist))))
3743 (let* ((decision 3728 (let* ((decision
3744 (ange-ftp-save-match-data (funcall conversion-func name))) 3729 (save-match-data (funcall conversion-func name)))
3745 (compressing (car decision)) 3730 (compressing (car decision))
3746 (newfile (nth 1 decision))) 3731 (newfile (nth 1 decision)))
3747 (if compressing 3732 (if compressing
3748 (ange-ftp-compress name newfile) 3733 (ange-ftp-compress name newfile)
3749 (ange-ftp-uncompress name newfile))) 3734 (ange-ftp-uncompress name newfile)))
4391 ;(defvar ange-ftp-vos-host-regexp nil 4376 ;(defvar ange-ftp-vos-host-regexp nil
4392 ; "If a host matches this regexp then it is assumed to be running VOS.") 4377 ; "If a host matches this regexp then it is assumed to be running VOS.")
4393 ; 4378 ;
4394 ;(defun ange-ftp-vos-host (host) 4379 ;(defun ange-ftp-vos-host (host)
4395 ; (and ange-ftp-vos-host-regexp 4380 ; (and ange-ftp-vos-host-regexp
4396 ; (ange-ftp-save-match-data 4381 ; (save-match-data
4397 ; (string-match ange-ftp-vos-host-regexp host)))) 4382 ; (string-match ange-ftp-vos-host-regexp host))))
4398 ; 4383 ;
4399 ;(defun ange-ftp-parse-vos-listing () 4384 ;(defun ange-ftp-parse-vos-listing ()
4400 ; "Parse the current buffer which is assumed to be in VOS list -all 4385 ; "Parse the current buffer which is assumed to be in VOS list -all
4401 ;format, and return a hashtable as the result." 4386 ;format, and return a hashtable as the result."
4403 ; (type-list 4388 ; (type-list
4404 ; '(("^Files: [0-9]+ +Blocks: [0-9]+\n+" nil 40) 4389 ; '(("^Files: [0-9]+ +Blocks: [0-9]+\n+" nil 40)
4405 ; ("^Dirs: [0-9]+\n+" t 30))) 4390 ; ("^Dirs: [0-9]+\n+" t 30)))
4406 ; type-regexp type-is-dir type-col file) 4391 ; type-regexp type-is-dir type-col file)
4407 ; (goto-char (point-min)) 4392 ; (goto-char (point-min))
4408 ; (ange-ftp-save-match-data 4393 ; (save-match-data
4409 ; (while type-list 4394 ; (while type-list
4410 ; (setq type-regexp (car (car type-list)) 4395 ; (setq type-regexp (car (car type-list))
4411 ; type-is-dir (nth 1 (car type-list)) 4396 ; type-is-dir (nth 1 (car type-list))
4412 ; type-col (nth 2 (car type-list)) 4397 ; type-col (nth 2 (car type-list))
4413 ; type-list (cdr type-list)) 4398 ; type-list (cdr type-list))
4434 ;;;; ------------------------------------------------------------ 4419 ;;;; ------------------------------------------------------------
4435 4420
4436 ;; Convert NAME from UNIX-ish to VMS. If REVERSE given then convert from VMS 4421 ;; Convert NAME from UNIX-ish to VMS. If REVERSE given then convert from VMS
4437 ;; to UNIX-ish. 4422 ;; to UNIX-ish.
4438 (defun ange-ftp-fix-name-for-vms (name &optional reverse) 4423 (defun ange-ftp-fix-name-for-vms (name &optional reverse)
4439 (ange-ftp-save-match-data 4424 (save-match-data
4440 (if reverse 4425 (if reverse
4441 (if (string-match "^\\([^:]+:\\)?\\(\\[.*\\]\\)?\\([^][]*\\)$" name) 4426 (if (string-match "^\\([^:]+:\\)?\\(\\[.*\\]\\)?\\([^][]*\\)$" name)
4442 (let (drive dir file) 4427 (let (drive dir file)
4443 (if (match-beginning 1) 4428 (if (match-beginning 1)
4444 (setq drive (substring name 4429 (setq drive (substring name
4520 (defvar ange-ftp-vms-host-regexp nil) 4505 (defvar ange-ftp-vms-host-regexp nil)
4521 4506
4522 ;; Return non-nil if HOST is running VMS. 4507 ;; Return non-nil if HOST is running VMS.
4523 (defun ange-ftp-vms-host (host) 4508 (defun ange-ftp-vms-host (host)
4524 (and ange-ftp-vms-host-regexp 4509 (and ange-ftp-vms-host-regexp
4525 (ange-ftp-save-match-data 4510 (save-match-data
4526 (string-match ange-ftp-vms-host-regexp host)))) 4511 (string-match ange-ftp-vms-host-regexp host))))
4527 4512
4528 ;; Because some VMS ftp servers convert filenames to lower case 4513 ;; Because some VMS ftp servers convert filenames to lower case
4529 ;; we allow a-z in the filename regexp. I'm not too happy about this. 4514 ;; we allow a-z in the filename regexp. I'm not too happy about this.
4530 4515
4554 ;; format, and return a hashtable as the result. 4539 ;; format, and return a hashtable as the result.
4555 (defun ange-ftp-parse-vms-listing () 4540 (defun ange-ftp-parse-vms-listing ()
4556 (let ((tbl (ange-ftp-make-hashtable)) 4541 (let ((tbl (ange-ftp-make-hashtable))
4557 file) 4542 file)
4558 (goto-char (point-min)) 4543 (goto-char (point-min))
4559 (ange-ftp-save-match-data 4544 (save-match-data
4560 (while (setq file (ange-ftp-parse-vms-filename)) 4545 (while (setq file (ange-ftp-parse-vms-filename))
4561 (if (string-match "\\.\\(DIR\\|dir\\);[0-9]+" file) 4546 (if (string-match "\\.\\(DIR\\|dir\\);[0-9]+" file)
4562 ;; deal with directories 4547 ;; deal with directories
4563 (ange-ftp-put-hash-entry 4548 (ange-ftp-put-hash-entry
4564 (substring file 0 (match-beginning 0)) t tbl) 4549 (substring file 0 (match-beginning 0)) t tbl)
4588 ;; completion functions? 4573 ;; completion functions?
4589 4574
4590 (defun ange-ftp-vms-delete-file-entry (name &optional dir-p) 4575 (defun ange-ftp-vms-delete-file-entry (name &optional dir-p)
4591 (if dir-p 4576 (if dir-p
4592 (ange-ftp-internal-delete-file-entry name t) 4577 (ange-ftp-internal-delete-file-entry name t)
4593 (ange-ftp-save-match-data 4578 (save-match-data
4594 (let ((file (ange-ftp-get-file-part name))) 4579 (let ((file (ange-ftp-get-file-part name)))
4595 (if (string-match ";[0-9]+$" file) 4580 (if (string-match ";[0-9]+$" file)
4596 ;; In VMS you can't delete a file without an explicit 4581 ;; In VMS you can't delete a file without an explicit
4597 ;; version number, or wild-card (e.g. FOO;*) 4582 ;; version number, or wild-card (e.g. FOO;*)
4598 ;; For now, we give up on wildcards. 4583 ;; For now, we give up on wildcards.
4629 (let ((files (ange-ftp-get-hash-entry 4614 (let ((files (ange-ftp-get-hash-entry
4630 (file-name-directory name) 4615 (file-name-directory name)
4631 ange-ftp-files-hashtable))) 4616 ange-ftp-files-hashtable)))
4632 (if files 4617 (if files
4633 (let ((file (ange-ftp-get-file-part name))) 4618 (let ((file (ange-ftp-get-file-part name)))
4634 (ange-ftp-save-match-data 4619 (save-match-data
4635 (if (string-match ";[0-9]+$" file) 4620 (if (string-match ";[0-9]+$" file)
4636 (ange-ftp-put-hash-entry 4621 (ange-ftp-put-hash-entry
4637 (substring file 0 (match-beginning 0)) 4622 (substring file 0 (match-beginning 0))
4638 nil files) 4623 nil files)
4639 ;; Need to figure out what version of the file 4624 ;; Need to figure out what version of the file
4678 ange-ftp-vms-host-regexp) 4663 ange-ftp-vms-host-regexp)
4679 ange-ftp-host-cache nil))) 4664 ange-ftp-host-cache nil)))
4680 4665
4681 4666
4682 (defun ange-ftp-vms-file-name-as-directory (name) 4667 (defun ange-ftp-vms-file-name-as-directory (name)
4683 (ange-ftp-save-match-data 4668 (save-match-data
4684 (if (string-match "\\.\\(DIR\\|dir\\)\\(;[0-9]+\\)?$" name) 4669 (if (string-match "\\.\\(DIR\\|dir\\)\\(;[0-9]+\\)?$" name)
4685 (setq name (substring name 0 (match-beginning 0)))) 4670 (setq name (substring name 0 (match-beginning 0))))
4686 (ange-ftp-real-file-name-as-directory name))) 4671 (ange-ftp-real-file-name-as-directory name)))
4687 4672
4688 (or (assq 'vms ange-ftp-file-name-as-directory-alist) 4673 (or (assq 'vms ange-ftp-file-name-as-directory-alist)
4840 ;; (setq ange-ftp-dired-ls-trim-alist 4825 ;; (setq ange-ftp-dired-ls-trim-alist
4841 ;; (cons '(vms . ange-ftp-dired-vms-ls-trim) 4826 ;; (cons '(vms . ange-ftp-dired-vms-ls-trim)
4842 ;; ange-ftp-dired-ls-trim-alist))) 4827 ;; ange-ftp-dired-ls-trim-alist)))
4843 4828
4844 (defun ange-ftp-vms-sans-version (name) 4829 (defun ange-ftp-vms-sans-version (name)
4845 (ange-ftp-save-match-data 4830 (save-match-data
4846 (if (string-match ";[0-9]+$" name) 4831 (if (string-match ";[0-9]+$" name)
4847 (substring name 0 (match-beginning 0)) 4832 (substring name 0 (match-beginning 0))
4848 name))) 4833 name)))
4849 4834
4850 (or (assq 'vms ange-ftp-sans-version-alist) 4835 (or (assq 'vms ange-ftp-sans-version-alist)
4997 4982
4998 4983
4999 ;; Convert NAME from UNIX-ish to MTS. If REVERSE given then convert from 4984 ;; Convert NAME from UNIX-ish to MTS. If REVERSE given then convert from
5000 ;; MTS to UNIX-ish. 4985 ;; MTS to UNIX-ish.
5001 (defun ange-ftp-fix-name-for-mts (name &optional reverse) 4986 (defun ange-ftp-fix-name-for-mts (name &optional reverse)
5002 (ange-ftp-save-match-data 4987 (save-match-data
5003 (if reverse 4988 (if reverse
5004 (if (string-match "^\\([^:]+:\\)?\\(.*\\)$" name) 4989 (if (string-match "^\\([^:]+:\\)?\\(.*\\)$" name)
5005 (let (acct file) 4990 (let (acct file)
5006 (if (match-beginning 1) 4991 (if (match-beginning 1)
5007 (setq acct (substring name 0 (match-end 1)))) 4992 (setq acct (substring name 0 (match-end 1))))
5047 (defvar ange-ftp-mts-host-regexp nil) 5032 (defvar ange-ftp-mts-host-regexp nil)
5048 5033
5049 ;; Return non-nil if HOST is running MTS. 5034 ;; Return non-nil if HOST is running MTS.
5050 (defun ange-ftp-mts-host (host) 5035 (defun ange-ftp-mts-host (host)
5051 (and ange-ftp-mts-host-regexp 5036 (and ange-ftp-mts-host-regexp
5052 (ange-ftp-save-match-data 5037 (save-match-data
5053 (string-match ange-ftp-mts-host-regexp host)))) 5038 (string-match ange-ftp-mts-host-regexp host))))
5054 5039
5055 ;; Parse the current buffer which is assumed to be in mts ftp dir format. 5040 ;; Parse the current buffer which is assumed to be in mts ftp dir format.
5056 (defun ange-ftp-parse-mts-listing () 5041 (defun ange-ftp-parse-mts-listing ()
5057 (let ((tbl (ange-ftp-make-hashtable))) 5042 (let ((tbl (ange-ftp-make-hashtable)))
5058 (goto-char (point-min)) 5043 (goto-char (point-min))
5059 (ange-ftp-save-match-data 5044 (save-match-data
5060 (while (re-search-forward ange-ftp-date-regexp nil t) 5045 (while (re-search-forward ange-ftp-date-regexp nil t)
5061 (end-of-line) 5046 (end-of-line)
5062 (skip-chars-backward " ") 5047 (skip-chars-backward " ")
5063 (let ((end (point))) 5048 (let ((end (point)))
5064 (skip-chars-backward "-A-Z0-9_.!") 5049 (skip-chars-backward "-A-Z0-9_.!")
5160 ;; usually close the connection after 5 minutes of inactivity. 5145 ;; usually close the connection after 5 minutes of inactivity.
5161 5146
5162 ;; Have I got the filename character set right? 5147 ;; Have I got the filename character set right?
5163 5148
5164 (defun ange-ftp-fix-name-for-cms (name &optional reverse) 5149 (defun ange-ftp-fix-name-for-cms (name &optional reverse)
5165 (ange-ftp-save-match-data 5150 (save-match-data
5166 (if reverse 5151 (if reverse
5167 ;; Since we only convert output from a pwd in this direction, 5152 ;; Since we only convert output from a pwd in this direction,
5168 ;; we'll assume that it's a minidisk, and make it into a 5153 ;; we'll assume that it's a minidisk, and make it into a
5169 ;; directory file name. Note that the expand-dir-hashtable 5154 ;; directory file name. Note that the expand-dir-hashtable
5170 ;; stores directories without the trailing /. Is this 5155 ;; stores directories without the trailing /. Is this
5250 "Regular expression to match hosts running the CMS operating system.") 5235 "Regular expression to match hosts running the CMS operating system.")
5251 5236
5252 ;; Return non-nil if HOST is running CMS. 5237 ;; Return non-nil if HOST is running CMS.
5253 (defun ange-ftp-cms-host (host) 5238 (defun ange-ftp-cms-host (host)
5254 (and ange-ftp-cms-host-regexp 5239 (and ange-ftp-cms-host-regexp
5255 (ange-ftp-save-match-data 5240 (save-match-data
5256 (string-match ange-ftp-cms-host-regexp host)))) 5241 (string-match ange-ftp-cms-host-regexp host))))
5257 5242
5258 (defun ange-ftp-add-cms-host (host) 5243 (defun ange-ftp-add-cms-host (host)
5259 "Mark HOST as the name of a CMS host." 5244 "Mark HOST as the name of a CMS host."
5260 (interactive 5245 (interactive
5287 ; (ange-ftp-put-hash-entry "." t root-tbl) 5272 ; (ange-ftp-put-hash-entry "." t root-tbl)
5288 ; (ange-ftp-set-files root root-tbl))) 5273 ; (ange-ftp-set-files root root-tbl)))
5289 ;; Now do the usual parsing 5274 ;; Now do the usual parsing
5290 (let ((tbl (ange-ftp-make-hashtable))) 5275 (let ((tbl (ange-ftp-make-hashtable)))
5291 (goto-char (point-min)) 5276 (goto-char (point-min))
5292 (ange-ftp-save-match-data 5277 (save-match-data
5293 (while 5278 (while
5294 (re-search-forward 5279 (re-search-forward
5295 "^\\([-A-Z0-9$_]+\\) +\\([-A-Z0-9$_]+\\) +[VF] +[0-9]+ " nil t) 5280 "^\\([-A-Z0-9$_]+\\) +\\([-A-Z0-9$_]+\\) +[VF] +[0-9]+ " nil t)
5296 (ange-ftp-put-hash-entry 5281 (ange-ftp-put-hash-entry
5297 (concat (buffer-substring (match-beginning 1) 5282 (concat (buffer-substring (match-beginning 1)