Google
 

Trailing-Edge - PDP-10 Archives - BB-Y390U-BM - t20src/ptycon.mac
There are 31 other files named ptycon.mac in the archive. Click here to see a list.
;Edit 19 to PTYCON.MAC by LOMARTIRE on Tue 15-Nov-83
;		Fix "Byte count too small" errors with LOG, GET, and SAVE
;Edit 18 to PTYCON.MAC by LOMARTIRE on Thu 1-Sep-83, for SPR #19489
;		Ensure that the filename buffers do not overflow;
;;		Also, add SAVBUF for the SAVE command filename buffer
;Edit 17 by LOMARTIRE on Wed 6-Apr-83, for SPR #18532
;		Fix hanging while processing commands from .ATO file
; UPD ID= 65, FARK:<5-1-WORKING-SOURCES.UTILITIES>PTYCON.MAC.4,   2-Dec-82 11:53:20 by LOMARTIRE
;Edit 16 - Restrict access to PTY JFNs so that lower EXECs don't CLOSE them
; UPD ID= 18, FARK:<5-WORKING-SOURCES.UTILITIES>PTYCON.MAC.3,   5-May-82 13:15:16 by MOSER
;EDIT 15 - CHANGE EDIT NUMBER TO 15.
; UPD ID= 5, FARK:<5-WORKING-SOURCES.UTILITIES>PTYCON.MAC.2,   5-Apr-82 09:14:41 by DONAHUE
;Edit 8 - Release log file at exit so LPT files printed
;<5.UTILITIES>PTYCON.MAC.7, 28-Oct-81 15:34:11, EDIT BY GRANT
;Change major version to 5
; UPD ID= 23, SNARK:<5.UTILITIES>PTYCON.MAC.6,  13-Aug-81 09:40:16 by DONAHUE
;TCO 5.1452 - Log the filename to a GET command into the log file
; UPD ID= 20, SNARK:<5.UTILITIES>PTYCON.MAC.5,   6-Aug-81 15:27:30 by DONAHUE
;TCO 5.1445 - If <esc> terminates jobname in DEFINE command, wait for more input
; UPD ID= 1768, SNARK:<5.UTILITIES>PTYCON.MAC.4,  25-Mar-81 17:48:44 by GRANT
;Update Copyright
; UPD ID= 1500, SNARK:<5.UTILITIES>PTYCON.MAC.3,  26-Jan-81 16:53:59 by MURPHY
;UPDATE LOG FILE LESS OFTEN
;IMPLEMENT SAVE (INPUT TO FILE) COMMAND
; UPD ID= 997, SNARK:<5.UTILITIES>PTYCON.MAC.2,  11-Sep-80 10:55:07 by SCHMITT
;TCO 5.1143 - Replace DING fork with a TIMER mechanism for dinging terminal
; UPD ID= 379, SNARK:<4.1.UTILITIES>PTYCON.MAC.3,  26-Mar-80 15:49:52 by KONEN
;TCO 4.1.1125 -- Correct PTY buffers overlapping each other
; UPD ID= 243, SNARK:<4.1.UTILITIES>PTYCON.MAC.2,   4-Feb-80 14:53:28 by MURPHY
;PREVENT HANG WHEN HIGH OUTPUT RATE FROM SUBJOB ON 2020 (TIMING PROB)
;<4.UTILITIES>PTYCON.MAC.9, 24-Oct-79 15:38:07, EDIT BY ENGEL
;ADD CODE TO AT PTYOU3 TO CHECK FOR PTY BUFFER FULL.  DO DIBE IF IT IS FULL.
;<4.UTILITIES>PTYCON.MAC.8,  9-Oct-79 17:12:38, Edit by SCHMITT
;TCO 4.2522 - Remove RLJFN after GET for push to EXEC and supporting changes
;<4.UTILITIES>PTYCON.MAC.7, 27-Sep-79 18:10:48, EDIT BY SCHMITT
;TCO 4.2497 - Cure ghost characters from appearing in PTY's input buffer
;<4.UTILITIES>PTYCON.MAC.6, 13-May-79 13:38:16, EDIT BY MILLER
;<4.UTILITIES>PTYCON.MAC.5, 12-May-79 13:12:46, EDIT BY MILLER
;<4.UTILITIES>PTYCON.MAC.4, 12-May-79 13:11:59, EDIT BY MILLER
;<4.UTILITIES>PTYCON.MAC.3, 12-May-79 13:09:56, EDIT BY MILLER
;MORE
;<4.UTILITIES>PTYCON.MAC.2, 11-May-79 15:45:23, EDIT BY MILLER
;MAKE VARIOUS FIXES TO INSURE THAT CHARACTERS TYPED ON THE TTY
; HAVE THE CORRECT PARITY.
;<4.UTILITIES>PTYCON.MAC.1, 12-Mar-79 14:13:24, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980,1981 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	TITLE PTYCON - CONTROLLER FOR JOBS ON PTY'S
	SUBTTL PETER M. HURLEY  APRIL 18,1974

	SEARCH MONSYM,MACSYM
	IFNDEF .PSECT,<
	.DIRECT .XTABM>

	SALL

; VERSION NUMBER DEFINITIONS

VMAJOR==5		;MAJOR VERSION OF PTYCON
VMINOR==0		;MINOR VERSION NUMBER
VEDIT==^D19		;EDIT NUMBER
VWHO==0			;GROUP WHO LAST EDITED PROGRAM (0=DEC DEVELOPMENT)

VPTYCN== <VWHO>B2+<VMAJOR>B11+<VMINOR>B17+VEDIT

	A=1			;TEMPORARY AC, NOT SAVED BY SUBROUTINES
	B=2			;TEMP
	C=3			;TEMP
	D=4			;TEMP
	E=5			;TEMP
	Q1=6			;PRESERVED ACS, MUST BE SAVED
	Q2=7			;PRESERVED AC
	Q3=10			;PRESERVED AC
	P1=11			;PRESERVED AC
	P2=12			;PRESERVED AC
	P3=13			;PRESERVED AC
	P4=14			;PRESERVED AC
	I=15			;PRESERVED, HOLDS CURRENT SUBJOB INDEX
	P=17			;PUSH DOWN AC

	MAXPTC==^D80		;SIZE OF THE PTY BUFFER

PTYNCH==6			;# OF INTERRUPT CHANNELS FOR PTY'S
PTYCHN==^D24			;STARTING AT 24, 2 CHANNELS PER PTY



;FLAGS IN LEFT HALF OF PTYSTS

	PTIGNF==1		;IGNORE OUTPUT FROM THIS PTY
	PTREFF==2		;REFUSE OUTPUT FROM THIS PTY

STDECH=="X"-100			;STANDARD ESCAPE CHARACTER
STDESC==1B<STDECH>		;CHANNEL MASK FOR ESCAPE CHARACTER
CNTRLO==1B15			;CONTROL-O MASK
TABSIZ==13			;WIDTH OF A TAB FOR THE WHAT COMMAND
DEFINE BUG(X,Y)<
	JRST [PUSH P,A
		HRROI A,[ASCIZ/
? UNEXPECTED PTYCON ERROR: Y
/]
		PUSHJ P,TTSOUT
		POP P,A
	IFIDN <X> <HLT>,<HALTF>
		JRST .+1]>

DEFINE ERRMES (MESSAGE)<
	PUSHJ P,[MOVEI A,100	;CLEAR TYPE AHEAD
		CFIBF
		PUSHJ P,CHKLM	;ON LEFT MARGIN?
		  PUSHJ P,CRLF	;NO, TYPE CR-LF
		HRROI A,[ASCIZ/MESSAGE
/]
		JRST TTSOUT]>

DEFINE WRNMES (MESSAGE)<
	PUSHJ P,[PUSHJ P,CHKLM	;ON LEFT MARGIN?
		  PUSHJ P,CRLF	;NO, TYPE CR-LF
		HRROI A,[ASCIZ/MESSAGE
/]
		JRST TTSOUT]>

DEFINE SYSGET(X)<
	MOVE A,[SIXBIT/X/]
	SYSGT
	HRRZM B,X>
;PROGRAM ENTRY VECTOR

ENTVEC:	JRST PTYCON		;STARTING LOCATION
	JRST PTYCON		;REENTER LOCATION
	VPTYCN			;VERSION NUMBER

