;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*- ;;; Patch file for System version 123.175 ;;; Reason: ;;; Our Supdup Server and Telnet Servers now treat interrupt characters ;;; (Abort, M-Abort, C-Abort, C-M-Abort, Break, M-Break, C-Break, C-M-Break) ;;; the same way the keyboard process does. ;;; Written 5-Jan-88 12:17:35 by pld at site Gigamos Cambridge ;;; while running on Jack Flanders from band 2 ;;; with Experimental System 123.174, Experimental Local-File 73.3, Experimental FILE-Server 22.1, Experimental Unix-Interface 11.0, Experimental Tape 18.0, Experimental KERMIT 34.3, Experimental ZMail 71.0, Experimental Lambda-Diag 15.0, microcode 1754, SDU Boot Tape 3.12, SDU ROM 8. ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; GENERIC-SERVER.LISP#25 at 5-Jan-88 12:17:56 #10R TCP-APPLICATION#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP-APPLICATION"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; GENERIC-SERVER  " (defun *subprocess (function &optional &key closure-variables restart-after-reset &allow-other-keys) "Does a PROCESS-RUN-FUNCTION but keeps track of the process with the NETWORK-SERVER so that it will get killed at the right time, etc." (process-run-function (list :name (format nil "Sub#~D: ~A" (1+ (length (network-server-subprocesses *server*))) (network-server-process-name *server*)) :restart-after-reset restart-after-reset) (global:closure (append closure-variables *subprocess-closure-variables*) #'tcp-generic-server-subprocess-function) function)) )) ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; GENERIC-SERVER.LISP#25 at 5-Jan-88 12:18:02 #10R TCP-APPLICATION#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP-APPLICATION"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; GENERIC-SERVER  " (defun tcp-generic-server-subprocess-function (f) (unwind-protect (progn (with-network-server-lock (*server*) (push sys:current-process (network-server-subprocesses *server*))) (global:condition-case-if (not *tcp-generic-server-toplevel-debug*) () (funcall f) (tcp::tcp-error (tcp-generic-server-subprocess-error)) (tcp::exos-error (tcp-generic-server-subprocess-error)))) (with-network-server-lock (*server*) (setf (network-server-subprocesses *server*) (remove sys:current-process (network-server-subprocesses *server*)))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET-UTILITIES.LISP#14 at 5-Jan-88 12:22:55 #10R NETWORK-USER#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "NETWORK-USER"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET-UTILITIES  " (defun handle-abort (&rest ignore) (setq inhibit-scheduling-flag nil) ;It was T in the IO-BUFFER-OUTPUT-FUNCTION (send *terminal-io* :clear-rest-of-line) (send *terminal-io* :string-out "[Abort]") (signal-condition eh:abort-object)) (defun handle-abort-all (&rest ignore) (setq inhibit-scheduling-flag nil) ;It was T in the IO-BUFFER-OUTPUT-FUNCTION (send *terminal-io* :clear-rest-of-line) (send *terminal-io* :string-out "[Abort all]") (send current-process :reset :always)) (defun handle-break (&optional char &rest ignore) (setq inhibit-scheduling-flag nil) ;It was T in the IO-BUFFER-OUTPUT-FUNCTION (break "BREAK") (values char t)) (defun handle-error-break (&optional char &rest ignore) (declare (dbg:error-reporter)) (setq inhibit-scheduling-flag nil) ;It was T in the IO-BUFFER-OUTPUT-FUNCTION (multiple-value-bind (buffer position) (send *standard-input* :send-if-handles :save-rubout-handler-buffer) (unwind-protect (signal-condition (make-condition 'break :format-string "Keyboard break.") '(:no-action) t) (if buffer (send *standard-input* :restore-rubout-handler-buffer buffer position)))) (values char t)) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#110 at 5-Jan-88 12:23:14 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (defun supdup-server-function (remote-stream) (let* ((safe-input-stream (make-eof-throwing-stream remote-stream)) (si:user-id nil) (network-user:*term* nil) (cvars '(network-user:*term* si:user-id))) (global:using-resource (terminal supdup-server remote-stream safe-input-stream) (catch 'eof (send terminal :supdup-greeting "Welcome to ~A SUPDUP Server." (send si:local-host :name)) (send terminal :initialize-terminal) (network-user-login terminal) (send terminal :terpri) (global:print-herald terminal) (format terminal "~%Type (help) for keyboard help~%~%") (send terminal :force-output) (subprocess :closure-variables cvars (loop (send terminal :force-output) (sys:process-sleep *telnet-asynchronous-force-output-period*))) (multiple-value-bind (buffer-stream buffer) (make-simple-io-buffer-stream) (send terminal :set-input-stream buffer-stream) (send terminal :set-more-p t) (send sys:current-process :set-priority 1) (catch 'telnet-server-logout (supdup-server-input (subprocess :closure-variables cvars :restart-after-reset t (global:progw (append *network-user-process-bindings* si:*break-bindings*) (catch 'telnet-server-logout (si:lisp-top-level1 terminal)) (send (network-server-process *server*) :interrupt #'network-user:logout))) buffer remote-stream terminal))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#110 at 5-Jan-88 12:23:22 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (defun supdup-server-input (user-process buffer remote-stream terminal) (declare (ignore terminal)) (do (c bits code) ((null (setq c (send remote-stream :tyi)))) (cond ((= c #o34) (setq bits (send remote-stream :tyi)) (cond ((null bits) (simple-io-buffer-put buffer nil)) ((= bits #o34) (simple-io-buffer-put buffer c)) (t (setq bits (logand bits #o37)) (setq code (send remote-stream :tyi)) (cond ((null code) (simple-io-buffer-put buffer nil)) (t (setq c (dpb (logand bits #o20) (byte 5 7) (logand #o177 code))) (setq c (make-char (cond ((cadr (assoc c *ascii-supdup-translations* :test #'eq))) ((= bits #o20) code) (t (global:char-flipcase code))) (logand bits #o17))) (case c (#\Control-Abort (send user-process :interrupt 'network-user:handle-abort)) (#\Control-Meta-Abort (send user-process :interrupt 'network-user:handle-abort-all)) (#\Control-Break (send user-process :interrupt 'network-user:handle-break)) (#\Control-Meta-Break (send user-process :interrupt 'network-user:handle-error-break)) (otherwise (simple-io-buffer-put buffer c)))))))) (t (simple-io-buffer-put buffer c))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#90 at 5-Jan-88 12:28:32 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defmethod (supdup-server :any-tyi) (&optional ignore &aux idx c) (char-int-if-any (loop (cond ((> (tv:rhb-fill-pointer) (setq idx (tv:rhb-scan-pointer))) ;;untyi'd characters... (incf (tv:rhb-scan-pointer)) (return (aref tv:rubout-handler-buffer idx))) ((not (eq tv:rubout-handler self)) ;;rubout handling not in effect... (when need-force-output (send self :force-output)) (unless (or untyi-char (send input :listen)) (send self :notice :input-wait)) (case (setq c (send self :subtyi)) ((#\Abort #.(char-int #\Abort)) (network-user:handle-abort)) ((#\Meta-Abort #.(char-int #\Meta-Abort)) (network-user:handle-abort-all)) ((#\Break #.(char-int #\Break)) (network-user:handle-break)) ((#\Meta-Break #.(char-int #\Meta-Break)) (network-user:handle-error-break)) (otherwise (return c)))) (t ;;Rubout handler (will call us for new characters) (return (funcall (or tv:stream-rubout-handler 'tv:default-rubout-handler)))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#110 at 5-Jan-88 12:29:22 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (defvar *telnet-interrupt-characters* `((,(glass-tty-ascii-code #\Control-g) network-user:handle-abort) (,(glass-tty-ascii-code #\Control-t) network-user:status-interrupt process-status-info) (,(glass-tty-ascii-code #\Control-z) network-user:handle-error-break))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#110 at 5-Jan-88 12:30:02 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (defun telnet-server-function (remote-stream) (let* ((safe-input-stream (make-eof-throwing-stream remote-stream)) (si:user-id nil) (network-user:*term* nil) (cvars '(network-user:*term* si:user-id))) (global:using-resource (terminal telnet-server remote-stream safe-input-stream) (catch 'eof (send terminal :send-if-handles :send-initial-telnet-frobs) (format terminal "~%Welcome to ~A Server Telnet.~%" (send si:local-host :name)) (send terminal :force-output) (network-user-login terminal) (send terminal :initialize-terminal) (global:print-herald terminal) (format terminal "~%Type (help) for keyboard help~%~%") (send terminal :force-output) (subprocess :closure-variables cvars (loop (send terminal :force-output) (sys:process-sleep *telnet-asynchronous-force-output-period*))) (multiple-value-bind (buffer-stream buffer) (make-simple-io-buffer-stream) (send terminal :set-input-stream buffer-stream) (send terminal :set-more-p t) (send sys:current-process :set-priority 1) (catch 'telnet-server-logout (telnet-server-input (subprocess :closure-variables cvars :restart-after-reset t (global:progw (append *network-user-process-bindings* si:*break-bindings*) (catch 'telnet-server-logout (si:lisp-top-level1 terminal)) (send (network-server-process *server*) :interrupt #'network-user:logout))) buffer remote-stream terminal))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#110 at 5-Jan-88 12:31:11 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (defun telnet-server-input (user-process buffer remote-stream terminal) (do (c int quote extended) ((null (setq c (send remote-stream :tyi)))) (setq extended (termcap.extended-keyboard (global:symeval-in-instance terminal 'termcap))) (cond ((= c (get 'iac 'telnet-sym)) (let* ((c1 (send remote-stream :tyi)) (action (cadr (assoc c1 *telsyms* :test #'eq)))) (cond ((eq action 'ip) (send user-process :interrupt 'network-user:handle-abort-all)) (t (simple-io-buffer-put buffer c) (simple-io-buffer-put buffer c1))))) ((and extended (= c #o34)) (let ((bits (send remote-stream :tyi))) (cond ((= bits #o034) (simple-io-buffer-put buffer c)) (t (setq c (make-char (global:char-flipcase (send remote-stream :tyi)) (logand bits #o77))) (case c (#\Control-Abort (send user-process :interrupt 'network-user:handle-abort)) (#\Control-Meta-Abort (send user-process :interrupt 'network-user:handle-abort-all)) (#\Control-Break (send user-process :interrupt 'network-user:handle-break)) (#\Control-Meta-Break (send user-process :interrupt 'network-user:handle-error-break)) (otherwise (simple-io-buffer-put buffer c))))))) ((and (not quote) (= c *telnet-ascii-quote-character*)) (setq quote t)) ((and (not quote) (= c *telnet-ascii-stop-output-character*)) (unless (eq (global:symeval-in-instance terminal 'output-lock) global:current-process) (global:process-lock (locf (global:symeval-in-instance terminal 'output-lock))))) ((and (not quote) (= c *telnet-ascii-resume-output-character*)) (when (eq (global:symeval-in-instance terminal 'output-lock) global:current-process) (global:process-unlock (locf (global:symeval-in-instance terminal 'output-lock))))) ((and (not quote) (setq int (assoc c *telnet-interrupt-characters* :test #'eq))) (cond ((third int) (send user-process :interrupt (second int) (funcall (third int) user-process))) (t (send user-process :interrupt (second int))))) ((simple-io-buffer-full-p buffer) ;; GOOD QUESTION. LETS JUST THROW AWAY CHARACTERS, OTHERWISE ;; WE WILL MISS ANY #\CONTROL-G'S COMING DOWN. (send remote-stream :tyo (glass-tty-ascii-code #\Control-g))) (t (when quote (simple-io-buffer-put buffer *telnet-ascii-quote-character*) (setq quote nil)) (simple-io-buffer-put buffer c))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#90 at 5-Jan-88 12:34:54 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defmethod (telnet-server :any-tyi) (&optional ignore) (let ((extended (termcap.extended-keyboard termcap)) idx c quote) (char-int-if-any (loop (cond ((> (tv:rhb-fill-pointer) (setq idx (tv:rhb-scan-pointer))) (incf (tv:rhb-scan-pointer)) (setq c (aref tv:rubout-handler-buffer idx)) (cond ((and (not quote) (= c *telnet-quote-character*)) (setq quote t)) (extended (return c)) (t (return c)))) ((not (eq tv:rubout-handler self)) (setq c (send self :subtyi)) (cond ((null c) (return nil)) ((and (not quote) (= c *telnet-quote-character*)) (setq quote t)) ((eq c #\Abort) (network-user:handle-abort)) ((eq c #\Meta-Abort) (network-user:handle-abort-all)) ((eq c #\Break) (network-user:handle-break)) ((eq c #\Meta-Break) (network-user:handle-error-break)) (extended (return c)) (quote (return c)) ((eq c #\Control-U) (return #\Clear-Input)) ((eq c #\Control-R) (return #\Delete)) (t (return c)))) (t (return (funcall (or tv:stream-rubout-handler 'tv:default-rubout-handler))))))))) ))