;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*- ;;; Patch file for System version 123.163 ;;; Reason: ;;; Various cleanups in Telnet Server. All the hooks are there for a SUPDUP server. ;;; Better **MORE** processing. More functions shadowed in TELNET-USER: to keep ;;; windows from being created on host. ;;; Written 19-Dec-87 14:29:02 by pld at site Gigamos Cambridge ;;; while running on Jack Flanders from band 2 ;;; with Experimental System 123.162, 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.SERVER; TERMCAP.LISP#81 at 19-Dec-87 14:42:46 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defstruct (termcap (:conc-name termcap.) (:print-function (lambda (termcap stream ignore) (sys:printing-random-object (termcap stream :type :no-pointer) (format stream "of ~A" (termcap.name termcap)))))) name nicknames documentation add-blank-line (back-space #o10) clear-to-end-of-display clear-to-end-of-line clear-to-beginning-of-line clear-screen cursor-motion (number-of-columns 256) (number-of-lines 1000000) (carriage-return '(#o15 0)) change-scrolling-region cursor-horizontal-motion cursor-vertical-motion delete-character delete-line enter-delete-mode down-one-line end-delete-mode enter-insert-mode end-insert-mode (form-feed #o14) hardcopy-p home-cursor insert-character initialization-string cursor-right (line-feed #o12) (tab-stops 8) (tab #o11) cursor-up visible-bell (audible-bell #o7) (linewrap-indicator #\!) auto-new-line cursor-down cursor-left (cursor-motion-characters 0) clear-character multiple-character-insert multiple-character-delete multiple-line-insert multiple-line-delete fresh-line-and-clear (clear-screen-homes-cursor t) (selective-erase t) extended-keyboard overprint line-insert-delete character-insert-delete (new-line '(#o15 #o12)) ) (define-termcap default "the default terminal capabilities" ) (define-termcap h19 "Now manufactured by Zenith Data Systems. For Zenith-Mode functions" :nicknames '(h-19 z29 z-29 heath zenith) :add-blank-line '(*esc* "L") :clear-to-end-of-display '(*esc* "J") :clear-to-end-of-line '(*esc* "K") :clear-to-beginning-of-line '(*esc* "l") :clear-screen '(*esc* "E") :cursor-motion '(*esc* "Y" (+ y 32) (+ x 32)) :cursor-motion-characters 4 :number-of-columns 80 :number-of-lines 24 :delete-character '(*esc* "N") :delete-line '(*esc* "M") :enter-insert-mode '(*esc* "@") :end-insert-mode '(*esc* "O") :home-cursor '(*esc* "H") :cursor-up '(*esc* "A") :cursor-down '(*esc* "B") :cursor-right '(*esc* "C") :cursor-left '(*esc* "D") :tab nil :auto-new-line t ) (define-termcap vt-100 "Another commonly used terminal" :nicknames '(vt100) :clear-to-end-of-display '(*esc* "[J") :clear-to-end-of-line '(*esc* "[K") :clear-screen '(*esc* "[;H" *esc* "[2J") :cursor-motion '(*esc* "[" y ";" x "H") :cursor-motion-characters 6 :number-of-columns 80 :number-of-lines 24 :home-cursor '(*esc* "[H") ) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#81 at 19-Dec-87 15:05:25 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defmethod (simple-ascii-stream-terminal :after :init) (&rest ignored) (or termcap (send self :termcap term)) (setq tv:superior nil) ;We are a screen (setq tv:line-height 1) (setq tv:char-width 1) (setq tv:width (termcap.number-of-columns termcap)) (setq tv:height (termcap.number-of-lines termcap)) (send self :set-more-p t)) (defmethod (simple-ascii-stream-terminal :no-inferior-windows-p) () t) (defmethod (simple-ascii-stream-terminal :notice) (event &rest args) (declare (ignore args)) (case event ((:input :output) ;Deexposed window needs some attention t) (:input-wait ;Hanging up waiting for input. (setf (tv:sheet-more-flag self) 0) (cond ((null tv:more-vpos)) ;Unless MORE inhibited entirely ((< (* (- tv:height tv:cursor-y) 4) ;More than 3/4 way down window? tv:height) ;; Wrap around and more just before the current line (setq tv:more-vpos (- tv:cursor-y tv:line-height))) (t ;; More at bottom (setq tv:more-vpos (- tv:height tv:line-height)))) t) (:error ;Error in process using this window as its *TERMINAL-IO*. t) (otherwise nil))) (defmethod (simple-ascii-stream-terminal :any-tyi) (&optional ignore &aux idx c) (char-int-if-any (cond (untyi-char (prog1 untyi-char (setq untyi-char nil))) ((> (tv:rhb-fill-pointer) (setq idx (tv:rhb-scan-pointer))) ;;untyi'd characters... (incf (tv:rhb-scan-pointer)) (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 (send input :listen) (send self :notice :input-wait)) (setq c (send input :tyi)) (cond ((null c) nil) ((eq c #\Control-U) #\Clear-Input) ((eq c #\Control-R) #\Delete) (t c))) (t ;;Rubout handler (will call us for new characters) (funcall (or tv:stream-rubout-handler 'tv:default-rubout-handler)))))) (defmethod (simple-ascii-stream-terminal :tyi) (&optional ignore) (loop (let ((c (send self :any-tyi))) (when (or (null c) (numberp c)) (return c))))) (defmethod (simple-ascii-stream-terminal :terpri) (&aux fresh-line) (with-lock (output-lock) (setq tv:cursor-x 0) (incf tv:cursor-y tv:line-height) (cond ((= tv:cursor-y tv:height) (send self :home-cursor) (send self :clear-rest-of-line)) ((setq fresh-line (termcap.fresh-line-and-clear termcap)) (send self :output-control-sequence fresh-line)) (t (send self :output-control-sequence (termcap.new-line termcap)) (send self :clear-rest-of-line))) (when (eql tv:cursor-y tv:more-vpos) (setf (tv:sheet-more-flag self) 1)))) (defmethod (simple-ascii-stream-terminal :more-exception) () (when (plusp (tv:sheet-more-flag self)) (setf (tv:sheet-more-flag self) 0) (let ((more-vpos tv:more-vpos)) (unwind-protect (progn (princ "**MORE**" output) (send self :clear-rest-of-line) (force-output self) (send self :clear-input) (send self :any-tyi)) (setq tv:more-vpos more-vpos) (send self :output-control-sequence (termcap.carriage-return termcap)) (send self :clear-rest-of-line))))) (defmethod (simple-ascii-stream-terminal :clear-rest-of-line) (&aux clear) (when (setq clear (termcap.clear-to-end-of-line termcap)) (send self :output-control-sequence clear))) (defmethod (simple-ascii-stream-terminal :clear-window) (&aux clear) (cond ((setq clear (termcap.clear-screen termcap)) (send self :output-control-sequence clear) (cond ((termcap.clear-screen-homes-cursor termcap) (setq tv:cursor-x 0) (setq tv:cursor-y 0)) (t (send self :home-cursor)))) (t (send self :fresh-line))) t) (defmethod (simple-ascii-stream-terminal :set-cursorpos) (x y &optional (type :pixel)) (ecase type (:pixel (let ((cursor-motion (termcap.cursor-motion termcap))) (cond (cursor-motion ;Terminal can move cursor (dolist (item cursor-motion) (send self :output-control-sequence (eval-cursorpos-item (pixels-to-chars x) (pixels-to-lines y) item))) (setq tv:cursor-x x) (setq tv:cursor-y y)) ((= tv:cursor-y y) ;Same line (if (> x tv:cursor-x) (dotimes (i (pixels-to-chars (- x tv:cursor-x))) ;;***Probably destructive.... (send self :tyo #\Space)) (dotimes (i (pixels-to-chars (- tv:cursor-x x))) (send self :tyo #\Backspace)))) (t ;Different line. Sorry.... )))) (:character (send self :set-cursorpos (chars-to-pixels x) (lines-to-pixels y))))) (defun eval-multiple-item (n item) (cond ((eq item 'n) n) ((and (symbolp item) (boundp item)) (symbol-value item)) ((atom item) item) ('else (apply (car item) (mapcar #'(lambda (z) (eval-multiple-item n z)) (cdr item)))))) (defmethod (simple-ascii-stream-terminal :insert-string) (string &optional (start 0) end (type-too t) &aux insert count) (when (null end) (setq end (string-length string))) (setq count (- end start)) (multiple-value-bind (x y) (send self :read-cursorpos) (cond ((setq insert (termcap.multiple-character-insert termcap)) (dolist (elt insert) (send self :output-control-sequence (eval-multiple-item count elt)))) ((setq insert (termcap.enter-insert-mode termcap)) (send self :output-control-sequence insert) (send self :string-out string start end) (send self :output-control-sequence (termcap.end-insert-mode termcap))) ((setq insert (termcap.insert-character termcap)) (dotimes (i count) (send self :output-control-sequence insert)) (send self :set-cursorpos x y) (send self :string-out string start end)) (t ;Sorry... )) (unless type-too (send self :set-cursorpos x y)))) (defmethod (simple-ascii-stream-terminal :delete-string) (string &optional (start 0) end &aux delete count) (when (null end) (setq end (string-length string))) (setq count (- end start)) (cond ((setq delete (termcap.multiple-character-delete termcap)) (dolist (elt delete) (send self :output-control-sequence (eval-multiple-item count elt)))) ((setq delete (termcap.delete-character termcap)) (dotimes (i count) (send self :output-control-sequence delete))) ((setq delete (termcap.enter-delete-mode termcap)) ;;I don't known how to use this... ) (t ;Sorry.... ))) (defmethod (simple-ascii-stream-terminal :clear-between-cursorposes) (x1 y1 x2 y2) (normal-clear-between-cursorposes x1 y1 x2 y2)) (defun normal-clear-between-cursorposes (x1 y1 x2 y2) (declare (:self-flavor simple-ascii-stream-terminal)) (cond ((null (termcap.cursor-motion termcap)) ;;No cursor motion (cond ((= y1 y2) ;clear in same line (erase-chars (pixels-to-chars (- x2 x1)))) ((= y2 tv:cursor-y) ;multiple lines, but end on current line (erase-chars (pixels-to-chars x2))) (t ;sorry... ))) ((= y1 y2) ;Erase within line (let ((delete (pixels-to-chars (- x2 x1)))) (cond ((= tv:cursor-x x1) (dotimes (i delete) (send self :tyo #\Space)) (send self :set-cursorpos x1 y1)) ((or (/= tv:cursor-x x2) (< (+ (* 2 (termcap.cursor-motion-characters termcap)) delete) (* 3 delete))) (send self :set-cursorpos x1 y1) (dotimes (i delete) (send self :tyo #\Space)) (send self :set-cursorpos x1 y1)) (t (erase-chars delete))))) (t (let ((clear-to-bol (termcap.clear-to-beginning-of-line termcap)) (clear-to-eol (termcap.clear-to-end-of-line termcap))) (cond (clear-to-bol (send self :set-cursorpos x2 y2) (send self :output-control-sequence clear-to-bol)) (t (send self :set-cursorpos 0 y2) (dotimes (i (pixels-to-chars x2)) (send self :tyo #\Space)))) (dotimes (i (- (pixels-to-lines (+ y2 (if (> y2 y1) 0 tv:height))) (pixels-to-lines y1) 1)) (send self :set-cursorpos 0 (mod (+ y1 (* (1+ i) tv:line-height)) tv:height)) (send self :output-control-sequence clear-to-eol)) (send self :set-cursorpos x1 y1) (send self :output-control-sequence clear-to-eol))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#81 at 19-Dec-87 14:29:26 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defconstant %tdbs #o211 "Back space") (defconstant %tdlf #o212 "Line Feed") (defconstant %tdcr #o213 "Carriage Return") (defconstant %tdors #o214 "Output reset") (defconstant %tdqot #o215 "Quote following character") (defconstant %tdbel #o221 "Create audible tone") (defconstant %tdbow #o227 "Black on White mode") (defconstant %tdrst #o230 "Reset") (defconstant %tdgrf #o231 "Graphics") (define-termcap supdup "Supdup" :add-blank-line '(%tdilp 1) :clear-character %tddlf :clear-to-end-of-display %tdeof :clear-to-end-of-line %tdeol :clear-screen %tdclr :cursor-right %tdfs :cursor-motion '(%tdmv0 y x) :delete-character '(%tddcp 1) :delete-line '(%tddlp 1) :insert-character '(%tdicp 1) :multiple-character-insert '(%tdicp n) :multiple-character-delete '(%tddcp n) :multiple-line-insert '(%tdilp n) :multiple-line-delete '(%tddlp n) :fresh-line-and-clear %tdcrl :back-space %tdbs :carriage-return %tdcr :line-feed %tdlf :new-line '(%tdcr %tdlf) :audible-bell %tdbel :tab nil ) (defun start-supdup-output (type) (declare (:self-flavor simple-ascii-stream-terminal)) (let ((nwords (dpb (get-18-bits input) (byte 18. 0) -1)) (ttyopt-left 0) (ttyopt-right 0) (ttyrol 0)) (when (or (< nwords -16.) (> nwords 0)) (return-from start-supdup-output nil)) (get-18-bits input) (when (not (zerop nwords)) (get-18-bits input) (unless (= (get-18-bits input) 7) (return-from start-supdup-output nil)) (incf nwords)) (send self :termcap type) (setq termcap (copy-termcap termcap)) (when (not (zerop nwords)) (setq ttyopt-left (get-18-bits input)) (setf (termcap.selective-erase termcap) (not (zerop (logand ttyopt-left #o40000)))) (setf (termcap.overprint termcap) (not (zerop (logand ttyopt-left #o1000)))) (setf (termcap.extended-keyboard termcap) (not (zerop (logand ttyopt-left #o10)))) (setf (termcap.line-insert-delete termcap) (not (zerop (logand ttyopt-left #o2)))) (setf (termcap.character-insert-delete termcap) (not (zerop (logand ttyopt-left #o1)))) (send self :set-more-p (not (zerop (logand ttyopt-left #o200)))) (setq ttyopt-right (get-18-bits input)) (incf nwords)) (when (not (zerop nwords)) (get-18-bits input) (setq tv:height (get-18-bits input)) ;height in lines (setf (termcap.number-of-lines termcap) tv:height) (incf nwords)) (when (not (zerop nwords)) (get-18-bits input) (setq tv:width (get-18-bits input)) ;width in characters (setf (termcap.number-of-columns termcap) tv:width) (incf nwords)) (when (not (zerop nwords)) ;;scroll glitch (get-18-bits input) (setq ttyrol (get-18-bits input)) (incf nwords)) (when (not (zerop nwords)) ;;TTYSMT (let ((x (get-18-bits input))) (setq tv:line-height (ldb (byte 8 10) x)) (setq tv:height (* tv:height tv:line-height)) (setq tv:char-width (ldb (byte 4 6) x)) (setq tv:width (* tv:width tv:char-width))) (get-18-bits input) (incf nwords)) (do () ((zerop nwords)) (get-18-bits input) (get-18-bits input) (incf nwords)) )) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#81 at 19-Dec-87 15:13:22 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (define-termcap supdup-output "Telnet Supdup Output" :add-blank-line '(supdup-sb 2 %tdilp 1 supdup-se) :clear-character '(supdup-sb 1 %tddlf supdup-se) :clear-to-end-of-display '(supdup-sb 1 %tdeof supdup-se) :clear-to-end-of-line '(supdup-sb 1 %tdeol supdup-se) :clear-screen '(supdup-sb 1 %tdclr supdup-se) :cursor-right '(supdup-sb 1 %tdfs supdup-se) :cursor-motion '(supdup-sb 3 %tdmv0 y x supdup-se) :delete-character '(supdup-sb 2 %tddcp 1 supdup-se) :delete-line '(supdup-sb 2 %tddlp 1 supdup-se) :insert-character '(supdup-sb 2 %tdicp 1 supdup-se) :multiple-character-insert '(supdup-sb 2 %tdicp n supdup-se) :multiple-character-delete '(supdup-sb 2 %tddcp n supdup-se) :multiple-line-insert '(supdup-sb 2 %tdilp n supdup-se) :multiple-line-delete '(supdup-sb 2 %tddlp n supdup-se) :fresh-line-and-clear '(supdup-sb 1 %tdcrl supdup-se) :cursor-motion-characters 12 ) (defmethod (telnet-server :notice) (event &rest args) (declare (ignore args)) (case event ((:input :output) ;Deexposed window needs some attention t) (:input-wait ;Hanging up waiting for input. (setf (tv:sheet-more-flag self) 0) (cond ((null tv:more-vpos)) ;Unless MORE inhibited entirely ((< (* (- tv:height tv:cursor-y) 4) ;More than 3/4 way down window? tv:height) ;; Wrap around and more just before the current line (setq tv:more-vpos (- tv:cursor-y tv:line-height))) (t ;; More at bottom (setq tv:more-vpos (- tv:height tv:line-height)))) (unless (find-option telnet-options-received 'telopt_sga '(do)) ;;Unless remote side said Do Suppress Go-aheads, send a Go-ahead (send-iac 'ga)) t) (:error ;Error in process using this window as its *TERMINAL-IO*. t) (otherwise nil))) (defmethod (telnet-server :subtyi) () (if need-force-output (send self :force-output)) (flet ((getc (tcp stream) (unless (send tcp :listen) (send stream :notice :input-wait)) (send tcp :tyi))) (do ((c) (quote) (extended (termcap.extended-keyboard termcap))) ((not (setq c (or untyi-char (getc input self)))) nil) (cond (untyi-char (return (prog1 untyi-char (setq untyi-char nil)))) ((= c iac) (multiple-value-bind (done value) (receive-iac) (when done (return value)))) ((and (not quote) (= c *telnet-ascii-quote-character*)) (setq quote t)) ((and (not extended) (not quote) (= c (glass-tty-ascii-code #\Altmode))) (setq c (send self :subtyi)) (return (set-char-bit (make-char (if (plusp (char-bits c)) c (global:char-flipcase (char-code c))) (char-bits c)) :meta t))) ((and (not quote) (= c (glass-tty-ascii-code #\Control-\\))) (cond (extended (let ((bits (send input :tyi))) (when (= bits #o034) (return c)) (setq c (send input :tyi)) (return (make-char (global:char-flipcase c) (logand bits #o77))))) (t (setq c (send self :subtyi)) (return (set-char-bit (make-char (if (plusp (char-bits c)) c (global:char-flipcase (char-code c))) (char-bits c)) :super t))))) ((= (setq c (translate-char c)) #\Return) (setq flush-next-lf t) (return #\Return)) ((and (= c #\Line) flush-next-lf) (setq flush-next-lf nil)) ('else (setq flush-next-lf nil) (when quote (setq untyi-char c) (setq c *telnet-quote-character*)) (return c)))))) (defmethod (telnet-server :any-tyi) (&optional ignore) (let ((extended (termcap.extended-keyboard termcap)) idx c quote) (char-int-if-any (loop (cond (untyi-char (return (prog1 untyi-char (setq untyi-char nil)))) ((> (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)) (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))))))))) (defmethod (telnet-server :clear-between-cursorposes) (x1 y1 x2 y2) (if (eq term :supdup-output) (supdup-clear-between-cursorposes x1 y1 x2 y2) (normal-clear-between-cursorposes x1 y1 x2 y2))) (defun handle-subnegotiation () (declare (:self-flavor telnet-server)) (let* ((c (send input :tyi)) (option (cadr (assoc c *telopts* :test #'eq)))) (case option (telopt_supdup-output (when (= (send input :tyi) 1) (start-supdup-output :supdup-output)))) ;;Here to skip to end of subnegotiation (do ((iac-seen nil)) ((and iac-seen (= (send input :tyi) se))) (setq iac-seen (= (send input :tyi) iac))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET-UTILITIES.LISP#9 at 19-Dec-87 16:51:02 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET-UTILITIES  " (defun telnet-user:help () (format t "~&You are logged into a Lisp Machine Telnet Server. Interrupt Keys: Control-G Abort Interrupt Control-T Status Interrupt Control-S Stop Output Control-Q Resume Output Control-Z Break Interrupt Quote character: Control-V ") (cond ((eq 'tv:alternate-rubout-handler (global:symeval-in-instance *terminal-io* 'tv:stream-rubout-handler)) (format t " Your terminal is smart enough to use the full Lisp Machine Rubout handler for editing input. ")) (t (format t " Your terminal is smart enough only to provide minimal rubout handling. Keys to Edit Input: Rubout Delete one character Meta-Rubout Delete one word Control-U Delete all input Control-L Clear screen and refresh input Control-R Fresh Line and refresh input "))) (cond ((telnet:termcap.extended-keyboard (global:symeval-in-instance *terminal-io* 'telnet:termcap)) (format t " Your terminal can send Control, Meta, Super, and Hyper bits with its characters. ")) (t (format t " Ascii Keys for the rubout handler: Control-U Delete all input (Clear-Input) Control-L Clear screen and refresh input (Clear-Screen) Prefix keys to modify characters: Escape Meta- Control-\\ Super- "))) (format t " Useful programs in the TELNET-USER package: (logout) Close the Telnet connection (help) Print this message ") ) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#105 at 21-Dec-87 11:57:58 #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) (telnet-user:*term* nil) (cvars '(telnet-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) (telnet-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 (global:progw (append *telnet-user-process-bindings* si:*break-bindings*) (catch 'telnet-server-logout (si:lisp-top-level1 terminal)) (send (network-server-process *server*) :interrupt #'telnet-user:logout))) buffer remote-stream terminal))))))) )) ; From modified file DJ: L.NETWORK; PACKAGES.LISP#25 at 21-Dec-87 12:08:26 #10R USER#: (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "USER"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; PACKAGES  " (defpackage telnet-user ;;Like USER, but has a few functions shadowed... (:shadow "LOGOUT" "ED" "FED" "INSPECT" "KERMIT" "PEEK" "SUPDUP" "TELNET" "ZMAIL") (:use "GLOBAL")) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET-UTILITIES.LISP#10 at 21-Dec-87 12:08:44 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET-UTILITIES  " (defun telnet-user:ed (&rest ignored) (no-window-calls)) (defun telnet-user:fed (&rest ignored) (no-window-calls)) (defun telnet-user:inspect (&rest ignored) (no-window-calls)) (defun telnet-user:kermit (&rest ignored) (no-window-calls)) (defun telnet-user:peek (&rest ignored) (no-window-calls)) (defun telnet-user:supdup (&rest ignored) (no-window-calls)) (defun telnet-user:telnet (&rest ignored) (no-window-calls)) (defun telnet-user:zmail (&rest ignored) (no-window-calls)) (defun telnet:no-window-calls () "You can't call a function that switches windows") ))