Annotation of 43BSDReno/contrib/emacs-18.55/lisp/ftp.el, revision 1.1.1.1

1.1       root        1: ;; File input and output over Internet using FTP
                      2: ;; Copyright (C) 1987 Free Software Foundation, Inc.
                      3: ;; Author [email protected].
                      4: 
                      5: ;; This file is part of GNU Emacs.
                      6: 
                      7: ;; GNU Emacs is distributed in the hope that it will be useful,
                      8: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                      9: ;; accepts responsibility to anyone for the consequences of using it
                     10: ;; or for whether it serves any particular purpose or works at all,
                     11: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     12: ;; License for full details.
                     13: 
                     14: ;; Everyone is granted permission to copy, modify and redistribute
                     15: ;; GNU Emacs, but only under the conditions described in the
                     16: ;; GNU Emacs General Public License.   A copy of this license is
                     17: ;; supposed to have been given to you along with GNU Emacs so you
                     18: ;; can know your rights and responsibilities.  It should be in a
                     19: ;; file named COPYING.  Among other things, the copyright notice
                     20: ;; and this notice must be preserved on all copies.
                     21: 
                     22: 
                     23: ;; you can turn this off by doing
                     24: ;;  (setq ftp-password-alist 'compulsory-urinalysis)
                     25: (defvar ftp-password-alist () "Security sucks")
                     26: 
                     27: (defun read-ftp-user-password (host user new)
                     28:   (let (tem)
                     29:     (if (and (not new)
                     30:             (listp ftp-password-alist)
                     31:             (setq tem (cdr (assoc host ftp-password-alist)))
                     32:             (or (null user)
                     33:                 (string= user (car tem))))
                     34:        tem
                     35:       (or user
                     36:          (progn
                     37:            (setq tem (or (and (listp ftp-password-alist)
                     38:                               (car (cdr (assoc host ftp-password-alist))))
                     39:                          (user-login-name)))
                     40:            (setq user (read-string (format
                     41:                                      "User-name for %s (default \"%s\"): "
                     42:                                      host tem)))
                     43:            (if (equal user "") (setq user tem))))
                     44:       (setq tem (cons user
                     45:                      ;; If you want to use some non-echoing string-reader,
                     46:                      ;; feel free to write it yourself.  I don't care enough.
                     47:                      (read-string (format "Password for %s@%s: " user host)
                     48:                        (if (not (listp ftp-password-alist))
                     49:                            ""
                     50:                          (or (cdr (cdr (assoc host ftp-password-alist)))
                     51:                              (let ((l ftp-password-alist))
                     52:                                (catch 'foo
                     53:                                  (while l
                     54:                                    (if (string= (car (cdr (car l))) user)
                     55:                                        (throw 'foo (cdr (cdr (car l))))
                     56:                                      (setq l (cdr l))))
                     57:                                  nil))
                     58:                              "")))))
                     59:       (message "")
                     60:       (if (and (listp ftp-password-alist)
                     61:               (not (string= (cdr tem) "")))
                     62:          (setq ftp-password-alist (cons (cons host tem)
                     63:                                         ftp-password-alist)))
                     64:       tem)))
                     65: 
                     66: (defun ftp-read-file-name (prompt)
                     67:   (let ((s ""))
                     68:     (while (not (string-match "\\`[ \t]*\\([^ \t:]+\\)[ \t]*:\\(.+\\)\\'" s))
                     69:       (setq s (read-string prompt s)))
                     70:     (list (substring s (match-beginning 1) (match-end 1))
                     71:          (substring s (match-beginning 2) (match-end 2)))))
                     72: 
                     73: 
                     74: (defun ftp-find-file (host file &optional user password)
                     75:   "FTP to HOST to get FILE, logging in as USER with password PASSWORD.
                     76: Interactively, HOST and FILE are specified by reading a string with
                     77:  a colon character separating the host from the filename.
                     78: USER and PASSWORD are defaulted from the values used when
                     79:  last ftping from HOST (unless password-remembering is disabled).
                     80:  Supply a password of the symbol `t' to override this default
                     81:  (interactively, this is done by giving a prefix arg)"
                     82:   (interactive
                     83:        (append (ftp-read-file-name "FTP get host:file: ")
                     84:                (list nil (not (null current-prefix-arg)))))
                     85:   (ftp-find-file-or-directory host file t user password))
                     86: 
                     87: (defun ftp-list-directory (host file &optional user password)
                     88:   "FTP to HOST to list DIRECTORY, logging in as USER with password PASSWORD.
                     89: Interactively, HOST and FILE are specified by reading a string with
                     90:  a colon character separating the host from the filename.
                     91: USER and PASSWORD are defaulted from the values used when
                     92:  last ftping from HOST (unless password-remembering is disabled).
                     93:  Supply a password of the symbol `t' to override this default
                     94:  (interactively, this is done by giving a prefix arg)"
                     95:   (interactive
                     96:        (append (ftp-read-file-name "FTP get host:directory: ")
                     97:                (list nil (not (null current-prefix-arg)))))
                     98:   (ftp-find-file-or-directory host file nil user password))
                     99: 
                    100: (defun ftp-find-file-or-directory (host file filep &optional user password)
                    101:   "FTP to HOST to get FILE.  Third arg is t for file, nil for directory.
                    102: Log in as USER with PASSWORD.  If USER is nil or PASSWORD is nil or t,
                    103: we prompt for the user name and password."
                    104:   (or (and user password (not (eq password t)))
                    105:       (progn (setq user (read-ftp-user-password host user (eq password t))
                    106:                   password (cdr user)
                    107:                   user (car user))))
                    108:   (let ((buffer (get-buffer-create (format "*ftp%s %s:%s*"
                    109:                                           (if filep "" "-directory")
                    110:                                           host file))))
                    111:     (set-buffer buffer)
                    112:     (let ((process (ftp-setup-buffer host file))
                    113:          (case-fold-search nil))
                    114:       (let ((win nil))
                    115:        (unwind-protect
                    116:            (if (setq win (ftp-login process host user password))
                    117:                (message "Logged in")
                    118:              (error "Ftp login lost"))
                    119:          (or win (delete-process process))))
                    120:       (message "Opening %s %s:%s..." (if filep "file" "directory")
                    121:               host file)
                    122:       (if (ftp-command process
                    123:                       (format "%s \"%s\" -\nquit\n" (if filep "get" "dir")
                    124:                               file)
                    125:                       "\\(150\\|125\\).*\n"
                    126:                       "200.*\n")
                    127:          (progn (forward-line 1)
                    128:                 (let ((buffer-read-only nil))
                    129:                   (delete-region (point-min) (point)))
                    130:                 (message "Retrieving %s:%s in background.  Bye!" host file)
                    131:                 (set-process-sentinel process
                    132:                                       'ftp-asynchronous-input-sentinel)
                    133:                 process)
                    134:        (switch-to-buffer buffer)
                    135:        (let ((buffer-read-only nil))
                    136:          (insert-before-markers "<<<Ftp lost>>>"))
                    137:        (delete-process process)
                    138:        (error "Ftp %s:%s lost" host file)))))
                    139: 
                    140: 
                    141: (defun ftp-write-file (host file &optional user password)
                    142:   "FTP to HOST to write FILE, logging in as USER with password PASSWORD.
                    143: Interactively, HOST and FILE are specified by reading a string with colon
                    144: separating the host from the filename.
                    145: USER and PASSWORD are defaulted from the values used when
                    146:  last ftping from HOST (unless password-remembering is disabled).
                    147:  Supply a password of the symbol `t' to override this default
                    148:  (interactively, this is done by giving a prefix arg)"
                    149:   (interactive
                    150:     (append (ftp-read-file-name "FTP write host:file: ")
                    151:            (list nil (not (null current-prefix-arg)))))
                    152:   (or (and user password (not (eq password t)))
                    153:       (progn (setq user (read-ftp-user-password host user (eq password t))
                    154:                   password (cdr user)
                    155:                   user (car user))))
                    156:   (let ((buffer (get-buffer-create (format "*ftp %s:%s*" host file)))
                    157:        (tmp (make-temp-name "/tmp/emacsftp")))
                    158:     (write-region (point-min) (point-max) tmp)
                    159:     (set-buffer buffer)
                    160:     (make-local-variable 'ftp-temp-file-name)
                    161:     (setq ftp-temp-file-name tmp)
                    162:     (let ((process (ftp-setup-buffer host file))
                    163:          (case-fold-search nil))
                    164:       (let ((win nil))
                    165:        (unwind-protect
                    166:            (if (setq win (ftp-login process host user password))
                    167:                (message "Logged in")
                    168:                (error "Ftp login lost"))
                    169:          (or win (delete-process process))))
                    170:       (message "Opening file %s:%s..." host file)
                    171:       (if (ftp-command process
                    172:                       (format "send \"%s\" \"%s\"\nquit\n" tmp file)
                    173:                       "150.*\n"
                    174:                       "200.*\n")
                    175:          (progn (forward-line 1)
                    176:                 (let ((buffer-read-only nil))
                    177:                   (delete-region (point-min) (point)))
                    178:                 (message "Saving %s:%s in background.  Bye!" host file)
                    179:                 (set-process-sentinel process
                    180:                                       'ftp-asynchronous-output-sentinel)
                    181:                 process)
                    182:        (switch-to-buffer buffer)
                    183:        (let ((buffer-read-only nil))
                    184:          (insert-before-markers "<<<Ftp lost>>>"))
                    185:        (delete-process process)
                    186:        (error "Ftp write %s:%s lost" host file)))))
                    187: 
                    188: 
                    189: (defun ftp-setup-buffer (host file)
                    190:   (fundamental-mode)
                    191:   (and (get-buffer-process (current-buffer))
                    192:        (progn (discard-input)
                    193:              (if (y-or-n-p (format "Kill process \"%s\" in %s? "
                    194:                                    (process-name (get-buffer-process
                    195:                                                    (current-buffer)))
                    196:                                    (buffer-name (current-buffer))))
                    197:                  (while (get-buffer-process (current-buffer))
                    198:                    (kill-process (get-buffer-process (current-buffer))))
                    199:                (error "Foo"))))
                    200:   ;(buffer-flush-undo (current-buffer))
                    201:   (setq buffer-read-only nil)
                    202:   (erase-buffer)
                    203:   (make-local-variable 'ftp-host)
                    204:   (setq ftp-host host)
                    205:   (make-local-variable 'ftp-file)
                    206:   (setq ftp-file file)
                    207:   (setq buffer-read-only t)
                    208:   (start-process "ftp" (current-buffer) "ftp" "-i" "-n" "-g"))
                    209: 
                    210: 
                    211: (defun ftp-login (process host user password)
                    212:   (message "FTP logging in as %s@%s..." user host)
                    213:   (if (ftp-command process
                    214:                   (format "open %s\nuser %s %s\n" host user password)
                    215:                   "230.*\n"
                    216:                   "\\(Connected to \\|220\\|331\\).*\n")
                    217:       t
                    218:     (switch-to-buffer (process-buffer process))
                    219:     (delete-process process)
                    220:     (if (listp ftp-password-alist)
                    221:        (setq ftp-password-alist (delq (assoc host ftp-password-alist)
                    222:                                       ftp-password-alist)))
                    223:     nil))
                    224: 
                    225: (defun ftp-command (process command win ignore)
                    226:   (process-send-string process command)
                    227:   (let ((p 1))
                    228:     (while (numberp p)
                    229:       (cond ;((not (bolp)))
                    230:            ((looking-at win)
                    231:             (goto-char (point-max))
                    232:             (setq p t))
                    233:            ((looking-at "^ftp> \\|^\n")
                    234:             (goto-char (match-end 0)))
                    235:            ((looking-at ignore)
                    236:             (forward-line 1))
                    237:            ((not (search-forward "\n" nil t))
                    238:             ;; the way asynchronous process-output fucks with (point)
                    239:             ;;  is really really disgusting.
                    240:             (setq p (point))
                    241:             (condition-case ()
                    242:                 (accept-process-output process)
                    243:               (error nil))
                    244:             (goto-char p))
                    245:            (t
                    246:             (setq p nil))))
                    247:     p))
                    248: 
                    249: 
                    250: (defun ftp-asynchronous-input-sentinel (process msg)
                    251:   (ftp-sentinel process msg t t))
                    252: (defun ftp-synchronous-input-sentinel (process msg)
                    253:   (ftp-sentinel process msg nil t))
                    254: (defun ftp-asynchronous-output-sentinel (process msg)
                    255:   (ftp-sentinel process msg t nil))
                    256: (defun ftp-synchronous-output-sentinel (process msg)
                    257:   (ftp-sentinel process msg nil nil))
                    258: 
                    259: (defun ftp-sentinel (process msg asynchronous input)
                    260:   (cond ((null (buffer-name (process-buffer process)))
                    261:         ;; deleted buffer
                    262:         (set-process-buffer process nil))
                    263:        ((and (eq (process-status process) 'exit)
                    264:              (= (process-exit-status process) 0))
                    265:         (save-excursion
                    266:           (set-buffer (process-buffer process))
                    267:           (let (msg
                    268:                 (r (if input "[0-9]+ bytes received in [0-9]+\\.[0-9]+ seconds.*$" "[0-9]+ bytes sent in [0-9]+\\.[0-9]+ seconds.*$"))
                    269:                 (buffer-read-only nil))
                    270:             (goto-char (point-max))
                    271:             (search-backward "226 ")
                    272:             (if (looking-at r)
                    273:                 (search-backward "226 "))
                    274:             (let ((p (point)))
                    275:               (setq msg (concat (format "ftp %s %s:%s done"
                    276:                                         (if input "read" "write")
                    277:                                         ftp-host ftp-file)
                    278:                                 (if (re-search-forward r nil t)
                    279:                                     (concat ": " (buffer-substring
                    280:                                                    (match-beginning 0)
                    281:                                                    (match-end 0)))
                    282:                                     "")))
                    283:               (delete-region p (point-max))
                    284:               (save-excursion
                    285:                 (set-buffer (get-buffer-create "*ftp log*"))
                    286:                 (let ((buffer-read-only nil))
                    287:                   (insert msg ?\n)))
                    288:               (set-buffer-modified-p nil))
                    289:             (if (not input)
                    290:                 (progn
                    291:                   (condition-case ()
                    292:                       (and (boundp 'ftp-temp-file-name)
                    293:                            ftp-temp-file-name
                    294:                            (delete-file ftp-temp-file-name))
                    295:                     (error nil))
                    296:                   (kill-buffer (current-buffer)))
                    297:               ;; You don't want to look at this.
                    298:               (let ((kludge (generate-new-buffer (format "%s:%s (ftp)"
                    299:                                                          ftp-host ftp-file))))
                    300:                 (setq kludge (prog1 (buffer-name kludge) (kill-buffer kludge)))
                    301:                 (rename-buffer kludge)
                    302:                 ;; ok, you can look again now.
                    303:                 (ftp-setup-write-file-hooks)))
                    304:             (if (and asynchronous
                    305:                      ;(waiting-for-user-input-p)
                    306:                      )
                    307:                 (progn (message "%s" msg)
                    308:                        (sleep-for 2))))))
                    309:        ((memq (process-status process) '(exit signal))
                    310:         (save-excursion
                    311:           (set-buffer (process-buffer process))
                    312:           (setq msg (format "Ftp died (buffer %s): %s"
                    313:                             (buffer-name (current-buffer))
                    314:                             msg))
                    315:           (let ((buffer-read-only nil))
                    316:             (goto-char (point-max))
                    317:             (insert ?\n ?\n msg))
                    318:           (delete-process proc)
                    319:           (set-buffer (get-buffer-create "*ftp log*"))
                    320:           (let ((buffer-read-only nil))
                    321:             (goto-char (point-max))
                    322:             (insert msg))
                    323:           (if (waiting-for-user-input-p)
                    324:               (error "%s" msg))))))
                    325: 
                    326: (defun ftp-setup-write-file-hooks ()
                    327:   (let ((hooks write-file-hooks))
                    328:     (make-local-variable 'write-file-hooks)
                    329:     (setq write-file-hooks (append write-file-hooks
                    330:                                   '(ftp-write-file-hook))))
                    331:   (make-local-variable 'revert-buffer-function)
                    332:   (setq revert-buffer-function 'ftp-revert-buffer)
                    333:   (setq default-directory "/tmp/")
                    334:   (setq buffer-file-name (concat default-directory
                    335:                                 (make-temp-name
                    336:                                  (buffer-name (current-buffer)))))
                    337:   (setq buffer-read-only nil))
                    338: 
                    339: (defun ftp-write-file-hook ()
                    340:   (let ((process (ftp-write-file ftp-host ftp-file)))
                    341:     (set-process-sentinel process 'ftp-synchronous-output-sentinel)
                    342:     (message "FTP writing %s:%s..." ftp-host ftp-file)
                    343:     (while (eq (process-status process) 'run)
                    344:       (condition-case ()
                    345:          (accept-process-output process)
                    346:        (error nil)))
                    347:     (and (eq (process-status process) 'exit)
                    348:         (= (process-exit-status process) 0)
                    349:         (set-buffer-modified-p nil)))
                    350:   (message "Written")
                    351:   t)
                    352: 
                    353: (defun ftp-revert-buffer (&rest ignore)
                    354:   (let ((process (ftp-find-file ftp-host ftp-file)))
                    355:     (set-process-sentinel process 'ftp-synchronous-input-sentinel)
                    356:     (message "FTP reverting %s:%s" ftp-host ftp-file)
                    357:     (while (eq (process-status process) 'run)
                    358:       (condition-case ()
                    359:          (accept-process-output process)
                    360:        (error nil)))
                    361:     (and (eq (process-status process) 'exit)
                    362:         (= (process-exit-status process) 0)
                    363:         (set-buffer-modified-p nil))
                    364:     (message "Reverted")))

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.