;;; -*- Mode:Lisp; Readtable:CL; Package:USER; Base:10; Patch-File:T -*- ;;; Patch file for System version 123.166 ;;; Reason: ;;; TCP SUPDUP Server. ;;; Written 21-Dec-87 16:06:25 by pld at site Gigamos Cambridge ;;; while running on Jack Flanders from band 2 ;;; with Experimental System 123.163, 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#86 at 21-Dec-87 16:15:15 #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 :tab) () (let ((stops (termcap.tab-stops termcap))) (cond ((null stops) (send self :string-out " ")) ((numberp stops) (let ((spaces (mod (pixels-to-chars tv:cursor-x) stops))) (dotimes (i (or (plusp spaces) stops)) (send self :tyo #\Space)))) ('else ;; a list of tab stops. write this some other time nil )))) (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))) (send self :string-out string start end)) ((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 :compute-motion) (string &optional (start 0) (end (string-length string)) (x tv:cursor-x) (y tv:cursor-y)) (declare (values end-x end-y)) ;;Returns where cursor will be after buffer has been output. (setq x (pixels-to-chars x)) (setq y (pixels-to-lines y)) (do* ((end-x x) (end-y y) (stops (termcap.tab-stops termcap)) (lines (truncate tv:height tv:line-height)) (columns (- (truncate tv:width tv:char-width) (if (termcap.linewrap-indicator termcap) 1 0))) (index start (1+ index)) c) ((eql index end) (values (chars-to-pixels end-x) (lines-to-pixels end-y))) (labels ((inc-y (dy) (incf end-y dy) (when (> end-y (- lines 2)) (setq end-y (mod end-y lines)))) (inc-x (dx) (incf end-x dx) (when (> end-x columns) (setq end-x (mod end-x columns)) (inc-y 1)))) (setq c (char string index)) (when (null c) (return (values (chars-to-pixels end-x) (lines-to-pixels end-y)))) (cond ((< c #o40)) ((= c #\Return) (setq end-x 0) (inc-y 1)) ((= c #\Tab) (inc-x (cond ((null stops) 8) ((numberp stops) (let ((x (mod end-x stops))) (if (zerop x) stops x))) (t 0)))) ((= c #\Backspace) (inc-x -1)) ((graphic-char-p c) (inc-x 1)) (t))))) (defmethod (telnet-server :compute-motion) (string &optional (start 0) (end (string-length string)) (x tv:cursor-x) (y tv:cursor-y)) (declare (values end-x end-y)) (setq x (pixels-to-chars x)) (setq y (pixels-to-lines y)) ;;Returns where cursor will be after buffer has been output. (do* ((end-x x) (end-y y) (stops (termcap.tab-stops termcap)) (lines (truncate tv:height tv:line-height)) (columns (- (truncate tv:width tv:char-width) (if (termcap.linewrap-indicator termcap) 1 0))) (index start (1+ index)) c) ((eql index end) (values (chars-to-pixels end-x) (lines-to-pixels end-y))) (labels ((inc-y (dy) (incf end-y dy) (when (> end-y (- lines 2)) (setq end-y (mod end-y lines)))) (inc-x (dx) (incf end-x dx) (when (> end-x columns) (setq end-x (mod end-x columns)) (inc-y 1)))) (setq c (char string index)) (when (null c) (return (values (chars-to-pixels end-x) (lines-to-pixels end-y)))) (cond ((< c #o40) (inc-x (string-length (aref *telnet-graphic-translations* c)))) ((= c #\Return) (setq end-x 0) (inc-y 1)) ((= c #\Tab) (inc-x (cond ((null stops) 8) ((numberp stops) (let ((x (mod end-x stops))) (if (zerop x) stops x))) (t 0)))) ((= c #\Backspace) (inc-x -1)) ((graphic-char-p c) (inc-x 1)) ((and (zerop (char-bits c)) (> c #\Network)) (inc-x (cond ((< c #o10) 3) ((< c #o100) 4) (t 5)))) ('else (inc-x (string-length (format nil "~:C" c)))))))) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TERMCAP.LISP#86 at 21-Dec-87 16:06:26 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TERMCAP  " (defflavor supdup-server (who-string) (simple-ascii-stream-terminal) (:settable-instance-variables who-string) :initable-instance-variables) (defvar *ascii-supdup-translations* '((#o00 #\Null) (#o10 #\Backspace) (#o11 #\Tab) (#o12 #\Line) (#o14 #\FF) (#o15 #\Return) (#o32 #\Call) (#o33 #\Altmode) (#o177 #\Rubout) (#o233 #\End) (#o310 #\Resume) (#o323 #\Hold-Output) (#o4101 #\Escape) (#o4102 #\Break) (#o4103 #\Clear-Input) (#o4110 #\Help) (#o4177 #\Integral))) (defmethod (supdup-server :subtyi) (&aux c bits code) (loop (setq c (send input :tyi)) (cond ((null c) (return nil)) ((= c #o300) (case (setq c (send input :tyi)) (#o301 ;Logout (telnet-user:logout)) (#o302 (setq who-string (make-string 64 :fill-pointer 0)) (loop (setq c (send input :tyi)) (when (or (null c) (zerop c)) (return)) (vector-push-extend c who-string))))) ((= c #o34) (setq bits (send input :tyi)) (cond ((null bits) (format self "~&null bits") (return nil)) ((= bits #o34) (return c))) (setq bits (logand bits #o37)) (setq code (send input :tyi)) (when (null code) (return nil)) (setq c (logior (ash bits 7) (logand #o177 code))) (return (or (cadr (assoc c *ascii-supdup-translations* :test #'eq)) (and (= bits #o20) code) (make-char (global:char-flipcase code) bits)))) (t (return (or (cadr (assoc c *ascii-supdup-translations* :test #'eq)) c)))))) (defmethod (supdup-server :any-tyi) (&optional ignore &aux idx) (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)) (send self :subtyi)) (t ;;Rubout handler (will call us for new characters) (funcall (or tv:stream-rubout-handler 'tv:default-rubout-handler)))))) (defmethod (supdup-server :tyo-unlocked) (c) (when (plusp (tv:sheet-more-flag self)) (case (send self :more-exception) ((#.(char-int #\Clear-Input) #.(char-int #\Abort)) (telnet-user:abortion-interrupt)) (#.(char-int #\Break) (telnet-user:break-interrupt)))) (when (= tv:cursor-y tv:height) (send self :home-cursor) (send self :clear-rest-of-line)) (cond ((null c)) ((= c #\Return) (send self :terpri)) ((= c #\Tab) (send self :tab)) ((= c #\Backspace) (when (plusp tv:cursor-x) (send self :output-control-sequence (termcap.back-space termcap)) (decf tv:cursor-x tv:char-width))) ((graphic-char-p c) (cond ((= tv:cursor-x (- tv:width tv:char-width)) (send self :end-of-line-exception c)) (t (send output :tyo c) (incf tv:cursor-x tv:char-width))) (setq need-force-output t)) ((and (zerop (char-bits c)) (> c #\Network)) ;; otherwise there will be a recursive call to this :TYO from FORMAT below. (format self "<~O>" c)) ('else (format self "~:C" c))) (and (zerop tv:cursor-x) (eql tv:cursor-y tv:more-vpos) (setf (tv:sheet-more-flag self) 1))) (defmethod (supdup-server :compute-motion) (string &optional (start 0) (end (string-length string)) (x tv:cursor-x) (y tv:cursor-y)) (declare (values end-x end-y)) (setq x (pixels-to-chars x)) (setq y (pixels-to-lines y)) ;;Returns where cursor will be after buffer has been output. (do* ((end-x x) (end-y y) (stops (termcap.tab-stops termcap)) (lines (truncate tv:height tv:line-height)) (columns (- (truncate tv:width tv:char-width) (if (termcap.linewrap-indicator termcap) 1 0))) (index start (1+ index)) c) ((eql index end) (values (chars-to-pixels end-x) (lines-to-pixels end-y))) (labels ((inc-y (dy) (incf end-y dy) (when (> end-y (- lines 2)) (setq end-y (mod end-y lines)))) (inc-x (dx) (incf end-x dx) (when (> end-x columns) (setq end-x (mod end-x columns)) (inc-y 1)))) (setq c (char string index)) (when (null c) (return (values (chars-to-pixels end-x) (lines-to-pixels end-y)))) (cond ((= c #\Return) (setq end-x 0) (inc-y 1)) ((= c #\Tab) (inc-x (cond ((null stops) 8) ((numberp stops) (let ((x (mod end-x stops))) (if (zerop x) stops x))) (t 0)))) ((= c #\Backspace) (inc-x -1)) ((graphic-char-p c) (inc-x 1)) ((and (zerop (char-bits c)) (> c #\Network)) (inc-x (cond ((< c #o10) 3) ((< c #o100) 4) (t 5)))) ('else (inc-x (string-length (format nil "~:C" c)))))))) (defmethod (supdup-server :clear-between-cursorposes) (x1 y1 x2 y2) (supdup-clear-between-cursorposes x1 y1 x2 y2)) (defmethod (supdup-server :supdup-greeting) (format-string &rest args) (start-supdup-output :supdup) (apply #'format self format-string args) (send output :tyo %tdnop) (send self :terpri) (force-output output)) (compile-flavor-methods supdup-server) )) ; From modified file DJ: L.NETWORK; SUPDUP.LISP#309 at 21-Dec-87 16:47:56 #8R SUPDUP#: #!:ZL (COMPILER-LET ((*PACKAGE* (PKG-FIND-PACKAGE "SUPDUP"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; SUPDUP  " (defmethod (basic-nvt :new-connection) (host protocol contact contact-p window &aux label-spec conn) (multiple-value-setq (host contact label-spec) (expand-path tv:name host contact contact-p)) (when host (dotimes (i 2) (setq conn (condition-case (error) (ecase protocol (:chaos (chaos:connect host contact window)) (:internet (open (format nil "TCP-HOST:~D.~D" host contact) :keyword tv:name :optimistic nil))) (error error))) (unless (errorp conn) (send self :set-label label-spec) (send self :set-connection conn) (return conn)) (setq protocol (if (eq protocol :chaos) :internet :chaos)) conn))) )) ; From modified file DJ: L.NETWORK.IP-TCP.KERNEL; GENERIC-SERVER.LISP#24 at 21-Dec-87 17:59:28 #10R TCP-APPLICATION#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TCP-APPLICATION"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; KERNEL; GENERIC-SERVER  " (defun *define-network-service (name protocol-name transport-protocol documentation &key toplevel-function listen-port auto-enable? stream-flavor) (when (global:record-source-file-name name 'define-network-service) (proclaim `(special ,name)) (setf (documentation name 'network-service) (or documentation name)) (let ((service (set name (make-network-service)))) (pushnew name *network-services*) (setf (network-service-name service) protocol-name) (setf (network-service-transport-protocol service) transport-protocol) (setf (network-service-listen-port service) (eval listen-port)) (setf (network-service-toplevel-function service) toplevel-function) (setf (network-service-auto-enable? service) auto-enable?) (setf (network-service-stream-flavor service) stream-flavor) (setf (network-service-active-servers service) nil) (setf (network-service-listening-server service) nil) (setf (network-service-lock service) nil)) name)) )) ; From modified file DJ: L.NETWORK.IP-TCP.SERVER; TELNET.LISP#106 at 21-Dec-87 17:57:20 #10R TELNET#: (COMPILER-LET ((*PACKAGE* (GLOBAL:PKG-FIND-PACKAGE "TELNET"))) (COMPILER::PATCH-SOURCE-FILE "SYS: NETWORK; IP-TCP; SERVER; TELNET  " (define-network-service *tcp-supdup-service* :supdup :tcp "SUPDUP Terminal Capability" :listen-port (sym tcp-application:ipport-supdup) :toplevel-function 'supdup-server-function :auto-enable? t) (global:defresource supdup-server (&optional ascii-output-stream ascii-input-stream) :constructor (make-instance 'supdup-server :output ascii-output-stream :input ascii-input-stream) :matcher (progn object) :initializer (progn (setf (global:symeval-in-instance object 'output) ascii-output-stream) (setf (global:symeval-in-instance object 'input) ascii-input-stream) (setf (global:symeval-in-instance object 'output-lock) nil) (send object :termcap :default)) :deinitializer (progn (setf (global:symeval-in-instance object 'output) nil) (setf (global:symeval-in-instance object 'input) nil) (send object :termcap :default))) (defun supdup-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 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) (telnet-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 (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))))))) (defun supdup-server-input (user-process buffer remote-stream terminal) (declare (ignore user-process)) (declare (ignore terminal)) (do (c) ((null (setq c (send remote-stream :tyi)))) (simple-io-buffer-put buffer c))) )) (tcpa:enable-one-network-service telnet:*tcp-supdup-service*)