;;; -*- Mode:Lisp; Readtable:ZL; Package:USER; Base:10; Patch-File:T -*- ;;; Patch file for System version 124.12 ;;; Reason: ;;; Make use of new TCP whostate feature in User FTP and FTP-ACCESS. ;;; Written 27-May-88 18:47:19 by pld (Peter L. DeWolf) at site Gigamos Cambridge ;;; while running on Cthulhu from band 2 ;;; with Experimental System 124.10, Experimental Local-File 74.0, Experimental File-Server 23.0, Experimental Unix-Interface 12.0, Experimental ZMail 72.0, Experimental Tape 23.0, Experimental Lambda-Diag 16.0, microcode 1756, SDU Boot Tape 3.14, SDU ROM 8. ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:18 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :open) (file pathname &key &optional (direction :input) (characters t) (byte-size :default) (error t) if-exists ; if-does-not-exist raw-directory-list probe-directory-list &allow-other-keys &aux probe-stream) (cond ((memq direction '(nil :probe)) (make-instance 'ftp-probe-stream :truename nil :pathname pathname :host host :raw-data (and (ftp-directory-line-parserp host t) (with-output-to-string (s) (with-open-file (d file :raw-directory-list t :probe-directory-list t :error error) (when (streamp d) (stream-copy-until-eof d s))))))) ('else (when (and (memq direction *ftp-probe-before-open-directions*) (not raw-directory-list) (or (eq *ftp-probe-before-open-p* t) (memq (send host :system-type) *ftp-probe-before-open-p*) (get host :ftp-probe-before-open-p))) (setq probe-stream (open file :direction nil :error error)) (when (and (eq direction :output) (memq (send file :version) '(nil :newest))) (cond ((not (send probe-stream :truename)) (send probe-stream :set-truename (send file :new-version 1))) ((numberp (send (send probe-stream :truename) :version)) ;; kludge-a-rama. The *FTP-PROBE-BEFORE-OPEN-P* is useful ;; if the host cant take so many simultaneous servers ;; as would be created if we probe *after* the opening of ;; the file data connection. The most sensible solution to ;; all of this is to use another file protocol. (send probe-stream :set-truename (send (send probe-stream :truename) :new-version (1+ (send (send probe-stream :truename) :version)))))) (when (not (plist probe-stream)) (setf (plist probe-stream) `(:creation-date ,(time:get-universal-time)))))) (handling-file-errors (error) (allocating-host-unit (unit) (let ((command nil) (buffers nil) (optimistic nil) (tcp:*tcp-stream-whostate* (cond (probe-directory-list "Probe") (raw-directory-list "Directory") (t "Open")))) (when probe-directory-list (setq buffers 1) (setq optimistic t)) (cond (raw-directory-list (setq command "LIST ~A")) ((eq direction :output) (setq command (caseq if-exists (:append "APPE ~A") (t "STOR ~A")))) ((eq direction :input) (setq command "RETR ~A"))) (and (eq byte-size :DEFAULT) (eq characters t) (setq byte-size 8)) (cond ((and (eq characters :DEFAULT) (eq byte-size :DEFAULT)) ;; almost no way of getting this information ;; unix uses magic numbers, on VMS maybe character if ;; record format variable length CR. ;; for now kludge it so that at least load works on ;; qfasl files. (multiple-value (characters byte-size) (kludge-ftp-characterp file pathname))) ((eq byte-size :default) (setq byte-size 8))) (cond ((not characters) (send unit :setbinary byte-size)) ((eq (send host :system-type) :lispm) (send unit :setbinary 8)) ('else ;; in fact if the host is a unix host then ;; binary mode with our own easier-to-do translation ;; would be better than forcing kludgy ascii ;; translation to happen on both hosts. (send unit :setascii))) (ftp-access-operation file unit :initconn direction buffers optimistic) (multiple-value-bind (c code) (send unit :command command (fixup-ftp-string-for-host (send file :string-for-host) file)) (cond ((= c (tcp-application:sym ftp:PRELIM)) (ftp-access-operation file unit :dataconn file pathname direction byte-size raw-directory-list probe-stream)) ((and (= code 530.) (progn (send unit :login unit t host) ;; some hosts forget about the PORT ;; command after a USER command is ;; given, so give it again. (ftp-access-operation file unit :initconn direction buffers optimistic) (= (tcp-application:sym ftp:PRELIM) (send unit :command command (send file :string-for-host))))) (ftp-access-operation file unit :dataconn file pathname direction byte-size raw-directory-list probe-stream)) ('else (send unit :close-dataconn nil) (send unit :ftp-error "Access error" file)))))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:20 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :rename) (file new-pathname error-p) (command-using-unit (unit error-p) (let ((tcp:*tcp-stream-whostate* "Rename")) (ftp-access-operation file unit :renamefile (send file :string-for-host) (send new-pathname :string-for-host)))) ;; should be real truename here... new-pathname) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:21 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :delete) (file error-p) (command-using-unit (unit error-p) (let ((tcp:*tcp-stream-whostate* "Delete")) (ftp-access-operation file unit :delete (send file :string-for-host)))) ;; should be real truename here file) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:23 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :change-properties) (file error-p &rest properties) (if (change-properties-is-undelete properties) (command-using-unit (unit error-p) (let ((tcp:*tcp-stream-whostate* "Undelete")) (ftp-access-operation file unit :undelete (send file :string-for-host)))) (handling-file-errors (error-p) (ftp-lose file :change-properties)))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:25 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :expunge) (pathname error) (command-using-unit (unit error) (let ((tcp:*tcp-stream-whostate* "Expunge")) (ftp-access-operation pathname unit :expunge (send pathname :string-for-host))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:29 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :create-directory) (file error) (command-using-unit (unit error) (let ((tcp:*tcp-stream-whostate* "Create Directory")) (ftp-access-operation file unit :makedir (send file :string-for-host))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:52 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :multiple-file-plists) (files options) (do* ((list files (cdr list)) (file (car list) (car list)) (error-p (not (memq :noerror options))) (result nil)) ((null list) (nreverse result)) (let* ((pathname (normalize-ftp-directory-list-pathname file host)) (tcp:*tcp-stream-whostate* "File Properties") (plist (with-open-file (s pathname :raw-directory-list t :error error-p) (if (errorp s) s (ftp-access-canonicalize-directory-list (cons `(nil :pathname ,pathname) (do ((line) (eofp) (list)) (eofp (nreverse list)) (multiple-value (line eofp) (send s :line-in)) (when line (let* ((plist (ftp-parse-directory-list-line line host pathname))) (when (and plist (car plist)) (push plist list))))))))))) (if (errorp plist) (push plist result) (dolist (elt plist) (push elt result)))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:57 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-file-stream-mixin :after :close) (&optional abortp) (unless (eq status :closed) (let ((tcp:*tcp-stream-whostate* "Close")) (send actual :close abortp)) (send host-unit :remove-file-stream self) (send host-unit :close-dataconn) (send host-unit :free) (setq status :closed))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:48:59 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-input-raw-stream :next-input-buffer) (&optional no-hang-p) (let ((tcp:*tcp-stream-whostate* "Net File Input")) (send actual :next-input-buffer no-hang-p))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:49:00 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-input-binary-stream :next-input-buffer) (&optional no-hang-p) ;; maybe change this in the future to call :next-input-buffer ;; copy the contents, then call :discard-input-buffer on actual. (let ((tcp:*tcp-stream-whostate* "Net File Input")) (ecase byte-size (8 (send actual :next-input-buffer no-hang-p)) (16 (multiple-value-bind (array start end) (send actual :next-input-buffer no-hang-p) (when array (when (oddp (- end start)) (error "16 bit stream, but odd byte count in input buffer")) (let ((length (ceiling (- end start) 2))) (values (make-array length :element-type '(unsigned-byte 16) :displaced-to array :displaced-index-offset start) 0 length)))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:49:02 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-input-character-stream :next-input-buffer) (&OPTIONAL NO-HANG-P) (multiple-value-bind (ARRAY START END) (let ((tcp:*tcp-stream-whostate* "Net File Input")) (send actual :next-input-buffer no-hang-p)) (cond ((null array) nil) ('else ;; we know that the array-cache makes things faster ;; when we are concentrating on a single array at a time ;; so we preallocate a big enough buffer and do an in-place ;; translation. (let* ((size (- end start)) (string (allocate-resource 'simple-string-buffer size))) (copy-array-portion array start end string 0 size) ;; might as well free up the dma resource now in the ;; actual stream. (send actual :discard-input-buffer array) ;; the VAX instruction MOVTUC would be useful here. ;; (move translated until character) (do ((j 0 (1+ j)) (i 0) (c)) ((= j size) (values string 0 i)) (cond ((= 13 (setq c (aref string j)))) ((= c 10) (aset #\return string i) (incf i)) ((or (= c 8) (= c 9) (= c 12) (= c 13)) (aset (+ c #o200) string i) (incf i)) ('else (aset c string i) (incf i))))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:49:04 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-output-raw-stream :new-output-buffer) () (declare (values array start end)) (let ((tcp:*tcp-stream-whostate* "Net File Output")) (send actual :new-output-buffer))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:49:05 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-output-binary-stream :new-output-buffer) () (declare (values array start end)) (let ((tcp:*tcp-stream-whostate* "Net File Output")) (ecase byte-size (8 (send actual :new-output-buffer)) (16 (let* ((array (send actual :new-output-buffer)) (length (floor (array-length array) 2))) (values (make-array length :element-type '(unsigned-byte 16) :displaced-to array) 0 length)))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:49:06 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-output-character-stream :send-output-buffer) (buff limit) (let ((offset 0) (actual-stream actual) (tcp:*tcp-stream-whostate* "Net File Output")) (labels ((outbuff (end) (do ((j offset (1+ j)) (s buff) (c)) ((= j end) (send actual-stream :string-out s offset end)) (if (> (setq c (aref s j)) #o200) (aset (- c #o200) s j)))) (outc (c) (send actual-stream :tyo c))) (do ((n)) ((null (setq n (string-search-char #\return buff offset limit))) (outbuff limit)) (outbuff n) (outc (tcp-application:sym ftp:CR)) (outc (tcp-application:sym ftp:LF)) (setq offset (1+ n))))) (deallocate-resource 'simple-string-buffer BUFF)) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP-ACCESS.LISP#45 at 27-May-88 18:50:17 #10R FILE-SYSTEM#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "FILE-SYSTEM"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP-ACCESS  " (defmethod (ftp-access :directory-list) (given-pathname options) (let ((pathname (normalize-ftp-directory-list-pathname given-pathname host)) (no-error-p nil) ;T to not generate errors (deleted-p nil) ;T to include deleted files (sorted-p nil) ;T to sort generated list (tcp:*tcp-stream-whostate* "Directory List")) (do ((l options (cdr l))) ((null l)) (case (car l) (:noerror (setq no-error-p t)) (:sorted (setq sorted-p t)) (:deleted (setq deleted-p t)) (otherwise (ferror nil "~S is not a known DIRECTORY option" (car l))))) (with-open-file (s pathname :raw-directory-list t :error (not no-error-p)) (if (errorp s) s (let ((dir-list (ftp-access-canonicalize-directory-list (cons `(nil :pathname ,pathname) (do ((line) (eofp) (list)) (eofp (nreverse list)) (multiple-value (line eofp) (send s :line-in)) (when line (let ((plist (ftp-parse-directory-list-line line host pathname))) (when plist (let ((truename (getf (cdr plist) :truename)) (deleted (getf (cdr plist) :deleted))) (when (or (not deleted) deleted-p) (when truename (setf (car plist) truename)) (push plist list))))))))))) (when sorted-p (let ((null-elem (assq nil dir-list))) (and null-elem (setq dir-list (delq null-elem dir-list))) (setq dir-list (sortcar dir-list #'pathname-lessp)) (and null-elem (push null-elem dir-list)))) dir-list))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:29 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun hookup (host port &optional (keyword "FTP Control Connection")) (setq *remote-hostname* (if (numberp host) (format nil "~X" host) (string host))) (let ((tcp:*tcp-stream-whostate* "Open Control Connection")) (setq *control* (open (string-append "TCP-HOST:" host "." port) :keyword keyword)) (setq *connected* t) (if *verbose* (format t "~&Connected to ~S~%" host)) (getreply nil))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:32 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun ftp-getreply (expecteof) (let ((tcp:*tcp-stream-whostate* "Reply")) (getreply expecteof))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:44 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun close-control-connection () (when *control* (let ((tcp:*tcp-stream-whostate* "Close Control Connection")) (unwind-protect (close *control*) (setq *control* nil))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:45 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun close-data-connection () (when *data* (let ((tcp:*tcp-stream-whostate* "Close Data Connection")) (unwind-protect (close *data*) (setq *data* nil))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:46 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun lostpeer () (when *connected* (setq *type* 'ascii) (setq *struct* 'file) (setq *form* 'non-print) (setq *mode* 'stream) (setq *bytesize* 8.) (close-control-connection) (close-data-connection) (setq *connected* nil) (let ((s (last-reply)) (bogo "599 server randomly died, lost connection, did not print this")) (when s (setf (fill-pointer s) (length bogo)) (copy-array-contents bogo s))) (throw 'lostpeer (values (sym error) 599)))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:50 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun ftp-command (fmt &rest args) "Send an FTP command to the control connection. For use within (ftp:ftp)" (let ((tcp:*tcp-stream-whostate* "Command")) (command-1 (apply #'format nil fmt args)))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:57 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun recvrequest (cmd local remote) "local is a string describing the local place to put the requested data. remote is a remote description." (prog (start stop bytes din fout) (setq bytes 0) (unwind-protect (progn (when (initconn :input) (go done)) (let ((x (if remote (ftp-command "~A ~A" cmd remote) (ftp-command cmd)))) (unless (= x (sym prelim)) (go done))) (setq din (dataconn :input)) (if (not din) (go bad)) (setq fout (cond ((null local) *standard-output*) ((streamp local) local) ((stringp local) (if (eq *type* '16bit) (make-8b-to-16b-translating-output-stream (open local :direction :output :byte-size 16 :characters nil)) (open local :direction :output))))) (setq start (time:time)) (let ((tcp:*tcp-stream-whostate* "Net File Input")) (global:stream-copy-until-eof din fout)) (setq stop (time:time)) (setq bytes (send din :bytes))) (unless stop (setq stop (time:time)) (if din (setq bytes (send din :bytes)))) (close-data-connection) (when fout (unless (eq fout *standard-output*) (close fout)))) bad (ftp-getreply nil) done (if (and (> bytes 0) *verbose*) (ptransfer "received" bytes start stop)) (return nil))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:30:58 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun sendrequest (cmd local remote) (prog (start stop bytes dout) (setq bytes 0) (unwind-protect (progn (if (initconn :output) (go bad)) (unless (= (ftp-command "~A ~A" cmd remote) (sym prelim)) (go done)) (setq dout (dataconn :output)) (if (null dout) (go bad)) (when (eq *type* '16bit) (setq dout (make-16b-to-8b-translating-output-stream dout))) (with-open-stream (fin (if (eq *type* '16bit) (open local :byte-size 16 :characters nil) (open local))) (setq start (time:time)) (let ((tcp:*tcp-stream-whostate* "Net File Output")) (global:stream-copy-until-eof fin dout)) (send dout :force-output) (setq stop (time:time)) (setq bytes (send dout :bytes)))) (unless stop (setq stop (time:time)) (if dout (setq bytes (send dout :bytes)))) (close-data-connection)) (close dout) bad (ftp-getreply nil) done (if (and (> bytes 0) *verbose*) (ptransfer "sent" bytes start stop)) (return nil))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:31:03 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun initconn (direction &optional buffers optimistic) (unless (numberp buffers) (setq buffers *ftp-buffers*)) (close-data-connection) (let ((addr nil) (port nil) (result nil) (tcp:*tcp-stream-whostate* "Open Data Connection")) (setq *data* (tcpa:open-easy-tcp-stream (send *control* :remote-address) (sym-value 'tcpa:ipport-ftp-data) (unless *sendport* (send *control* :local-port)) :direction direction :input-buffers (ecase direction (:input buffers) (:output 0)) :output-buffers (ecase direction (:output buffers) (:input 0)) :optimistic optimistic :keyword "FTP Data Connection" :connect nil)) (when *sendport* (setq addr (send *data* :local-address)) (setq port (send *data* :local-port)) (setq result (command "PORT ~D,~D,~D,~D,~D,~D" (ldb (byte 8 24) addr) (ldb (byte 8 16) addr) (ldb (byte 8 8) addr) (ldb (byte 8 0) addr) (ldb (byte 8 8) port) (ldb (byte 8 0) port))) (if (= result (sym error)) (let ((*sendport* nil)) (initconn direction)) (not (= result (sym complete))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:31:06 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun close-dataconn (&optional (getreply t)) (close-data-connection) (and getreply *connected* (ftp-getreply nil))) #| Character translation hair. The operations provided by the stream-default-handler are: :tyipeek :listen :any-tyi :tyi-no-hang :any-tyi-no-hang :read-char :any-read-char :read-char-no-hang :any-read-char-no-hang :read-byte :unread-char :write-char :write-byte :clear-output :clear-input :force-output :finish :close :eof :fresh-line :string-out :line-out :line-in :string-in :string-line-in :operation-handled-p :characters :element-type :direction :send-if-handles Although we are only concerned with what stream-copy-until-eof will send, which is :read-input-buffer on :input, and :string-out on :output. |# )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:31:09 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defun try-login (u p a) (let ((logged-in nil) (tcp:*tcp-stream-whostate* "Login")) (multiple-value-setq (u logged-in) (send-user-info "(username) " "USER" u)) (cond ((null u) (return-from try-login)) (logged-in (return-from try-login (values u p a)))) (multiple-value-setq (p logged-in) (send-user-info "(password) " "PASS" p nil)) (cond ((null p) (return-from try-login)) (logged-in (return-from try-login (values u p a)))) (multiple-value-setq (a logged-in) (send-user-info "(account) " "ACCT" a)) (cond ((null a) (return-from try-login)) (logged-in (return-from try-login (values u p a)))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.USER; FTP.LISP#47 at 31-May-88 13:31:12 #10R FTP#: #!:CL (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "FTP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; USER; FTP  " (defcmd cmd-close () t "terminate ftp session" (when *connected* (setq *type* 'ascii) (setq *struct* 'file) (setq *form* 'non-print) (setq *mode* 'stream) (setq *bytesize* 8.) (command "QUIT") (close-control-connection) (close-data-connection) (setq *connected* nil))) ))