perm filename SUPSER.MID[S,NET]4 blob sn#796095 filedate 1985-06-06 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00016 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00005 00002	X INTFOP INTPTO INTCLK INTQUIT FCS FULTWX XON TLKRNG
C00007 00003	%TOALT %TOCLC %TOERS %TOHDX %TOMVB %TOSAI %TOSA1 %TOOVR %TOMVU %TOMOR %TOROL %TORAW %TOLWR %TOFCI %TOIML %TOLID %TOCID %TPPLF %TPPCR %TPPTB %TPPRN %TPTEL %TPCBS %TP11T %TPORS %TQMCH %TQIM1 %TQIM4 %TQP11 %TQHGT %TQWID %TQVIR %TQBNK %TQXOR %TQREC %TQSET %TQGRF %TRGIN %TRGHC %TNPRT %TNDP %TNODP %TNIML %TNTEK %TNTV %TNMEM %TNSFW %TNTRM %TNESC %TNDTM %TNMAX %TXASC %TXCTL %TXMTA %TXSFT %TXSFL %TXTOP
C00012 00004	%GOMVR %GOXOR %GOSET %GOMSR %GOINV %GOBNK %GOCLR %GOPSH %GOVIR %GOHRD %GOGIN %GOLMT %GOMVA %GOIOR %GOMSA %GOVIS %GOCLS %GOPHY %GODLR %GODPR %GODRR %GODCH %GODLA %GODPA %GODRA %GOELR %GOEPR %GOERR %GOECH %GOELA %GOEPA %GOERA %TDMOV %TDMV1 %TDEOF %TDEOL %TDDLF %TDMTF %TDMTN %TDCRL %TDNOP %TDBS %TDLF %TDRCR %TDORS %TDQOT %TDFS %TDMV0 %TDCLR %TDBEL %TDINI %TDILP %TDDLP %TDICP %TDDCP %TDBOW %TDRST %TDMAX
C00017 00005	TYSBLK IMPSET LINCHR XONOFF DPYSET GAGOFF MODSET NTYSTS DPYBLK SETVSZ SETHSZ PADCHR PDBAUD TABFLG EDITKY DPYDES CNSBLK TCTYP TTYOPT TCMXV TCMXH TTYROL SMARTS ISPEED OSPEED CNSBLL TERMID CORBEG TERSTR HPOS VPOS SCRMST GETCXP GETCYP INDLMP ROLLP LFFLSP QUOTEP 128CHP OVRPRP PTINTP NTINTP DOQUIT PRESCP SDCMDP EATERP NODETP BKYBTS FLSCNT TERMBP TTYLIN TPCSAV IDLTIM PTIBUF PDL COREND
C00022 00006	INTSER CLKSER INTDIE CLKSR1
C00025 00007	SUPSER CPYHST 1DIGTP NOTTIP
C00028 00008	NOFLAK GETSIZ GETCNS CHKTRM NOTSAI
C00031 00009	GETPTY MAINL MAINL0
C00034 00010	NTISER
C00037 00011	PTYSN0 FNYQOT PTYSN1 PTYSN2 PTYSND
C00040 00012	PTISER PTISR1 CHKCYP CHKDMC DMSND DMSND0 MRKNBL ISPCH NOTPCH
C00043 00013	SCLEAR CANCEL CLEOL SETCPS SNDPOS INSLIN IDCMND SPACE FORSPC
C00046 00014	DMCTAB
C00050 00015	DMCTAB...
C00053 00016	GETSMD BITTAB SNDMSG MSGLUP ERRDIE SUICID DIEDIE ...LIT SVRRTS ERRTNS ERRHAN ERRINS HSTTAB HSTSIX
C00056 ENDMK
C⊗;
;X INTFOP INTPTO INTCLK INTQUIT FCS FULTWX XON TLKRNG

TITLE SUPSER
SUBTTL Definitions

; Mark Crispin, SU-AI, October 1979

; Assembly switches

IFNDEF SVRSKT,SVRSKT==137		; default listen socket
IFNDEF LOKTMO,LOKTMO==5			; # of 15-second frobs of lock timeout
IFNDEF PDLLEN,PDLLEN==50		; stack length
IFNDEF VSZMAX,VSZMAX==70.		; maximum TCMXV
IFNDEF HSZMAX,HSZMAX==95.		; maximum TCMXH

; AC definitions.  0→3 are used by NETWRK

X=4 ? Y=5 ? Z=6 ? A=7 ? B=10 ? C=11 ? D==12 ? P=17

; SAIL system bit definitions

INTFOP==040000,,			; PTY clear output buffer
INTPTO==001000,,			; PTY interrupt
INTCLK==000200,,			; clock interrupt
INTQUIT==002000				; (right half) interrupt on QUIT cmd
FCS==   000020,,			; full character set mode
FULTWX==000004,,			; no echo
XON==   000002,,			; paper tape mode
TLKRNG==000001,,			; TALKing
;%TOALT %TOCLC %TOERS %TOHDX %TOMVB %TOSAI %TOSA1 %TOOVR %TOMVU %TOMOR %TOROL %TORAW %TOLWR %TOFCI %TOIML %TOLID %TOCID %TPPLF %TPPCR %TPPTB %TPPRN %TPTEL %TPCBS %TP11T %TPORS %TQMCH %TQIM1 %TQIM4 %TQP11 %TQHGT %TQWID %TQVIR %TQBNK %TQXOR %TQREC %TQSET %TQGRF %TRGIN %TRGHC %TNPRT %TNDP %TNODP %TNIML %TNTEK %TNTV %TNMEM %TNSFW %TNTRM %TNESC %TNDTM %TNMAX %TXASC %TXCTL %TXMTA %TXSFT %TXSFL %TXTOP

