perm filename CHTSER.MID[S,NET]5 blob
sn#776188 filedate 1984-11-14 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00007 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 A INTPTO INTPTI INTCLK INTIMS INTINP IODTER IOBKTL IODEND ECHARR FCS TBXPND FULTWX XON TLKRNG INTBTS
C00005 00003 CORBEG INBUFH OUTBFH GOTINT FLSCHP TTYLIN PTIBUF COREND LPDL PDL LSNBLK LSNSTS LSNFSK HOST SMRBLK RMRBLK INPBLK ECHOFF TYSBLK IMPSET LINCON LINCOF GAGOFF NTYSTS TERMID TERSTR CLKTIM IDLECT WORKED MAXIDL DOQUIT
C00008 00004 INTRPT CHTSER
C00011 00005 FOO1 FOO2 FOO3 FOO4
C00015 00006 LOOPCL TIMEIN LOOP0 PUPLP0 PUPLP1 PUPIC0
C00019 00007 PUPICH PTILP0 PTILP2 PTILUP PUPSND TIMOUT CLOSED GOAWAY GOAWA2 GOAWA3
C00025 ENDMK
C⊗;
;A INTPTO INTPTI INTCLK INTIMS INTINP IODTER IOBKTL IODEND ECHARR FCS TBXPND FULTWX XON TLKRNG INTBTS
TITLE CHTSER
SUBTTL Definitions
; Mark Crispin, SU-AI, February '81
; Ethernet TELNET server -- save as PUP001.DMP[NET,SYS] for normal use.
; NOTE: This is eventually to be replaced by regular version of TELSER
printx /Save as PUP001.DMP[NET,SYS] for normal use.
/
; AC definitions. 0→7 are used by NETWRK
X=10 ? A=11 ? B=12 ? C=13 ? D=14 ? P=17
; System definitions
INTPTO==001000,, ; PTY output interrupt
INTPTI==010000,, ; PTY-needs-input interrupt
INTCLK==000200,, ; clock interrupts
INTIMS==000020,, ; closed interrupt
INTINP==000010,, ; input interrupt
INTQUIT==002000 ; (right half) interrupt on monitor QUIT cmd
INTBTS==INTPTO\INTCLK\INTINP\INTIMS\INTQUIT
JOBCNI=126 ; loc containing interrupt bits upon interrupt
IODERR==200000 ; Some kind of error
IODTER==100000 ; Host dead
IOBKTL==040000 ; Mark seen
IODEND==020000 ; End seen
TMO== 000200 ; Timeout
ECHARR==010000,, ; echo controls with uparrow
FCS== 000020,, ; full character set
TBXPND==000010,, ; software tabs
FULTWX==000004,, ; no echo
XON== 000002,, ; paper tape mode
TLKRNG==000001,, ; in talk ring
; Macros
DEFINE FATAL TEXT
JRST [ OUTSTR [ASCIZ\!TEXT
\]
EXIT 1,
JRST .-1]
TERMIN
;⊗ CORBEG INBUFH OUTBFH GOTINT FLSCHP TTYLIN PTIBUF COREND LPDL PDL LSNBLK LSNSTS LSNFSK HOST SMRBLK RMRBLK INPBLK ECHOFF TYSBLK IMPSET LINCON LINCOF GAGOFF NTYSTS TERMID TERSTR CLKTIM IDLECT WORKED MAXIDL DOQUIT
SUBTTL Data area
CORBEG==. ; first loc zeroed at init time
INBUFH: BLOCK 3 ; input buffer header
OUTBFH: BLOCK 3 ; output buffer header
GOTINT: BLOCK 1 ; -1 → got an interrupt
FLSCHP: BLOCK 1 ; -1 → ignore following character
TTYLIN: BLOCK 1 ; remember PTY line number here
PTIBUF: BLOCK 30. ; PTY input buffer
COREND==.-1
LPDL==40
PDL: BLOCK LPDL ;stack
LSNBLK: 1 ;Opcode = LISTEN
LSNSTS: 0 ;Status
1 ;Local socket (GENSYM)
-1 ;Wait for connection
8 ;Bytesize (checked, but not used by PUP)
LSNFSK: -1 ;Foreign socket
HOST: 0 ;Host number
SMRBLK: 25 ; send Mark
0 ; status word
6 ; Timing Mark Reply
RMRBLK: 26 ; read last Mark
0 ; status word
0 ; Mark type returned here
INPBLK: 10 ; skip if input available
0 ; status word
ECHOFF: 001400,,(FULTWX) ; echo off
TYSBLK==. ; TTYSET command block
IMPSET: 034400,, ; IMP TTY
LINCON: 001400,,(ECHARR\FCS\TBXPND) ; default line chars
LINCOF: 002400,,(XON\FULTWX)
GAGOFF: 024400,, ; gag off
NTYSTS==.-TYSBLK
TERMID: 'TERMID ; terminal ID for FINGER
TERSTR: BLOCK 10.
CLKTIM==15.*60. ; time between clock ints (some seconds)
IDLECT: 0 ; count of times through main loop while idle
WORKED: -1 ; nonzero if did work this time around main loop
MAXIDL==3 ; idle count at which we go away if no job
DOQUIT: 0 ; nonzero if seen QUIT cmd on PTY
;INTRPT CHTSER
SUBTTL Start of program
;Interrupt routine
INTRPT: SETOM GOTINT
MOVE A,JOBCNI ; get cause of interrupt
TRNE A,INTQUIT ; is this a QUIT interrupt?
SETOM DOQUIT ; yes, tell main routine to go away
DISMIS
;Main program
CHTSER: CAI
RESET ; flush all I/O
MOVE ['CHTSER]
SETNAM
MOVE P,[-LPDL,,PDL-]
PTYGET A ; snarf a PTY
FATAL Unable to get any PTY
HRRZM A,TTYLIN
SETZM DOQUIT ; haven't seen QUIT cmd yet
SETZM IDLECT ; haven't been idle yet
INIT
SIXBIT/PUP/
OUTBFH,,INBUFH
JRST 4,.-1
MOVEI 8. ; change byte size in buffer header
DPB [300600,,INBUFH+1]
DPB [300600,,OUTBFH+1]
INBUF
OUTPUT ; for some reason OUTBUF loses
SETSTS ; kill IOIMPM bit
MTAPE LSNBLK ; accept the connection
MOVE LSNSTS ; check for MTAPE error
STATO 467600
TRNE 77
FATAL Listen failed
MOVS TTYLIN ; set up TTYSET command words
IRPS FOO,,ECHOFF IMPSET LINCON LINCOF GAGOFF
IORM FOO
TERMIN
HRROI ECHOFF
TTYSET
MOVE A,TTYLIN ; get TTY line number back
MOVEI B,[ASCIZ/Hello
/]
PTWRS7 A
MOVE [-NTYSTS,,TYSBLK] ; set up initial TTY status
TTYSET
LOCK
MOVEI INTRPT
MOVEM JOBAPR ; set up interrupt server address
CLKINT CLKTIM ; set up keep alive time (also used for idle check)
MOVE [INTBTS]
INTENB ; enable interrupts
;FOO1 FOO2 FOO3 FOO4
MOVEI TERMID
MOVEM JOBVER
; Log this connection
OUTSTR [ASCIZ/Connected to /]
IOPUSH 0, ; preserve our one and only IO channel
JRST 4,. ; IO stack overflow!
PUSHJ P,MAPHST ; map in host table
MOVE HOST
HRLI 0,(NW%SU) ; set network field in host number
PUSHJ P,HSTNUM ; get HDB
CAI ; sorry about errors
MOVEI A,(1) ; host name
MOVE X,[440700,,TERSTR]
LDB 2,[000600,,LSNFSK] ;Get low-order bits of foreign socket
PUSHJ P,TTYSTR ;Try to get TTY location string
JRST CPYNET ;Failed
MOVE A,1 ;TTYSTR returns a byte ptr
JRST CPYHST
CPYNET: HRLI A,440700
PUSH P,A ;Save byte ptr to host name
SKIPA A,[440700,,[ASCIZ/Ethernet /]]
IDPB B,X
ILDB B,A
JUMPN B,.-2
POP P,A ;Now copy host name
CAIA
IDPB B,X
CPYHST: ILDB B,A
JUMPN B,.-2
repeat 0,[ ;no TACs on Ethernet
HLRZ A,1 ; pointer to system name
MOVE B,(A) ; get system name
MOVE A,FSOCKT ; and ICP socket
CAME B,[ASCIZ/TAC/] ; TACs are llke TIPs
CAMN B,[ASCII/TIP/] ; on a TIP?
TRNE A,177774 ; just paranoia; make sure a TIP port
JRST NOTTIP
MOVEI B,"#
IDPB B,X
LSH A,-16.
IDIVI A,8. ; ports are octal
JUMPE A,1DIGTP
ADDI A,"0 ? IDPB A,X
1DIGTP: ADDI B,"0 ? IDPB B,X
];repeat 0
NOTTIP: MOVEI B,0
IDPB B,X
PUSHJ P,SETANM ; set our alias name
PUSHJ P,UNMHST ; map out the host table
OUTSTR TERSTR
OUTSTR [ASCIZ/
/]
IOPOP 0, ; restore IO channel
JRST 4,. ; no such channel!
repeat 0,[
MOVE A,[440700,,TERSTR]
SKIPA B,[440700,,[ASCIZ/Ethernet host /]]
IDPB A
ILDB B
JUMPN .-2
LDB B,[101000,,HOST] ; get network number
IDIVI B,100 ; split into separate parts
IDIVI C,10
JUMPE B,[JUMPE C,FOO2
JRST FOO1]
ADDI B,"0
IDPB B,A
FOO1: ADDI C,"0
IDPB C,A
FOO2: ADDI D,"0
IDPB D,A
MOVEI "# ; network/host delimiter
IDPB A
LDB B,[001000,,HOST] ; get host number
IDIVI B,100 ; split into separate parts
IDIVI C,10
JUMPE B,[JUMPE C,FOO4
JRST FOO3]
ADDI B,"0
IDPB B,A
FOO3: ADDI C,"0
IDPB C,A
FOO4: ADDI D,"0
IDPB D,A
SETZ ; tie off line
IDPB A
];repeat 0
JRST LOOP0
;LOOPCL TIMEIN LOOP0 PUPLP0 PUPLP1 PUPIC0
SUBTTL Main program
LOOPCL: AOS A,IDLECT ; increment idle count
SKIPE WORKED ; were we really idle?
TIMEIN: SETZB A,IDLECT ; no, restart count
SKIPE DOQUIT ; QUIT cmd seen?
JRST GOAWAY ; yes, close up shop
CAIL A,MAXIDL ; idle too long?
JRST TIMOUT ; yes, see if any job on our pty
comment $
outchr [60
61
62
63
64](A)
skipe gotint
outchr [56] ;"." $
SKIPN GOTINT ; got an interrupt?
IMSTW [INTBTS] ; no, wait for an interrupt to happen
LOOP0: INTMSK [0] ; mask off all interrupts
SETZM GOTINT ; flag no interrupts here
SETZM WORKED ; haven't found any useful work to do yet
PUPLP0: SOSLE INBUFH+2 ; any data in buffer?
JRST PUPICH ; yes, go read a char
HRRZ A,INBUFH ; no, look for more buffers
HRRZ A,(A)
SKIPGE (A) ; anything in further buffers?
JRST PUPLP1 ; yes, get it
MTAPE INPBLK ; no, anything in system?
JRST PTILP0 ; no, look for some output from pty
PUPLP1: SETOM WORKED ; supposedly we'll find something to do
; outchr [156] ;n
IN ; get the buffer
JRST PUPIC0
GETSTS A
TRNE A,IODEND\IODTER\IODERR\TMO ; End or error seen?
JRST CLOSED
TRZN A,IOBKTL ; Mark seen?
JRST 4,.-1
;; SETSTS (A) ; clear status [no longer needed]
MTAPE RMRBLK ; read the mark
JRST CLOSED
MOVE RMRBLK+2 ; get Mark type
;; Until implemented
;; CAIN 1 ; Data Mark?
;; AOS NTOINP
CAIN 5 ; Timing Mark?
JRST [ MTAPE SMRBLK ; yes, send Timing Mark Reply
JRST CLOSED
JRST PUPLP0]
CAIL 2 ; between Line Width
CAILE 4 ; and Terminal Type?
JRST PUPLP0 ; no, ignore
SETOM FLSCHP ; yes, ignore one byte
JRST PUPLP0
PUPIC0: MOVE A,INBUFH ;Get address of buffer
ADD A,1(A) ;Address last word in buffer
; LDB A,[POINT 4,1(A),35] ;Get padding information
LDB A,[ 000400+A,,1]
SKIPG A,[0?-1?2?-2?4?5?6?-3?10?11?12?13?14?15?16?17](A)
;Should NEVER skip
ADDB A,INBUFH+2 ;Update byte count
JRST PUPICH
;PUPICH PTILP0 PTILP2 PTILUP PUPSND TIMOUT CLOSED GOAWAY GOAWA2 GOAWA3
PUPICH: MOVE C,TTYLIN
ILDB D,INBUFH+1
AOSN FLSCHP ; send character to PTY unless need to ignore
JRST PUPLP0
PTWR1S C
AOSA INBUFH+2 ; failed, backup the byte count, input buffer full
JRST PUPLP0
MOVSI A,100000
ADDM A,INBUFH+1 ; backup the byte pointer
STATZ IODEND ; connection closed?
JRST CLOSED ; yes, go away
MOVE A,TTYLIN ; read buffer from PTY
MOVE B,[441140,,PTIBUF]
PTRDS A ; read without waiting
ILDB B
JUMPN PTILP2 ; jump if read anything from PTY
MOVEI 0,1
SLEEP 0, ; sleep a second, maybe PTY will read some input
MOVE B,[441140,,PTIBUF]
PTRDS A ; read without waiting
ILDB B
JUMPN PTILP2 ; jump if read anything from PTY
ILDB D,INBUFH+1 ; get back the char
SOS INBUFH+2 ; decrement the count again
PTWR1S C ; one last attempt to send char to PTY
TDZA B,B ; lost, echo bell, set up empty byte ptr
JRST PUPLP0 ; won at last
MOVEI ↑G ; a bell to warn of input buffer full
JRST PTILP2 ; send the bell back
PTILP0: STATZ IODEND ; connection closed?
JRST CLOSED ; yes, go away
MOVE A,TTYLIN ; read buffer from PTY
MOVE B,[441140,,PTIBUF]
PTRDS A ; read without waiting
ILDB B
JUMPE LOOPCL ; jump if didn't read anything from PTY
PTILP2: SETOM WORKED ; we found something, so haven't been idle
; outchr [120] ;P
PTILUP: ANDI 377
SOSG OUTBFH+2
OUT ; full, no need to mess with padding
CAIA
JRST CLOSED
IDPB OUTBFH+1
ILDB B
JUMPN PTILUP
PUPSND: MOVE A,OUTBFH+2
ANDI A,3
MOVE A,[0
1
3
7](A)
SKIPLE OUTBFH ; set fill bits only if buffers are setup properly
DPB A,[ 000420,,OUTBFH+1]
; POINT 4,@OUTBFH+1,35 ; Sigh... This can't be in a literal???
OUTPUT ; send the buffer
JRST PUPLP0 ; Go look for more output, after checking
; first checking for pending input.
TIMOUT: HRRZ A,TTYLIN ; number of our pty
TTYJOB A, ; see if any job on the pty
JUMPN A,TIMEIN ; jump if job logged in, or pty INITed/ASSIGNed
HRRZ A,TTYLIN ; pty number
PTGETL A ; get line characteristics
TLNE B,(TLKRNG) ; is pty in a talk ring?
JRST TIMEIN ; pty in talk ring, stick around longer
; close
OUTSTR [ASCIZ/Idle too long, no job logged in, quitting/]
; movei 63 ;hang around a little to allow debugging
; sleep
; sleep
EXIT
CLOSED: OUTSTR [ASCIZ/Connection closed/]
JRST GOAWA3
GOAWAY: OUTSTR [ASCIZ/QUIT cmd seen; closing connection./]
JRST GOAWA3
GOAWA2: MOVEI A,1
SLEEP A, ; wait for chance to place forced command
GOAWA3: HRRZ A,TTYLIN ; number of our pty
MOVEI B,10 ; detach command
PTJOBX A ; detach any job still here
JRST GOAWA2 ; try again in a moment
MOVEI A,1
SLEEP A, ; wait for detach to happen before flushing PTY
EXIT
; Wonderful network routines
SVRRTS==0 ; no server routines
ERRTNS==0 ; no error routines
ERRHAN==0 ; no automagic error handling
;ERRINS==<JRST ERRDIE> ; no error instruction
HSTTAB==-1 ; include host table magic
HSTSIX==-1 ; and alias name kludge
TTYSTS==-1 ;and TTY location string code
.INSRT NETWRK
END CHTSER