PTYCON:	MOVE P,[IOWD PDLEN,PDL]	;SET UP STACK
	SETZM PUSHF		;NOT PUSHED DOWN A LEVEL NOW
	SETZM IOWATF		;INITIALIZE WAITING FOR INTERRUPT FLAG
	MOVE A,[SIXBIT/PTYPAR/]	;GET # OF PTYS IN SYSTEM
	SYSGT			;...
	HRRZM A,FIRPTY		;STORE TTY CORRESPONDENCE FOR PTY'S
	HLRZS A			;GET NUMBER OF PTY'S IN SYSTEM
	MOVEM A,SYSPTY		;REMEMBER THE NUMBER OF PTY'S ON SYSTEM
	CAILE A,MAXPTY		;TOO HIGH?
	MOVEI A,MAXPTY		;YES
	MOVEM A,NUMPTY		;REMEMBER # OF PTYS
	SYSGET (TTYJOB)		;GET TABLE # OF GETAB ENTRIES
	SYSGET (JOBPNM)
	SYSGET (SNAMES)
	SYSGET (JOBRT)
	MOVE A,[STDESC]		;SET UP ENABLE MASK FOR SUBJOBS
	SKIPN ESCMSK		;WAS ONE ALREADY SET UP?
	 MOVEM A,ESCMSK		;NO, USE THE STANDARD ONE
	MOVE A,[STDESC+CNTRLO] ;GET ENABLE MASK FOR TERMINAL INTERRUPTS
	SKIPN TIMASK		;HAS THIS BEEN SET UP ALREADY?
	  MOVEM A,TIMASK	;NO, SET IT TO BE STANDARD
	MOVEI A,STDECH		;GET STD ESCAPE CHARACTER
	SKIPN TRPCHR		;BEEN SET UP YET?
	  MOVEM A,TRPCHR	;NO, SET IT UP ON FIRST TIME THROUGH
	MOVEI A,400000		;SET UP CAPABILITIES OF JOB
	RPCAP			;GET CURRENT CAPABILITIES
	TLNN B,(1B0)		;CAN WE ENABLE CONTROL-C INTERCEPT?
	  BUG(HLT,<CANNOT ENABLE FOR CONTROL-C INTERCEPT>)
	TLON C,(1B0)		;YES, THEN DO IT
	  EPCAP			;SET THIS ENABLE BIT
	MOVEI A,400000		;NOW INITIALIZE THE INTERRUPT SYSTEM
	DIR			;FIRST TURN IT OFF
	SETOM PICNT		;INITIALIZE LEVEL OF PIOFF'S
	MOVE B,[LEVTAB,,CHNTAB]	;SET UP PI SYSTEM
	SIR
	HRLZ A,TRPCHR		;ENABLE ESCAPE CHARACTER
	HRRI A,TRPCHN		;ON ITS OWN CHANNEL
	ATI			;...
	MOVEI A,400000		;NOW ACTIVATE ALL DESIRED CHANNELS
	MOVE B,ONCHNS
	AIC
	EIR			;ENABLE PI SYSTEM
	MOVEI A,100		;SET TERMINAL MODE WORD
	GDSTS			;GET PARITY ADD BIT
	ERCAL [	SETZM B
		RET]		;NO PARITY
	ANDX B,GD%PAR		;ISOLATE INTERESTING BIT
	MOVEM B,ADDPAR		;REMEMBER IT
	RFMOD			;GET CURRENT MODE
	SKIPN SAVMOD		;WAS IT SAVED BEFORE?
	  MOVEM B,SAVMOD	;NO, THIS IS FIRST TIME THROUGH
	MOVE B,SAVMOD		;GET ORIGINAL MODE
	TRO B,17B23!3B29!1B31	;SET BREAK ON EVERYTHING, ASCII, UPPER
	SFMOD			;...
	STPAR			;...
	RFCOC			;GET ECHO MODES
	TRZ C,3B19		;MAKE ALTMODES NOT ECHO
	SFCOC
	GTTYP			;GET TERMINAL TYPE ...
	MOVEM B,SAVTYP		;  ... AND SAVE IT 
	MOVEI A,100
	MOVEM A,TERJFN		;USE NON-BINARY CHANNEL FOR COMMAND PARSING.
	MOVE A,BINTTY		;GET ANY PREVIOUS BINARY CHANNEL.
	CLOSF			;CLOSE IT
	JFCL			;FAILURE PROBABLY BECAUSE IT WAS NEVER OPEN.
	MOVSI A,(GJ%SHT)	;PREPARE TO OPEN BINARY CHANNEL ON TTY.
	HRROI B,[ASCIZ /TTY:/]	;THIS IS FOR PIPELINE FOR SUBJOBS.
	GTJFN
	 BUG(HLT,<COULDN'T GET HANDLE ON TTY FOR BINARY CHANNEL>)
	MOVEM A,BINTTY		;SAVE THE BINARY CHANNEL.
	MOVE B,[100000,,OF%WR+OF%RD]
	OPENF			;OPEN IT IN BINARY MODE (IMPLIED BY 8 BIT BYTESIZE)
	 BUG(HLT,<COULDN'T OPEN THE TTY IN BINARY FOR PTY COMMUNICATION>)
	JRST COMLVL		;GO TO COMMAND LEVEL
;COMMAND LEVEL

COMLVL:	MOVE P,[IOWD PDLEN,PDL]	;SET UP A FRESH PUSH DOWN LIST
	SETZM IOWATF		;CLEAR WAITING FOR INTERRUPT FLAG
	SETZM NOFLAG		;INITIALIZE NEGATE FLAG
	SETZM IGNORF		;CLEAR IGNORE FLAG
	SETOB I,LSTHDR		;ALWAYS CLEAR SUBJOB INDEX
	MOVNI A,5		;NOW GRAB ALL TERMINAL INTERRUPT CHARS
	RTIW			;READ CURRENT
	SKIPN SAVTIW		;WAS IT SAVED ALREADY?
	  MOVEM B,SAVTIW	;NO, SAVE IT FOR EXITING
	MOVE B,TIMASK		;ONLY ESCAPE CHARACTER AND CONTROL-O
	STIW			;  ARE SPECIAL
	PUSHJ P,CHKLM		;SEE IF AT START OF LINE
	  PUSHJ P,CRLF		;NO, TYPE CR-LF
	HRROI A,[ASCIZ/PTYCON> /] ;GET PROMPT MESSAGE
	PUSHJ P,TTSOUT		;TYPE OUT PROMPT
	TIME			;GET REAL TIME
	SKIPE RDJFN		;INPUT COMING FROM FILE?
	CAML A,NXLOGC		;YES, TIME TO UPDATE LOG?
	CALL [	ADDI A,^D60000	;COMPUTE TIME FOR NEXT UPDATE
		MOVEM A,NXLOGC
		CALLRET LOGCLS]	;CLOSE AND REOPEN LOG FILE IN CASE CRASH
COM0:	MOVE A,TERJFN		;SEE IF ANYTHING IN TTY INPUT BUFFER
	SIBE
	  JRST COM0A		;YES, DON'T TYPE OUT ANYTHING FROM PTY'S
	SETZM TOFLAG		;INITIALIZE TTY OUTPUT FLAG
	PUSHJ P,PTOCHK		;SEE IF ANY OUTPUT FROM SUBJOBS READY
	SKIPE TOFLAG		;WAS ANYTHING TYPED ON TTY?
	  JRST COMLVL		;YES, START OVER AGAIN
COM0A:	PUSHJ P,COMINI		;INITIALIZE COMMAND BUFFER FOR RDTXT
COM1:	MOVEI A,100		;INITIALIZE MODE OF TTY
	MOVE B,SAVMOD		;
	TLZ B,(1B0)		;CLEAR CNTRL-O
	SFMOD			;
	MOVEI A,100
	MOVEM A,TERJFN		;USE REGULAR TTY CHANNEL FOR COMMAND INPUT.
	PUSHJ P,RDSTR		;GET A COMMAND FROM TTY
	  JRST CHKPTO		;INTERRUPT OCCURRED BEFORE DONE
	PUSH P,A		;SAVE TERMINATOR CHARACTER
	CAIE A,"!"		;A NEW FLAVOR COMMENT?
	CAIN A,";"		;OR AN OLD FLAVOR COMMENT
	  JRST COMENT		;POSSIBLY
	CAIN A,3		;CONTROL-C?
	  JRST COMCC		;YES
	CAIN A,"-"		;IS THIS A ONE LINER FOR SUBJOB?
	  JRST SINGLE		;YES, GO GET REST OF LINE TO BE SENT
	MOVE A,STRING		;SEE IF THIS IS A NO COMMAND
	CAME A,[ASCIZ/N/]
	CAMN A,[ASCIZ/NO/]
	  JRST NOCOMM		;YES, GO PROCESS NO COMMAND
	MOVEI A,COMTAB		;SEE IF THIS IS A KNOWN COMMAND
	MOVE B,[POINT 7,STRING]	;GET START OF COMMAND BUFFER
	PUSHJ P,TABLK		;LOOKUP THE COMMAND
	  JRST COM2		;NOT A MATCH
	HRRZ B,(A)		;SAVE ADDRESS OF TABLE ENTRY OF MATCH
	POP P,A			;GET BACK TERMINATING CHAR
	CAIN A,33		;WAS THE TERMINATOR AN ALTMODE?
	  JRST COMALT		;YES, FINISH OUT STRING
	JRST (B)		;CALL APPROPRIATE COMMAND ROUTINE
COM2:	POP P,D			;GET BACK TERMINATOR
	JUMPG B,COM3		;UNIQUE SUBSET OF COMMAND?
	CAIN D,12		;NO, IS THIS A LINE FEED?
	  JRST COM4		;YES, UNRECOGNIZED COMMAND
	MOVE A,D		;GET TERMINTAOR
	CAIE A,33		;ALTMODE?
	PUSHJ P,STOCHR		;NO, PUT IT IN THE BUFFER
	MOVEI A,7		;NO, RING BELL
	PUSHJ P,TTBOUT
	JRST COM1		;AND GO BACK FOR MORE CHARACTERS

COM3:	HRRZ B,(A)		;GET TABLE ADDRESS OF TABLE ENTRY
	CAIE D,33		;WAS TERMINATOR AN ALTMODE
	  JRST [MOVE A,D	;NO, IS THIS THE END OF A LINE
		JRST (B)]	;  AND CALL APPROPRIATE ROUTINE
COMALT:	MOVE A,C		;FINISH OUT COMMAND AND NOISE WORDS
	PUSH P,B		;SAVE ADDRESS OF ROUTINE TO CALL
	PUSHJ P,TTSOUT		;SEND OUT REST OF COMMAND
	MOVEI A," "		;TERMINATED WITH A SPACE
	POPJ P,			;GO TO APPROPRIATE ROUTINE

NOCOMM:	SKIPE NOFLAG		;ALREADY SEEN A NO COMMNAD?
	  JRST COMERR		;YES, THIS IS AN ERROR
	POP P,A			;GET TERMINATOR
	CAIN A,33		;ALTMODE?
	 JRST [	MOVE B,STRING	;YES, FINISH IT OUT
		CAMN B,[ASCIZ/N/]
		SKIPA A,[POINT 7,[ASCIZ/O /]]
		HRROI A,[ASCIZ/ /]
		PUSHJ P,TTSOUT	;TYPE OUT THE REMAINDER OF THE FIELD
		JRST NOCOM1]
	CAIN A,12		;LF?
	  JRST COMERR		;YES, ERROR
NOCOM1:	SETOM NOFLAG		;SET FLAG TO SIGNAL COMMANDS
	JRST COM0		;GO GET NEXT COMMAND

STOCHR:	SOSG COMCNT		;DECREMENT COUNT OF CHARS LEFT
	JRST COMERR		;NO ROOM
	IDPB A,COMBP		;STORE THE CHAR
	MOVE B,COMBP		;AND FOLLOW IT WITH A NULL
	MOVEI C,0
	IDPB C,B
	POPJ P,
COM4:	MOVE A,COMCNT		;UNRECOGNIZED COMMAND
	CAIN A,MAXSTC		;WAS IT A NULL COMMAND?
	JRST COMLVL		;
COMERR:	ERRMES (<? UNRECOGNIZED PTYCON COMMAND>)
	JRST COMLVL		;AND RETURN TO COMMAND LEVEL

COMCC:	PUSHJ P,CHKLOG		;SEE IF ANY JOBS LOGGED IN
	  JRST [ERRMES (<? TYPE "EXIT" TO EXIT FROM PTYCON!>)
		JRST COMLVL]	;NO ACTIVE SUBJOBS
	ERRMES (<? SUBJOBS ACTIVE, USE "PUSH" COMMAND!>)
	JRST COMLVL

CHKLOG:	MOVE E,PTYHGH		;GET HIGHEST PTY JOB
	SETZ I,			;START AT NUMBER 0
CHKLG1:	SKIPN PTYJFN(I)		;IS THERE A JOB ON THIS LINE?
	  JRST CHKLG2		;NO, CHECK OTHER SUBJOBS
	HRRZ A,PTYTTD(I)	;GET TTY DESIGNATOR
	MOVE B,[-1,,D]		;GET LOGGED-IN DIR NUMBER
	MOVEI C,.JIUNO
	SETZ D,			;START WITH 0 DIR NUM
	GETJI
	  SETZ D,		;ASSUME 0 IF FAILURE
	JUMPN D,CPOPJ1		;JOB IS LOGGED IN
CHKLG2:	ADDI I,PTYLEN		;GO TO NEXT JOB
	SOJGE E,CHKLG1		;LOOP BACK FOR ALL SUBJOBS
	POPJ P,			;NO ACTIVE JOBS

COMENT:	MOVE B,COMCNT		;NULL STRING SO FAR?
	CAIE B,MAXSTC		;...
	  JRST COMBEL		;NO, USER IS CONFUSED
	POP P,A			;GET BACK ;
	PUSHJ P,READLN		;GET A LINE
	JRST COMLVL		;  AND PROMPTLY FORGET IT
SINGLE:	SKIPE STRING		;NULL NAME?
	JRST SINGL0		;NO
	SKIPGE I,LSTCON		;GET LAST SUBJOB NUMBER IF ANY
	JRST COMBEL		;ILLEGAL IF NONE
	JRST SINGL1		;GO USE THIS SUBJOB NUMBER

SINGL0:	PUSHJ P,FNDPTY		;SET UP INDEX OF SUBJOB
	  JRST SINGL2		;NOT DEFINED, CHECK "ALL"
SINGL1:	MOVEM I,LSTCON		;SAVE LAST SINGLE SUBJOB #
	POP P,A			;GET BACK TERMINATOR
	PUSHJ P,READLN		;GO READ IN A WHOLE LINE OF TEXT
	PUSHJ P,SNGOUT		;SEND IT OUT TO DESIRED SUBJOB
	JRST COMLVL		;  AND RETURN TO COMMAND LEVEL

SNGOUT:	PUSHJ P,PTYFIL		;FIRST MAKE SURE OUTPUT BUFFER IS EMPTY
	PUSH P,P1		;SAVE PRESERVED AC
	MOVE P1,[POINT 7,STRING]
SINLOP:	ILDB A,P1		;GET NEXT CHARACTER TO GO OUT
	JUMPE A,SINLPD		;IF ZERO, THEN DONE
	PUSHJ P,PTYOUT		;SEND IT OUT
	JRST SINLOP		;LOOP FOR ALL CHARACTERS
SINLPD:	POP P,P1		;RESTORE PRESERVED AC
	POPJ P,			;AND RETURN

SINGL2:	MOVE A,STRING		;GET STRING
	CAME A,[ASCIZ/ALL/]	;IS IT SPECIAL CASE "ALL"?
COMBEL:	 JRST [	POP P,(P)	;NO, GO RING BELL
		MOVEI A,7
		PUSHJ P,TTBOUT
		JRST COM1]	;AND GET MORE CHARACTERS
	POP P,A			;YES, NOW TYPE OUT TERMINATOR
	PUSHJ P,READLN		;AND READ IN THE TEXT LINE TO BE SENT
	PUSH P,P1		;SAVE PRESERVED AC
	MOVE P1,PTYHGH		;SET UP TO LOOP FOR ALL PTY'S
	SETZ I,			;INITIALIZE INDEX
SNGALL:	SKIPE PTYJFN(I)		;IS THERE A PTY INITIALIZED HERE?
	PUSHJ P,SNGOUT		;YES, SEND OUT LINE
	ADDI I,PTYLEN		;GO TO NEXT PTY
	SOJGE P1,SNGALL		;LOOP FOR ALL LINES
	POP P,P1		;RESTORE PRESERVED AC
	JRST COMLVL		;AND RETURN
READLN:	PUSHJ P,COMINI		;INITIALIZE STRING
READL1:	PUSHJ P,RDSTR		;GO READ IN A WORD
	  JRST READL1		;IGNORE INTERRUPTS
	IDPB A,COMBP		;STORE TERMINATOR
	SOS COMCNT		;COUNT DOWN BYTE COUNTER
	CAIE A,12		;LF?
	  JRST READL1		;NO, WAIT FOR TERMINATOR
	MOVEI A,0		;YES, END WITH A NULL
	IDPB A,COMBP
	POPJ P,			;AND RETURN

CHKPTO:	MOVE A,COMCNT		;CHECK FOR TYPE OUT NECESSARY FROM PTYS
	CAIE A,MAXSTC		;ANY CHARACTERS TYPED YET?
	  JRST COM1		;YES, DON'T INTERRUPT USER
	SETZM TOFLAG		;CLEAR OUTPUT FLAG
	PUSHJ P,PTOCHK		;GO TYPE OUT OUTPUT FROM PTY'S
	SKIPE TOFLAG		;WAS ANYTHING TYPED?
	  JRST COMLVL		;YES, GO TYPE PROMPT
	JRST COM0		;NO, DON'T TYPE PROMPT

COMINI:	MOVE A,[POINT 7,STRING]	;INITIALIZE COMMAND STRING
	MOVEM A,COMBP		;SET UP POINTER
	MOVEI A,MAXSTC		;  AND CHARACTER COUNT
	MOVEM A,COMCNT
	SETZM STRING		;ZERO BUFFER
	MOVE A,[XWD STRING,STRING+1]
	BLT A,STRING+STRNGL-1
	POPJ P,			;AND RETURN
;COMMAND TABLE - MUST BE IN ALPHABETICAL ORDER

DEFINE COMAND<
	CMND(<ACCEPT (OUTPUT FROM SUBJOBS) >,RECPTY,1)
	CMND(<BELL (WHEN OUTPUT WAITING) >,BELL,1)
	CMND(<CONNECT (TO SUBJOB) >,CONPTY,0)
	CMND(<DEFINE (SUBJOB #) >,DEFPTY,0)
	CMND(<DISCARD (OUTPUT FROM SUBJOB) >,IGNOR,1)
	CMND(<EXIT (FROM PTYCON) >,EXIT,0)
	CMND(<GET (COMMANDS FROM FILE) >,READ,0)
	CMND(<HELP MESSAGE >,HELP,0)
	CMND(<KILL (SUBJOB) >,KILL,0)
	CMND(<LOG (OUTPUT TO FILE) >,LOG,1)
	CMND(<PUSH (EXEC LEVEL) >,PUSHE,0)
	CMND(<REDEFINE (PTYCON ESCAPE CHARACTER TO BE) >,CHANGE,0)
	CMND(<REFUSE (OUTPUT FROM SUBJOBS) >,REFPTY,1)
	CMND(<SAVE (INPUT IN FILE) >,SAVINP,1)
	CMND(<SILENCE (ALL OUTPUT TO TERMINAL) >,SILNCE,1)
	CMND(<WHAT (IS STATE OF SUBJOB) >,WHATPT,0)
>

DEFINE CMND(A,B,C)<
	XWD [ASCIZ/A/],B>

COMTAB:	XWD COMTBL-1,COMTBL
	COMAND
COMTBL==.-COMTAB

DEFINE CMND(A,B,C)<
	EXP C>

COMFLG:	COMAND


HELP:	SKIPE NOFLAG		;DO NOT ALLOW "NO HELP"
	JRST COMERR
	PUSHJ P,CRWAIT		;WAIT FOR TERMINATNG CR-LF
	HRROI A,[ASCIZ/
THE DEFINED COMMANDS ARE:

/]
	PUSHJ P,TTSOUT		;TYPE OUT HEADER
	MOVSI C,1-COMTBL	;GET # OF ELEMENTS IN TABLE
HELPLP:	HLRO A,COMTAB+1(C)	;GET POINTER TO COMMAND
	PUSHJ P,TTSOUT		;TYPE IT OUT WITH ITS NOISE WORDS
	PUSHJ P,HLPSTR		;PUT A "*" AFTER STRING IF NEEDED
	PUSHJ P,CRLF		;END WITH A CRLF
	AOBJN C,HELPLP		;LOOP FOR ALL COMMANDS
	HRROI A,[ASCIZ/
"*" MEANS THE COMMAND CAN BE PRECEDED BY "NO" TO REVERSE ITS MEANING

THE ESCAPE CHARACTER TO RETURN TO COMMAND LEVEL IS:  /]
	PUSHJ P,TTSOUT
	MOVE A,TRPCHR		;GET ESCAPE CHARACTER
	PUSHJ P,TTBOUT		;TYPE IT OUT
	JRST COMLVL		;DONE


HLPSTR:	SKIPN COMFLG(C)		;IS THIS A COMMAND THAT TAKES "NO"?
	POPJ P,			;NO
	HRROI A,[ASCIZ/  */]	;YES, TYPE IT OUT
	PUSHJ P,TTSOUT
	POPJ P,
;TABLK - TABLE LOOKUP WITH ABBREVIATION RECOGNITION
;
;CALL:
; A/ TABLE ADDRESS
; B/ TEST STRING POINTER
;	PUSHJ P, TABLK
;RETURN:
; +1 = FAILED,	A/ ADR OF WHERE ENTRY WOULD BE IF IT WERE IN TABLE
;		B/ -1 FOR NO MATCH AT ALL
;		     0 FOR AMBIGUOUS
;		    +1 FOR UNIQUE ABREVIATION OF A DEFINED NAME
;		C/ POINTER TO REMAINDER OF ABREVIATED NAME
; +2 = SUCCESS, A/ ADDRESS OF TABLE ENTRY WHICH MATCHED

;AC USAGE:
; A/ TEST STRING FROM CALL
; B/ STRING FROM TABLE
; C/ CLOBBERED BY STRCMP
; D/ " "
; Q1/ CURRENT TABLE INDEX
; Q2/ ADR OF TABLE(Q1)
; Q3/ SIZE OF TABLE
; P3/ INDEX INCREMENT FOR LOG SEARCH

TABLK:	PUSH P,P3		;SAVE PERMANENT ACS
	PUSH P,Q1
	PUSH P,Q2
	PUSH P,Q3
	HRLI A,Q1		;CONSTRUCT TABADR(Q1)
	AOS Q2,A		;LEAVE IT HERE
	HLRZ Q1,-1(A)		;SET INITIAL INDEX TO SIZ/2
	ASH Q1,-1
	HLRZ P3,-1(A)		;INITIAL INCREMENT IS SIZE
	MOVE Q3,P3		;SAVE SIZE FOR RANGE CHECKS
	PUSH P,B		;SAVE TEST STRING
	JUMPE Q3,TABLKX		;IF NO ENTRIES IN TABLE, THEN NO MATCH
TABLK0:	HLRZ B,@Q2		;GET ADR OF STRING FROM TABLE
	HRLI B,(POINT 7,0)	;MAKE BYTE PTR
	MOVE A,0(P)		;TEST STRING
	PUSHJ P,STRCMP		;COMPARE STRINGS
	 JRST TABLK1		;NOT EXACTLY EQUAL
TABLKF:	AOS -5(P)		;EXACTLY EQUAL, DOUBLE SKIP RETURN
TABLKM:	TDZA B,B		;SET UP FOR AN AMBIGUOUS RETURN
TABLKX:	SETO B,			;GIVE NO-MATCH CODE IN B
TABLKA:	MOVEI A,@Q2		;RETURN TABLE ADDRESS OF ENTRY
	POP P,0(P)
	POP P,Q3		;RESTORE PERMANENT ACS
	POP P,Q2
	POP P,Q1
	POP P,P3
	POPJ P,
;STRING MAY HAVE BEEN UNEQUAL OR A SUBSET, SEE WHICH

TABLK1:	JUMPN A,TABLKN		;UNEQUAL, GO SETUP NEXT PROBE
TABLK3:	JUMPE Q1,TABLK2		;IF NOW AT TOP OF TABLE, CHECK NO HIGHER
	PUSH P,B		;SAVE POINTER TO REMAINDER OF STRING
	MOVEI A,@Q2		;CHECK PREVIOUS ENTRY, GET ITS ADDRESS
	HLRZ B,-1(A)		;GET STRING ADDRESS
	HRLI B,(POINT 7,0)
	MOVE A,-1(P)		;GET ORIGINAL STRING AGAIN
	PUSHJ P,STRCMP		;SEE ABOUT PREVIOUS ENTRY
	 JRST .+2
	SOJA Q1,[POP P,B	;EXACTLY EQUAL, DONE
		 JRST TABLKF]	;...
	JUMPG A,TBLK2B		;IF LESS, THEN HAVE FOUND HIGHEST SUBSET
	POP P,0(P)		;POP AWAY UNDESIRED BASE STRING
	SOJA Q1,TABLK3		;STILL A SUBSET, CHECK PREVIOUS

;NOW POINTING AT HIGHEST ENTRY WHICH IS SUBSET.  IF THERE IS AN EXACT
;MATCH, IT IS BEFORE ALL SUBSETS AND HAS ALREADY BEEN FOUND

TABLK2:	PUSH P,B		;SAVE PTR TO REST OF BASE
TBLK2B:	MOVEI A,@Q2		;CHECK NEXT ENTRY FOR AMBIGUOUS
	CAIL Q1,-1(Q3)		;IS THIS THE LAST ENTRY ALREADY?
	  JRST [POP P,C		;YES, THIS ENTRY IS DISTINCT
		JRST TBLK2A]	;GO RETURN +1 IN B
	HLRZ B,1(A)
	HRLI B,(POINT 7,0)
	MOVE A,-1(P)
	PUSHJ P,STRCMP
	 JRST .+2
	BUG(CHK,<TABLK2: TABLE NOT IN PROPER FORMAT>)
	POP P,B
	JUMPE A,TABLKM		;NEXT ENTRY NOT DISTINCT, GIVE AMBIGUOUS RETURN
	MOVE C,B		;GET POINTER TO REST OF BASE STRING
TBLK2A:	MOVEI B,1		;SET UP FOR ABBREVIATION RETURN
	JRST TABLKA		;GIVE NON-SKIP RETURN
;HERE WHEN PROBE NOT EQUAL

TABLKN:	CAIG P3,1		;INCREMENT NOW 1?
	  JRST [JUMPL A,TABLKX	;YES, NO MATCH FOUND
		AOJA Q1,TABLKX]	;IF STRING GREATER, MAKE ADDR ONE MORE
	ADDI P3,1		;NEXT INC = <INC+1>/2
	ASH P3,-1
	JUMPG A,[ADD Q1,P3	;IF LAST PROBE LOW, ADD INCREMENT
		JRST TBLKN1]	;GO CHECK BOUNDS
	SUB Q1,P3		;LAST PROBE HIGH, SUBTRACT INCREMENT
TBLKN1:	CAIL Q1,0(Q3)		;OVER THE TOP OF THE TABLE?
	  JRST [SETO A,		;YES, FAKE PROBE TO HIGH
		JRST TABLKN]	;GO PROBE AGAIN
	JUMPGE Q1,TABLK0	;IF STILL WITHIN TABLE, GO PROBE
	MOVEI A,1		;BELOW TABLE, FAKE LOW PROBE
	JRST TABLKN

;STRING COMPARE ROUTINE
;CALL:
; A/ TEST STRING POINTER
; B/ BASE STRING POINTER
;	PUSHJ P,STRCMP
;RETURN:
; +1 = NOT EXACT MATCH, A GIVES STATUS:
;	-1 = TEST STRING LESS THAN BASE STRING
;	0 = TEST STRING SUBSET OF BASE STRING
;	+1 - TEST STRING GREATER THAN BASE STRING
; +2 = EXACT MATCH

STRCMP: ILDB C,A		;GET NEXT CHAR FROM EACH STRING
	ILDB D,B
	CAME C,D		;STILL EQUAL?
	JRST STRC2		;NO, GO SEE WHY
	JUMPN C,STRCMP		;KEEP GOING IF NOT END OF STRING
	AOS 0(P)		;STRINGS ENDED TOGETHER, EXACT MATCH
	POPJ P,

STRC2:	JUMPE C,[SETZ A,	;TEST STRING ENDED, IS A SUBSET
		ADD B,[70000,,0] ;DECREMENT BYTE POINTER BY ONE BYTE
		POPJ P,]
	CAMG C,D		;STRINGS UNEQUAL
	SKIPA A,[-1]		;TEST STRING LESS, RETURN -1
	MOVEI A,1		;TEST STRING GREATER, RETURN +1
	POPJ P,
;ROUTINE TO GET A CHARACTER FROM TTY

TTYGET:	SKIPE RDJFN		;READING FROM A FILE
	  JRST FILGET		;YES, GET CHARACTER FROM FILE INSTEAD
	MOVE A,TERJFN		;SEE IF ANY CHARACTERS HAVE BEEN TYPED.
	SIBE
	 JRST [	SETO B,
		JRST TTGETR]	;YES
	PUSH P,[TTGETR]		;SET UP TO ALLOW INTERRUPTS TO TAKE
	SETOB B,IOWATF		;MARK THAT INTERRUPTS CAN TAKE
	MOVE A,TERJFN		;PRIMARY INPUT OR BINARY CHANNEL
	SKIPN WAKEF		;INTERRUPT PENDING ??
	BIN			;NO, WAIT FOR ONE.
	SETZM IOWATF		;CLEAR OK TO INTERRUPT FLAG.
	MOVE A,B		;MOVE CHARACTER INTO A
	ANDI A,177		;TRUNCATE TO 7 BITS
	POPJ P,			;GO TO TTGETR

TTGETR:	SETZM WAKEF		;CLEAR WAKE UP FLAG
	JUMPL B,TTGET7		;JUMP IF NO CHARACTER HAS BEEN INPUT.
	JRST CPOPJ1		;EXIT.
TTGET7:	MOVE A,TERJFN		;GET CHARACTER IF THERE IS ONE.
	SIBE			;ANY CHARACTERS TYPED IN?
	CAIA			;THERE ARE SOME.
	POPJ P,			;NO, GIVE NO SKIP RETURN
	MOVE A,TERJFN
	BIN			;READ IN WAITING CHARACTER
	ERJMP CPOPJ		;IF ERROR, RETURN FAILURE
	MOVE A,B
	ANDI A,177		;TRUNCATE TO 7 BITS
	JRST CPOPJ1
FILGET:	HRRZ A,RDJFN		;GET JFN OF FILE BEING READ
	BIN			;GET THE NEXT CHARACTER
	CAIN B,"^"		;UPARROW?
	  PUSHJ P,[BIN		;YES, GET NEXT CHARACTER
		CAIN B,"^"	;ANOTHER UPARROW?
		  POPJ P,	;YES, RETURN
		CAIN B,"$"	;DOLLAR SIGN?
		  JRST [MOVEI B,33
			POPJ P,] ;YES, MAKE IT AN ALTMODE
		CAIL B,141	;LOWER CASE?
		CAILE B,172
		  SKIPA		;NO
		  SUBI B,40	;YES, MAKE IT UPPER CASE
		TRZ B,100	;MAKE IT A CONTROL
		POPJ P,]
	CAIN B,.CHCRT		;CR?
	JRST [	BIN		;YES, PEEK AT NEXT ONE
		CAIN B,.CHLFD	;AN LF?
		SKIPA B,TERJFN	;YES, RETURN CR IF BINARY, LF IF ASCII
		BKJFN		;NO, PUT IT BACK AND RETURN CR
		 CAMN B,BINTTY
		SKIPA B,[.CHCRT]
		MOVEI B,.CHLFD
		JRST .+1]
	JUMPN B,[MOVE A,B	;DID WE GET A CHARACTER?
		CAME A,TRPCHR	;YES, WAS IT THE ESCAPE CHARACTER
		  JRST CPOPJ1	;NO, GIVE SUCCESSFUL RETURN
		MOVEI A,"^"	;ECHO THE ESCAPE CHARACTER ON THE TTY
		PUSHJ P,TTBOUT
		MOVE A,TRPCHR	;GET THE TRAP CHARACTER
		TRO A,100	;MAKE IT INTO THE ASCII COUNTERPART
		PUSHJ P,TTBOUT
		JRST COMLVL]	;AND RETURN TO COMMAND LEVEL
	GTSTS			;SEE IF EOF
	TLNN B,(1B8)		;...
	  JRST FILGET		;NO, IGNORE NULLS
	CLOSF			;YES, CLOSE THE FILE
	  JFCL
	SETZM RDJFN		;CLEAR READING FLAG
	SETZM SILNCF		;AND CLEAR SILENCE FLAG
	JRST TTYGET		;GO GET CHARACTER FROM TTY
;ROUTINES TO TURN ON AND OFF PI SYSTEM

PIOFF:	MOVEI A,400000
	DIR			;DISABLE INTERRUPTS
	AOS PICNT		;COUNT # OF TIMES DONE
	POPJ P,			;AND RETURN

PION:	SOSL PICNT		;NESTED?
	  POPJ P,		;YES, DON'T ENABLE
	SETOM PICNT		;NO, OK TO TURN BACK ON
	MOVEI A,400000
	EIR			;TURN ON PI SYSTEM
	POPJ P,			;AND RETURN

TRAP:	CALL ASCTER		;GET ASCII TERMINAL SET UP
	MOVEI A,"^"		;ECHO THE ESCAPE CHARACTER ON THE TTY
	PUSHJ P,TTBOUT
	MOVE A,TRPCHR		;GET THE TRAP CHARACTER
	TRO A,100		;MAKE IT INTO THE ASCII COUNTERPART
	PUSHJ P,TTBOUT
	PUSHJ P,CRLF		;TYPE CRLF FIRST
TRAP1:	SKIPE A,RDJFN		;IS THIS AN ABORT OUT OF A GET COMMAND?
	  CLOSF			;YES, CLOSE THE GET FILE
	  JFCL
	SETZM RDJFN		;STOP READING FROM FILE
	SETZM IOWATF		;CLEAR OK TO INTERRUPT FLAG
	MOVEI A,100		;CLEAR TYPE AHEAD
	CFIBF			;  OF UNREAD JUNK
	MOVEI A,PTYCON		;START FROM SCRATCH
	MOVEM A,RETSAV		;  AFTER DEBRK
	DEBRK

PANIC:	CALL ASCTER		;GET ASCII TERMINAL SET UP
	BUG(CHK,<PANIC LEVEL INTERRUPT OCCURRED!>)
	HRROI A,ERRSTR		;PUT MESSAGE INTO A STRING
	HRLOI B,400000		;AND REASON FOR PANIC
	MOVEI C,0
	ERSTR
	JFCL
	SKIPA A,[POINT 7,[ASCIZ/UNKNOWN ERROR CODE/]]
	HRROI A,ERRSTR		;NOW OUTPUT THE MESSAGE
	PUSHJ P,TTSOUT
	MOVEI A,101
	DOBE			;WAIT FOR IT TO GO OUT
	JRST TRAP1		;  AND GO TO COMMAND LEVEL

;SET UP ASCII TERMINAL

ASCTER:	MOVEI A,.PRIOU		;THE I.D. OF IT
	MOVEM A,TERJFN		;SET IT
	RET			;AND DONE
EXIT:	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMING CHAR
	SKIPE NOFLAG		;DID USER SAY NO?
	  JRST COMERR		;YES, THIS IS AN ERROR
	PUSHJ P,LOGCLS		;CLOSE THE LOG FILE IF ANY
	PUSHJ P,CHKLOG		;SEE IF ANY ACTIVE SUBJOBS
	 JRST EXIT1		;NONE, GO EXIT
	HRROI A,[ASCIZ/CAUTION: EXITING MAY LOG OUT THE STILL ACTIVE SUBJOBS!
CONFIRM: (TYPE CONTROL-/]
	PUSHJ P,TTSOUT
	MOVE A,TRPCHR		;TYPE OUT THE ESCAPE CHAR
	TRO A,100
	PUSHJ P,TTBOUT
	HRROI A,[ASCIZ/ TO GET BACK TO PTYCON) /]
	PUSHJ P,TTSOUT		;ISSUE WARNING
	MOVEI A,0
	PUSHJ P,CRWAIT		;WAIT FOR ANOTHER CONFIRMING CR
EXIT1:	CALL RSTTY		;[8] RESET TTY PARAMETERS
	SKIPE A, LOGJFN		;[8] GET LOGJFN
	CLOSF			;[8] CLOSE IT
	 JFCL			;[8] IGNORE ERROR
	HALTF			;[8] STOP
	CALL RSTTY		;[8] RESET TTY IF CONTINUED
	SKIPN LOGJFN		;[8] WAS THERE A LOG FILE
	JRST COMLVL		;[8] NO, CONTINUE
	HRROI B,LOGBUF		;[8] GET NAME OF LAST LOG FILE
	JRST LOG2		;[8] OPEN IT
RSTTY:	MOVEI A,.PRIIN		;[8] GET PRIMARY INPUT
	RFMOD			;[8] GET STATE NOW
	EXCH B,SAVMOD		;[8] SAVE STATE NOW, GET OLD STATE
	SFMOD			;[8] RESET OLD STATE
	STPAR			;[8] ...
	RET			;[8]

CHKLM:	SKIPLE LMFLAG		;AT LEFT MARGIN?
	 POPJ P,		;NO
	MOVEI A,101
	RFPOS			;SEE IF AT LEFT MARGIN
	TRNN B,-1
	JRST CPOPJ1		;YES, SKIP RETURN
	POPJ P,			;NO, GIVE NON-SKIP RETURN

CRLF:	HRROI A,[ASCIZ/
/]
	PUSHJ P,TTSOUT		;TYPE OUT CR-LF
	SETZM LMFLAG		;RESET FLAG TO -1
	POPJ P,

TTBOUT:	EXCH A,LSTCHR		;GET LAST CHAR TYPED
	CAIE A,15		;CR?
	SKIPA			;NO
	CAME A,LSTCHR		;YES, IS THIS CHAR A CR ALSO?
	SKIPA A,LSTCHR		;NO, THEN TYPE IT
	POPJ P,			;YES, DONT TYPE TWO IN A ROW
	CAILE A,37		;DON'T INCREMENT COLUMN COUNTER FOR NON-PRINTING CHARACTERS.
	AOS LMFLAG
	CAIE A,12
	CAIN A,15
	SETZM LMFLAG		;RESET COUNTER FOR CARRIAGE RETURN.
	SKIPE RDJFN		;READING FROM A FILE?
	SKIPN SILNCF		;AND RIGGED FOR SILENT RUNNING?
	SKIPE IGNORF		;NO, IGNORING THIS PTY?
	  JRST TTBLG0		;YES
	PUSH P,B		;DON'T CLOBBER B.
	MOVE B,A		;PUT CHARACTER IN B.
	MOVE A,TERJFN		;GET APPROPRIATE TTY CHANNEL (BINARY OR REGULAR)
	BOUT			;TYPE THE CHARACTER.
	MOVE A,B		;RESTORE A AS THE CHARACTER.
	POP P,B			;AND WHATEVER WAS IN B.
	CAIE A,7		;BELL?
	  SETOM TOFLAG		;NO, SET TYPE OUT OCCURRED FLAG
	JRST TTBLG0

TTBLOG:	JUMPE A,CPOPJ		;DON'T LOG NULLS.
	EXCH A,LSTCHR		;GET LAST CHAR TYPED
	CAIE A,15		;CR?
	SKIPA			;NO
	CAME A,LSTCHR		;YES, IS THIS CHAR A CR ALSO?
	SKIPA A,LSTCHR		;NO, THEN TYPE IT
	POPJ P,			;YES, DONT TYPE TWO IN A ROW
TTBLG0:	SKIPN LOGJFN		;LOGGING THIS?
	  POPJ P,		;NO, RETURN
	PUSH P,B		;SAVE ALL ACS
	MOVE B,A		;GET CHAR
	MOVE A,LOGJFN		;GET LOGGING JFN
	CAIE B,33		;DONT SEND ALTMODES TO FILE
	BOUT			;SEND OUT CHAR
TTBLG1:	MOVE A,B		;RESTORE ACS
	POP P,B
	POPJ P,			;RETURN

TTSOUT:	PUSH P,TERJFN		;SAVE THE TTY CHANNEL.
	PUSH P,A		;AND THE STRING POINTER.
	MOVEI A,100		;GET NON-BINARY CHANNEL FOR PRINTING THE MESSAGE.
	MOVEM A,TERJFN		;SET UP THE NON-BINARY CHANNEL.
	POP P,A			;RETRIEVE THE POINTER TO THE MESSAGE.
	PUSHJ P,TTSOU1		;PRINT IT.
	POP P,TERJFN		;RESTORE THE TTY CHANNEL.
	POPJ P,

TTSOU1:	TLC A,-1		;LEFT HALF = -1?
	TLCN A,-1
	HRLI A,(POINT 7,0)	;YES, SET UP BYTE POINTER
	PUSH P,B		;SAVE ACS
	MOVE B,A		;GET STRING POINTER OUT OF A
TTSOUL:	ILDB A,B		;GET NEXT CHAR OF STRING
	JUMPE A,TTSOUD		;IF NULL, THEN DONE
	CALL TTBOUT		;TYPE OUT CHAR
	JRST TTSOUL		;LOOP TILL NULL FOUND

TTSOUD:	MOVE A,B		;RETURN UPDATED STRING POINTER IN A
	POP P,B			;RESTORE ACS
	POPJ P,


TTSLOG:	SKIPN LOGJFN		;LOGGING?
	POPJ P,			;NO
	PUSH P,B		;DO NOT CLOBBER ACS
	PUSH P,C
	MOVEI C,0
	MOVE B,A		;GET STRING POINTER
	MOVE A,LOGJFN		;AND JFN OF LOG FILE
	SOUT
	MOVE A,B		;CLEAN UP ACS
	POP P,C
	POP P,B
	POPJ P,			;AND RETURN
CRWAIT:	CAIN A,12		;LF?
	  POPJ P,		;YES, DONE
CRWAT0:	PUSHJ P,TTYGET		;GET A CHARACTER
	  JRST CRWAT0		;IGNORE INTERRUPTS
	PUSHJ P,TTBLOG		;PUT THIS CHARACTER IN THE LOG FILE
	CAIN A,12		;LF YET?
	 POPJ P,		;YES, RETURN
	CAIN A,"U"-100		;CONTROL-U?
	  JRST CRWAT1		;YES, ABORT COMMAND
	CAIN A,15		;CR
	 JRST CRWAT0		;YES
	MOVEI A,7		;NO, RING BELL
	PUSHJ P,TTBOUT
	JRST CRWAT0		;GO GET ANOTHER CHAR
CRWAT1:	HRROI A,[ASCIZ/ XXX/]	;ECHO ABORT COMMAND
	PUSHJ P,TTSOUT
	JRST COMLVL		;AND GO TO COMMAND LEVEL
;ROUTINE TO CHANGE THE PTYCON ESCAPE CHARACTER

CHANGE:	SKIPE NOFLAG		;NO IS NOT ALLOWED
	JRST COMERR
	PUSHJ P,COMINI		;INITIALIZE THE COMMAND BUFFER
	PUSHJ P,RDSTR		;GET A FIELD
	 JRST .-1		;DONT ALLOW INTERRUPTS
	PUSH P,A		;SAVE THE TERMINATOR
	PUSHJ P,CRWAIT		;THEN WAIT FOR CONFIRMATION
	POP P,A			;GET BACK THE TERMINATOR
	SKIPE STRING		;MAKE SURE NOTHING ELSE WAS TYPED
	JRST CHNGIL
	CAIE A,11		;DONT ALLOW IT TO BE TAB
	CAIL A,34		;AND IT MUST BE A CONTROL CHARACTER
	JRST CHNGIL		;ILLEGAL
	CAIE A,"C"-100		;NOT CONTROL-C
	CAIN A,"O"-100		;NOR CONTROL-O
	JRST CHNGIL
	CAIE A,33		;NO ALTMODES
	CAIN A,14		;OR FORM FEEDS
	JRST CHNGIL
	CAIE A,12		;LINE FEED
	CAIN A,15		;OR CARRIAGE RETURNS ARE ILLEGAL
	JRST CHNGIL
	EXCH A,TRPCHR		;GET OLD TRAP CHARACTER
	DTI			;DEASSIGN IT
	ERJMP .+1
	MOVSI A,400000		;NOW BUILD THE MASK
	MOVN B,TRPCHR		;GET SHIFT COUNTER
	LSH A,(B)		;GET MASK
	MOVEM A,ESCMSK		;SAVE THIS MASK FOR SUBJOB LEVEL
	IOR A,[CNTRLO]		;INCLUDE CONTROL-O ALSO
	MOVEM A,TIMASK		;SAVE THE NEW MASK
	JRST PTYCON		;GO SET THIS UP


CHNGIL:	ERRMES (<? ILLEGAL PTYCON ESCAPE CHARACTER>)
	JRST COMLVL
RECPTY:	SKIPE NOFLAG		;USER TYPE NO?
	  JRST NOREC		;YES, TURN IT INTO REFUSE
NOREF:	CAIN A,12		;USER END WITH LF?
	  JRST RECPT3		;YES, ASSUME ALL
RECPT0:	PUSHJ P,GETSJB		;GET A SUBJOB NUMBER IN I
	  JRST RECPT5		;NO MATCH, CHECK FOR NULL STRING
	  JRST RECPT1		;USER SAID ALL
	MOVSI B,PTREFF		;SET UP TO CLEAR REFUSE FLAG
	ANDCAM B,PTYSTS(I)	;ALLOW TYPE OUT
	CAIN A,","		;WAS THE TERMINATOR A COMMA
	JRST RECPTY		;NO, LOOP BACK FOR MORE ARGUMENTS
	PUSHJ P,CRWAIT		;NO, WAIT FOR CR-LF
	JRST COMLVL		;RETURN

RECPT1:	PUSHJ P,CRWAIT		;WAIT FOR A CRLF
RECPT4:	MOVE C,PTYHGH		;GET HIGHEST PTY NUMBER
	MOVEI I,0		;START WITH NUMBER 0
	MOVSI B,PTREFF		;GET FLAG
RECPT2:	ANDCAM B,PTYSTS(I)	;CLEAR REFUSE FLAG
	ADDI I,PTYLEN		;STEP TO NEXT PTY
	SOJGE C,RECPT2		;LOOP BACK FOR ALL PTY'S
	SETZM REFALL		;MARK THAT A ACCEPT ALL WAS DONE
	JRST COMLVL		;ALL THROUGH

RECPT3:	PUSH P,A		;SAVE TERMINATOR
	HRROI A,[ASCIZ/ ALL/]
	PUSHJ P,TTSOUT		;ECHO ALL
	MOVEI A," "		;GET A SPACE FOR CRWAIT
	POP P,B			;GET BACK TERMINATOR
	CAIN B,33		;ALTMODE?
	  PUSHJ P,CRWAIT	;YES, WAIT FOR A TERMINATOR
	JRST RECPT4		;GO DO ALL

RECPT5:	MOVE B,COMCNT		;GET COUNT OF CHARACTERS IN BUFFER
	CAIE B,MAXSTC		;IS THIS A NULL STRING?
	  JRST ILLSJB		;NO, THEN THIS IS AN ERROR
	CAIE A,12		;LF?
	CAIN A,33		;  OR ALTMODE?
	  JRST RECPT3		;YES, ASSUME ALL
	MOVEI A,7		;NO, RING BELL
	PUSHJ P,TTBOUT
	JRST RECPT0		;AND TRY AGAIN
REFPTY:	SKIPE NOFLAG		;DID USER TYPE NO?
	  JRST NOREF		;YES, TURN IT INTO AN ACCEPT
NOREC:	CAIN A,12		;USER END WITH LF?
	  JRST REFPT3		;YES, GO ASSUME ALL
REFPT0:	PUSHJ P,GETSJB		;GET SUBJOB NUMBER
	  JRST REFPT5		;NO MATCH, CHECK FOR NULL STRING
	  JRST REFPT1		;USER SAID "ALL"
	MOVSI B,PTREFF		;GET REFUSE FLAG
	IORM B,PTYSTS(I)	;SET REFUSE FLAG
	CAIN A,","		;WAS TERMINATOR A COMMA?
	JRST REFPTY		;YES, GO GET ANOTHER ARG
	PUSHJ P,CRWAIT		;WAIT FOR EOL
	JRST COMLVL		;AND EXIT

REFPT1:	PUSHJ P,CRWAIT		;WAIT FOR EOL
REFPT4:	MOVE C,PTYHGH		;GET NUMBER OF PTYS OPEN
	MOVEI I,0		;START AT # 0
	MOVSI B,PTREFF		;PREPARE TO SET FLAG
REFPT2:	IORM B,PTYSTS(I)	;SET REFUSE FLAG
	ADDI I,PTYLEN		;STEP TO NEXT PTY
	SOJGE C,REFPT2		;LOOP FOR ALL
	SETOM REFALL		;REMEMBER REFUSE ALL COMMAND
	JRST COMLVL		;ALL THROUGH

REFPT3:	PUSH P,A		;SAVE TERMINATOR
	HRROI A,[ASCIZ/ ALL/]
	PUSHJ P,TTSOUT
	MOVEI A," "		;GET A SPACE FOR CRWAIT
	POP P,B			;GET BACK TERMINATOR
	CAIN B,33		;ALTMODE?
	  PUSHJ P,CRWAIT	;YES, WAIT FOR A TERMINATOR
	JRST REFPT4		;ASSUME ALL

REFPT5:	MOVE B,COMCNT		;GET NUMBER OF CHARACTERS LEFT IN BUFFER
	CAIE B,MAXSTC		;IS BUFFER EMPTY?
	  JRST ILLSJB		;NO, THIS IS AN ERROR
	CAIE A,12		;LF?
	CAIN A,33		;  OR ALTMODE?
	  JRST REFPT3		;YES, ASSUME ALL
	MOVEI A,7		;NO, RING BELL
	PUSHJ P,TTBOUT
	JRST REFPT0		;AND TRY AGAIN
;ROUTINE TO DEFINE A PTY SUBJOB NAME

DEFPTY:	SKIPE NOFLAG		;USER SAY NO?
	  JRST COMERR		;YES, ERROR
	CAIN A,12		;TERMINATOR A LF?
	JRST TOOFEW		;YES, GO COMPLAIN
	PUSHJ P,COMINI		;INITIALIZE COMMAND STRING
DEFPT1:	PUSHJ P,RDSTR		;READ IN A WORD
	  JRST DEFPT1		;DON'T ALLOW INTERRUPTS
	CAIN A,12		;LF?
	  JRST [MOVEI B,MAXSTC	;SEE IF SOMETHING WAS TYPED IN
		CAMN B,COMCNT
		  JRST TOOFEW	;NEED AT LEAST ONE ARGUMENT
		JRST .+1]	;OK
	PUSH P,A		;SAVE TERMINATOR
	CAIN A,33		;WAS IT AN ALTMODE?
	  JRST DEFPTF		;YES, GET NEXT FREE PTY
DEFPT5:	HRROI A,STRING		;READ THIS AS A NUMBER
	MOVEI C,12		;IN DECIMAL
	NIN
DEFPT0:	  JRST [POP P,A		;NOT A VALID ARGUMENT
		CAIE A,15	;USER TYPE CR
		CAIN A,12	;  OR LF?
		  JRST ILLSJB	;YES, ILLEGAL SUBJOB DESIGNATOR
		MOVEI A,7	;DING THE BELL
		PUSHJ P,TTBOUT
		JRST DEFPT1]	;AND GET MORE INPUT
	SKIPL B			;WITHIN BOUNDS?
	 CAML B,NUMPTY
	  JRST DEFPT0		;NO, RING BELL
DEFPT4:	POP P,A			;GET BACK TERMINATOR
	CAIN A,33		;ENDED WITH AN ALTMODE?
	  JRST [HRROI A,[ASCIZ/ (AS) /]
		PUSHJ P,TTSOUT	;YES, TYPE OUT NOISE WORDS
		JRST DEFPT3]
DEFPT3:	PUSH P,A		;SAVE TERMINATOR
	CAML B,PTYHGH		;IS THIS A NEW HIGH
	  PUSHJ P,NEWHGH	;YES, SET UP NEW HIGH NUMBER
	IMULI B,PTYLEN		;CALCULATE INDEX
	MOVE I,B		;SET UP INDEX
	PUSHJ P,COMINI		;PREPARE FOR SECOND ARG
	POP P,A			;GET BACK TERMINATOR
	PUSH P,P1		;SAVE FLAG REGISTER
	SETZ P1,		;INITIALIZE IT FOR NO MESSAGE
	CAIN A,12		;LF?
	  JRST DEFPT6		;YES, GO INITIALIZE PTY
DEFPTR:	PUSHJ P,RDSTR		;READ IN A WORD
	  JRST .-1		;DON'T ALLOW INTERRUPTS
	CAIN A,33		;TERMINATOR AN ESCAPE?
	 JRST [ MOVEI A,7	;YES,
		PUSHJ P,TTBOUT	;SEND A BELL
		JRST DEFPTR ]	;GET MORE INPUT
	PUSH P,A		;SAVE TERMINATOR
	PUSH P,I		;SAVE INDEX
	MOVE A,COMCNT		;SEE IF THIS WAS A NULL FIELD
	CAIE A,MAXSTC		;...
	PUSHJ P,FNDPTY		;GO SEE IF NAME ALREADY EXISTS?
	  JRST DEFPT7		;NO NAME IN USE
	SETZM PTYNAM(I)		;YES, CLEAR NAME
	SETO P1,		;MAKE MESSAGE COME OUT
DEFPT7:	POP P,I			;GET BACK INDEX OF THIS SUBJOB
	POP P,A			;GET BACK TERMINATOR
DEFPT6:	MOVE B,STRING		;GET FIVE CHARACTER NAME
	MOVEM B,PTYNAM(I)	;STORE NAME EVEN IF NULL
	MOVEM I,LSTCON		;DEFINE IS SAME AS CONNECT
	PUSH P,A		;SAVE TERMINATOR
	SKIPN PTYJFN(I)		;IS PTY OPENED YET?
	  PUSHJ P,PTINIT	;NO, GO INITIALIZE IT
	POP P,A			;GET TERMINATOR BACK
	PUSHJ P,CRWAIT		;GO WAIT FOR EOL
	SKIPE P1		;WAS NAME ALREADY IN USE?
	 WRNMES (<% NAME ALREADY IN USE, REASSIGNED TO THIS SUBJOB>)
	POP P,P1		;RESTORE PERMANENT AC
	JRST COMLVL		;AND RETURN
DEFPTF:	MOVE C,COMCNT		;SEE IF A NULL STRING WAS TYPED
	CAIE C,MAXSTC		;...
	  JRST DEFPT5		;NO, GO INTERPRET STRING
	MOVNI I,PTYLEN		;FIND FIRST FREE SUBJOB NUMBER
	MOVE C,NUMPTY		;LOOP FOR ALL PTY'S
DEFPTL:	ADDI I,PTYLEN		;GO TO NEXT SUBJOB
	SKIPE PTYJFN(I)		;INITIALIZED?
	SOJG C,DEFPTL		;YES, TRY NEXT ONE
	JUMPLE C,DEFPT0		;FOUND A FREE ONE?
	PUSHJ P,TYPNUM		;YES, ECHO IT OUT
	JRST DEFPT4		;AND RETURN FOR NAME

TYPNUM:	MOVEI B,(I)		;TYPE SUBJOB NUMBER FROM INDEX
	IDIVI B,PTYLEN		;GET SUBJOB NUMBER
	HRROI A,STRING		;PUT NUMBER IN STRING
	MOVEI C,12		;DECIMAL
	NOUT			;TYPE OUT NUMBER
	  JFCL
	HRROI A,STRING		;NOW TYPE IT
	PUSHJ P,TTSOUT
	POPJ P,			;AND RETURN

TOOFEW:	ERRMES (<? TOO FEW ARGUMENTS!>)
	JRST COMLVL
;ROUTINE TO CONNECT TO A PTY LINE

CONPTY:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST COMERR		;YES, ERROR
	PUSH P,A		;SAVE TERMINATOR
	PUSHJ P,COMINI		;INIT COMMAND BUFFER
	POP P,A			;GET BACK TERMINATOR
	CAIN A,12		;WAS IT A LF?
	  JRST CONPT4		;YES, ASSUME LAST CONNECTED SUBJOB
CONPT0:	PUSHJ P,RDSTR		;GET WORD
	  JRST CONPT0		;IGNORE INTERRUPTS
	CAIE A,12		;LF?
	CAIN A,33		;  OR ALTMODE?
	  JRST CONPT4		;YES, SPECIAL CASE
CONPT5:	PUSH P,A		;SAVE TERMINATOR
	PUSHJ P,FNDPTY		;SEE IF LEGAL SUBJOB
	  JRST [POP P,A		;NO, RING BELL
		CAIN A,12	;USER END WITH LF?
		  JRST ILLSJB	;YES, ILLEGAL SUBJOB DESIGNATOR
		MOVEI A,7
		PUSHJ P,TTBOUT
		JRST CONPT0]	;AND GO GET MORE CHARACTERS
CONPT3:	POP P,A			;GET BACK TERMINATOR
	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	HRRZS I			;SET UP NEW INDEX
	MOVEM I,LSTHDR		;AS NEW LAST CONNECTED TO SUBJOB
	MOVEM I,LSTCON		;AND DONT TYPE OUT A HEADER
	HRROI A,[ASCIZ/[CONNECTED TO SUBJOB /]
	PUSHJ P,TTSOUT
	PUSHJ P,TYPNAM		;TYPE SUBJOB NAME
	HRROI A,[ASCIZ/]
/]
	PUSHJ P,TTSOUT
	PUSHJ P,PTYFIL		;READ IN ANY CHARACTERS IN BUFFER
	PUSHJ P,PTOCHK		;TYPE OUT ANYTHING BUFFERED UP
	JRST PTYLOP		;GO CONNECT

CONPT4:	MOVE B,COMCNT		;NULL STRING?
	CAIGE B,MAXSTC
	  JRST CONPT5		;NO, SEE IF LEGAL SUBJOB NAME
	CAIE A,15		;YES, CR-LF?
	CAIN A,12		;
	 JRST CONPT6		;YES, GET LAST CONNECTED SUBJOB
	MOVEI A," "		;NO, SAVE SPACE AS TERMINATOR
	PUSH P,A
	MOVE I,LSTCON		;GET LAST SUBJOB CONNECTED TO
	SKIPE C,PTYNAM(I)	;IS THERE A NAME DEFINED FOR IT
	  JRST CONPTN		;YES
	PUSHJ P,TYPNUM		;NO, TYPE OUT THE NUMBER
	JRST CONPT3		;  AND NOT THE NAME
CONPTN:	HRROI A,C		;GET NAME
	SETZ D,
	PUSHJ P,TTSOUT		;TYPE IT OUT
	JRST CONPT3

CONPT6:	PUSH P,A
	MOVE I,LSTCON		;GET LAST SUBJOB CONNECTED TO
	JRST CONPT3

ILLSJB:	ERRMES (<? ILLEGAL SUBJOB DESIGNATOR>)
	JRST COMLVL
;ROUTINE TO SET UP I WITH PTY NUMBER

FNDPTY:	SKIPN A,STRING		;NON NULL NAME?
	  POPJ P,		;NO, CANNOT FIND
	MOVE C,PTYHGH		;GET MAX DEFINED PTY
	SETZ I,			;START AT 0
FNDPT1:	CAMN A,PTYNAM(I)	;A MATCH
	  JRST CPOPJ1		;YES, THEN DONE
	ADDI I,PTYLEN		;NO, TRY NEXT ONE
	SOJGE C,FNDPT1		;LOOP FOR ALL SUBJOBS
	HRROI A,STRING		;DID NOT FIND ONE, SEE IF THIS IS A #
	MOVEI C,12
	NIN			;READ IN NUMBER
	  POPJ P,		;BAD
	LDB C,A			;SEE IF ANY CHARACTERS AFTER NUMBER
	JUMPN C,CPOPJ		;IF YES, THEN NOT SPECIFIING A NUMBER
	CAML B,NUMPTY		;WITHIN BOUNDS?
	  POPJ P,		;NO, BAD
	CAML B,PTYHGH		;NEW HIGH?
	  PUSHJ P,NEWHGH	;YES, SAVE IT
	IMULI B,PTYLEN		;CALCULATE INDEX
	MOVE I,B
	JRST CPOPJ1		;SUCCESS

NEWHGH:	PUSH P,P1		;SAVE A FEW ACS
	PUSH P,P2
	PUSH P,P3
	MOVE P1,PTYHGH		;GET CURRENT HIGH
	IMULI P1,PTYLEN		;GET INDEX
	MOVE P2,B		;GET NEW HIGH
	SUB P2,PTYHGH		;GET NUMBER OF JOBS NEEDING INITIALIZING
	SETZ P3,		;START WITH 0 FOR STATUS
	SKIPE REFALL		;REFUSING ALL?
	  TLO P3,PTREFF		;YES, SET BIT
	SKIPE IGNALL		;IGNORING ALL?
	  TLO P3,PTIGNF		;YES
NEWHG1:	ADDI P1,PTYLEN		;GO TO NEXT AREA
	MOVEM P3,PTYSTS(P1)	;STORE INITIAL STATUS WORD
	SOJG P2,NEWHG1		;LOOP FOR ALL JOBS
	MOVEM B,PTYHGH		;STORE NEW HIGH VALUE
	POP P,P3		;RESTORE ACS
	POP P,P2
	POP P,P1
	POPJ P,			;AND RETURN
;ROUTINE TO READ IN A FIELD INTO STRING

RDSTR:	SETOM LMFLAG		;MARK THAT RFPOS TO BE USED IN CHKLM
	SKIPE RDJFN		;READING FROM FILE?
	  JRST RDSTRF		;YES
RDSTR3:	PUSHJ P,TTYGET		;GET A CHARACTER FROM TTY
	  POPJ P,		;AN INTERRUPT OCCURED
	CAIN A,15		;WAS CHAR A CR?
	JRST RDSTR3		;YES, GET ANOTHER CHAR
RDSTR1:	MOVEI A,100		;BACK UP
	BKJFN			;SO RDTXT CAN READ CHAR
	JFCL			;******FIX THIS************
	MOVE A,[100,,101]	;SET UP FOR RDTXT
	MOVE B,COMBP		;BYTE POINTER
	MOVE C,COMCNT		;COUNT
	HRLI C,(RD%RND!RD%BRK!RD%PUN!RD%BEL!RD%CRF!RD%JFN!RD%BBG)
	PUSH P,COMBP		;SAVE BYTE POINTER
	MOVE D,[POINT 7,STRING]	;START OF STRING
	RDTXT			;READ IN A WORD
	  BUG(HLT,<RDTXT JSYS FAILED>)
	MOVEM B,COMBP		;STORE NEW BYTE POINTER
	HRRZM C,COMCNT		;AND COUNT
	TLNN C,(RD%BTM)		;TERMINATED WITH TERMINATOR?
	  JRST [MOVE A,COMCNT	;GET # OF CHARACTERS IN BUFFER
		JUMPE A,RDSTRL	;IF FULL, GO GIVE ERROR MESSAGE
		CAIN A,MAXSTC	;IS BUFFER EMPTY
		 JRST RDSTRD	;YES, GO RING BELL
		POP P,A		;NO, ECHO CHARACTERS RECEIVED SO FAR
		PUSHJ P,TTSLOG	;PUT CHARACTERS INTO LOG FILE
		JRST RDSTR]	;AND GO GET MORE
	LDB B,COMBP		;GET TERMINATOR
	MOVEI A,0		;STORE NULL IN BUFFER
	DPB A,COMBP
	POP P,A			;GET BACK POINTER TO UN ECHOED CHARS
	PUSH P,B		;SAVE TERMINATOR
	PUSHJ P,TTSLOG		;ECHO CHARACTERS INTO LOG FILE
	MOVE A,COMBP		;BACK UP THE POINTER
	BKJFN
	  JFCL
	MOVEM A,COMBP		;STORE NEW POINTER
	AOS COMCNT		;FREE UP A CHAR
	POP P,A			;GET BACK TERMINATOR
	PUSHJ P,TTBLOG		;AND LOG THE TERMINATOR CHARACTER
	JRST CPOPJ1		;AND GIVE SUCCESSFUL RETURN


RDSTRD:	MOVEI A,100		;GET BACK THE LAST CHAR TYPED
	BKJFN
	 JRST COMLVL		;IF ERROR, GO START OVER
	BIN			;GET CHAR BACK
	 ERJMP COMLVL
	CAIN B,"U"-100		;CONTROL-U?
	JRST COMLVL		;YES, ABORT THE COMMAND
	MOVEI A,7		;RING BELL
	CALL TTBOUT
	POP P,(P)		;CLEAN UP THE STACK
	JRST RDSTR		;AND LOOP BACK FOR MORE

RDSTRL:	ERRMES (<? LINE TOO LONG>)
	JRST COMLVL
RDSTRF:	PUSHJ P,TTYGET		;GET NEXT CHARACTER FROM FILE
	  POPJ P,		;AN INTERRUPT OCCURRED
	SKIPN RDJFN		;STILL READING FROM FILE?
	  JRST RDSTR1		;NO, GO GET CHARS FROM TTY
	CAIN A,12		;LINE FEED?
	JRST [	MOVEI A,15	;YES, ECHO CR-LF
		PUSHJ P,TTBOUT
		MOVEI A,12	;GET BACK THE LINE FEED
		JRST .+1]
	PUSHJ P,TTBOUT		;ECHO THE CHARACTER
	CAIL A,"0"		;A NUMBER?
	CAILE A,"9"
	  SKIPA			;NO
	  JRST RDSTR2		;YES
	CAIL A,"A"		;A LETTER?
	CAILE A,"Z"
	  SKIPA			;NO
	  JRST RDSTR2		;YES
	CAIL A,141		;A LOWER CASE LETTER?
	CAILE A,172
	  JRST CPOPJ1		;NO, END OF WORD
RDSTR2:	IDPB A,COMBP		;STORE THIS ALPHANUMERIC CHAR
	SOSLE COMCNT		;KEEP COUNT
	  JRST RDSTRF		;GET ANOTHER
	JRST CPOPJ1		;BUFFER IS FULL
;ROUTINE TO SET UP A READ FILE

READ:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST COMERR		;YES, ERROR
	SKIPE RDJFN		;READING ALREADY?
	JRST [	PUSHJ P,CRWAIT	;WAIT FOR END OF LINE
		ERRMES (<? DOING A "GET" WITHIN A "GET" IS ILLEGAL>)
		JRST COMLVL]
	MOVEI B,0		;GET NAME OF FILE TO BE READ
	CAIN A,12		;TERMINATED WITH LF?
	  JRST READA		;YES, READ DEFAULT
	MOVX A,GJ%OLD+GJ%CFM+GJ%XTN
	MOVEM A,RDBLOK
READ1:	MOVEI B,0		;RESET B TO ZERO
READ2:	MOVEI A,RDBLOK		;GET E-BLOCK FOR GTJFN
;**;[19]  Add 2 lines after READ2:+0			DML	14-NOV-83
	MOVEI C,GTBSZE		;[19] GET BUFFER SIZE
	MOVEM C,RDBLOK+.GJCPC	;[19] PLACE IN GTJFN BLOCK
;**;[18]  Replace 1 line with 2 at READ2:+1		DML	1-SEP-83
	HRROI C,GETBUF		;[18] GET POINTER TO THE FILENAME
	MOVEM C,RDBLOK+.GJCPP	;[18] SAVE POINTER IN GTJFN BLOCK
	GTJFN
	  JRST RDGTJF		;NO SUCH FILE
	HRRZM A,RDJFN		;SAVE JFN
	MOVE B,[7B5+1B19]	;NOW OPEN IT
	OPENF
	  JRST RDOPNF		;FAILED
	MOVE A,C		;GET FILENAME POINTER
	PUSHJ P,TTSLOG		;LOG IT
	JRST COMLVL		;RETURN

READA:	MOVEI A," "		;TYPE OUT A SPACE
	PUSHJ P,TTBOUT
	MOVSI A,(1B2)
	MOVEM A,RDBLOK
	HRROI B,[BYTE (7) 33,15,12,0]
	JRST READ2		;GET DEFAULT JFN

RDBLOK:	GJ%OLD+GJ%CFM+GJ%XTN
	100,,101
	0
	0
	-1,,[ASCIZ/PTYCON/]
	-1,,[ASCIZ/ATO/]
	0
	0
	0
	G1%RND+2
	-1,,GETBUF
;**;[19]  Change 1 line at RDBLOK:+11			DML	14-NOV-83
	0			;[19] BUFFER SIZE

RDOPNF:	PUSH P,A
	MOVE A,RDJFN		;RELEASE JFN
	RLJFN
	  JFCL
	SETZM RDJFN
	POP P,A
RDGTJF:	PUSHJ P,TYPERR		;AND TYPE ERROR MESSAGE
	JRST COMLVL

SILNCE:	PUSHJ P,CRWAIT		;WAIT FOR TERMINATOR
	SETZM SILNCF		;INIT SILENCE FLAG
	SKIPN NOFLAG		;WAS THIS A "NO SILENCE" REQUEST?
	SETOM SILNCF		;NO, THEN SILENCE THE OUTPUT FROM GET
	JRST COMLVL
; ROUTINE TO SET UP A LOG FILE

LOG:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST NOLOG		;YES, GO TURN OFF LOGGING
	MOVEI B,0		;INITIALIZE FOR GTJFN OF LOG FILE
	CAIN A,12		;WAS COMMAND TERMINATED WITH LF?
	  JRST LOGA		;YES, GET DEFAULT
	MOVSI A,(1B4!1B15)	;CONFIRMATION REQ'D & LONGER GTJFN CALL
	MOVEM A,LOGBLK		;STORE FOR LONG FORM GTJFN
LOG1:	MOVEI B,0		;...
	SKIPN RDJFN		;READING FROM A FILE?
	JRST LOG2		;NO
	PUSHJ P,READLN		;YES, GET THE NAME TO USE
	HRROI B,STRING		;USE THIS AS A MAIN STRING
LOG2:	MOVEI A,LOGBLK		;GET E-BLOCK FOR GTJFN
;**;[19]  Add 2 lines after LOG2:+0			DML	14-NOV-83
	MOVEI C,GTBSZE		;[19] GET BUFFER SIZE
	MOVEM C,LOGBLK+.GJCPC	;[19] PLACE IN GTJFN BLOCK
;**;[18]  Add 2 lines after LOG2:+0			DML	1-SEP-83
	HRROI C,LOGBUF		;[18] GET POINTER TO THE FILENAME
	MOVEM C,LOGBLK+.GJCPP	;[18] SAVE POINTER IN GTJFN BLOCK
	GTJFN
	  JRST LGFAIL		;FAILED
LOG3:	HRRZS A			;CLEAR LEFT HALF OF JFN
	EXCH A,LOGJFN		;SAVE NEW LOGGING JFN
	SKIPE A			;WAS THERE A JFN
	  CLOSF			;CLOSE THE OTHER ONE
	  JFCL
	HRRZ A,LOGJFN		;GET BACK JFN
	MOVE B,[7B5+1B20+1B22]	;APPEND MODE
	OPENF
	  JRST LGOPNF		;OPEN FAILED
	HRROI B,[ASCIZ/

************************************************************************
	PTYCON LOG FILE		/]
	SETZ C,
	SOUT			;SEND OUT HEADER
	SETO B,			;NOW SEND OUT THE DATE
	ODTIM
	HRROI B,[ASCIZ/

/]
	SOUT
	JRST COMLVL		;AND RETURN

LOGA:	MOVEI A," "		;SEPARATE COMMAND FROM DEFAULT NAME
	PUSHJ P,TTBOUT
	MOVSI A,(1B15)		;LONGER GTJFN CALL
	MOVEM A,LOGBLK		;STORE FOR LONGER FORM GTJFN
	HRROI B,[BYTE (7) 33,15,12,0]
	JRST LOG2		;GO GET DEFAULT JFN

LGOPNF:	PUSH P,A		;SAVE ERROR CODE
	MOVE A,LOGJFN		;GET JFN
	RLJFN			;RELEASE IT
	  JFCL
	SETZM LOGJFN		;CLEAR JFN WORD
	POP P,A			;GET BACK ERROR
	JRST RDGTJF		;GO TYPE OUT ERROR MESSAGE

LOGCLS:	SKIPN LOGJFN		;IS THERE A LOG FILE OPEN
	  POPJ P,		;NO, RETURN
	PUSHJ P,PIOFF		;DON'T ALLOW INTERRUPTS HERE
	MOVE A,LOGJFN		;GET LOGGING JFN
	HRLI A,(1B0)		;CLOSE IT BUT KEEP THE JFN
	CLOSF
	  JRST LGCLSF		;HAD A PROBLEM, GO TYPE MESSAGE
	HRRZ A,LOGJFN		;GET JFN AGAIN
	MOVE B,[7B5+1B20+1B22]	;OPEN IT AGAIN IN APPEND MODE
	OPENF
	  JRST LGCLSF		;FAILED
	PUSHJ P,PION		;TURN PI'S BACK ON
	POPJ P,			;RETURN

LGCLSF:	PUSH P,A		;SAVE ERROR CODE
	PUSHJ P,PION		;TURN INTERRUPTS BACK ON
	POP P,A			;GET BACK ERROR CODE
	JRST LGOPNF		;GO TYPE OUT ERROR MESSAGE

; GTJFN FAILED INITIALLY ON LOG FILE

LGFAIL:	CAIN A,GJFX37		;USER TYPE ^U TO DELETE TYPE-IN ?
	  JRST COMLVL		;YES, FEED HIM A NEW PROMPT
	JRST RDGTJF		;FAILURE FOR OTHER REASONS

LOGBLK:	20000,,0		;CONFIRMATION,,DEFAULT VERSION #
	100,,101		;PRIMARY TTY
	0
	0
	-1,,[ASCIZ/PTYCON/]
	-1,,[ASCIZ/LOG/]
	BLOCK 3
	G1%RND+2		;# OF ADDITIONAL WORDS FOR LONGER GTJFN
	-1,,LOGBUF		;RETURN BUFFER POINTER
;**;[19]  Change 1 line at LOGBLK:+9			DML	14-NOV-83
	0			;[19] BUFFER SIZE


NOLOG:	PUSHJ P,CRWAIT		;WAIT FOR EOL
	HRRZ A,LOGJFN		;GET JFN OF LOGGING DEVICE
	JUMPE A,COMLVL		;IF NONE, DON'T CLOSE IT
	CLOSF			;CLOSE IT
	  JRST LGOPNF		;BAD
	SETZM LOGJFN		;CLEAR JFN WORD
	JRST COMLVL		;ALL THROUGH
; ROUTINE TO SET UP A SAVE INPUT FILE

SAVINP:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST NOSAVI		;YES, GO TURN OFF LOGGING
	MOVEI B,0		;INITIALIZE FOR GTJFN OF LOG FILE
	CAIN A,12		;WAS COMMAND TERMINATED WITH LF?
	  JRST SVIA		;YES, GET DEFAULT
	MOVSI A,(1B4!1B15)	;CONFIRMATION REQ'D & LONGER GTJFN CALL
	MOVEM A,SVIBLK		;STORE FOR LONG FORM GTJFN
SVI1:	MOVEI B,0		;...
	SKIPN RDJFN		;READING FROM A FILE?
	JRST SVI2		;NO
	PUSHJ P,READLN		;YES, GET THE NAME TO USE
	HRROI B,STRING		;USE THIS AS A MAIN STRING
SVI2:	MOVEI A,SVIBLK		;GET E-BLOCK FOR GTJFN
;**;[19]  Add 2 lines after SVI2:+0			DML	14-NOV-83
	MOVEI C,GTBSZE		;[19] GET BUFFER SIZE
	MOVEM C,SVIBLK+.GJCPC	;[19] PLACE IN GTJFN BLOCK
;**;[18]  Add 2 lines after SVI2:+0			DML	1-SEP-83
	HRROI C,SAVBUF		;[18] GET POINTER TO THE FILENAME
	MOVEM C,SVIBLK+.GJCPP	;[18] SAVE POINTER IN GTJFN BLOCK
	GTJFN
	  JRST SVIFAI		;FAILED
SVI3:	HRRZS A			;CLEAR LEFT HALF OF JFN
	EXCH A,SVIJFN		;SAVE NEW LOGGING JFN
	SKIPE A			;WAS THERE A JFN
	  CLOSF			;CLOSE THE OTHER ONE
	  JFCL
	HRRZ A,SVIJFN		;GET BACK JFN
	MOVE B,[7B5+OF%WR]	;OPEN FOR WRITE
	OPENF
	  JRST SVIPNF		;OPEN FAILED
	HRROI B,[ASCIZ/

************************************************************************
	PTYCON SAVED INPUT FILE		/]
	SETZ C,
	SOUT			;SEND OUT HEADER
	SETO B,			;NOW SEND OUT THE DATE
	ODTIM
	HRROI B,[ASCIZ/

/]
	SOUT
	JRST COMLVL		;AND RETURN

SVIA:	MOVEI A," "		;SEPARATE COMMAND FROM DEFAULT NAME
	PUSHJ P,TTBOUT
	MOVSI A,(1B15)		;LONGER GTJFN CALL
	MOVEM A,SVIBLK		;STORE FOR LONGER FORM GTJFN
	HRROI B,[BYTE (7) 33,15,12,0]
	JRST SVI2		;GO GET DEFAULT JFN

SVIPNF:	PUSH P,A		;SAVE ERROR CODE
	MOVE A,SVIJFN		;GET JFN
	RLJFN			;RELEASE IT
	  JFCL
	SETZM SVIJFN		;CLEAR JFN WORD
	POP P,A			;GET BACK ERROR
	JRST RDGTJF		;GO TYPE OUT ERROR MESSAGE

SVILSF:	PUSH P,A		;SAVE ERROR CODE
	PUSHJ P,PION		;TURN INTERRUPTS BACK ON
	POP P,A			;GET BACK ERROR CODE
	JRST SVIPNF		;GO TYPE OUT ERROR MESSAGE

; GTJFN FAILED INITIALLY ON LOG FILE

SVIFAI:	CAIN A,GJFX37		;USER TYPE ^U TO DELETE TYPE-IN ?
	  JRST COMLVL		;YES, FEED HIM A NEW PROMPT
	JRST RDGTJF		;FAILURE FOR OTHER REASONS

SVIBLK:	20000,,0		;CONFIRMATION,,DEFAULT VERSION #
	100,,101		;PRIMARY TTY
	0
	0
	-1,,[ASCIZ/SAVED-INPUT/]
	-1,,[ASCIZ/TXT/]
	BLOCK 3
	G1%RND+2		;# OF ADDITIONAL WORDS FOR LONGER GTJFN
	-1,,SAVBUF		;[18] RETURN BUFFER POINTER
;**;[19]  Change 1 line at SVIBLK:+9			DML	14-NOV-83
	0			;[19] BUFFER SIZE


NOSAVI:	PUSHJ P,CRWAIT		;WAIT FOR EOL
	HRRZ A,SVIJFN		;GET JFN OF LOGGING DEVICE
	JUMPE A,COMLVL		;IF NONE, DON'T CLOSE IT
	CLOSF			;CLOSE IT
	  JRST SVIPNF		;BAD
	SETZM SVIJFN		;CLEAR JFN WORD
	JRST COMLVL		;ALL THROUGH

;SAVE INPUT IN FILE IF ONE HAS BEEN SPECIFIED

LOGINP:	SAVEAC <A,B,C>
	SKIPN A,SVIJFN		;HAVE A JFN?
	RET			;NO
	CAIN B,.CHESC		;CHECK SPECIAL CHARACTERS, ESC
	JRST [	MOVEI B,"^"
		BOUT
		MOVEI B,"$"
		JRST SAVIP1]
	CAIN B,.CHCRT		;CR
	JRST [	BOUT		;PUT IN LF TOO
		MOVEI B,.CHLFD
		JRST SAVIP1]
	CAIN B,.CHDEL		;A RUBOUT?
	JRST [	BKJFN		;YES, TRY TO DELETE LAST CHAR FROM FILE
		 SKIPA A,SVIJFN	;COULDN'T, GET JFN BACK
		RET		;OK, DON'T NEED TO PUT RUBOUT IN FILE
		MOVEI B,.CHDEL	;MUST PUT RUBOUT IN FILE
		JRST SAVIP1]
	CAIGE B,40		;PRINTING CHAR
	CAIN B,.CHTAB		;OR TAB
	JRST SAVIP1		;YES, SEND AS IS
	MOVE C,B		;CONTROL CHAR, SAVE IT
	MOVEI B,"^"
	BOUT			;SEND ESCAPE CHAR
	MOVEI B,100(C)		;CONVERT CONTROL TO PRINTING EQUIV
SAVIP1:	BOUT
	RET
TYPERR:	PUSH P,A		;TYPE ERROR
	PUSHJ P,CHKLM		;AT LEFT MARGIN?
	  PUSHJ P,CRLF		;NO, TYPE CR-LF
	HRROI A,ERRSTR		;PUT MESSAGE INTO A STRING
	POP P,B
	HRLI B,400000
	SETZ C,
	ERSTR			;TYPE ERROR
	 JFCL
	 SKIPA A,[POINT 7,[ASCIZ/UNKNOWN ERROR CODE/]]
	HRROI A,ERRSTR
	PUSHJ P,TTSOUT		;TYPE OUT STRING
	POPJ P,
;ROUTINE TO KILL A JOB

KILL:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST COMERR		;YES, ERROR
	CAIE A,15		;END WITH CR
	CAIN A,12		;  OR LF?
	  JRST TOOFEW		;YES, NEED MORE ARGUMENTS
KILL1:	PUSHJ P,GETSJB
	  JRST KILL3		;NO MATCH, CHECK FOR NULL STRING
	  JRST KILL2		;USER TYPED ALL
	CAIN A,","		;IS THIS A STRING OF ARGUMENTS?
	  JRST [PUSHJ P,TTBOUT	;YES, DO THIS ONE
		PUSHJ P,KILJOB	;THEN GO BACK FOR MORE
		JRST KILL1]
	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	PUSHJ P,KILJOB		;THEN KILL SPECIFIED JOB
	JRST COMLVL		;GO TYPE OUT PROMPT

KILL2:	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	PUSH P,I		;SAVE SUBJOB INDEX
	PUSH P,P1		;AND PERMANENT ACS
	MOVE P1,PTYHGH		;SET UP TO SCAN ALL SUBJOBS
	MOVEI I,0		;START AT 0
KILLLP:	PUSHJ P,KILJOB		;KILL EACH ONE
	ADDI I,PTYLEN		;GO TO NEXT SUBJOB
	SOJGE P1,KILLLP		;LOOP FOR ALL SUBJOBS
	POP P,P1		;RESTORE PERMANENT ACS
	POP P,I
	JRST COMLVL		;GO BACK TO COMMAND LEVEL

KILL3:	MOVE B,COMCNT		;SEE IF A NULL STRING WAS GIVEN
	CAIE B,MAXSTC		;...
	  JRST ILLSJB		;NO, ERROR
	CAIN A,12		;YES, WAS IT ENDED WITH LF?
	  JRST COMLVL		;YES, END OF COMMAND
	MOVEI A,7		;...OTHERWISE RING BELL
	PUSHJ P,TTBOUT		;...
	JRST KILL1		;AND TRY AGAIN
KILJOB:	SKIPN A,PTYTTD(I)	;IS THERE A JOB STARTED HERE?
	  POPJ P,		;NO, DON'T KILL IT
	HRLZS A			;GET TTY NUMBER
	TLZ A,400000		;TURN OFF TTY DESIGNATOR
	HRR A,TTYJOB		;GET TTYJOB TABLE NUMBER FOR GETAB
	GETAB			;GET JOB NUMBER ASSOCIATED WITH TTY
	  JRST KILJB1		;FAILED
	HLRES A
	JUMPL A,KILJB1		;IF -1 OR -2, THEN NO JOB
	LGOUT			;LOG THIS JOB OUT
	 JRST [	HRROI A,[ASCIZ/COULD NOT KILL SUBJOB /]
		PUSHJ P,TTSOUT
		PUSHJ P,TYPNAM
		PUSHJ P,CRLF
		POPJ P,]
KILJB1:	HRRZ A,PTYJFN(I)	;THEN RELEASE JFN
	CLOSF
	  JFCL			;JOB WILL BECOME DETACHED
	SETZM PTYTAB(I)		;MARK THAT JOB WAS KILLED
	HRLI A,PTYTAB(I)	;CLEAR UP ALL TRACKS
	HRRI A,PTYTAB+1(I)
	BLT A,PTYTAB+PTYLEN-1(I)
	POPJ P,			;AND RETURN
;ROUTINE TO READ IN A SUBJOB NUMBER OR NAME AND SET UP I

;CALL GETSJB
;RETURN +1	NO SUBJOB MATCH, BUT TERMINATOR SEEN (IN A)
;	+2	USER SAID "ALL"
;	+3	SUBJOB # IN I, TERMINATOR IN A

GETSJB:	PUSHJ P,COMINI		;INITIALIZE COMMAND BUFFER
GTSJB1:	PUSHJ P,RDSTR		;GO READ IN A STRING
	  JRST GTSJB1		;NO INTERUPTIONS NOW
	PUSH P,A		;SAVE TERMINATOR
	PUSHJ P,FNDPTY		;SEE IF THIS WAS A LEGAL JOB #
	  JRST GTSJB2		;NO
	POP P,A			;LEAVE TERMINATOR IN A
	JRST CPOPJ2		;TAKE DOUBLE SKIP RETURN

GTSJB2:	MOVE A,STRING		;NOW CHECK FOR "ALL"
	CAME A,[ASCIZ/ALL/]
	  JRST [POP P,A		;NOT "ALL" SO GIVE ERROR RETURN
		CAIN A,33
		  POPJ P,	;IF ALTMODE, RETURN
		CAIN A,12
		  POPJ P,	;OR IF LF
		MOVEI A,7	;OTHERWISE RING BELL
		PUSHJ P,TTBOUT
		JRST GTSJB1]	;AND GO GET MORE FROM USER
	POP P,A			;GET TERMINATOR
	JRST CPOPJ1		;GIVE SKIP RETURN FOR "ALL"

IGNOR:	CAIN A,12		;USER END WITH LF?
	  JRST TOOFEW		;YES, DEMAND SUBJOB
IGNOR0:	PUSHJ P,GETSJB		;GET THE ARGUMENT
	  JRST IGNOR3		;CR-LF OR ALTMODE
	  JRST IGNOR1		;"ALL"
	MOVSI B,PTIGNF		;USER GAVE A LEGAL SUBJOB #
	MOVE C,[IORM B,PTYSTS(I)]
	SKIPE NOFLAG		;DOES USER WANT TO SET OR CLEAR IT
	  MOVE C,[ANDCAM B,PTYSTS(I)]
	XCT C			;SET OR CLEAR THE IGNORE FLAG
	CAIN A,","		;WAS THIS JUST ONE NAME IN A LIST?
	JRST IGNOR0
	PUSHJ P,CRWAIT		;NO, WAIT FOR CONFIRMATION
	JRST COMLVL		;THEN RETURN TO COMMAND LEVEL

IGNOR1:	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	MOVSI B,PTIGNF		;SET UP TO SET OR CLEAR IGNORE BIT
	MOVE C,[IORM B,PTYSTS(I)]
	SKIPE NOFLAG		;IF USER SAID "NO", THEN CLEAR BIT
	  MOVE C,[ANDCAM B,PTYSTS(I)]
	MOVE D,PTYHGH		;LOOP FOR ALL SUBJOBS
	MOVEI I,0		;STARTING AT 0
IGNOR2:	XCT C			;SET OR CLEAR THE IGNORE BIT
	ADDI I,PTYLEN		;STEP TO NEXT SUBJOB
	SOJGE D,IGNOR2		;LOOP BACK FOR ALL SUBJOBS
	SETOM IGNALL		;SET IGNORE ALL FLAG
	SKIPE NOFLAG		;WAS A NO TYPED?
	  SETZM IGNALL		;YES, CLEAR FLAG
	JRST COMLVL		;THEN RETURN TO COMMAND LEVEL

IGNOR3:	MOVE B,COMCNT		;SEE IF THIS WAS A NULL COMMAND
	CAIE B,MAXSTC
	  JRST ILLSJB		;IF NOT, THEN THIS IS AN ERROR
	CAIN A,12		;DID THE USER TYPE LF?
	 JRST TOOFEW		;YES, GO COMPLAIN
	MOVEI A,7		;NO, THEN THIS IS AN ERROR, RING BELL
	PUSHJ P,TTBOUT
	JRST IGNOR0		;GO GET ANOTHER SUBJOB NAME
;WHAT ROUTINE

WHATPT:	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST COMERR		;YES, ERROR
	PUSH P,A		;SAVE TERMINATOR
	PUSHJ P,COMINI		;START WITH A FRESH COMMAND BUFFER
	POP P,A			;GET BACK TERMINATOR
	CAIN A,12		;WAS IT A LF?
	  JRST WHAT4		;YES, DO "ALL"
WHAT1:	PUSHJ P,RDSTR		;NO, GO GET A SUBJOB NAME
	  JRST WHAT1		;NO INTERRUPTIONS
	CAIE A,12		;ENDED WITH LF?
	CAIN A,33		;  OR ALTMODE?
	  JRST WHAT4		;YES, CHECK FOR "ALL"
WHAT3:	PUSH P,A		;SAVE TERMINATOR
	PUSHJ P,FNDPTY		;SEE IF THIS WAS A LEGAL NAME
	  JRST WHAT2		;NO
	POP P,A			;GET BACK TERMINATOR
	PUSHJ P,CRWAIT		;WAIT R CONFIRMATION
	SETZM TOFLAG		;INITIALIZE TYPE OUT FLAG
	SKIPN PTYJFN(I)		;DOES THIS JOB EXIST?
	  JRST [HRROI A,[ASCIZ/SUBJOB "/] ;NO
		PUSHJ P,TTSOUT	;TYPE "SUBJOB X NOT IN USE"
		PUSHJ P,TYPNUM	;TYPE #
		HRROI A,[ASCIZ/" NOT IN USE./]
		PUSHJ P,TTSOUT
		JRST WATDON]	;AND EXIT
	PUSHJ P,TYPSYS		;GO TYPE OUT SYSTAT FOR THIS JOB
	JRST WATDON		;AND EXIT

WHAT2:	MOVE A,STRING		;CHECK FOR "ALL"
	CAME A,[ASCIZ/ALL/]
	  JRST [POP P,A		;NOT "ALL", RING BELL
		CAIN A,12	;WAS IT TERMINATED WITH LF?
		 JRST ILLSJB	;YES, TYPE OUT ERROR MESSAGE
		MOVEI A,7
		PUSHJ P,TTBOUT
		JRST WHAT1]	;AND GO BACK FOR MORE
WHAT5:	POP P,A			;GET BACK TERMINATOR
	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	PUSH P,P1		;SAVE PERMANENT ACS
	PUSH P,I
	MOVEI I,0		;START AT # 0
	MOVE P1,PTYHGH		;AND LOOP FOR ALL JOBS
	SETZM TOFLAG		;INIT TYPE OUT FLAG FOR "NONE ACTIVE"
WHATLP:	PUSHJ P,TYPSYS		;GO TYPE SYSTAT FOR EACH JOB
	ADDI I,PTYLEN		;STEP TO NEXT JOB
	SOJGE P1,WHATLP		;LOOP BACK FOR ALL JOBS
	POP P,I
	POP P,P1
WATDON:	SKIPE TOFLAG		;WAS ANYTHING TYPED
	  JRST COMLVL		;YES, THEN WE ARE THROUGH
	HRROI A,[ASCIZ/NONE ACTIVE!/]
	PUSHJ P,TTSOUT		;NO, TELL USER SOMETHING
	JRST COMLVL		;  AND RETURN TO COMLVL

WHAT4:	MOVE B,COMCNT		;SEE IF THIS WAS A NULL STRING
	CAIE B,MAXSTC
	  JRST WHAT3		;NO, THEN ERROR
	CAIE A,15		;CR OR LF?
	CAIN A,12
	JRST WHAT4A		;YES
	MOVEI A," "		;TYPE A SPACE
	PUSH P,A		;SAVE THIS NEW TERMINATOR
	HRROI A,[ASCIZ/ ALL/]
	PUSHJ P,TTSOUT		;ECHO "ALL"
	JRST WHAT5		;THEN GO DO SYSTAT

WHAT4A:	PUSH P,A
	JRST WHAT5
;ROUTINE TO TYPE A SYSTAT OF JOB

TYPSYS:	SKIPN PTYJFN(I)		;IS THERE A JOB HERE
	  POPJ P,		;NO, TYPE NOTHING
	PUSHJ P,CHKLM		;SEE IF ON LEFT MARGIN
	  PUSHJ P,CRLF		;NO, PUT US THERE
	PUSHJ P,TYPNAM		;START WITH NAME OF SUBJOB
	PUSHJ P,TYPTAB		;TAB
	HRLZ A,PTYTTD(I)	;NOW SEE IF LOGGED IN
	TLZ A,400000
	HRR A,TTYJOB		;GET TABLE # FOR GETAB
	GETAB
	  JRST TYPSNJ		;FAILED!
	HLRE B,A		;GET TSS JOB NUMBER
	  JUMPL B,TYPSNJ	;IF -1 OR -2, THEN NOT LOGGED IN
	PUSH P,B		;SAVE JOB NUMBER
	HRROI A,STRING		;PUT NUMBER IN STRING
	MOVEI C,12
	NOUT
	  JFCL
	HRROI A,STRING		;NOW TYPE OUT NUMBER
	PUSHJ P,TTSOUT		;SO NUMBER GETS IN LOG
	PUSHJ P,TYPTAB
	MOVE A,0(P)		;GET THE JOB NUMBER
	MOVE B,[-JITBLN,,JITAB]	;GET INFO ABOUT THIS JOB
	SETZ C,
	GETJI
	 JRST TYPSY2		;IF NONE, DONT TYPE ANY MORE
	MOVE B,JITAB+.JIUNO	;GET USER NUMBER
	JUMPE B,[PUSHJ P,TYPSN1	;NOT LOGGED IN IF 0
		JRST TYPSY1]
	HRROI A,STRING		;OUTPUT NAME TO STRING
	DIRST			;TYPE OUT LOGGED IN NAME
	  JFCL
	HRROI A,STRING
	PUSHJ P,TTSOUT		;NOW TYPE OUT NAME
	PUSHJ P,TYPTAB
	MOVE A,JITAB+.JIPNM	;GET PROGRAM NAME
	PUSHJ P,TYPSIX		;TYPE IT OUT
TYPSY1:	PUSHJ P,TYPTAB
	HRRZ A,PTYJFN(I)
	MOVEI B,25		;NOW SEE IF LINE IS HUNGRY
	MTOPR
	HRROI A,[ASCIZ/RN/]	;ASSUME NOT HUNGRY
	SKIPE B			;IS IT HUNGRY
	  HRROI A,[ASCIZ/TI/]	;YES
	SKIPE PTYCNT(I)		;IF JOB HAS OUTPUT WAITING,
	  HRROI A,[ASCIZ/TO/]	;  THEN ALWAYS SAY "TO"
	PUSHJ P,TTSOUT		;TYPE OUT STATE
	PUSHJ P,TYPSY3		;TYPE OUT I OR R IF NECESSARY
	PUSHJ P,TYPTAB
	MOVE A,JITAB+.JIRT	;GET RUN TIME OF THE JOB
	IDIVI A,^D1000		;TURN IT INTO SECONDS
	IDIVI A,^D60		;GET SECONDS
	PUSH P,B		;SAVE SECONDS
	IDIVI A,^D60		;GET MINUTES
	PUSH P,B
	PUSHJ P,TTDNUM		;TYPE OUT THE DECIMAL HOURS
	MOVEI A,":"		;FOLLOWED BY ":"
	PUSHJ P,TTBOUT
	POP P,A			;GET MINUTES
	PUSHJ P,TTDNUM
	MOVEI A,":"
	PUSHJ P,TTBOUT
	POP P,A			;AND NOW DO THE SECONDS
	PUSHJ P,TTDNUM
TYPSY2:	POP P,(P)
	POPJ P,

TYPSY3:	SETZ A,			;NOW SEE IF BEING REFUSED OR IGNORED
	MOVE D,PTYSTS(I)
	TLNE D,PTREFF		;REFUSED FLAG SET?
	  HRROI A,[ASCIZ/(R)/]	;YES, SAY SO
	TLNE D,PTIGNF		;LINE BEING IGNORED?
	  HRROI A,[ASCIZ/(D)/]	;YES, THIS OVERRIDES REFUSED FLAG
	SKIPE A
	  PUSHJ P,TTSOUT	;PRINT OUT STATE IF ON
	POPJ P,			;AND RETURN

TYPTAB:	PUSH P,B		;SAVE ACS
	MOVEI A,101		;GET COLUMN COUNT
	RFPOS
	HRRZ A,B
	IDIVI A,TABSIZ		;GET NUMBER OF SPACES TO TYPE
	MOVNS B			;CALCULATE NUMBER REMAINING
	ADDI B,TABSIZ
	MOVEI A," "		;SIMULATE WITH SPACES
	CALL TTBOUT
	SOJG B,.-1
	POP P,B			;RESTORE ACS
	POPJ P,

TYPSNJ:	HRROI A,[ASCIZ/NO JOB NUMBER ASSIGNED	TI/]
	PUSHJ P,TTSOUT
	PUSHJ P,TYPSY3		;TYPE OUT I OR R IF NECESSARY
	POPJ P,

TYPSNL:	POP P,(P)
TYPSN1:	HRROI A,[ASCIZ/NOT LOGGED IN/]
	PUSHJ P,TTSOUT
	POPJ P,

TYPSIX:	MOVE D,A		;SAVE ARG
	MOVEI C,6		;TYPE A MAX OF 6 CHARS
	MOVE B,[POINT 6,D]	;SET UP BYTE POINTER
TYPSXL:	ILDB A,B		;GET NEXT CHAR
	ADDI A,40		;CONVERT TO ASCII
	PUSHJ P,TTBOUT		;TYPE IT OUT
	SOJG C,TYPSXL		;LOOP FOR 6 CHARS
	POPJ P,


TTDNUM:	MOVEI C,12		;DECIMAL OUTPUT
	MOVE B,A		;GET CHARACTER
	HRROI A,STRING		;GET ANSWER INTO A STRING
	NOUT
	 BUG (CHK,<NOUT FAILED>)
	HRROI A,STRING		;NOW OUTPUT THE ANSWER
	PUSHJ P,TTSOUT
	POPJ P,
;ROUTINE TO DO OUTPUT FROM PTY'S

PTOCHK:	MOVE A,BINTTY
	MOVEM A,TERJFN		;SET UP BINARY CHANNEL FOR PTY TO TTY PIPELINE.

;ALTERNATE ENTRY POINT FOR WHEN TTY IS KNOWN TO ALREADY BE IN BINARY MODE ...
PTOCK9:

	HRRES I			;CLEAR LEFT HALF OF INDEX
	MOVEM I,CURENT		;REMEMBER THIS JOB INDEX
	JUMPL I,PTOCK0		;IF -1, THEN NO SPECIFIC JOB NUMBER
	PUSHJ P,PTYTP2		;GO TYPE OUT TEXT FROM THIS LINE
	  POPJ P,		;TYPE IN WAS SEEN
PTOCK0:	PUSH P,P2		;NOW CHECK OTHER PTY'S
	PUSH P,P1
	PUSH P,I
	SETZB I,P2		;START AT 0
	MOVE P1,PTYHGH		;AND DO ALL JOBS
PTOCK1:	SKIPN PTYCNT(I)		;IS THERE ANYTHING WAITING ON THIS
	  JRST PTOCK2		;NO, GO ON TO NEXT
	MOVE A,PTYSTS(I)	;YES, GET STATUS
	TLNE A,PTREFF		;BEING REFUSED?
	TLNE A,PTIGNF		;AND NOT IGNORED?
	  SKIPA			;NO
	  JRST [PUSHJ P,DINGGO	;YES, START DING FORK UP
		AOJA P2,PTOCK2]	;MARK THAT ONE WAS FOUND WAITING
	PUSHJ P,PTYTYP		;TYPE OUT HEADER AND TEXT
	  JRST PTOCK3		;TYPE IN IS NOW PENDING
PTOCK2:	ADDI I,PTYLEN		;STEP TO NEXT JOB NUMBER
	SOJGE P1,PTOCK1		;LOOP BACK FOR ALL LINES
	SKIPN P2		;WERE ANY LINES WAITING
	  PUSHJ P,STDING	;NO, THEN STOP THE DINGING
PTOCK3:	POP P,I			;RESTORE ACS
	POP P,P1
	POP P,P2
	JUMPL I,CPOPJ		;IF NO CURRENT JOB, JUST RETURN
	PUSHJ P,PTYTYP		;TYPE OUT NEW HEADER IF NECESSARY
	JFCL
	POPJ P,			;AND RETURN
PTYTYP:	SETZM IGNORF		;INITIALIZE IGNORE FLAG
	MOVE A,PTYSTS(I)	;GET PTY STATUS
	TLNE A,PTIGNF		;IGNORING TYPE OUT?
	  SETOM IGNORF		;YES, MARK IT SUCH
	HRRE A,I		;GET SUBJOB INDEX
	CAMN A,LSTHDR		;SAME AS LAST HEADER TYPED?
	  JRST PTYTP2		;YES, DON'T TYPE A HEADER
	MOVEI A,101
	DOBE			;WAIT FOR TTY TO BE QUIET
	RFMOD			;NOW SEE IF CONTROL-O ON
	TLZE B,(1B0)
	  SFMOD			;YES, CLEAR IT
	CALL PIOFF		;PREVENT INTS
	PUSH P,TERJFN		;SAVE PRESENT JFN STATE
	CALL ASCTER		;GET ASCII TERMINAL
	PUSHJ P,CHKLM		;SEE IF AT START OF A LINE
	  PUSHJ P,CRLF		;NO, GO TO LEFT MARGIN
	HRROI A,[ASCIZ/**** /]
	PUSHJ P,TTSOUT
	PUSHJ P,TYPNAM		;TYPE JOB NAME
	MOVEI A," "
	PUSHJ P,TTBOUT
	HRROI A,STRING
	SETO B,
	MOVSI C,(1B0)
	ODTIM			;FOLLOWED BY THE DATE
	HRROI A,STRING
	PUSHJ P,TTSOUT		;AS A TIME STAMP
	HRROI A,[ASCIZ/ ****
/]
	PUSHJ P,TTSOUT		;END OF HEADER
	POP P,TERJFN		;RESTORE TERM DESIGNATOR
	CALL PION		;ENABLE INTS
	SKIPN IGNORF		;IF BEING IGNORED, DON'T STORE I
	HRREM I,LSTHDR		;REMEMBER THIS JOB INDEX
PTYTP2:	HRRE C,I		;GET INDEX
	SKIPGE CURENT		;AT COMMAND LEVEL?
	JRST PTYTP7		;YES, CHECK FOR TTY INPUT
	CAME C,CURENT		;SEE IF THIS IS THE CURRENT JOB
	  JRST PTYTP5		;NO
PTYTP7:	MOVE A,TERJFN
	SIBE			;ANY CHARACTERS IN INPUT BUFFER FOR TTY
	  JRST [SETZM IGNORF	;YES, THEN EXIT NOW
		POPJ P,]	;  SO THOSE CHARACTERS CAN BE SENT
PTYTP5:	MOVSI B,PTIGNF		;IGNORING THIS LINE?
	TDNE B,PTYSTS(I)	;...
	  JRST PTYTP6		;YES
	CAME C,LSTHDR		;IS A HEADER NEEDED?
	  JRST PTYTYP		;YES, GO TYPE IT
PTYTP6:	PUSHJ P,PTYGET		;GET A CHARACTER FROM BUFFER
	  JRST PTYTP4		;NO MORE LEFT
PTYTP3:	MOVSI B,PTIGNF		;LINE BEING IGNORED?
	TDNE B,PTYSTS(I)
	CAMN I,CURENT		;AND NOT THE CURRENT JOB
	JRST PTYTP8		;NO, TYPE OUT CHARACTER
	PUSHJ P,TTBLG0		;YES, JUST LOG THE CHARACTER
	JRST PTYTP2		;LOOP BACK

PTYTP4:	MOVEI A,101
	DOBE			;WAIT FOR OUTPUT TO FINISH
	PUSHJ P,PTYGET		;SEE IF ANY MORE CHARACTERS ARRIVED
	  JRST [SETZM IGNORF	;NO, ALL DONE
		JRST CPOPJ1]	;RETURN SUCCESSFULLY
	JRST PTYTP3		;YES, GO TYPE THESE OUT

PTYTP8:	PUSHJ P,TTBOUT		;TYPE THE CHARACTER
	CAIN A,12		;IS IT A LF?
	JRST [MOVEI A,101
	      RFPOS		;YES, GET FILE POSITION
	      HRRZS B		;RESET CTRL-Q COUNTER
	      SFPOS		;
	      JRST .+1]		;CONTINUE
	JRST PTYTP2		;LOOP BACK FOR MORE
TYPNAM:	SKIPN D,PTYNAM(I)	;IS THERE A NAME FOR THIS LINE?
	  JRST TYPNM1		;NO, JUST USE NUMBER
	SETZ E,			;YES, TYPE IT OUT
	HRROI A,D
	PUSHJ P,TTSOUT
	MOVEI A,"("		;THEN TYPE "(JOB NUMBER)"
	PUSHJ P,TTBOUT
	PUSHJ P,TYPNUM		;TYPE OUT JOB NUMBER
	MOVEI A,")"
	PUSHJ P,TTBOUT
	POPJ P,

TYPNM1:	HRRE B,I		;GET SUBJOB NUMBER
	IDIVI B,PTYLEN		;  FROM INDEX
	HRROI A,STRING
	MOVEI C,12
	NOUT			;CONVERT IT TO ASCIZ
	  JFCL
	HRROI A,STRING
	PUSHJ P,TTSOUT		;TYPE OUT NUMBER
	POPJ P,
DINGGO:	SKIPN BELLF		;IS BELL DISABLED
	SKIPE DINGON		;  OR ALREADY ON?
	  POPJ P,		;YES, DO NOTHING
	MOVEI A,.FHSLF		;GET OUR PROCESS HANDLE
	MOVX B,1B<.DNGCH>	;GET DING CHANNEL
	AIC			;ACTIVATE THE CHANNEL
	IIC			;INITIATE THE INTERRUPT ROUTINE
	SETOM DINGON		;AND MARK THAT IT IS ON
	POPJ P,

STDING:	MOVEI A,.FHSLF		;GET OUR PROCESS HANDLE
	MOVX B,1B<.DNGCH>	;GET THE DING CHANNEL
	DIC			;DEACTIVATE THE CHANNEL
	SETZM DINGON		;MARK THAT IT IS STOPPED
	POPJ P,

DING:	CALL DING0		;DO THE WORK
	DEBRK			;AND DEBREAK FROM INTERRUPT
	
DING0:	SAVEAC <A,B,C,I>	;SAVE THESE ACS
	MOVEI I,0		;CHECK ALL JOBS FOR CHARACTERS
	MOVE A,PTYHGH
DINGLP:	SKIPE PTYCNT(I)		;ANY WAITING
	  JRST DINGER		;YES
	ADDI I,PTYLEN		;STEP TO NEXT LINE
	SOJGE A,DINGLP		;LOOP FOR ALL JOBS
	JRST DINGWT		;WAIT FOR 10 SECONDS
DINGER:	MOVEI A,7		;OUTPUT A BELL
	PBOUT
DINGWT:	MOVE A,[XWD .FHSLF,.TIMEL] ;ELAPSED TIME FOR OUR FORK
	MOVEI B,^D10000		;TEN SECONDS TILL NEXT INTERRUPT
	MOVEI C,.DNGCH		;GENERATE IT ON THE DING CHANNEL
	TIMER			;...
	 JFCL
	RET			;AND DONE

NOPTYS:	ERRMES (<? NO MORE PTY'S AVAILABLE!>)
	JRST COMLVL

BELL:	PUSHJ P,CRWAIT		;WAIT FOR TERMINATOR
	SKIPN NOFLAG		;  TO BE NEGATED?
	  TDZA A,A		;NO
	SETO A,			;YES
	MOVEM A,BELLF		;SAVE STATE OF BELL
	PUSHJ P,STDING		;TURN OFF BELL TO START WITH
	PUSHJ P,PTOCHK		;GO TURN IT ON OR OFF
	JRST COMLVL		;RETURN
;MAIN LOOP FOR TALKING WITH A PTY

PTYLOP:	SKIPN PTYJFN(I)		;IS THERE A PTY OPENED FOR THIS JOB
	  PUSHJ P,PTINIT	;NO, GO INIT ONE
	MOVNI A,5		;SET JUST ESCAPE CHAR AS INTERRUPT CHAR
	MOVE B,ESCMSK		;GET ESCAPE MASK
	STIW			;SO CONTROL-O IS PASSED DOWN
	MOVE A,BINTTY		;SET UP BINARY CHANNEL.
	MOVEM A,TERJFN
PTYLP0:	MOVEI A,MAXPTC		;INIT THE PTY BUFFER COUNTER
	MOVEM A,CHRCNT		;INITIALIZE THE COUNT OF CHARS SEEN
PTYLP1:	MOVE A,TERJFN		;SEE IF ANY CHARACTERS ARE READY.
	SIBE
	 JRST PTYLP3		;YES, GO GET THE CHARACTER
	SKIPE PTYCNT(I)		;ANYTHING TO TYPE OUT?
	JRST PTYLP2		;YES, GO TYPE IT
PTYLP3:	PUSHJ P,TTYGET		;GET A CHARACTER FROM TTY
	  JRST PTYLP2		;NONE THERE
	SOS CHRCNT		;COUNT DOWN THE NUMBER OF CHARACTERS
	PUSH P,A		;SAVE CHARACTER
	PUSHJ P,PTYOUT		;TYPE IT OUT
	POP P,A			;GET BACK CHARACTER
	SKIPN RDJFN		;READING FROM A FILE?
	JRST PTYLP0		;NO, GET ALL INPUT FROM TTY FIRST
	CAIE A,.CHLFD		;LF? OR
	CAIN A,.CHCRT		;CR?
	JRST PTYLP4		;YES, GO READ IN ANY ECHOES
	SKIPLE CHRCNT
	JRST PTYLP1		;IF PTY BUFFER NOT FULL, GO GET MORE
	MOVEI A,^D20		;BUFFER FULL, LET SUBJOB EAT THEM
	DISMS
	JRST PTYLP1		;LOOP BACK

PTYLP4:	MOVEI A,MAXPTC		;GET PTY BUFFER SIZE
	MOVEM A,CHRCNT		;INITIALIZE CHARACTER COUNT
	MOVE A,PTYJFN(I)
	MOVX B,.MOPIH
	MTOPR			;SEE IF TTY HUNGRY
	JUMPN B,PTYLP2		;GO DO MORE INPUT IF HUNGRY
	PUSHJ P,PTYLP6		;WAIT FOR TIME OR INTERRUPT
	 JRST [	PUSHJ P,PTOCK9	;GOT INTERRUPT, CHECK OUTPUT
		JRST PTYLP4]
	HRRZ A,RDJFN
	BIN			;PEEK AT NEXT FILE CHAR
	ERJMP PTYLP4 		; IF ERROR, EOF. DON'T BKJFN
	BKJFN
	 JFCL
	CAIE B,"^"		;SOME SORT OF ESCAPE?
	JRST PTYLP4		;NO, RECHECK HUNGRY. OTHERWISE GET MORE INPUT
PTYLP2:	PUSHJ P,PTOCK9		;GO SEE IF ANYTHING TO BE ECHOED
	JRST PTYLP1		;LOOP BACK

;WAIT FOR 1 SECOND OR INTERRUPT

PTYLP6:	SETOM IOWATF		;SET FLAG FOR INTERRUPT ROUTINE
	SKIPE WAKEF		;INTERRUPT RECENTLY?
	JRST [	SETZM IOWATF	;YES, RETURN IMMED
		SETZM WAKEF	;CLEAR WAKE FLAG
		POPJ P,]
	MOVEI A,^D1000		;ONE SECOND
	DISMS			;NO, BLOCK
	SETZM IOWATF		;CLEAR FLAG
	JRST CPOPJ1
;PTY RELATED ROuTINES

;ROUTINE TO GET A PTY JFN

GETPTY:	MOVN D,SYSPTY		;GET # OF PTYS IN SYSTEM
	HRLZS D
GETPT1:	MOVSI A,600013		;GET PTY DESIGNATOR
	HRRI A,(D)		;TRY TO GET NEXT PTY
	DVCHR			;GET CHARACTERISTICS OF THIS PTY
	TLNN B,(1B5)		;IS IT AVAILABLE?
	  JRST GETPT2		;NO
	MOVE B,A
	HRROI A,DEVNAM		;TURN IT INTO AN ASCII STRING
	DEVST
	  JRST GETPT2
	MOVEI B,":"		;TERMINATED BY A COLON
	IDPB B,A
	MOVEI B,0
	IDPB B,A		;ENDED WITH A 0 BYTE
;**;[16]  Change 1 line at GETPT1:+13			DML	29-NOV-82
	MOVSI A,(GJ%SHT+GJ%ACC)	;[16] SHORT FORM GTJFN, NO ACCESS BY INFERIORS
	HRROI B,DEVNAM
	GTJFN
	  JRST GETPT2		;NOT AVAILABLE
	MOVE B,[10B5+1B19+1B20]	;NOW TRY TO OPEN IT
	PUSH P,A
	OPENF
	  JRST GETPT3		;NOT AVAILABLE
	POP P,A			;GET BACK JFN
	ADD D,FIRPTY		;TURN PTY UNIT # INTO TTY #
	TRO D,400000		;MAKE IT A TTY DESIGNATOR
	HRRZM D,PTYTTD(I)	;STORE TTY DESIGNATOR
	HRRZM A,PTYJFN(I)	;STORE JFN ALSO
	MOVEI A,101		;REFER TO THE TERMINAL WE'RE ON.
	GTTYP			;ASK THE SYSTEM WHAT TYPE WE ARE.
	MOVE A,PTYTTD(I)	;REFERENCE THE PTY.
	STTYP			;SET THE PTY TYPE TO THE SAME AS OURSELF.
CPOPJ1:	AOS (P)			;GIVE OK RETURN
CPOPJ:	POPJ P,

CPOPJ2:	AOS (P)			;DOUBLE SKIP RETURN
	JRST CPOPJ1

GETPT3:	POP P,A			;GET BACK JFN
	RLJFN			;AND RELEASE IT
	  JFCL
GETPT2:	AOBJN D,GETPT1		;TRY FOR ANOTHER PTY
	POPJ P,			;NONE LEFT
;ROUTINE TO INITIALIZE A PTY LINE

PTINIT:	PUSHJ P,GETPTY		;GO OPEN A PTY
	  JRST NOPTYS		;NONE LEFT
	SETZM PTYCNT(I)		;INITIALIZE DATA BASE FOR THIS PTY
	MOVEI A,(I)		;GET INDEX
	IDIVI A,PTYLEN		;TURN IT INTO SUBJOB #
	IMULI A,PTYBSZ		;GET START OF OUTPUT BUFFER AREA
	ADDI A,PTYBUF
	HRLI A,(POINT 8,0)	;SET UP BYTE POINTERS TO BUFFER
	MOVEM A,PTYIBP(I)
	MOVEM A,PTYGBP(I)
	MOVEM A,PTYPBP(I)
	ADDI A,PTYBSZ-1		;NOW GET BYTE POINTER TO END OF BUFFER
	HRLI A,(POINT 8,0,31)
	MOVEM A,PTYEBP(I)	;FOR END CHECKING
	HRRZ A,PTYJFN(I)	;NOW PUT PTY ON A CHANNEL
	MOVEI B,(I)
	IDIVI B,PTYLEN		;GET SUBJOB #
	IDIVI B,PTYNCH		;MODULO CHANNEL NUMBER
	ASH C,1			;DIVIDE BY 2
	HRLI B,PTYCHN(C)	;GET ACTUAL CHANNEL # FOR THIS PTY
	TLO B,(1B0+1B1)		;WANT TO WAKE ON HUNGRY AND OUTPUT WAIT
	HRRI B,24
	MTOPR			;PUT PTY ON SOFTWARE CHANNEL
	POPJ P,
;ROUTINE TO OUTPUT A CHARACTER TO A PTY

PTYOUT:	PUSH P,A
	SKIPN PTYJFN(I)		;IS THERE A JFN FOR THIS PTY?
	  PUSHJ P,PTINIT	;NO, GO GET ONE
	PUSHJ P,PTYPRM		;DOES THIS LINE NEED PRIMING
	  JRST PTYOU0		;YES
	  JRST PTYOU1		;WAITING FOR ^C TO TAKE EFFECT
	JRST PTYOU3		;NO, GO TYPE OUT CHARACTER

PTYOU0:	MOVE A,0(P)		;GET CHARACTER TO BE SENT
	CAIN A,3		;IS IT A CONTROL-C (ODD PARITY AS RECEIVED FROM TTY)
	  JRST PTYOU3		;YES, JUST SEND IT DIRECTLY
	HRRZ A,PTYJFN(I)	;GET JFN
	MOVEI B,3		;SEND A CONTROL-C TO PRIME LINE
	BOUT
PTYOU1:	MOVEI A,^D500		;  FOR CONTROL-C TO TAKE EFFECT
	DISMS
	PUSHJ P,PTYPRM		;SEE IF PRIMED YET?
	  JRST PTYOU0		;NO, GO SEND CHARACTER ANYWAY
	  JRST PTYOU1		;WAIT SOME MORE
PTYOU3:	POP P,B			;ALL PRIMED, GET CHARACTER AGAIN
PTYOU4:	HRRZ A,PTYJFN(I)	;GET PTY JFN
	BOUT			;SEND OUT THE CHARACTER
	 ERJMP [PUSH P,A	;SAVE A 
		PUSH P,B	; AND B
		MOVX A,.FHSLF	;GET THE LAST ERROR
		GETER		;GET THE CODE
		HRRZ B,B	;GET RID OF PROCESS HANDLE
		CAIE B,IOX33	;BUFFER FULL?
		JRST [POP P,B	;NO - SOME OTHER ERROR
		      POP P,A
		      CALL TYPERR	;TELL USER ABOUT ERROR
		      JRST .+1]	;REJOIN THE PATH
;**;[17]  Replace 3 lines with 12 at PTYOU4:+12		DML	6-APR-83
		MOVE A,PTYTTD(I);[17] TTY DESCRIPTOR
		SOBE		;[17] IS THERE TTY OUTPUT PENDING?
		  PUSHJ P,PTYFIL;[17] YES, READ IN ONE LINE
		PUSH P,[PTYOU6]	;[17] CONTINUATION ADDRESS AFTER INTERRUPT
		SETOM IOWATF	;[17] WAITING FOR INTERRUPT
		MOVEI A,^D1000	;[17] WAIT FOR ONE SECOND
		DISMS		;[17] 
		SETZM IOWATF	;[17] NO LONGER WAITING
		POP P,A		;[17] REMOVE UNWANTED ADDRESS
	PTYOU6:	SETZM WAKEF	;[17] WAKE UP HAS OCCURRED
		POP P,B		;[17] RESTORE REGS
		POP P,A		;[17]
		JRST PTYOU4]	;TRY AGAIN
	CAIN B,"O"-100		;CONTROL-O?
	CALL PTYFLU		;YES, FLUSH INTERNAL BUFFER
	CALL LOGINP		;SAVE INPUT MAYBE
	EXCH B,PTYLCH(I)	;SAVE LAST CHARACTER
	CAIE B,3		;CONTROL-C AS LAST CHAR?
	POPJ P,			;NO, THEN DONE
	CAMN B,PTYLCH(I)	;IS THIS A CONTROL-C ALSO
	CALL PTYFLU		;YES, FLUSH INTERNAL BUFFER
	POPJ P,

PTYPRM:	HRLZ A,PTYTTD(I)	;GET TTY #
	HRR A,TTYJOB		;AND TABLE #
	TLZ A,400000		;CLEAR TTY DEV DESIGNATOR
	GETAB			;GET JOB # FOR THIS TTY
	  JRST CPOPJ1		;NOT LOGGED IN
	JUMPGE A,CPOPJ2		;POSITIVE MEANS ALREADY PRIMED.
	TLC A,-1		;SEE IF -1
	TLCE A,-1
	  JRST CPOPJ1		;-2 MEANS IN PROCESS OF GETTING JOB #
	POPJ P,			;NEEDS PRIMING
;ROUTINE TO FILL A PTY BUFFER IF ANY ROOM

PTYFIL:	SKIPN PTYJFN(I)		;GET JFN
	  POPJ P,		;NONE, RETURN
	PUSHJ P,PIOFF		;TURN OFF PI SYSTEM
PTYFL0:	MOVE A,PTYCNT(I)	;GET CHARACTER COUNT
	CAIL A,PTYMXC		;BUFFER FULL?
	  JRST PTYFL1		;YES, DONT GET ANY MORE
	MOVE A,PTYTTD(I)	;GET DEVICE DESIGNATOR
	SOBE			;ANY CHARACTERS WAITING
	  SKIPA			;YES
	  JRST PTYFL1		;NO, ALL DONE
	HRRZ A,PTYJFN(I)	;GET JFN AGAIN
	BIN			;READ IN CHARACTER
	MOVE A,B
	PUSHJ P,PTYPUT		;STORE CHARACTER
	  JFCL
	ANDI A,177
	CAIN A,.CHLFD		;END OF A LINE?
	JRST PTYFL1		;YES, STOP HERE IN CASE SOMETHING ELSE TO DO
	MOVE A,PTYSTS(I)	;GET CURRENT STATUS OF THIS PTY
	TLNE A,PTIGNF		;OUTPUT BEING IGNORED?
	JRST PTYFL0		;YES, DONT START THE BELL
	SKIPE PUSHF		;IS USER IN LOWER EXEC?
	  PUSHJ P,DINGGO	;YES, START DINGER
	JRST PTYFL0		;LOOP FOR REST OF CHARACTERS

PTYFL1:	PUSHJ P,PION		;TURN INTERRUPTS BACK ON
	POPJ P,

;ROUTINE TO STORE A CHARACTER INTO A PTY BUFFER

PTYPUT:	MOVE B,PTYCNT(I)	;GET COUNT OF CHARS IN BUFFER
	CAIL B,PTYMXC		;IS BUFFER FULL
	  POPJ P,		;YES, DONT OVERFILL IT
	SKIPN ADDPAR		;ALLOW PARITY?
	ANDI A,177		;NO
	IDPB A,PTYPBP(I)	;STORE CHARACTER
	MOVE B,PTYPBP(I)	;GET NEW POINTER
	CAMN B,PTYEBP(I)	;IS IT TIME TO WRAP AROUND?
	  MOVE B,PTYIBP(I)	;YES, WRAP IT AROUND TO BEGINING
	MOVEM B,PTYPBP(I)	;STORE UPDATED POINTER
	AOS PTYCNT(I)		;INCREMENT COUNT
	JRST CPOPJ1		;GIVE SUCCESSFUL RETURN

;ROUTINE TO GET A CHARACTER FROM THE PTY BUFFER

PTYGET:	SKIPG PTYCNT(I)		;ANY CHARACTERS THERE
	JRST PTYGT1		;NO, CHECK FOR LOSSAGE
	SOS PTYCNT(I)		;COUNT DOWN COUNT OF CHARS
	ILDB A,PTYGBP(I)	;YES, GET THE CHARCTER
	MOVE B,PTYGBP(I)	;SEE IF POINTER NEEDS WRAPPING AROUND
	CAMN B,PTYEBP(I)
	  MOVE B,PTYIBP(I)	;YES, WRAP IT AROUND TO BEGINNING
	MOVEM B,PTYGBP(I)	;STORE NEW POINTER
	PUSH P,A		;SAVE CHARACTER
	SKIPG PTYCNT(I)		;DECREMENT COUNT
	  PUSHJ P,PTYFIL	;IF NOW ZERO, GO TRY TO FILL IT
	POP P,A			;GET BACK CHAR
	JRST CPOPJ1		;AND GIVE SUCCESSFUL RETURN

PTYGT1:	MOVE B,PTYGBP(I)	;OUT OF SYNC?
	CAMN B,PTYPBP(I)
	POPJ P,			;NO
	PUSH P,A		;POSSIBLY
	PUSHJ P,PIOFF		;TOUCHY CODE
	MOVE B,PTYPBP(I)	;GET OUTPUT POINTER
	SKIPG PTYCNT(I)		;OUT OF SYNC REALLY?
	MOVEM B,PTYGBP(I)	;YES, FIX THIS PROBLEM
	PUSHJ P,PION		;ALL DONE
	POP P,A
	POPJ P,


;ROUTINE TO FLUSH OUTPUT FROM A PTY

PTYFLU:	PUSH P,A
	PUSHJ P,PIOFF		;TOUCHY CODE AGAIN
	SETZM PTYCNT(I)		;GONE!
	MOVE A,PTYPBP(I)	;SET UP BYTE POINTERS
	MOVEM A,PTYGBP(I)
	SETZM PTYLCH(I)		;CLEAR LAST CHAR ALSO
	PUSHJ P,PION
	POP P,A
	POPJ P,
;PTY INTERRUPT LEVEL ROUTINES

DEFINE BLDCHN(A)<
PTYCH'A:	PUSHJ P,ACSAVE
	MOVEI I,A*PTYLEN
	JRST PTYINT>

ZZ=0
REPEAT PTYNCH,<BLDCHN(\ZZ)
		ZZ=ZZ+1>
PTYINT:	SKIPE PTYJFN(I)		;IS THERE A JFN FOR THIS PTY?
	PUSHJ P,PTYFIL		;YES, GO SEE IF IT HAS CHARACTERS READY
	ADDI I,PTYNCH*PTYLEN	;STEP TO NEXT PTY IN THIS GROUP
	MOVE A,PTYHGH		;GET HIGHEST PTY
	IMULI A,PTYLEN		;CALCULATE ITS INDEX
	CAMG I,A		;HAVE WE REACHED THE END YET?
	  JRST PTYINT		;NO, TRY THIS PTY
	PUSHJ P,ACLOAD		;YES, RESTORE THE ACS

;TTY INPUT INTERRUPT COMES HERE TO WAKE UP MAIN LEVEL

	SKIPE IOWATF		;IS LOWER LEVEL WAITING
	  POP P,RETSAV		;YES, WAKE IT UP
	SETZM IOWATF		;CLEAR WAIT FLAG
	SETOM WAKEF		;MARK THAT A WAKE HAPPENED
	DEBRK			;AND DISMISS THE INTERRUPT

ACSAVE:	EXCH A,0(P)		;SAVE A AND GET RETURN PC IN A
	PUSH P,B		;SAVE B
	PUSH P,C		;SAVE C
	PUSH P,D		;SAVE D
	PUSH P,I		;SAVE I
	JRST (A)		;RETURN TO CALLER

ACLOAD:	POP P,A			;LOAD AC A WITH RETURN ADDRESS
	POP P,I			;RESTORE I
	POP P,D			;RESTORE D, C, AND B
	POP P,C
	POP P,B
	EXCH A,0(P)		;RESTORE A AND PUT RETURN ON STACK
	POPJ P,			;RETURN TO CALLER
;ROUTINE TO PUSH DOWN TO A LOWER EXEC

PUSHE:	PUSHJ P,CRWAIT		;WAIT FOR CONFIRMATION
	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST COMERR		;YES, ERROR
	MOVSI A,(1B1)		;CREATE A LOWER FORK FOR EXEC
	CFORK
	  JRST NOFORK		 
	PUSH P,A		; SAVE PROCESS HANDLE
	MOVSI A,(1B2!1B17)	;GET A JFN FOR THE EXEC
	HRROI B,[ASCIZ/SYSTEM:EXEC.EXE/]
	GTJFN
	  JRST NOEXEC		;NO EXEC FOUND
	HRL A,0(P)
	GET			;NOW GET THE EXEC INTO THE LOWER FORK
	MOVEI A,.FHSLF		;DONT ALLOW LOWER FORK TO LOG OUT
	RPCAP
	TXZ B,SC%LOG
	SETZ C,			;NO PRIVS ENABLED
	MOVE A,0(P)		;GET LOWER FORK HANDLE
	EPCAP			;SET ITS CAPABILITIES
	MOVE A,TRPCHR
	DTI			;DEACTIVATE INTERRUPT CHARACTER
	MOVEI A,400000		;TURN OFF THE TRAP CHANNEL
	MOVE B,[1B<TRPCHN>]	;...
	DIC
	HRLI A,3		;NOW PUT CONTROL-C ONTO CHANNEL
	HRRI A,TRPCHN		;THIS PREVENTS A ^C FROM LEAVING PTYCON
	ATI
	MOVNI A,5
	MOVE B,SAVTIW		;PUT TERMINAL INTERRUPT WORDS BACK
	STIW
	MOVEI A,100
	MOVE B,SAVMOD		;SET UP ORIGINAL TTY MODE
	SFMOD
	STPAR
	SETZM SAVMOD		;MODES MAY BE SET IN LOWER EXEC
	SETO A,			;REMEMBER OUR NAME TO RESTORE IT LATER
	MOVE B,[-2,,NAMES]	;GET BOTH NAMES
	MOVEI C,.JISNM
	GETJI
	  JFCL
	POP P,A			;GET BACK FORK NUMBER
	SETZ B,
	SETOM PUSHF		;MARK THAT WE ARE PUSHED DOWN
	SFRKV			;START THE EXEC
	WFORK			;AND WAIT FOR IT TO HALT
	SETZM PUSHF		;OUT OF EXEC
	KFORK			;KILL THE LOWER FORK
PUSHE1:	DMOVE A,NAMES
	SETSN			;RESTORE NAME OF PROGRAM
	  JFCL
	JRST PTYCON		;RESTART
NOEXEC:	ERRMES (<? NO EXEC>)
	POP P,A			; GET BACK PROCESS HANDLE
	KFORK			; KILL IT
	 JFCL
	JRST COMLVL

NOFORK:	ERRMES (<? NO LOWER FORKS AVAILABLE>)
	JRST PUSHE1
;STORAGE AREA DEFINITIONS

PTYBSZ==10000			;SIZE OF BUFFER FOR EACH PTY
PTYBUF==400000			;START OF PTY BUFFERS
PTYMXC==PTYBSZ*4		;# OF CHARACTERS IN A BUFFER
MAXPTY==30			;MAXIMUM NUMBER OF JOBS ALLOWED

;**;[19]  Add 1 line after MAXPTY==30			DML	14-NOV-83
GTBSZE==200			;[19] BUFFER SIZES FOR GTJFN BLOCKS

DEFINE ALC (NAM,SIZ)<
	NAM=LC
	LC=LC+SIZ>

LC=300000			;LOCAL STORAGE STARTS HERE

ALC ADDPAR,1			;ADD PARITY BIT FOR REAL TERMINAL
ALC PICNT,1			;# OF PIOFF'S DONE
ALC PTYHGH,1			;HIGHEST SUBJOB IN USE
ALC IOWATF,1			;WAITING FOR AN INTERRUPT
ALC WAKEF,1			;AN INTERRUPT HAS HAPPENED
ALC FIRPTY,1			;TTY NUMBER OF FIRST PTY
ALC NUMPTY,1			;# OF PTY LINES AVAILABLE FOR PTYCON
ALC SYSPTY,1			;NUMBER OF PTY'S IN SYSTEM
ALC TTYJOB,1			;TABLE # OF TTYJOB FOR GETAB
ALC JOBPNM,1			;GETAB TABLE # OF JOBNAM
ALC SNAMES,1			;GETAB TABLE # OF SNAMES
ALC JOBRT,1			;GETAB TABLE # OF JOBRT
ALC TIMASK,1			;TERMINAL INTERRUPT MASK
ALC TRPCHR,1			;TRAP CHARACTER TO GET BACK TO COMLVL
ALC ESCMSK,1			;MASK FOR STIW WHEN AT SUBJOB LEVEL
ALC CHRCNT,1			;COUNT OF CHARACTERS IN LINE SO FAR
ALC COMCNT,1			;NUMBER OF CHARS LEFT IN COMMNAD BUF
ALC COMBP,1			;POINTER TO NEXT CHAR IN COMAND BUFFER
ALC XJSYS,1			;JSYS TO BE EXECUTED BY DO JSYS ROUTINE
ALC TERJFN,1			;HOLDS TTY JFN CURRENTLY IN USE.
ALC BINTTY,1			;JFN OF BINARY CHANNEL FOR TTY.
ALC SAVMOD,1			;ORIGINAL TTY MODE
ALC SAVTYP,1			;ORIGINAL TTY TYPE
ALC SAVTIW,1			;ORIGINAL TERMINAL INTERRUPT WORD
ALC LSTCHR,1			;LAST CHARACTER TYPED
ALC NOFLAG,1			;IF SET, "NO" WAS TYPED
ALC IGNORF,1			;IGNORING THIS LINE FLAG
ALC BELLF,1			;DISABLE BELL FLAG
ALC SILNCF,1			;-1 = TURN OF ECHOING OF GET COMMANDS
ALC LMFLAG,1			;LEFT MARGIN FLAG
ALC REFALL,1			;REFUSE ALL WAS TYPED
ALC IGNALL,1			;IGNORE ALL WAS TYPED
ALC DINGON,1			;DING FORK IS ON FLAG
ALC LSTHDR,1			;INDEX OF LAST JOB A HEADER WAS TYPED
ALC LSTCON,1			;LAST JOB CONNECTED TO
ALC NXLOGC,1			;TIME FOR NEXT LOG FILE UPDATE
ALC RDJFN,1			;JFN OF AUTO COMMAND FILE
ALC LOGJFN,1			;JFN OF LOGGING FILE
ALC SVIJFN,1			;JFN OF SAVE INPUT FILE
ALC CURENT,1			;INDEX OF CURRENT JOB
ALC TOFLAG,1			;SET TO -1 WHENEVER A CHAR IS TYPED
ALC PUSHF,1			;SET TO -1 WHEN PUSHED DOWN TO EXEC
ALC NAMES,2			;PROGRAM NAMES
ALC RETSAV,1			;INTERRUPT PC
	CNTRLC==3		;CONTROL-C
	CCMAX==4		;MAX # OF ^C'S BEFORE TURNING OFF ^S
ALC CCCNT,1			;COUNT OF ^C'S SEEN IN A ROW
ALC DEVNAM,2			;ASCIZ DEVICE NAME OF PTY
	JITBLN==.JIBAT+1	;ROOM FOR UP TO JIBAT
ALC JITAB,JITBLN		;GETJI INFO FOR JOBS DURING "WHAT"
	STRNGL==400
	MAXSTC==STRNGL*5-1
ALC STRING,STRNGL		;TEMP STRING FOR BUILDING COMMANDS

	ERRSTL==20
ALC ERRSTR,ERRSTL		;BLOCK FOR ERSTR STRINGS

	PDLEN==30
ALC PDL,PDLEN			;STACK
ALC PTYTAB,0			;PTY STORAGE AREA, MUST BE LAST SPACE ASSIGNED

PTYTTD==0+PTYTAB		;TTY DESIGNATOR
PTYJFN==1+PTYTAB		;JFN OF PTY
PTYCNT==2+PTYTAB		;COUNT OF CHARACTERS IN BUFFER
PTYIBP==3+PTYTAB		;INITIAL BUFFER POINTER
PTYEBP==4+PTYTAB		;END OF BUFFER POINTER
PTYPBP==5+PTYTAB		;PUTTER POINTER
PTYGBP==6+PTYTAB		;GETTER POINTER
PTYNAM==7+PTYTAB		;SUBJOB NAME (5 ASCII CHARACTERS)
PTYSTS==10+PTYTAB		;STATUS OF SUBJOB
PTYLCH==12+PTYTAB		;LAST CHAR SENT TO THIS SUBJOB
PTYLEN==13
.DNGCH==1			;DING CHANNEL FROM TIMER INTERRUPT
LEVTAB:	RETSAV			;PI LEVEL TABLE
	0
	0

CHNTAB:	0			;0
	1,,DING			;1
	0			;2
	0			;3
	0			;4
	1,,TRAP			;5
TRPCHN==5
	0			;6
	0			;7
	0			;8
	XWD 1,PANIC		;9 PDL OVERFLOW
	0			;10
	XWD 1,PANIC		;11 - DATA ERROR
	0			;12
	0			;13
	0			;14
	XWD 1,PANIC		;15 - ILLEGAL INSTRUCTION
	XWD 1,PANIC		;16 - ILLEGAL MEM READ
	XWD 1,PANIC		;17 - ILL MEM WRITE
	XWD 1,PANIC		;18 - ILL MEM EXECUTE
	0			;19
	XWD 1,PANIC		;20 - MACHINE SIZE EXCEEDED
	0			;21
	0			;22
	0			;23

	DEFINE CHNBLD(A)<
	XWD 1,PTYCH'A
	XWD 1,PTYCH'A>

ZZ==0
REPEAT PTYNCH,<CHNBLD(\ZZ)
		ZZ==ZZ+1>

ONCHNS:	1B<TRPCHN>+1B9+1B11+1B15+1B16+1B17+1B18+1B20+7777


;**;[18]  Add 1 line before LOGBUF:+0			DML	1-SEP-83
;**;[19]  Change 3 lines at SAVBUF:+0			DML	14-NOV-83
SAVBUF:	BLOCK GTBSZE		;[19][18] BUFFER FOR SAVE COMMAND FILENAME
LOGBUF:	BLOCK GTBSZE		;[19] TEXT BUFFER FOR LOG COMMAND
GETBUF:	BLOCK GTBSZE		;[19] BUFFER FOR GET COMMAND FILENAME


	END <3,,ENTVEC>