SUBTTL ITS TTY definitions

;  These definitions are the various bits, words, etc. for the ITS terminal
; service system calls and are here for convenience and clarity.  This is
; abridged from [MIT-AI] SYSTEM;BITS >, the monitor bits definition file.

; TTYOPT variable (terminal capabilities)

%TOALT==200000,,			; 1 → standardise altmodes
%TOCLC==100000,,			; 1 → convert cases on input
%TOERS==040000,,			; 1 → this terminal can erase
%TOHDX==020000,,			; 1 → half duplex
%TOMVB==010000,,			; 1 → can backspace
%TOSAI==004000,,			; 1 → has SAIL graphics
%TOSA1==002000,,			; 1 → init %TSSAI in new jobs (use graphics)
%TOOVR==001000,,			; 1 → can overprint
%TOMVU==000400,,			; 1 → can line starve (ie a display)
%TOMOR==000200,,			; 1 → do **More** processing (init %TSMOR)
%TOROL==000100,,			; 1 → scroll (init %TSROL for new jobs)
%TORAW==000040,,			; 1 → no cursor motion optimization
%TOLWR==000020,,			; 1 → lower case keyboard
%TOFCI==000010,,			; 1 → has bucky bit keyboard
%TOIML==000004,,			; 1 → acts like a grIMLAC (funny ↑PF, ↑PB)
%TOLID==000002,,			; 1 → can insert/delete lines
%TOCID==000001,,			; 1 → can insert/delete characters
%TPPLF==700000				; LF padding
%TPPCR==070000				; CR padding
%TPPTB==007000				; TAB padding (0 → no tabs, 1 → tabs)
%TPPRN==000200				; 1 → swap () with [] on input
%TPTEL==000100				; 1 → CR → CRLF for ARPAnet protocol
%TPCBS==000040				; 1 → intelligent terminal protocol (↑\)
%TP11T==000020				; 1 → PDP-11 TV (reflects %TY11T)
%TPORS==000010				; 1 → output reset should do something

; SMARTS variable (terminal smarts)

%TQMCH==700000,,			; machine type
 %TQIM1==300000,,			; PDS1
 %TQIM4==200000,,			; PDS4
 %TQP11==100000,,			; PDP-11
%TQHGT==076000,,			; character height in dots
%TQWID==001700,,			; character width in dots
%TQVIR==000040,,			; virtual coordinates
%TQBNK==000020,,			; blinking
%TQXOR==000010,,			; XOR mode
%TQREC==000004,,			; rectangle command
%TQSET==000002,,			; multiple sets
%TQGRF==000001,,			; understands graphics
%TRGIN==400000				; graphics input
%TRGHC==200000				; hardcopy device

; TCTYP variable (terminal type)

%TNPRT==0				; printing console, glass TTY, etc.
%TNDP==1				; good Datapoint
%TNODP==2				; inferior losing Datapoint
%TNIML==3				; grIMLAC
%TNTEK==4				; Tektronix 4000 series
%TNTV==5				; PDP-11 TV
%TNMEM==6				; Memowreck
%TNSFW==7				; Software
%TNTRM==10				; Terminet
%TNESC==11				; ASCII standard display (VT52, etc.)
%TNDTM==12				; Datamedia 2500
%TNMAX==13				; 1 + largest terminal type

; Components of an input character in 12-bit mode.

%TXASC==0177				; ASCII part
%TXCTL==0200				; control
%TXMTA==0400				; meta
%TXSFT==1000				; shift
%TXSFL==2000				; shift lock
%TXTOP==4000				; top
;%GOMVR %GOXOR %GOSET %GOMSR %GOINV %GOBNK %GOCLR %GOPSH %GOVIR %GOHRD %GOGIN %GOLMT %GOMVA %GOIOR %GOMSA %GOVIS %GOCLS %GOPHY %GODLR %GODPR %GODRR %GODCH %GODLA %GODPA %GODRA %GOELR %GOEPR %GOERR %GOECH %GOELA %GOEPA %GOERA %TDMOV %TDMV1 %TDEOF %TDEOL %TDDLF %TDMTF %TDMTN %TDCRL %TDNOP %TDBS %TDLF %TDRCR %TDORS %TDQOT %TDFS %TDMV0 %TDCLR %TDBEL %TDINI %TDILP %TDDLP %TDICP %TDDCP %TDBOW %TDRST %TDMAX

; Graphics output buffer codes

%GOMVR==001				; move cursor to P
%GOXOR==002				; turn on XOR mode
%GOSET==003				; select set N
%GOMSR==004				; move set origin to P
%GOINV==006				; make current set invisible
%GOBNK==007				; make current set blink
%GOCLR==010				; erase whole screen
%GOPSH==011				; push status information
%GOVIR==012				; use virtual coordinates
%GOHRD==013				; divert output to N
%GOGIN==014				; request input, reply code N
%GOLMT==015				; limit to subrectangle P1 P2
%GOMVA==021				; move cursor to P, abs addr
%GOIOR==022				; turn off XOR mode
%GOMSA==024				; move set origin to P, abs addr
%GOVIS==026				; make current set visible
%GOCLS==030				; erase current set
%GOPHY==032				; use unit coordinates

%GODLR==101				; draw line relative, to P
%GODPR==102				; draw point relative, at P
%GODRR==103				; draw rectangle relative, at P
%GODCH==104				; display STRING
%GODLA==121				; draw line absolute, to P
%GODPA==122				; draw point absolute, at P
%GODRA==123				; draw rectangle absolute, at P

%GOELR==141				; erase line relative, to P
%GOEPR==142				; erase point relative, at P
%GOERR==143				; erase rectangle relative, at P
%GOECH==144				; erase STRING
%GOELA==161				; erase line absolute, to P
%GOEPA==162				; erase point absolute, at P
%GOERA==163				; erase rectangle absolute, at P

; Non-graphics output buffer codes

%TDMOV==200				; move cursor OV OH NV NH
%TDMV1==201				; move cursor; NV NH
%TDEOF==202				; clear to end of screen
%TDEOL==203				; clear to end of line
%TDDLF==204				; delete character after cursor
%TDMTF==205				; motor off
%TDMTN==206				; motor on
%TDCRL==207				; terpri
%TDNOP==210				; no-op
%TDBS==211				; backspace
%TDLF==212				; line feed
%TDRCR==213				; carriage return
%TDORS==214				; output reset
%TDQOT==215				; quote next character (mystery command)
%TDFS==216				; cursor forward
%TDMV0==217				; move cursor NV NH
%TDCLR==220				; clear screen
%TDBEL==221				; feep!
%TDINI==222				; reset reset reset
%TDILP==223				; insert line; count
%TDDLP==224				; delete line; count
%TDICP==225				; insert character; count
%TDDCP==226				; delete character; count
%TDBOW==227				; inverse video
%TDRST==230				; reset inverse video, etc.
%TDMAX==231				; 1 + largest display code
;TYSBLK IMPSET LINCHR XONOFF DPYSET GAGOFF MODSET NTYSTS DPYBLK SETVSZ SETHSZ PADCHR PDBAUD TABFLG EDITKY DPYDES CNSBLK TCTYP TTYOPT TCMXV TCMXH TTYROL SMARTS ISPEED OSPEED CNSBLL TERMID CORBEG TERSTR HPOS VPOS SCRMST GETCXP GETCYP INDLMP ROLLP LFFLSP QUOTEP 128CHP OVRPRP PTINTP NTINTP DOQUIT PRESCP SDCMDP EATERP NODETP BKYBTS FLSCNT TERMBP TTYLIN TPCSAV IDLTIM PTIBUF PDL COREND

SUBTTL Data area

; TTYSET command words

TYSBLK==.
IMPSET:	034400,,			; IMP TTY
LINCHR:	001400,,(FCS)			; default line characteristics
XONOFF:	002400,,(XON\FULTWX)		; generate LF after CR
DPYSET:	064400,,DPYBLK			; set display characteristics
GAGOFF:	024400,,			; gag off
MODSET:	014400,,			; set DM mode
NTYSTS==.-TYSBLK

DPYBLK:	'DM2500				; Datamedia 2500
SETVSZ:	BLOCK 1				; screen height
SETHSZ:	BLOCK 1				; screen width
PADCHR:	400000,,			; padding character
PDBAUD:	400000,,			; pad baud rate (no padding)
TABFLG:	1				; have tabs
EDITKY:	0				; EDITKY bits - use default for now
DPYDES:	0				; DPYDES bits - use default for now
	BLOCK 4				; reserved bits

; Terminal characteristics

CNSBLK:	BLOCK 1				; CNSGET info
TCTYP:	%TNSFW				; TCTYP for server
TTYOPT:	%TOERS\%TOMVB\%TOMVU\%TOFCI\%TOLID\%TOCID\%TPCBS ; TTYOPT for server
TCMXV:	24.				; TTY page length
TCMXH:	79.				; TTY width
TTYROL:	0				; TTYROL variable
SMARTS:	0				; SMARTS variable
ISPEED:	0				; input speed
OSPEED:	0				; output speed
CNSBLL==.-CNSBLK

; Terminal location string

TERMID:	'TERMID

CORBEG==.				; start of initialized core storage

TERSTR:	BLOCK 20.			; console location string

; Datamedia translator variables

HPOS:	BLOCK 1				; horizontal position
VPOS:	BLOCK 1				; vertical position
SCRMST:	BLOCK 3*<VSZMAX+1>		; screen character allocation table
GETCXP:	BLOCK 1				; -1 → get cursor X position
GETCYP:	BLOCK 1				; -1 → get cursor Y position
INDLMP:	BLOCK 1				; -1 → in I/D mode
ROLLP:	BLOCK 1				; -1 → in roll mode
LFFLSP:	BLOCK 1				; -1 → flush a line feed
QUOTEP:	BLOCK 1				; -1 → quote next character
128CHP:	BLOCK 1				; -1 → FCS terminal
OVRPRP:	BLOCK 1				; -1 → TV terminal

; Interrupt flags

PTINTP:	BLOCK 1				; -1 → PTI interrupt
NTINTP:	BLOCK 1				; -1 → NTI interrupt
DOQUIT:	BLOCK 1				; -1 → QUIT interrupt

; Protocol flags

PRESCP:	BLOCK 1				; -1 → protocol escape seen
SDCMDP:	BLOCK 1				; -1 → in SUPDUP protocol command
EATERP:	BLOCK 1				; -1 → getting terminal string
NODETP:	BLOCK 1				; -1 → don't detach this guy
BKYBTS:	BLOCK 1				; -1 → incoming bucky bits

; Other storage

FLSCNT:	BLOCK 1				; flush count for NTISER
TERMBP:	BLOCK 1				; terminal byte pointer
TTYLIN:	BLOCK 1				; line number of PTY
TPCSAV:	BLOCK 1				; save of JOBTPC
IDLTIM:	BLOCK 1				; idle time in 15-second units
PTIBUF:	BLOCK 30.			; PTY input buffer
PDL:	BLOCK PDLLEN			; stack

COREND==.-1				; end of initialized storage
;INTSER CLKSER INTDIE CLKSR1

SUBTTL Interrupt server

;  Interrupts only set flags which the main program (normally in INTW⊗
; state) looks at.

INTSER:	SKIPN X,JOBCNI			; get interrupt status
	 JRST 4,.-1
	TLNE X,(INTPTO)			; PTY int
	 SETOM PTINTP
	TRNE X,INTQUIT			; QUIT int?
	 SETOM DOQUIT
	TLNE X,(INTCLK)			; CLK int
	 JRST CLKSER
	TLNE X,(INTFOP)			; output reset?
	 JRST [	MOVE JOBTPC
		MOVEM TPCSAV
		INTMSK [0]
		UWAIT
		PUSH P,TPCSAV
		INTMSK [-1]
		DEBREAK
		PUSHJ P,NETINS
		MOVEI %TDORS
		PUSHJ P,NETOCH
		JRST NETSND]
	TLNE X,(INTINP)			; NTI int
	 SETOM NTINTP
	TLNE X,(INTIMS)			; status change
	 JRST [	INTMSK [0]
		DEBREAK
		JRST SUICID]
	TLNE X,(INTINR)
	 OUTSTR [ASCIZ/*INR*
/]
	TLNE X,(INTINS)			; IMP INS int
	 OUTSTR [ASCIZ/*INS*
/]
INTSR1:	MOVSI 1,-1			; requeue into TQ from any queue
	DISMIS 1,

; Service clock interrupt

CLKSER:	AOSGE IDLTIM			; bump idle time
	 JRST INTSR1
	UNLOCK				; idle timeout; unlock
	MOVE TTYLIN
	PTGETL
	TLNE 1,(TLKRNG)			; TALKing?
	 JRST INTSR1			; don't kill him if so!
	TTYJOB
	JUMPN INTSR1
	INTMSK [0]			; no more interrupts
	DEBREAK				; out of interrupt level
	SETOM NODETP			; forget about detaching
	MOVEI X,[ASCIZ/Autologout/]
	PUSHJ P,SNDMSG
	JRST SUICID
;SUPSER CPYHST 1DIGTP NOTTIP

SUBTTL Start of program

SUPSER:	CAI
	RESET
	MOVE ['SUPSER]
	SETNAM
	SETZM CORBEG
	MOVE [CORBEG,,CORBEG+1]
	BLT COREND
	MOVE P,[PDL(-PDLLEN)]
	MOVEI [DEBREAK ? EXIT]
	MOVEM JOBAPR
	CLKINT 5.*60.*60.		; must die if around too long
	OUTSTR [ASCIZ/SUPSER started
/]

; Listen for a connection on our socket

	SETOM NODETP			; don't try to detach
	MOVEI SVRSKT
	MOVEM LSNSKT
	PUSHJ P,LISTEN

; Set up interrupts

	MOVEI INTSER
	MOVEM JOBAPR			; set up server location
	CLKINT 60.*15.			; start slow ticking clock
	MOVE [INTPTO\INTFOP\INTCLK\INTINR\INTINS\INTIMS\INTINP\INTQUIT]
	INTENB				; turn on interrupts

; Set up terminal id for interested spies

	MOVEI TERMID
	MOVEM JOBVER

; Log this connection

	OUTSTR [ASCIZ/Connected to /]
	PUSHJ P,MAPHST			; map in host table
	MOVE HOST
	PUSHJ P,HSTNUM			; get HDB
	 CAI				; sorry about errors
	MOVEI Y,(1)			; host name
	HRLI Y,440700
	SKIPA X,[440700,,TERSTR]
CPYHST:	 IDPB Z,X
	ILDB Z,Y
	JUMPN Z,CPYHST
	HLRZ Y,1			; pointer to system name
	JUMPE Y,NOTTIP			; jump if no HDB was returned (unknown name)
	MOVE Z,(Y)			; get system name
	MOVE Y,FSOCKT			; and ICP socket
	CAME Z,[ASCII/TAC/]		; on a TAC?  (with SUPDUP???)
	 CAMN Z,[ASCII/TIP/]		; on a TIP?  (with SUPDUP???)
	  TRNE Y,177774			; just paranoia; make sure a TIP port
	   JRST NOTTIP
	MOVEI Z,"#
	IDPB Z,X
	LSH Y,-16.
	IDIVI Y,8.			; ports are octal
	JUMPE Y,1DIGTP
	ADDI Y,"0 ? IDPB Y,X
1DIGTP:	ADDI Z,"0 ? IDPB Z,X
NOTTIP:	MOVEM X,TERMBP
	PUSHJ P,SETANM			; set our alias name
	PUSHJ P,UNMHST			; map out the host table
	OUTSTR TERSTR
	OUTSTR [ASCIZ/
/]
	MOVEI X,[ASCIZ/SU A.I. Lab KL-10
/]
	PUSHJ P,SNDMSG
;NOFLAK GETSIZ GETCNS CHKTRM NOTSAI

SUBTTL Paw over user console characteristics

	MOVEI X,256			; LASTDISASTERTIME
	PEEK X,
	PEEK X,
	JUMPE X,NOFLAK
	ACCTIM A,
	SUB A,X
	TLZE A,1			; forgive one day
	 ADDI A,24.*60.*60.
	CAILE A,15.*60.			; lost within 15 minutes?
	 JRST NOFLAK
	MOVEI X,[ASCIZ/System is flakey--watch out!
/]
	PUSHJ P,SNDMSG

; Get terminal characteristics

NOFLAK:	MOVE Y,[440600,,CNSBLK]		; pointer to characteristics block
	MOVEI Z,6
GETSIZ:	PUSHJ P,NETICW
	IDPB Y
	SOJG Z,GETSIZ
	HLRO X,CNSBLK
	MOVNS Z,X			; size of block
	CAILE Z,CNSBLL-1
	 MOVEI Z,CNSBLL-1		; additional args we don't know about
	IMULI Z,6
GETCNS:	PUSHJ P,NETICW
	IDPB Y
	SOJG Z,GETCNS
	CAIN X,CNSBLL-1
	 JRST CHKTRM
	CAIG X,CNSBLL			; more than we wanted?
	 JRST CHKTRM			; too few
	SUBI X,CNSBLL-1			; too many
	IMULI X,6
	PUSHJ P,NETICW			; eat extra bytes
	SOJG X,.-1

; Check terminal out

CHKTRM:	MOVE TCTYP
	CAIE %TNSFW			; software?
	 JRST [	MOVEI X,[ASCIZ/Sorry, TCTYP must be %TNSFW.
/]
		OUTSTR (X)
		PUSHJ P,SNDMSG
		INTMSK [0]
		PUSHJ P,CLOSER
		JRST SUICID]
	MOVE TTYOPT
	TLNE (%TOOVR)
	 SETOM OVRPRP			; remember overprinting!
	TLNN (%TOSAI)			; FCS terminal?
	 JRST NOTSAI
	MOVEI X,1
	IORM X,MODSET			; set DM128 bit
	SETOM 128CHP
NOTSAI:	AND [%TOERS\%TOMVB\%TOMVU\%TOFCI\%TOLID\%TOCID\%TPCBS]
	CAMN [%TOERS\%TOMVB\%TOMVU\%TOFCI\%TOLID\%TOCID\%TPCBS]
	 JRST GETPTY
	MOVEI X,[ASCIZ\Sorry, your console has insufficient display capabilities.
\]
	OUTSTR (X)
	PUSHJ P,SNDMSG
	INTMSK [0]
	PUSHJ P,CLOSER
	JRST SUICID
;GETPTY MAINL MAINL0

SUBTTL Final initialization

; Get a PTY, put its number in A and other places

GETPTY:	PTYGET A
	 JRST [	MOVEI 254		; MAINTM
		PEEK
		PEEK
		SKIPE
		 SKIPA X,[[ASCIZ/SU-AI - System being debugged, users not allowed on.
/]]
		  MOVEI X,[ASCIZ/SU-AI - All network ports in use.
/]
		PUSHJ P,SNDMSG
		INTMSK [0]
		PUSHJ P,CLOSER
		JRST SUICID]
	HRRZM A,TTYLIN			; dumb interrupts
	MOVSI (A)
	IRPS FOO,,LINCHR XONOFF GAGOFF DPYSET MODSET IMPSET
	 IORM FOO
	TERMIN

; Initialize the user's display mode

	MOVEI %TDNOP
	PUSHJ P,NETOCH
	MOVEI %TDCLR
	PUSHJ P,NETOCH
	PUSHJ P,NETSND

; And get the terminal ready

	MOVE TCMXV
	CAILE VSZMAX
	 MOVEI VSZMAX
	MOVEM TCMXV
	MOVEM SETVSZ
	MOVE TCMXH
	CAILE HSZMAX
	 MOVEI HSZMAX
	MOVEM TCMXH
	ADDI 1				; width is less 1 for the excl
	ANDCMI 7			; round down to a multiple of 8
	MOVEM SETHSZ
	MOVE [-NTYSTS,,TYSBLK]
	TTYSET				; set up TTY parameters
	MOVEI B,↑M
	PTWR1W A

; Final initialization

	MOVNI LOKTMO
	MOVEM IDLTIM			; initialize lock timeout
	LOCK				; keep response good
	SETZM NODETP			; okay to detach jobs now
	JRST NTISER			; check network input

; Main program loop

MAINL:	IWAIT				; wait for an interrupt
MAINL0:	MOVEI 2				; check connection status
	MTAPE NET,
	TLNN 1,(CLSS\CLSR)		; send side gronked?
	 TLNE 2,(CLSS\CLSR)		; receive side?
	  JRST SUICID
	AOSG NTINTP			; net input?
	 JRST NTISER
	AOSG PTINTP			; PTY input?
	 JRST PTISER
	AOSG DOQUIT			; QUIT seen?
	 JRST SUICID
	JRST MAINL			; back to sleep for us
;NTISER

SUBTTL Network input interrupt

NTISER:	PUSHJ P,NETICH			; get character from the network
	 JRST MAINL0			; network input buffer empty
	SKIPL IDLTIM
	 LOCK
	MOVNI 1,LOKTMO
	MOVEM 1,IDLTIM			; reset idle time
	AOSGE 1,FLSCNT			; flush this character?
	 JRST NTISER
	JUMPE 1,[	PUSHJ P,SNDPOS	; tell user what position really is
			JRST NTISER]
	SKIPE BKYBTS			; if have bucky bits
	 JRST PTYSN0			; forget all this cruft
	SKIPE EATERP			; getting terminal name?
	 JRST [	IDPB TERMBP		; save character
		JUMPN NTISER
		SETZM EATERP		; got it all
		JRST NTISER]
	AOSN PRESCP
	 JRST [	CAIN ↑\			; quoted?
		 JRST PTYSN0
		CAIN ↑P
		 JRST [	MOVNI 2 ? MOVEM FLSCNT
			JRST NTISER]	; flush two characters
		CAIN ↑C			; redisplay screen?
		 JRST [	PUSH P,["P]	; [BREAK]P command fixifies us
			SETZ B,
			PTWR1S A	; send first part of [ESCAPE]
			 CAI		; will lose soon enough
			MOVEI B,"-	; convert [ESCAPE] to [BREAK]
			JRST PTYSN2]
		TRZN 100		; bucky bits?
		 JRST NTISER		; losing somehow
		LSH 7
		MOVEM BKYBTS
		JRST NTISER]
	AOSN SDCMDP
	 JRST [	CAIN 301		; logout?
		 SETOM NODETP
		CAIN 302		; get terminal name?
		 JRST [	SETOM EATERP
			MOVEI ":
			IDPB TERMBP
			MOVEI <" >
			IDPB TERMBP
			JRST NTISER]
		JRST NTISER]
	CAIN 300			; start of protocol command?
	 JRST [	SETOM SDCMDP
		JRST NTISER]
	CAIN ↑\				; protocol escape command?
	 JRST [	SETOM PRESCP
		JRST NTISER]
;PTYSN0 FNYQOT PTYSN1 PTYSN2 PTYSND

; Send character to the PTY

PTYSN0:	MOVE B,
	IOR B,BKYBTS			; add in bucky bits
	SETZM BKYBTS
	MOVE X,B
	TRZ X,%TXMTA\%TXCTL		; get character without CONTROL and META
	CAIN X,%TXTOP\"β		; beta?
	 JRST @FNYQOT
	CAIE X,%TXTOP\"≡		; equivalence?
	 CAIN X,%TXTOP\"∨		; or?
FNYQOT:	  JRST [PUSH P,B
		SETZ B,			; quote with escape
		PTWR1S A
		 CAI
		POP P,B
		JRST PTYSN1]
	CAIN X,%TXTOP\"_		; underscore?
	 JRST [	MOVEI X,137
		DPB X,[000700,,B]
		JRST PTYSN1]
	CAIN X,%TXTOP\↑K		; uparrow?
	 JRST [	MOVEI X,"↑
		DPB X,[000700,,B]
		JRST PTYSN1]
	CAIN X,"←			; backarrow?
	 JRST [	MOVEI X,030
		DPB X,[000700,,B]
		JRST PTYSN1]
	CAIN X,↑Z			; [CALL]?
	 JRST [	MOVEI X,↑C		; yes, convert to our [CALL]
		DPB X,[000700,,B]
		JRST PTYSN1]
	CAIN X,%TXTOP\"A		; [ESCAPE]?
	 JRST [	SETZ B,
		JRST PTYSND]
	CAIN X,%TXTOP\"B		; [BREAK]?
	 JRST [	PUSH P,["-]
		SETZ B,
		JRST PTYSN2]
	CAIN X,%TXTOP\"C		; [CLEAR]?
	 JRST [	MOVEI B,↑↑
		JRST PTYSND]
PTYSN1:	TRZ B,%TXTOP			; flush top now
	TRZN B,%TXMTA			; meta set?
	 JRST PTYSND
	PUSH P,B
	MOVEI B,200			; <EDIT>[NULL]
PTYSN2:	PTWR1S A			; send prefix meta command
	 CAI				; will lose soon enough
	POP P,B
PTYSND:	PTWR1S A			; send character to PTY
	 JRST [	MOVEI %TDBEL		; bell
		PUSHJ 17,NETOCH
		PUSHJ 17,NETSND		; output it
		JRST NTISER]
	JRST NTISER			; try for more user characters
;PTISER PTISR1 CHKCYP CHKDMC DMSND DMSND0 MRKNBL ISPCH NOTPCH

SUBTTL PTY input interrupt

PTISER:	MOVE B,[441140,,PTIBUF]
	PTRDS A				; read buffer from PTY
	ILDB B
	JUMPE [	PUSHJ P,NETSND		; buffer empty, force output out
		JRST MAINL0]
	SKIPA D,
PTISR1:	 ILDB D,B
	JUMPE D,PTISER
	MOVNI LOKTMO
	MOVEM IDLTIM			; reset idle time
	ANDI D,377			; flush funny 400 bit
	AOSN LFFLSP			; flush a line feed?
	 CAIE D,↑J
	  CAIA
	   JRST PTISR1
	AOSN QUOTEP			; quote frob?
	 JRST DMSND
	AOSN GETCXP			; set X position?
	 CAIG D,↑←			; yes, abort?
	  JRST CHKCYP
	XORI D,140
	CAMLE D,TCMXH			; beyond screen limit?
	 SETZ D,
	MOVEM D,HPOS
	SETOM GETCYP
	JRST PTISR1

CHKCYP:	AOSN GETCYP			; set Y position?
	 CAIG D,↑←			; yes, abort?
	  JRST CHKDMC
	XORI D,140
	CAML D,TCMXV			; beyond screen limit?
	 SETZ D,
	MOVEM D,VPOS
	JRST SETCPS			; finally set position

CHKDMC:	CAIG D,<" >			; DM command?
	 XCT DMCTAB(D)
DMSND:	CAIN D,013			; integral sign?
	 JRST [	MOVEI D,177
		JRST DMSND0]
	CAIN D,"_			; underscore?
	 JRST [	MOVEI D,137
		JRST DMSND0]
	SKIPN 128CHP
	 JRST DMSND0
	CAIN D,"↑			; uparrow?
	 JRST [	MOVEI D,013
		JRST DMSND0]
	CAIN D,"←			; backarrow?
	 JRST [	MOVEI D,030
		JRST DMSND0]
	CAIN D,177			; circumflex?
	 JRST [	MOVEI D,136
		JRST DMSND0]
DMSND0:	CAIL D,200			; a %TD code?
	 JRST NOTPCH
	SKIPN OVRPRP
	 JRST ISPCH
	PUSHJ P,GETSMD
	TDNN X,(Y)
	 JRST MRKNBL			; position already blank
	MOVEI %TDDLF			; delete character at this position
	PUSHJ P,NETOCH
MRKNBL:	IORM X,(Y)			; mark position as non-blank
ISPCH:	AOS HPOS			; no, account for character
NOTPCH:	MOVE D
	PUSHJ P,NETOCH
	JRST PTISR1
;SCLEAR CANCEL CLEOL SETCPS SNDPOS INSLIN IDCMND SPACE FORSPC

; Datamedia conversion subroutines

SCLEAR:	MOVEI %TDCLR			; clear screen
	PUSHJ P,NETOCH
	SETZM HPOS			; home up
	SETZM VPOS
	SKIPN OVRPRP
	 JRST CANCEL
	SETZM SCRMST			; clear screen bit mask
	MOVE [SCRMST,,SCRMST+1]
	BLT SCRMST+3*VSZMAX-1
	CAIA				; roll isn't cancelled by this
CANCEL:	 SETZM ROLLP
	SETZM INDLMP
;	MOVEI %TDRST
;	PUSHJ P,NETOCH
	JRST PTISR1

CLEOL:	MOVEI %TDEOL
	PUSHJ P,NETOCH
	SKIPN OVRPRP
	 JRST PTISR1
	PUSHJ P,GETSMD
	ANDCAM X,(Y)			; flag current position as blank
	SUBI X,1
	ANDCAM X,(Y)			; flag rest of word as blank
	CAIE Z,2
	 SETZM 1(Y)			; 0 or 1 → flag next word as blank
	JUMPN Z,PTISR1
	SETZM 2(Y)			; 0 → flag word after that as blank
	JRST PTISR1

SETCPS:	PUSHJ P,SNDPOS
	JRST PTISR1

SNDPOS:	MOVEI %TDMV0			; set cursor position
	PUSHJ P,NETOCH
	MOVE VPOS
	CAML TCMXV			; beyond screen limit?
	 SETZB VPOS			; paranoia for dumb ITS SUPDUP
	PUSHJ P,NETOCH
	MOVE HPOS
	CAMLE TCMXH
	 SETZM HPOS
	JRST NETOCH

INSLIN:	MOVEI %TDILP
	SKIPN OVRPRP
	 JRST IDCMND
	MOVEI X,VSZMAX-1
	SUB X,VPOS			; # of lines to move
	IMULI X,3
	ADDI X,377777			; # of lines-1 w/ sign bit
	HRL X,X
	HRRI X,SCRMST+3*<VSZMAX-1>-1	; source address
	POP X,3(X)			; reverse BLT
	JUMPL X,.-1
IDCMND:	PUSHJ P,NETOCH			; insert/delete mode command
	MOVEI 1
	PUSHJ P,NETOCH
	JRST PTISR1

SPACE:	SKIPN OVRPRP
	 JRST ISPCH
	MOVEI %TDDLF
	PUSHJ P,NETOCH
	PUSHJ P,GETSMD
	ANDCAM X,(Y)			; flag position as blank
FORSPC:	MOVEI %TDFS			; forespace
	PUSHJ P,NETOCH
	AOS HPOS
	JRST PTISR1
;DMCTAB

SUBTTL Datamedia command table

DMCTAB:	JRST PTISR1			; ↑@ no-op
	JRST PTISR1			; ↑A no-op
	JRST [	SETZM HPOS		; ↑B home up
		SETZM VPOS
		JRST SETCPS]
	JRST PTISR1			; ↑C no-op
	JRST PTISR1			; ↑D no-op
	JRST PTISR1			; ↑E no-op
	JRST PTISR1			; ↑F no-op
	MOVEI D,%TDBEL			; ↑G bell
	JRST [	SKIPE INDLMP		; ↑H backspace/delete character
		 JRST [	MOVEI %TDDCP
			SKIPN OVRPRP
			 JRST IDCMND
			PUSHJ P,GETSMD
			MOVE D,(Y)
			LSH X,1
			SUBI X,1	; mask for bits being hacked
			ANDCAM X,(Y)
			LSH D,1		; shift characters over
			AND D,X
			IORM D,(Y)
			CAIN Z,2
			 JRST IDCMND
			MOVEI C,1	; bit to bring in previous words if needed
			MOVE D,1(Y)
			LSH D,1		; shift characters over
			TLZE D,(1←32.)
			 IORM C,(Y)	; bring in overflow to next word
			MOVEM D,1(Y)
			JUMPN Z,IDCMND	; if last word flush
			MOVE D,2(Y)
			LSH D,1
			TLZE D,(1←32.)
			 IORM C,1(Y)
			MOVEM D,2(Y)
			JRST IDCMND]
		SOSGE HPOS
		 SETZM HPOS
		JRST SETCPS]
	JRST [	MOVE HPOS		; ↑I tab
		TRZ 7
		ADDI 8.
		MOVEM HPOS
		JRST SETCPS]
	JRST [	SKIPE INDLMP		; ↑J line feed/insert line
		 JRST INSLIN
		AOS VPOS
		JRST SETCPS]
	JRST PTISR1			; ↑K tab clear (no-op)
	JRST [	SETOM GETCXP		; ↑L cursor position
		JRST PTISR1]
	JRST [	AOS X,VPOS		; ↑M terpri
		SETZM HPOS
		SETOM LFFLSP
		SKIPN ROLLP		; scrolling?
		 JRST [	CAML X,TCMXV	; not scrolling; gone off bottom?
			 SETZM VPOS	; yes, wrap around to top of screen
			JRST SETCPS]	; use %TDMV0 to move cursor
		MOVEI %TDCRL		; scrolling, use %TDCRL instead
		PUSHJ P,NETOCH
		CAMGE X,TCMXV
		 JRST PTISR1
		MOVE TCMXV		; somehow we scrolled
		SOS
		MOVEM VPOS
		MOVE [SCRMST+3,,SCRMST]
		BLT SCRMST+3*VSZMAX-1
		JRST PTISR1]
;	MOVEI D,%TDBOW			; ↑N blink on (set complement mode)
	JRST PTISR1			; ↑N blink on (no op for now)
	JRST PTISR1			; ↑O bold on (no-op)
	JRST [	SETOM INDLMP		; ↑P enter I/D mode
		JRST PTISR1]
;DMCTAB...

	JRST PTISR1			; ↑Q transmit page to computer (no-op)
	JRST PTISR1			; ↑R transmit page to printer (no-op)
	JRST PTISR1			; ↑S transmit line to computer (no-op)
	JRST PTISR1			; ↑T no-op
	JRST PTISR1			; ↑U no-op
	JRST PTISR1			; ↑V no-op
	JRST CLEOL			; ↑W erase to end of line
	JRST CANCEL			; ↑X cancel bold, I/D, roll
	JRST PTISR1			; ↑Y set tab (no-op)
	JRST [	SKIPE INDLMP		; ↑Z line starve/delete row
		 JRST [	MOVEI %TDDLP
			SKIPN OVRPRP
			 JRST IDCMND
			MOVE X,VPOS
			LSH X,1
			ADD X,VPOS
			ADDI X,SCRMST
			HRLI X,3(X)
			BLT X,SCRMST+3*VSZMAX-1
			JRST IDCMND]
		SOSGE VPOS
		 SETZM VPOS
		JRST SETCPS]
	JRST [	SETOM QUOTEP		; ↑[ quote FCS character
		JRST PTISR1]
	JRST [	SKIPN INDLMP		; ↑\ forespace/insert character
		 JRST FORSPC
		MOVEI %TDICP
		SKIPN OVRPRP
		 JRST IDCMND
		PUSHJ P,GETSMD
		MOVE D,(Y)
		LSH X,1
		SUBI X,1		; fill in mask to the right
		ANDCAM X,(Y)
		AND D,X
		LSHC D,-1
		IORM D,(Y)
		CAIN Z,2
		 JRST IDCMND
		MOVE D,1(Y)
		SKIPGE C
		 TLO D,(1←31.)		; bring in bit from previous word
		LSHC D,-1
		MOVEM D,1(Y)
		JUMPN Z,IDCMND
		MOVE D,2(Y)
		SKIPGE C
		 TLO D,(1←31.)
		LSH D,-1
		TRZ D,100000		; flush overflow bit
		MOVEM D,2(Y)
		JRST IDCMND]
	JRST [	SETOM ROLLP		; ↑] roll on
		JRST PTISR1]
	JRST SCLEAR			; ↑↑ master clear
	JRST SCLEAR			; ↑← erase screen
	JRST SPACE			; sp delete character and forespace
IFN .-DMCTAB-1-" ,.ERR DMCTAB loses!
;GETSMD BITTAB SNDMSG MSGLUP ERRDIE SUICID DIEDIE ...LIT SVRRTS ERRTNS ERRHAN ERRINS HSTTAB HSTSIX

SUBTTL Subroutines

; Get screen mask data in Y, Z, X

GETSMD:	MOVE Y,VPOS
	LSH Y,1
	ADD Y,VPOS
	MOVE Z,HPOS
	LSH Z,-5			; Z ← word index in line (for cleol)
	ADDI Y,SCRMST(Z)		; Y ← addr of screen mask word
	MOVE X,HPOS
	ANDI X,37
	MOVE X,BITTAB(X)		; X ← mask for this byte
	POPJ P,

; Bit table

BITTAB:	REPEAT 32.,1←<31.-.RPCNT>	; bit table

; Send a message, b.p. in X

SNDMSG:	TLOA X,440700			; set up b.p.
MSGLUP:	 PUSHJ P,NETOCH
	ILDB X
	JUMPN MSGLUP			; continue until a null hit
	JRST NETSND

; Here to suicide on network errors or idle timeout

ERRDIE:	INTMSK [0]
SUICID:	OUTSTR [ASCIZ/Connection closed.
/]
	SKIPE NODETP
	 JRST DIEDIE			; logout the guy
	MOVE TTYLIN
	TTYJOB
	JUMPE DIEDIE
	MOVE A,TTYLIN
	MOVEI B,7
	PTJOBX A			; clear PTY's input buffer
	MOVEI 2
	MOVEI B,10			; DETACH
	PTJOBX A
	 JRST [SLEEP ? JRST .-1]
	SLEEP
	PTRD1S A			; slurp up stuff in buffer
	 CAIA
	  JRST .-2
DIEDIE:	RESET ? EXIT

...LIT:	CONSTANTS

; Wonderful network routines

SVRRTS==-1				; include server routines
ERRTNS==-1				; include error routines
ERRHAN==-1				; include automagic error handling
ERRINS==<JRST ERRDIE>			; error instruction
HSTTAB==-1				; include host table magic
HSTSIX==-1				; and alias name kludge

.INSRT NETWRK

END SUPSER