Google
 

Trailing-Edge - PDP-10 Archives - BB-H138E-BM - 6-1-sources/ptycon.mac
There are 31 other files named ptycon.mac in the archive. Click here to see a list.
; UPD ID= 143, SNARK:<6.1.UTILITIES>PTYCON.MAC.11,  14-Jun-85 13:22:02 by EVANS
;TCO 6.1.1450 - Make PUSH know about DEFAULT-EXEC:
; UPD ID= 118, SNARK:<6.1.UTILITIES>PTYCON.MAC.10,  30-Apr-85 14:53:44 by LOMARTIRE
;TCO 6.1.1349 - In PTYINT, restore the ACs in the right place to avoid panic
; UPD ID= 617, SNARK:<6.UTILITIES>PTYCON.MAC.9,  23-Oct-84 16:23:25 by LOMARTIRE
;TCO 6.2248 - Make the fields of the WHAT command line up in columns.
; UPD ID= 545, SNARK:<6.UTILITIES>PTYCON.MAC.8,   6-Jun-84 15:28:49 by LOMARTIRE
;TCO 6.2079 - Change order of command parse and fix subjob name parsing
; UPD ID= 473, SNARK:<6.UTILITIES>PTYCON.MAC.7,   8-Feb-84 10:38:41 by EVANS
;Add flag to edit number so I VER will display it in decimal.
; UPD ID= 349, SNARK:<6.UTILITIES>PTYCON.MAC.6,   7-Sep-83 16:32:09 by LOMARTIRE
;More TCO 6.1566 - Clean up comments and error messages
; UPD ID= 286, SNARK:<6.UTILITIES>PTYCON.MAC.5,  20-May-83 13:50:46 by LOMARTIRE
;More TCO 6.1566 - Don't append CR and LF to end of one-liner; only append CR
; UPD ID= 256, SNARK:<6.UTILITIES>PTYCON.MAC.4,  12-Apr-83 15:56:19 by LOMARTIRE
;TCO 6.1595 - Fix hanging while processing commands from .ATO file
; UPD ID= 255, SNARK:<6.UTILITIES>PTYCON.MAC.3,  12-Apr-83 12:58:33 by LOMARTIRE
;More TCO 6.1566 - Fix problem with printing of subjob output header
; UPD ID= 243, SNARK:<6.UTILITIES>PTYCON.MAC.2,   1-Apr-83 09:07:34 by LOMARTIRE
;TCO 6.1566 - Convert command parsing routines to COMND JSYS
; 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==6		;MAJOR VERSION OF PTYCON
VMINOR==0		;MINOR VERSION NUMBER
VEDIT==VI%DEC+^D23	;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
CNTRLC==1B<.TICCC>		;CONTROL-C MASK
TYPINM==1B<.TICTI>		;TYPIN OCCURRED MASK
ALLMSK==[777777,,700000]	;"ALL" COMPARISON 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,.PRIIN	;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,[PUSH P,B	;SAVE ERROR CODE
		 PUSHJ P,CHKLM	;ON LEFT MARGIN?
		  PUSHJ P,CRLF	;NO, TYPE CR-LF
		POP P,B		;RESTORE ERROR CODE
		HRROI A,[ASCIZ/MESSAGE/]
		JRST TTSOUT]>

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

;MACRO TO PARSE NOISE WORDS

DEFINE NOISE (GWRD) <
	MOVEI A,CMDSBK			
	MOVEI B,[FLDDB. .CMNOI,,<-1,,[ASCIZ /GWRD/]>]  
	COMND				;PARSE NOISE WORDS
	  ERJMP FJERR			;FATAL JSYS ERROR
	TXNE A,CM%NOP			;ERROR DURING NOISE PARSE?
	JRST COMERR>			;YES, OUTPUT ERROR MESSAGE

;MACRO TO CONFIRM COMMAND

DEFINE CONFIRM <			
	MOVEI A,CMDSBK			
	MOVEI B,[FLDDB. .CMCFM]		
	COMND				;PARSE CONFIRMATION
	  ERJMP FJERR			;FATAL JSYS ERROR
	TXNE A,CM%NOP			;ERROR DURING CONFIRM PARSE?
	JRST COMERR			;YES, OUTPUT ERROR MESSAGE
	TRYLOG>				;TRY TO LOG COMMAND

DEFINE TRYLOG <				;TRY TO LOG COMMAND LINE
	HRROI A,CMDBUF			;TRY TO LOG COMMAND
	PUSHJ P,TTSLOG			
	SKIPE RDJFN			;PROCESSING A COMMAND FILE?
	PUSHJ P,PRTCMD>			;PRINT COMMAND LINE
;PROGRAM ENTRY VECTOR

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

PTYSRT:	RESET			;FRESH START
PTYCON:	MOVE P,[IOWD PDLEN,PDL]	;SET UP STACK
	SETZM PUSHF		;NOT PUSHED DOWN A LEVEL NOW
	SETZM IOWATF		;INITIALIZE WAITING FOR INTERRUPT FLAG
	SETOM NOINT		;NO PTY INTERRUPTS UNCONDITIONALLY
	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+CNTRLC+TYPINM]  ;MASK FOR TERMINAL INTERRUPT
	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			;...
	HRLI A,.TICCC		;CONTROL-C INTERRUPT CODE
	HRRI A,CTLCHN		;CONTROL-C CHANNEL
	ATI			;ASSIGN CONTROL-C TO CHANNEL
	HRLI A,.TICTI		;TYPEIN OCCURRED CODE
	HRRI A,TINCHN		;TYPIN CHANNEL
	ATI			;ASSIGN TO CHANNEL
	MOVEI A,.FHSLF		;NOW ACTIVATE ALL DESIRED CHANNELS
	MOVE B,ONCHNS
	AIC
	EIR			;ENABLE PI SYSTEM
	MOVX B,1B<PTYOCN>	;START UP PTY OUTPUT CHECK
	IIC			
	HRLI A,.TICTI		;FLAG TERMINAL INPUT
	HRRI A,TINCHN		;INTERRUPT CHANNEL
	ATI			;ASSIGN INTERRUPT
	  ERJMP .+1		;IGNORE ERROR
	MOVEI A,.PRIIN		;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,.PRIIN		
	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>) 
	MOVE A,[1B10+1B12+1B13] ;SETUP PROGRAM BREAK MASK
	MOVEM A,PGMSK		;ALLOW ONLY LF, FF, OR CR
	SETZM PGMSK+1		;AS VALID BREAK CHARACTERS
	SETZM PGMSK+2		
	SETZM PGMSK+3		
	JRST COMLVL		;GO TO COMMAND LEVEL
;COMMAND LEVEL

COMLVL:	SETOM NOINT		;NO PTY INTERRUPTS UNCONDITIONALLY
	SKIPE A,JFNIP		;HAS A FILE JFN BEEN OBTAINED?
	PUSHJ P,RELJFN		;YES, RELEASE IT
	SETOM LMFLAG		;USE RFPOS IN CHKLM
	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
	MOVE A,PMTPR		;PRINT PROMPT
	PUSHJ P,TTSOUT		
	SETZM CMDBUF		
	HRLI A,CMDBUF		;CLEAR COMMAND AND ATOM BUFFERS
	HRRI A,CMDBUF+1		
	BLT A,GTJBLK-1		
	MOVEI A,CBUFSZ*5-1	;RESET BUFFER SIZE
	MOVEM A,CMDSBK+.CMCNT	
	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
	SKIPE RDJFN		;READING FROM FILE?
	PUSHJ P,GCNVT		;YES, READ AND CONVERT COMMAND FORM FILE
	SETZM TOFLAG		;INITIALIZE TYPOUT OCCURRED FLAG
	SETZM NOINT		;DISALLOW PTY INTERRUPTS CONDITIONALLY
COMSTR:	SETOB I,LSTHDR		;ALWAYS CLEAR SUBJOB INDEX
	MOVEM I,CURENT		;SAVE CURRENT INDEX OF JOB
	MOVEI A,.NULIO		;DON'T PRINT PROMPT AGAIN
	HRRM A,CMDSBK+.CMIOJ	
	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK
	MOVEI B,[FLDDB. .CMINI]	;GET INITIALIZE FUNC. DESC. BLOCK
	COMND			;INITIALIZE COMND
	  ERJMP FJERR		;FATAL JSYS ERROR
	SKIPE RDJFN		;READING FROM FILE?
	JRST [	MOVE A,CMDCNT	;GET CHARACTER COUNT
		MOVEM A,CMDSBK+.CMINC  ;SET AS NUMBER OF UNPARSED CHARS
		JRST COM0]	
COM0:	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
	SETZM NODEF		;ALLOW DEFAULT OF "ALL"
	SETZM CONDEF		;CLEAR CONNECT DEFAULT SUBJOB
	SETOB I,LSTHDR		;ALWAYS CLEAR SUBJOB INDEX
	MOVEM I,CURENT		;SAVE CURRENT INDEX OF JOB
	SETOM LMFLAG		;USE RFPOS IN CHKLM
	MOVEI A,.PRIOU		;SETUP INITIAL OUTPUT JFN
	SKIPE RDJFN		;READING FROM A FILE?
	MOVEI A,.NULIO		;YES, RESET OUTPUT JFN
	HRRM A,CMDSBK+.CMIOJ	
	MOVEI A,.PRIIN		;INITIALIZE MODE OF TTY
	MOVE B,SAVMOD		;
	TLZ B,(1B0)		;CLEAR CNTRL-O
	SFMOD			;
	MOVE A,CMDSBK		;GET FIRST WORD OF BLOCK
	TXO A,CM%WKF		;SET TO PARSE AFTER EVERY FIELD
	MOVEM A,CMDSBK		
COM2:	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK
	MOVEI B,CBLK		;FUNCTION BLOCK
	COMND			;PARSE KEYWORD
	  ERJMP FJERR		;FATAL JSYS ERROR
	SETOM NOINT		;DISALLOW PTY INTERRUPTS UNCONDITIONALLY
	TXNE A,CM%NOP		;PARSE OK?
	JRST COMERR		;NO, ERROR
	HRRZS C			;ISOLATE USED FUNCTION BLOCK
	MOVE D,CMDSBK+.CMPTR	;GET POINTER TO NEXT FIELD TO BE PARSED
	ILDB D,D		;GET THE NEXT CHARACTER
	CAIE D,"-"		;IS IT A DASH?
	JRST COM3		;  NO, CONTINUE WITH PARSING
	CAIE C,CBLK		;  YES, DID THE PARSE THINK IT WAS A COMMAND?
	JRST COM3		;    NO, SO EVERYTHING IS FINE, PROCEED
	SETZM C			;    YES, CLEAR WHATEVER FUNCTION BLOCK MAY BE
	JRST CMDSJN		;PARSE SUBJOB NAME INSTEAD OF COMMAND

COM3:	PUSH P,B		;SAVE ADDRESS
	MOVEM B,ARGS+1		;SAVE TABLE ADDRESS OR NUMBER
	MOVE B,ATMBUF		;PLACE ATOM BUFFER
	MOVEM B,ARGS		;IN TEMP STORAGE
	HRRZM C,ARGS+2		;SAVE FUNCTION BLOCK USED
	MOVE A,CMDSBK		;GET FIRST WORD OF BLOCK
	TXZ A,CM%WKF		;DON'T PARSE AFTER EVERY FIELD
	MOVEM A,CMDSBK		
	POP P,B			;RETRIEVE ADDRESS
	CAIE C,NBLK		;WAS A SUBJOB NUMBER ENTERED?
	CAIE C,CBLK		;OR A SUBJOB NAME?
	JRST SINGLE		;YES, GET TEXT FOR SINGLE LINE COMMAND
	HRRZ B,(B)		;GET DISPATCH ADDRESS
	JRST (B)		;DISPATCH TO ROUTINE
NOCOMM:	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK
	MOVEI B,[FLDDB. .CMKEY,,NOTBL]  ;SETUP FUNC. DESC. BLK FOR NO
	COMND			;PARSE NO COMMAND
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;PARSE A LEGAL NO COMMAND?
	JRST COMERR		;NO, OUTPUT ERROR MESSAGE
	SETOM NOFLAG		;SET FLAG TO SIGNAL COMMANDS
	HRRZ B,(B)		;GET DISPATCH ADDRESS
	JRST (B)		;DISPATCH TO ROUTINE

CMDSJN:	PUSH P,A		;SAVE REGISTERS
	PUSH P,B		
	MOVEI A,NAMTBL		;SEARCH NAMTBL
	SETZM ATMBUF+1		;TRUNCATE SUBJOB NAME ENTERED
	HRROI B,ATMBUF		;POINT TO TRUNCATED NAME
	TBLUK			;TRY TO FIND NAME
	  ERJMP .+1		;IGNORE ERROR
	TXNN B,TL%NOM		;WAS NAME FOUND?
	SKIPN ATMBUF		;AND WAS THERE SOMETHING IN ATOM BUFFER?
	JRST [	POP P,B		;NO, RESTORE REGISTERS
		POP P,A		
		JRST COMERR]	;PRINT ERROR
	POP P,B			;REMOVE UNWANTED ELEMENT
	MOVE B,A		;SAVE ADDRESS OF SUBJOB NAME
	POP P,A			;RETRIEVE SAVED REGISTER
	JRST COM3		;CONTINUE PARSE
COMERR:	TRYLOG			;TRY TO LOG COMMAND
	WRNMES (<? Unrecognized PTYCON command - >)  ;COMMAND ERROR
	PUSHJ P,TYPERR		;TYPE REST OF ERROR MESSAGE
	MOVEI A,.PRIIN		;CLEAR TYPEAHEAD
	CFIBF			
	JRST COMLVL		;AND RETURN TO COMMAND LEVEL

; CONTROL-C INTERRUPT HANDLER

COMCC:	HRROI A,[ASCIZ "^C"]	;PRINT OUT CONTROL-C
	PSOUT			;PRINT WITHOUT LOGGING
	  ERJMP .+1		;IGNORE ERROR
	MOVE A,CMDSBK+.CMBFP	;GET POINTER TO START OF COMMAND
	ILDB B,A		;GET FIRST CHARACTER
	SKIPN B			;IS IT NULL?
	JRST COMC1		;YES, ILLEGAL CONTROL-C
	MOVE A,CMDSBK+.CMPTR	;GET BYTE POINTER TO UNPARSED TEXT
	HRROI B,STRING		;DESTINATION
	MOVEI C,MAXSTC		;NUMBER OF CHARACTERS TO READ
	SETZ D,			;STOP AT NULL BYTE
	SIN			;READ IN COMMAND ENTERED SO FAR
	PUSH P,A		;SAVE PREVIOUS POINTERS
	PUSH P,B		
	PUSH P,C		
	MOVE A,CMDSBK+.CMBFP	;GET BYTE POINTER TO START OF COMMAND
	HRROI B,STRING		;DESTINATION
	MOVEI C,MAXSTC		;NUMBER OF CHARACTERS TO READ IN
	MOVEI D,"-"		;STOP AT THE HYPHEN
	SIN			
	LDB C,B			;GET LAST CHARACTER
	CAIE C,"-"		;IS IT A HYPHEN?
	JRST COMC1		;NO, ERROR
	MOVEM A,LNEPTR		;SAVE START OF TEXT POINTER
	SETZ C,			;WIPE OUT HYPHEN
	DPB C,B			
	MOVE C,STRING		;GET ARGUMENT ENTERED
	MOVEM C,ARGS		;SAVE IT
	MOVEI C,NBLK		;GET ADDRESS OF NUMBER FUNCTION BLOCK
	MOVEM C,ARGS+2		;SAVE AS BLOCK USED
	POP P,C			;RESTORE PREVIOUS POINTERS
	POP P,B			
	POP P,A			
COMC0:	MOVEI B,3		;CODE FOR CONTROL-C
	DPB B,A			;PLACE CONTROL-C IN BUFFER
	MOVEM A,CMDSBK+.CMPTR	;STORE AS POINTER TO NEXT PARSE
	SETZM CMDSBK+.CMINC	;NO UNPARSED CHARACTERS
	MOVEI D,MAXSTC		;COMPUTE NUMBER OF CHARACTERS ENTERED
	SUB D,C			
	MOVE C,CMDSBK+.CMCNT	;DECREMENT SPACE LEFT
	SUB C,D			
	MOVEM C,CMDSBK+.CMCNT	
	MOVEI A,SINGL0		;ASSUME PARSING ONE LINER ALREADY
	MOVE B,1(P)		;GET FUNCTION BLOCK ADDRESS
	CAIE B,SBLK		;WERE WE ALREADY PARSING THE LINE TEXT?
	MOVEI A,SINCC		;ADDRESS TO CONTINUE AT AFTER INTERRUPT
	MOVEM A,RETSAV		;
	DEBRK			;DISMISS INTERRUPT
COMC1:	SKIPE A,LOGJFN		;LOGGING THIS?
	JRST [	HRROI B,[ASCIZ "^C"]  ;STRING TO WRITE
		SETZM C		;WRITE IT ALL
		SOUT		;WRITE TO LOG FILE
		  ERJMP .+1	;IGNORE ERROR
		JRST .+1]	;CONTINUE
	PUSHJ P,CHKLOG		;SEE IF ANY JOBS LOGGED IN
	  JRST [ERRMES (<? Type "EXIT" to exit from PTYCON>)
		JRST COMC2]	;NO ACTIVE SUBJOBS
	ERRMES (<? Subjobs active, use "PUSH" command>)  
COMC2:	SKIPE A,RDJFN		;IS THIS AN ABORT OUT OF A GET COMMAND?
	  CLOSF			;YES, CLOSE THE GET FILE
	  JRST [ MOVE A,RDJFN	;ERROR, TRY TO RELEASE JFN
		 RLJFN		
		   ERJMP .+1	;IGNORE ERROR
		 JRST .+1]	
	SETZM RDJFN		;STOP READING FROM FILE
	SETZM SILNCF		;CLEAR SILENCE FLAG
	MOVE A,[.PRIIN,,.PRIOU]	;RESET TTY AS
	MOVEM A,CMDSBK+.CMIOJ	;PRIMARY INPUT AND OUTPUT JFNS
	MOVEI A,COMLVL		;RESTART FRESH AFTER DISMISS
	MOVEM A,RETSAV		
	DEBRK			;DISMISS INTERRUPT

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

; TTY TYPE IN INTERRUPT HANDLER

TYPIN:	SKIPE RDJFN		;READING FROM FILE?
	DEBRK			;YES, DISMISS INTERRUPT
	SKIPL TOFLAG		;TYPOUT IN PROGRESS?
	SETZM NOINT		;TYPE IN OCCURRED - DISALLOW PTY INTERRUPTS
	DEBRK			;DISMISS INTERRUPT
SINGLE:	MOVE A,CMDSBK		;PARSE AFTER FIELD IS TERMINATED
	TXO A,CM%WKF		
	MOVEM A,CMDSBK		
	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK
	MOVEI B,[FLDDB. .CMTOK,CM%HPP,<-1,,[ASCIZ "-"]>,<a dash>]
				;FUNCTION BLOCK
	COMND			;PARSE DASH
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;DASH PARSED CORRECTLY?
	JRST COMERR		;NO, ERROR
	MOVE A,CMDSBK+.CMPTR	;GET POINTER TO NEXT INPUT
	MOVEM A,LNEPTR		;SAVE IT
SINCC:	MOVE A,CMDSBK		;DON'T PARSE AFTER EVERY FIELD
	TXZ A,CM%WKF		
	MOVEM A,CMDSBK		
	MOVEI A,.FHSLF		;SET PROCESS TO SELF
	MOVE B,[1B<CTLCHN>]	;CHANNEL TO ASSIGN CONTROL-C TO
	AIC			;ASSIGN CONTROL-C
SINGL0:	MOVEI A,CMDSBK		;GET ADDRESS OF COMMAND STATE BLOCK
	MOVEI B,SBLK		;FUNCTION BLOCK
	COMND			;PARSE SINGLE LINE COMMAND TEXT
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;PARSE ERROR?
	JRST COMERR		;YES, REPORT IT
	CONFIRM			;CONFIRM COMMAND
	SETZM LNESTR		;CLEAR STRING
	MOVE A,LNEPTR		;GET POINTER TO LINE TEXT
	HRROI B,LNESTR		;PLACE IN LINE STRING
	SETZ C,			;STOP AT ZERO
	SIN			;GET STRING
	  ERJMP .+1		;IGNORE ERROR
	MOVEI A,0		;END WITH NULL
	DPB A,B			;MASK OFF LF - LEAVE ONLY CR
	MOVE A,ARGS+2		;GET ADDRESS OF FUNCTION BLOCK USED
	CAIN A,NBLK		;WAS A NUMBER ENTERED?
	JRST [ MOVE A,ARGS	;YES, GET NUMBER ENTERED
	       JRST SINGL1]	;CONTINUE
	HLRZ B,@ARGS+1		;GET ADDRESS OF SUBJOB NAME
	MOVE A,@B		;GET SUBJOB NAME
SINGL1:	MOVEM A,ATMBUF		;PLACE IN ATOM BUFFER
	SETZM NUMFL		;CLEAR NUMBER FLAG
	PUSHJ P,FNDPTY		;SET UP INDEX OF SUBJOB
	  JRST SINGL2		;NOT DEFINED, CHECK "ALL"
	SKIPE NUMFL		;WAS A NUMBER ENTERED?
	JRST [ IDIVI B,PTYLEN	;GET NUMBER
	       CAML B,PTYHGH	;WAS IT A NEW HIGH?
	       PUSHJ P,NEWHGH	;YES, SET IT
	       JRST .+1]	;CONTINUE
	MOVEM I,LSTCON		;SAVE LAST SINGLE SUBJOB #
	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,LNESTR];POINT TO TEXT
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
	AND A,ALLMSK		;MASK OFF GARBAGE
	CAME A,[ASCIZ/ALL/]	;IS IT SPECIAL CASE "ALL"?
	JRST ILLSJB		;NO, ILLEGAL SUBJOB DESIGNATOR
	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
;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

CMDTBL:	CTBL,,CTBL			;COMMAND TABLE
	CMND(<ACCEPT>,RECPTY)		;ACCEPT
	CMND(<BELL>,BELL)		;BELL
	CMND(<CONNECT>,CONPTY)		;CONNECT
	CMND(<DEFINE>,DEFPTY)		;DEFINE
	CMND(<DISCARD>,IGNOR)		;DISCARD
	CMND(<EXIT>,EXIT)		;EXIT
	CMND(<GET>,READ)		;GET
	CMND(<HELP>,HELP)		;HELP
	CMND(<KILL>,KILL)		;KILL
	CMND(<LOG>,LOG)			;LOG
	CMND(<NO>,NOCOMM)		;NO
	CMND(<PUSH>,PUSHE)		;PUSH
	CMND(<REDEFINE>,CHANGE)		;REDEFINE
	CMND(<REFUSE>,REFPTY)		;REFUSE
	CMND(<SAVE>,SAVINP)		;SAVE
	CMND(<SILENCE>,SILNCE)		;SILENCE
	CMND(<WHAT>,WHATPT)		;WHAT
CTBL==.-CMDTBL-1			;COMMAND TABLE LENGTH

NOTBL:	NTBL,,NTBL			;NO COMMAND TABLE
	CMND(<ACCEPT>,RECPTY)		;ACCEPT
	CMND(<BELL>,BELL)		;BELL
	CMND(<DISCARD>,IGNOR)		;DISCARD
	CMND(<LOG>,LOG)			;LOG
	CMND(<REFUSE>,REFPTY)		;REFUSE
	CMND(<SAVE>,SAVINP)		;SAVE
	CMND(<SILENCE>,SILNCE)		;SILENCE
NTBL==.-NOTBL-1				;LENGTH OF NO COMMAND TABLE

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

COMFLG:	COMAND


HELP:	NOISE (MESSAGE)		;PARSE NOISE WORD
	CONFIRM			;CONFIRM COMMAND
	CALL ASCTER		;INSURE ASCII TERMINAL
	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
	PUSHJ P,CRLF		;END LINE
	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,
;ROUTINE TO GET A CHARACTER FROM TTY - USED ONLY WHEN CONNECTED

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
		PUSHJ P,CRLF	;END LINE
		JRST COMLVL]	;AND RETURN TO COMMAND LEVEL
	GTSTS			;SEE IF EOF
	TLNN B,(1B8)		;...
	  JRST FILGET		;NO, IGNORE NULLS
	MOVEM I,CURENT		;SAVE SUBJOB CONNECTED TO
	JRST GEOF		;YES, CLOSE FILE AND STOP GET
;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
	  JRST [ MOVE A,RDJFN	;ERROR, TRY TO RELEASE JFN
		 RLJFN		
		   ERJMP .+1	
		 JRST .+1]	
	SETZM RDJFN		;STOP READING FROM FILE
	SETZM SILNCF		;CLEAR SILENCE FLAG
	MOVE A,[.PRIIN,,.PRIOU]	;RESET TTY AS
	MOVEM A,CMDSBK+.CMIOJ	;PRIMARY INPUT AND OUTPUT JFNS
	SETZM IOWATF		;CLEAR OK TO INTERRUPT FLAG
	MOVEI A,.PRIIN		;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,.PRIOU		
	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:	NOISE (FROM PTYCON)	;PARSE NOISE
	CONFIRM			;CONFIRM COMMAND
	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,CMDSBK		;COMMAND STATE BLOCK
	MOVEI B,[FLDDB. .CMCFM]	;FUNCTION BLOCK
	COMND			;PARSE CONFIRMATION
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;ERROR DURING CONFIRM PARSE?
	JRST COMERR		;YES, OUTPUT ERROR MESSAGE
EXIT1:	CALL RSTTY		;RESET TTY PARAMETERS
	SKIPE A, LOGJFN		;GET LOGJFN
	CLOSF			;CLOSE IT
	 JFCL			;IGNORE ERROR
	SKIPE A,SVIJFN		;GET SAVED INPUT JFN
	CLOSF			;CLOSE IT
	  JFCL			;IGNORE ERROR
	HALTF			;STOP
	CALL RSTTY		;RESET TTY IF CONTINUED
	SKIPN LOGJFN		;WAS THERE A LOG FILE
	JRST COMLVL		;NO, CONTINUE
	HRROI B,LOGBUF		;GET NAME OF LAST LOG FILE
	MOVX A,GJ%SHT		;SETUP FLAG BIT
	GTJFN			;GET JFN
	  ERJMP RDGTJF		;ERROR, OUTPUT MESSAGE
	JRST LOG3		;OPEN IT
RSTTY:	MOVEI A,.PRIIN		;GET PRIMARY INPUT
	RFMOD			;GET STATE NOW
	EXCH B,SAVMOD		;SAVE STATE NOW, GET OLD STATE
	SFMOD			;RESET OLD STATE
	STPAR			;...
	RET			

CHKLM:	SKIPLE LMFLAG		;AT LEFT MARGIN?
	 POPJ P,		;NO
	MOVEI A,.PRIOU		
	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
	SETOM 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,.PRIOU		;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
;ROUTINE TO PARSE A COMMA OR A CARRIAGE RETURN

;CALL COMACR
;RETURN  +1  IF COMMA PARSED
;	 +2  IF CONFIRMATION RECEIVED

COMACR:	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK
	MOVEI B,[FLDDB. .CMCMA,<CM%HPP+CM%SDH>,,<comma or confirm with carriage return>]			;FUNCTION DESCRIPTOR BLOCK FOR PARSE
	COMND			;PARSE COMMA OR CONFIRM
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%EOC		;CONFIRMATION RECEIVED?
	JRST [ TRYLOG		;YES, TRY TO LOG COMMAND
	       JRST CPOPJ1]	;SKIP RETURN
	TXNE A,CM%NOP		;COMMA RECEIVED?
	JRST COMERR		;NO, ERROR
	JRST CPOPJ		;COMMA WAS ENTERED

;ROUTINE TO CHANGE THE PTYCON ESCAPE CHARACTER

CHANGE:	NOISE (PTYCON ESCAPE CHARACTER TO BE)  ;PARSE NOISE
	MOVEI B,[FLDBK. .CMFLD,CM%HPP,,<a single control character>,,BMSK]
				;FUNCTION BLOCK
	COMND			;PARSE FIELD
	  ERJMP FJERR		;FATAL JSYS ERROR
	CONFIRM			;CONFIRM COMMAND
	MOVE A,[POINT 7,ATMBUF,6]  ;GET POINTER TO ATOM BUFFER
	LDB B,A			;LOAD FIRST CHARACTER
	SKIPN B			;WAS A CHARACTER ENTERED?
	JRST CHNGIL		;NO, ERROR
	ILDB C,A		;GET NEXT CHARACTER
	SKIPE C			;WAS THERE ONE?
	JRST CHNGIL		;YES, ERROR
	CAIE B,11		;DONT ALLOW IT TO BE TAB
	CAIL B,34		;AND IT MUST BE A CONTROL CHARACTER
	JRST CHNGIL		;ILLEGAL
	CAIE B,"C"-100		;NOT CONTROL-C
	CAIN B,"O"-100		;NOR CONTROL-O
	JRST CHNGIL
	CAIE B,33		;NO ALTMODES
	CAIN B,14		;OR FORM FEEDS
	JRST CHNGIL
	CAIE B,12		;LINE FEED
	CAIN B,15		;OR CARRIAGE RETURNS ARE ILLEGAL
	JRST CHNGIL
	EXCH B,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+CNTRLC+TYPINM]  ;INCLUDE CONTROL-O, CONTROL-C, INPUT
	MOVEM A,TIMASK		;SAVE THE NEW MASK
	JRST PTYCON		;GO SET THIS UP


CHNGIL:	ERRMES (<? Illegal PTYCON escape character>)  
	JRST COMLVL

BMSK:	446665,,670760		;ALLOW ONLY CERTAIN CONTROL
	777777,,777760		;CHARACTERS TO BE ENTERED
	777777,,777760		;FOR
	777777,,777760		;REDEFINE
RECPTY:	SKIPE NOFLAG		;USER TYPE NO?
	  JRST NOREC		;YES, TURN IT INTO REFUSE
NOREF:	NOISE (OUTPUT FROM SUBJOBS)  ;PARSE NOISE
	SETZM ARGCNT		;INITIALIZE ARGUMENT COUNT
RECPT0:	PUSHJ P,GETSJB		;GET A SUBJOB NUMBER IN I
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST RECPT1		;USER SAID ALL
	PUSHJ P,COMACR		;PARSE COMMA OR CONFIRM
	  JRST [PUSHJ P,SAVARG	;COMMA, SAVE SUBJOB INDEX
		JRST RECPT0]	;GET NEXT SUBJOB

	PUSHJ P,SAVARG		;SAVE SUBJOB INDEX
RECPT3:	MOVE I,ARGS(D)		;GET SUBJOB INDEX
	MOVSI B,PTREFF		;SET UP TO CLEAR REFUSE FLAG
	ANDCAM B,PTYSTS(I)	;ALLOW TYPE OUT
	SOJL D,COMLVL		;DECREMENT ARGUMENT COUNT
	JRST RECPT3		;CONTINUE FOR NEXT ARGUMENT

RECPT1:	CONFIRM			;CONFIRM COMMAND
	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

SAVARG:	MOVE D,ARGCNT		;GET NUMBER OF ARGUMENTS
	CAILE D,MAXARG		;IS THERE ROOM FOR ANOTHER ARGUMENT?
	JRST TOOARG		;NO, TOO MANY ARGUMENTS
	MOVEM I,ARGS(D)		;SAVE INDEX VALUE
	AOS ARGCNT		;INCREMENT ARGUMENT COUNT
	RET			;RETURN
REFPTY:	SKIPE NOFLAG		;DID USER TYPE NO?
	  JRST NOREF		;YES, TURN IT INTO AN ACCEPT
NOREC:	NOISE (OUTPUT FROM SUBJOBS)  ;PARSE NOISE WORDS
	SETZM ARGCNT		;INITIALIZE ARGUMENT COUNT
REFPT0:	PUSHJ P,GETSJB		;GET SUBJOB NUMBER
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST REFPT1		;USER SAID "ALL"
	PUSHJ P,COMACR		;PARSE COMMA OR CONFIRM
	  JRST [PUSHJ P,SAVARG	;COMMA, SAVE SUBJOB INDEX
		JRST REFPT0]	;GET NEXT SUBJOB

	PUSHJ P,SAVARG		;SAVE SUBJOB INDEX
REFPT3:	MOVE I,ARGS(D)		;GET SUBJOB INDEX
	MOVSI B,PTREFF		;GET REFUSE FLAG
	IORM B,PTYSTS(I)	;SET REFUSE FLAG
	SOJL D,COMLVL		;DECREMENT ARGUMENT COUNT
	JRST REFPT3		;CONTINUE FOR NEXT ARGUMENT

REFPT1:	CONFIRM			;CONFIRM COMMAND
	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
;ROUTINE TO DEFINE A PTY SUBJOB NAME

DEFPTY:	NOISE (SUBJOB #)	;PARSE NOISE
	SETOM ARGS		;INITIALIZE FIRST ARGUMENT
	SETOM ARGS+1		;INITIALIZE SECOND ARGUMENT
	MOVEI B,[FLDDB. .CMNUM,<CM%HPP+CM%SDH>,^D10,<subjob number>,0]
				;FUNCTION DESCRIPTOR BLOCK
	MOVNI I,PTYLEN		;FIND FIRST FREE SUBJOB NUMBER
	MOVE C,NUMPTY		;LOOP FOR ALL PTY'S
DEFPT1:	ADDI I,PTYLEN		;GO TO NEXT SUBJOB
	SKIPE PTYJFN(I)		;INITIALIZED?
	SOJG C,DEFPT1		;YES, TRY NEXT ONE
	JUMPLE C,[MOVE C,.CMFNP(B)  ;DIDN'T FIND A FREE ONE
		  TXZ C,CM%DPP	;DISALLOW DEFAULT
		  JRST DEFPT2]	;CONTINUE
	PUSH P,B		;SAVE POINTER TO FUNCTION BLOCK
	HRROI A,STRING		;DESTINATION STRING
	MOVEI B,(I)		;GET SUBJOB INDEX
	IDIVI B,PTYLEN		;CONVERT TO SUBJOB NUMBER
	MOVEI C,^D10		;OUTPUT IN DECIMAL
	NOUT			;OUTPUT NUMBER INTO STRING
	  ERJMP .+1		;IGNORE ERROR
	POP P,B			;RESTORE POINTER TO FUNCTION BLOCK
	HRROI A,STRING		;RECONSTRUCT POINTER
	MOVEM A,.CMDEF(B)	;STORE AS DEFAULT
	MOVE C,.CMFNP(B)	;GET FLAG
	TXO C,CM%DPP		;ALLOW DEFAULT
DEFPT2:	MOVEM C,.CMFNP(B)	;REPLACE FLAGS
	MOVEI A,CMDSBK		;RESTORE COMMAND STATE BLOCK ADDRESS
	COMND			;GET NUMBER
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;ERROR IN PARSING NUMBER?
	JRST COMERR		;YES
	SKIPL B			;WITHIN BOUNDS?
	 CAML B,NUMPTY
	  JRST ILLSJB		;NO, OUTPUT ERROR
	MOVE C,CMDSBK+.CMPTR	;GET POINTER TO UNPARSED CHARACTERS
	ILDB D,C		;GET NEXT CHARACTER
	CAIE D," "		;IS IT A SPACE?
	CAIN D,15		;OR A CR
	JRST DEFPT4		;YES, CONTINUE
	JRST ILLSJB		;OUTPUT ILLEGAL SUBJOB ERROR
DEFPT4:	MOVEM B,ARGS		;SAVE NUMBER
	PUSH P,P1		;SAVE FLAG REGISTER
	SETZ P1,		;INITIALIZE IT FOR NO MESSAGE
	NOISE (AS)		;PARSE NOISE
	MOVEI B,[FLDDB. .CMFLD,CM%HPP,,<subjob name>]  ;FUNCTION BLOCK
	COMND			;GET SUBJOB NAME
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%EOC		;DID USER END COMMAND?
	SETZM ARGS+1		;YES, SET ARGUMENT
	CONFIRM			;CONFIRM COMMAND
	SKIPL ARGS+1		;WAS A NAME ENTERED?
	JRST DEFPT3		;NO, CONTINUE ELSEWHERE
	SETZM NUMFL		;CLEAR NUMBER ENTERED FLAG
	PUSHJ P,FNDPTY		;GO SEE IF NAME ALREADY EXISTS?
	  JRST DEFPT7		;NO NAME IN USE
	SKIPE NUMFL		;WAS A NUMBER ENTERED?
	JRST DEFPT7		;YES, DO NOT CLEAR NAME
	SETZM PTYNAM(I)		;YES, CLEAR NAME
	SETO P1,		;MAKE MESSAGE COME OUT
DEFPT7:	MOVE B,STRING		;GET SUBJOB NAME
	MOVEM B,ARGS+1		;PLACE AS ARGUMENT
DEFPT3:	MOVE B,ARGS		;RETRIEVE NUMBER
	IMULI B,PTYLEN		;CALCULATE INDEX
	MOVE I,B		;SET UP INDEX
	SKIPN PTYJFN(I)		;IS PTY OPENED YET?
	  PUSHJ P,PTINIT	;NO, GO INITIALIZE IT
	MOVE B,ARGS		;GET NUMBER
	CAML B,PTYHGH		;IS THIS A NEW HIGH?
	PUSHJ P,NEWHGH		;YES, SET UP NEW HIGH NUMBER
	MOVE B,ARGS+1		;GET FIVE CHARACTER NAME
	PUSHJ P,DELNAM		;DELETE OLD NAME FROM TABLE
	MOVEM B,PTYNAM(I)	;STORE NAME EVEN IF NULL
	MOVEM I,LSTCON		;DEFINE IS SAME AS CONNECT
	SKIPE B			;NON NULL NAME ENTERED?
	PUSHJ P,ADDNAM		;YES, ADD NEW ONE
	SKIPE P1		;WAS NAME ALREADY IN USE?
	 WRNMES (<% Name already in use, reassigned to this subjob
>)				;PRINT WARNING MESSAGE
	POP P,P1		;RESTORE PERMANENT AC
	JRST COMLVL		;AND RETURN

ADDNAM:	MOVE A,PTYNAM(I)	;GET PTY NAME
	AND A,ALLMSK		;STRIP OFF ANY GARBAGE
	CAMN A,[ASCIZ "ALL"]	;WAS NAME ALL?
	RET			;YES, DON'T ADD
	MOVEI A,NAMTBL		;ADDRESS OF NAME TABLE
	HRLZI B,PTYNAM(I)	;TABLE ENTRY TO BE ADDED
	TBADD			;ADD SUBJOB NAME TO NAME TABLE
	  ERJMP .+1		;IGNORE ERROR
	RET			;RETURN
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

TOOARG:	TRYLOG			;TRY TO LOG COMMAND
	ERRMES (<? Too many arguments>)  ;TOO MANY ARGUMENTS
	JRST COMLVL		
;ROUTINE TO CONNECT TO A PTY LINE

CONPTY:	NOISE (TO SUBJOB)	;PARSE NOISE
	SKIPGE I,LSTCON		;GET LAST CONNECTED SUBJOB IF ANY
	JRST [SETOM NODEF	;IF NONE, ALLOW NO DEFAULTS
	      SETZM CONDEF	;CLEAR DEFAULT STRING FOR CONNECT
	      JRST CONPT3]	;CONTINUE
	SKIPE A,PTYNAM(I)	;IS THERE A NAME DEFINED FOR IT?
	JRST [MOVEM A,CONDEF	;STORE ADDRESS AS DEFAULT
	      JRST CONPT3]	;CONTINUE
	MOVEI B,(I)		;GET SUBJOB NUMBER FROM INDEX
	IDIVI B,PTYLEN		;GET SUBJOB NUMBER
	HRROI A,CONDEF		;STORE IN DEFAULT ADDRESS
	MOVEI C,^D10		;DECIMAL NUMBER
	NOUT			;PLACE NUMBER AS DEFAULT
	  ERJMP .+1		;ERROR, CONTINUE ANYWAY
CONPT3:	SETZM NUMFL		;CLEAR NUMBER WAS ENTERED FLAG
	PUSHJ P,GETSJB		;GET SUBJOB INDEX IN I
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST .+1		;USER DEFAULTED
	MOVEM B,ARGS		;SAVE NUMBER IF ENTERED
	CONFIRM			;CONFIRM COMMAND
	SKIPE NUMFL		;WAS A NUMBER ENTERED?
	JRST [ MOVE B,ARGS	;GET SUBJOB INDEX
	       IDIVI B,PTYLEN	;CONVERT TO SUBJOB NUMBER
	       CAML B,PTYHGH	;WAS IT A NEW HIGH?
	       PUSHJ P,NEWHGH	;YES, SET IT
	       JRST .+1]	;CONTINUE
	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

ILLSJB: MOVE A,[POINT 7,ATMBUF,6]  ;POINT TO FIRST CHARACTER OF ARG
	LDB B,A			;GET THE FIRST CHARACTER
	SKIPN B			;IS IT ZERO (ARG NOT SPECIFIED)?
	JRST TOOFEW		;YES, OUTPUT ERROR MESSAGE
	TRYLOG			;TRY TO LOG COMMAND
	ERRMES (<? Illegal subjob designator>)  ;ILLEGAL SUBJOB DESIG.
	JRST COMLVL
;ROUTINE TO SET UP I WITH PTY NUMBER

FNDPTY:	SETZM STRING		;CLEAR STRING
	HRROI A,ATMBUF		;POINT TO ATOM BUFFER
	HRROI B,STRING		;PLACE IN STRING
	MOVEI C,5		;READ ONLY FIVE CHARACTERS
	SETZ D,			;STOP AT ZERO
	SIN			;GET STRING
	  ERJMP .+1		;IGNORE ERROR
	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
	MOVE A,[POINT 7,ATMBUF,6]  ;DID NOT FIND ONE, SEE IF THIS IS A #
	LDB C,A			;FIRST, CHECK FOR A DASH (-)
	CAIN C,55		;WAS ONE INPUT?
	JRST CPOPJ		;YES, RETURN BAD
	HRROI A,ATMBUF		;NO, TRY TO GET THE NUMBER
	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
	SKIPL B			;LESS THAN LOWER BOUND OF ZERO?
	CAML B,NUMPTY		;WITHIN BOUNDS?
	  POPJ P,		;NO, BAD
	IMULI B,PTYLEN		;CALCULATE INDEX
	MOVE I,B
	SETOM NUMFL		;A NUMBER WAS ENTERED
	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 HANDLE END OF FILE WHEN DOING A GET COMMAND

GEOF:	HRRZ A,RDJFN		;GET READ JFN
	CLOSF			;CLOSE FILE AND RELEASE JFN
	  ERJMP .+1		;IGNORE ERROR
	SETZM RDJFN		;CLEAR READING FLAG
	SETZM SILNCF		;AND CLEAR SILENCE FLAG
	MOVE A,[.PRIIN,,.PRIOU]	;RESET TTY
	MOVEM A,CMDSBK+.CMIOJ	;AS INPUT AND OUTPUT JFN
	SKIPGE CURENT		;AT COMMAND LEVEL?
	JRST COMLVL		;YES, GET NEXT COMMAND
	JRST TTYGET		;NO, GET CHARACTERS FROM SUBJOB
;ROUTINE TO SET UP A READ FILE

READ:	NOISE (COMMANDS FROM FILE)  ;PARSE NOISE
	SKIPE RDJFN		;READING ALREADY?
	JRST [	TRYLOG		;TRY TO LOG COMMAND LINE
		ERRMES (<? Doing a "GET" within a "GET" is illegal>)  
		JRST COMLVL]
	MOVX A,GJ%OLD		;GTJFN FLAG
	MOVEM A,GTJBLK		;PLACE IN GTJFN BLOCK
	MOVE A,[POINT 7,[ASCIZ "PTYCON"]]  ; DEFAULT FILENAME
	MOVEM A,GTJBLK+.GJNAM	;PLACE IN GTJFN BLOCK
	MOVE A,[POINT 7,[ASCIZ "ATO"]]  ;DEFAULT EXTENSION
	MOVEM A,GTJBLK+.GJEXT	;STORE IN GTJFN BLOCK
	PUSHJ P,RDFJFN		;PARSE FILESPEC
	HRRZM A,RDJFN		;SAVE JFN
READ1:	MOVE B,[7B5+1B19]	;NOW OPEN IT
	OPENF
	  JRST RDOPNF		;FAILED
	MOVEI A,.NULIO		;DON'T READ FROM TTY ANYMORE
	HRLM A,CMDSBK+.CMIOJ	;SETUP INPUT JFN FOR COMND
	JRST COMLVL		;RETURN

RDOPNF:	PUSH P,A
	MOVE A,RDJFN		;RELEASE JFN
	RLJFN
	  JFCL
	SETZM RDJFN
	POP P,A
RDGTJF:	PUSH P,A		;MOVE ERROR CODE
	PUSHJ P,CHKLM		;AT LEFT MARGIN?
	  PUSHJ P,CRLF		;NO, TYPE CRLF
	POP P,B			;GET ERROR CODE
	PUSHJ P,TYPERR		;AND TYPE ERROR MESSAGE
	JRST COMLVL

RDFJFN:	SKIPE A,JFNIP		;ALREADY HAVE A JFN?
	PUSHJ P,RELJFN		;YES, RELEASE IT
	MOVEI A,CMDSBK		;GET COMMAND STATE BLOCK ADDRESS
	MOVEI B,[FLDDB. .CMFIL,<CM%HPP+CM%SDH>,,<filespec>]  ;FDB
	COMND			;PARSE FILESPEC
	  ERJMP FJERR		;FATAL JSYS ERROR
	TXNE A,CM%NOP		;PARSE SUCCESSFUL?
	JRST COMERR		;NO, OUTPUT ERROR
	MOVEM B,JFNIP		;SAVE JFN
	CONFIRM			;CONFIRM COMMAND
	MOVE A,JFNIP		;PLACE JFN IN A
	SETZM JFNIP		;CLEAR FLAG
	RET			;RETURN

RELJFN:	RLJFN			;RELEASE THE JFN
	  ERJMP .+1		;ERROR, CONTINUE ANYWAY
	SETZM JFNIP		;CLEAR FLAG
	RET			;RETURN

; ROUTINE TO GET MORE FROM ATO FILE WHEN EOF REACHED DURING PARSE

GETMOR:	HRROI A,CMDBUF		;READ IN COMMAND ENTERED SO FAR
	MOVE B,.NULIO		;DON'T WRITE IT ANYWHERE
	MOVEI C,CBUFSZ*5-1	;NUMBER OF CHARACTERS TO READ
	SETZM D			;STOP AT ZERO
	SIN			
	  ERJMP .+1		;SHOULDN'T HAPPEN!
	SUBI C,CBUFSZ*5-1	;CALCULATE NUMBER OF CHARACTERS
	SETCA 3,0		;FORM TWOS COMPLEMENT
	MOVEM C,CMDCNT		;STORE NEW COMMAND COUNT
	SETZM C			;CLEAR HYPHEN FLAG
	MOVE D,CMDSBK+.CMPTR	;POINT TO CORRECT POSITION IN BUFFER
	SKIPE CMDCNT		;IS THERE ANYTHING IN BUFFER ALREADY?
	IBP D			;ADJUST POINTER PAST LAST CHARACTER
	PUSHJ P,RCONV		;FILL BUFFER
	MOVE A,CMDCNT		;UPDATE UNPARSED CHARACTERS
	MOVEM A,CMDSBK+.CMINC	
	MOVE A,CMDSBK+.CMBFP	;RESET POINTER TO START OF BUFFER
	MOVEM A,CMDSBK+.CMPTR	
	MOVEI A,CBUFSZ*5-1	;RESET BUFFER SIZE
	MOVEM A,CMDSBK+.CMCNT	
	JRST COM0		;PARSE REST OF COMMAND

; ROUTINE TO READ IN AND CONVERT ATO FILE FOR GET COMMAND
; THE ^a (WHERE ^ IS UPARROW AND a IS A CHARACTER) IS CONVERTED
; INTO THE TRUE CONTROL CHARACTER.  ^$ IS CONVERTED TO AN ESCAPE.

GCNVT:	SETZM C			;CLEAR HYPHEN FLAG
	SETZM CMDCNT		;NO CHARACTERS YET
	MOVE D,CMDSBK+.CMBFP	;POINT TO COMMAND BUFFER
RCONV:	MOVE A,RDJFN		;GET CHARACTER FROM ORIGINAL ATO
	BIN			
	  ERJMP RCOND		;CHECK TO SEE IF IT IS DONE
	SKIPG CMDCNT		;ANYTHING ENTERED YET?
	JRST [	CAIE B," "	;NO, IS THIS A SPACE 
		CAIN B,.CHTAB	;OR A TAB?
		JRST RCONV	;YES, DISREGARD
		JRST .+1]	;NO, PROCESS
	CAIL B,"a"		;LOWER CASE?
	CAILE B,"z"		
	  SKIPA			;NO
	SUBI B,40		;YES, CONVERT TO UPPER CASE
	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,]	
	MOVE A,D		;WRITE IT TO THE COMMAND BUFFER
	BOUT			
	  ERJMP RCOND		;PROCESS ERROR
	MOVE D,A		;SAVE UPDATED POINTER
	AOS CMDCNT		;ONE MORE UNPARSED CHARACTER
	CAMN B,TRPCHR		;WAS IT THE ESCAPE CHARACTER?
	JRST [	SETZM A		;
		IDPB A,D	;END COMMAND LINE
		TRYLOG		;TRY TO LOG IT
		PUSHJ P,CRLF	;END LINE
		JRST COMLVL]	;AND RETURN TO COMMAND LEVEL
	CAIN B,.CHESC		;WAS CHARACTER AN ESCAPE?
	RET			;YES, PARSE COMMAND SO FAR
	CAIN B,.CHLFD		;WAS CHARACTER A LINE FEED?
	JRST [	MOVE A,CMDCNT	;GET NUMBER OF CHARACTERS ENTERED
		CAIE A,1	;WAS THERE ONLY THE LF?
		RET		;NO, RETURN TO PARSE LINE
		SETZM CMDBUF	;ERASE GARBAGE
		JRST GCNVT]	;YES, NULL LINE SO DON'T PARSE
	CAIN B,.CHCRT		;WAS CHARACTER A CR?
	JRST RCON1		;YES, HANDLE SPECIAL CASE
	SETZM C			;CLEAR HYPHEN FLAG
	CAIN B,"-"		;WAS CHARACTER A HYPHEN?
	SETOM C			;YES, SET HYPHEN FLAG
	JRST RCONV		;NO, PROCESS NEXT CHARACTER
RCON1:	MOVE A,RDJFN		;READ IN NEXT CHARACTER
	BIN			
	  ERJMP RCOND		;PROCESS ERROR
	CAIN B,.CHLFD		;CHARACTER A LINE FEED?
	JRST [	MOVE A,D	;YES, PLACE IN COMMAND BUFFER
		BOUT		
		MOVE D,A	;SAVE POINTER
		AOS CMDCNT	;ONE MORE UNPARSED CHARACTER
		JRST RCON2]	;CONTINUE
	BKJFN			;PUT CHARACTER BACK
	  ERJMP .+1		;IGNORE ERROR
RCON2:	SKIPL C			;WAS A HYPHEN ENTERED BEFORE CR?
	JRST [	MOVE A,CMDCNT	;GET NUMBER OF CHARACTERS ENTERED
		CAIE A,2	;WERE THERE ONLY THE CR AND LF?
		RET		;NO, RETURN TO PARSE LINE
		SETZM CMDBUF	;ERASE GARBAGE
		JRST GCNVT]	;YES, NULL LINE SO DON'T PARSE
	SETZM C			;YES, CLEAR HYPHEN FLAG
	JRST RCONV		;CONTINUE TO READ IN COMMAND

RCOND:	MOVE A,RDJFN		;GET ORIGINAL JFN
	GTSTS			;GET STATUS
	TXNE B,GS%EOF		;END OF FILE?
	JRST GEOF		;YES
	ERRMES(<? Error while converting ATO file - conversion and GET aborted>)  				;TELL USER
	JRST GEOF		;END GET

;ROUTINE TO PRINT COMMAND LINE DURING GET COMMAND

PRTCMD:	SKIPE SILNCF		;WAS OUTPUT SILENCED?
	RET			;YES, RETURN
	HRROI A,CMDBUF		;NO, PRINT COMMAND BUFFER
	PSOUT			;TO TERMINAL
	  ERJMP .+1		;IGNORE ERROR
	RET			;RETURN
SILNCE:	NOISE (ALL OUTPUT TO TERMINAL)  ;PARSE NOISE WORDS
	CONFIRM			;CONFIRM COMMAND
	SETZM SILNCF		;INIT SILENCE FLAG
	SKIPN NOFLAG		;WAS THIS A "NO SILENCE" REQUEST?
	SETOM SILNCF		;NO, THEN SILENCE THE OUTPUT FROM GET
	SKIPN RDJFN		;PROCESSING A GET COMMAND?
	JRST [WRNMES (<% This is only effective from within a command file
>)				
	      SETZM SILNCF	;DISALLOW SILNCF
	      JRST COMLVL]	;NO, ISSUE WARNING
	MOVEI A,.PRIOU		;ASSUME "NO SILENCE"
	SKIPE SILNCF		;WAS THIS A "NO SILENCE"
	MOVEI A,.NULIO		;NO, DONT PRINT PROMPT
	HRRM A,CMDSBK+.CMIOJ	;PLACE IN COMMAND STATE BLOCK
	JRST COMLVL
; ROUTINE TO SET UP A LOG FILE

LOG:	NOISE (OUTPUT TO FILE)	;PARSE NOISE WORDS
	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST NOLOG		;YES, GO TURN OFF LOGGING
	SETZM GTJBLK		;CLEAR GTJFN FLAGS
	MOVE A,[POINT 7,[ASCIZ "PTYCON"]]  ;DEFAULT FILENAME
	MOVEM A,GTJBLK+.GJNAM	;PLACE IN GTJFN BLOCK
	MOVE A,[POINT 7,[ASCIZ "LOG"]]  ;DEFAULT EXTENSION
	MOVEM A,GTJBLK+.GJEXT	;PLACE IN GTJFN BLOCK
	PUSHJ P,RDFJFN		;GET FILE JFN
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
	MOVE B,LOGJFN		;GET JFN
	HRROI A,LOGBUF		;POINT TO LOG NAME BUFFER
	MOVX C,JS%SPC		;WANT ENTIRE FILESPEC
	SETZ D, 		;CLEAR UNUSED REGISTER
	JFNS			;CONVERT JFN TO STRING
	  ERJMP COMLVL		;IGNORE ERROR
	JRST COMLVL		;AND RETURN

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

NOLOG:	CONFIRM			;CONFIRM COMMAND
	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:	NOISE (INPUT IN FILE)	;PARSE NOISE WORDS
	SKIPE NOFLAG		;USER SAY "NO"?
	  JRST NOSAVI		;YES, GO TURN OFF LOGGING
	SETZM GTJBLK		;CLEAR GTJFN FLAGS
	MOVE A,[POINT 7,[ASCIZ "SAVED-INPUT"]]  ;DEFAULT FILENAME
	MOVEM A,GTJBLK+.GJNAM	;SAVE IN GTJFN BLOCK
	MOVE A,[POINT 7,[ASCIZ "TXT"]]  ;DEFAULT EXTENSION
	MOVEM A,GTJBLK+.GJEXT	;SAVE IN GTJFN BLOCK
	PUSHJ P,RDFJFN		;GET FILE JFN
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

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

NOSAVI:	CONFIRM			;CONFIRM COMMAND
	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:	HRROI A,ERRSTR		;PUT MESSAGE INTO A STRING
	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
	PUSHJ P,CRLF		;END LINE
	POPJ P,

FJERR:	MOVX A,.FHSLF		;SET PROCESS TO SELF
	GETER			;GET LAST ERROR
	  ERJMP .+1		;ERROR, CONTINUE ANYWAY
	HRRZ B,B		;GET RID OF PROCESS HANDLE
	CAIE B,IOX4		;END OF FILE REACHED?
	CAIN B,COMNX9		;END OF INPUT FILE REACHED?
	JRST GETMOR		;YES, HANDLE CONDITION
	PUSH P,B		;SAVE ERROR CODE
	TRYLOG			;TRY TO LOG COMMAND LINE
	POP P,B			;GET ERROR CODE BACK
	CAIE B,COMNX2		;FIELD TOO LONG?
	CAIN B,COMNX3		;COMMAND TOO LONG?
	JRST TOOLNG		;OUTPUT APPROPRIATE ERROR MESSAGE
	WRNMES (<? Fatal JSYS error - >)  ;PRINT FIRST PART OF MSG
	PUSHJ P,TYPERR		;PRINT REST OF ERROR MESSAGE
	JRST EXIT1		;EXIT FROM PTYCON

TOOLNG:	TRYLOG			;TRY TO LOG COMMAND LINE
	ERRMES (<? Line too long>)  ;OUTPUT ERROR MESSAGE
	JRST COMLVL		;GET ANOTHER COMMAND
;ROUTINE TO KILL A JOB

KILL:	NOISE (SUBJOB)		;PARSE NOISE
	SETOM NODEF		;DISALLOW DEFAULT OF "ALL"
	SETZM ARGCNT		;INITIALIZE ARGUMENT COUNT
KILL1:	PUSHJ P,GETSJB
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST KILL2		;USER TYPED ALL
	PUSHJ P,COMACR		;PARSE COMMA OR CONFIRM
	  JRST [PUSHJ P,SAVARG	;COMMA - SAVE SUBJOB INDEX
		JRST KILL1]	;THEN GO BACK FOR MORE
	PUSHJ P,SAVARG		;SAVE SUBJOB INDEX
KILL3:	MOVE I,ARGS(D)		;GET SUBJOB INDEX
	PUSHJ P,DELNAM		;DELETE SUBJOB NAME FROM TABLE
	PUSHJ P,KILJOB		;KILL THE JOB
	SOJL D,COMLVL		;DECREMENT ARGUMENT COUNT
	JRST KILL3		;CONTINUE FOR NEXT ARGUMENT

KILL2:	CONFIRM			;CONFIRM COMMAND
	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,DELNAM		;DELETE SUBJOB NAME FROM TABLE
	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
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

DELNAM:	PUSH P,B		;SAVE REGISTER
	MOVE A,PTYNAM(I)	;GET PTY NAME
	AND A,ALLMSK		;STRIP OFF ANY GARBAGE
	CAMN A,[ASCIZ "ALL"]	;WAS NAME ALL?
	JRST DELRET		;YES, DON'T DELETE
	MOVEI A,NAMTBL		;ADDRESS OF SUBJOB NAME TABLE
	HRROI B,PTYNAM(I)	;POINTER TO NAME
	TBLUK			;FIND NAME IN TABLE
	  ERJMP .+1		;IGNORE ERROR
	TXNN B,TL%EXM		;AN EXACT MATCH FOUND?
	JRST DELRET		;NO, RETURN
	MOVE B,A		;MOVE ADDRESS OF NAME
	MOVEI A,NAMTBL		;ADDRESS OF NAME TABLE
	TBDEL			;DELETE ENTRY
	  ERJMP .+1		;IGNORE ERROR
DELRET:	POP P,B			;RESTORE REGISTER
	RET			;RETURN
;ROUTINE TO READ IN A SUBJOB NUMBER OR NAME AND SET UP I

;CALL GETSJB
;RETURN +1	NO SUBJOB MATCH
;	+2	USER SAID "ALL"
;	+3	SUBJOB # IN I

GETSJB:	MOVEI B,[FLDDB. .CMFLD,CM%HPP,,<subjob number or subjob name>,ALL]
				;FUNCTION BLOCK
	MOVE C,(B)		;GET FIRST WORD OF FUNCTION BLOCK
	TXO C,CM%DPP		;ASSUME DEFAULT OF "ALL" ALLOWED
	HRROI A,[ASCIZ "ALL"]	;SETUP POINTER
	MOVEM A,.CMDEF(B)	;STORE IN FUNCTION BLOCK
	SKIPE NODEF		;IS DEFAULT OF "ALL" ALLOWED?
	TXZ C,CM%DPP		;NO, CLEAR DEFAULT FLAG
	MOVEM C,(B)		;REPLACE IN FUNCTION BLOCK
	SKIPE CONDEF		;IS A SPECIAL CONNECT DEFAULT REQUIRED?
	JRST [HRROI A,CONDEF	;YES, SETUP POINTER
	      MOVEM A,.CMDEF(B)	;STORE IN FUNCTION BLOCK
	      JRST .+1]		;CONTINUE
	MOVEI A,CMDSBK		;RESTORE ADDRESS OF COMMAND STATE BLOCK
	COMND			;PARSE SUBJOB FIELD
	  ERJMP FJERR		;FATAL JSYS ERROR
	PUSHJ P,FNDPTY		;SEE IF THIS WAS A LEGAL JOB #
	  JRST GTSJB2		;NO
	JRST CPOPJ2		;TAKE DOUBLE SKIP RETURN

GTSJB2:	MOVE A,ATMBUF		;NOW CHECK FOR "ALL"
	AND A,ALLMSK		;MASK OFF GARBAGE
	CAME A,[ASCIZ/ALL/]
	POPJ P,			;COMMAND ERROR
	JRST CPOPJ1		;GIVE SKIP RETURN FOR "ALL"

IGNOR:	NOISE (OUTPUT FROM SUBJOB)  ;PARSE NOISE WORDS
	SETOM NODEF		;DISALLOW DEFAULT OF "ALL"
	SETZM ARGCNT		;INITIALIZE ARGUMENT COUNT
IGNOR0:	PUSHJ P,GETSJB		;GET THE ARGUMENT
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST IGNOR1		;"ALL"
	PUSHJ P,COMACR		;PARSE COMMA OR CONFIRM
	  JRST [PUSHJ P,SAVARG	;COMMA, SAVE SUBJOB INDEX
		JRST IGNOR0]	;GET NEXT SUBJOB
	PUSHJ P,SAVARG		;SAVE SUBJOB INDEX
IGNOR3:	MOVE I,ARGS(D)		;GET SUBJOB INDEX
	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
	SOJL D,COMLVL		;DECREMENT ARGUMENT COUNT
	JRST IGNOR3		;CONTINUE FOR NEXT ARGUMENT

IGNOR1:	CONFIRM			;CONFIRM COMMAND
	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
;WHAT ROUTINE

WHATPT:	NOISE (IS STATE OF SUBJOB)  ;PARSE NOISE WORDS
	PUSHJ P,GETSJB		;GET A SUBJOB NUMBER IN I
	  JRST ILLSJB		;NO MATCH, COMMAND ERROR
	  JRST WHAT5		;USER TYPED "ALL"
	CONFIRM			;CONFIRM COMMAND
	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
		SETOM TOFLAG	;INDICATE TYPEOUT OCCURRED
		JRST WATDON]	;AND EXIT
	PUSHJ P,TYPSYS		;GO TYPE OUT SYSTAT FOR THIS JOB
	JRST WATDON		;AND EXIT

WHAT5:	CONFIRM			;CONFIRM COMMAND
	SETOM LMFLAG		;AT LEFT MARGIN
	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 [PUSHJ P,CRLF	;END LINE
		JRST COMLVL]	;WE ARE THROUGH
	HRROI A,[ASCIZ/None active
/]				;NO ACTIVE SUBJOBS
	PUSHJ P,TTSOUT		;NO, TELL USER SOMETHING
	JRST COMLVL		;  AND RETURN TO COMLVL
;ROUTINE TO TYPE A SYSTAT OF JOB

TYPSYS:	CALL ASCTER		;SETUP AS ASCII TERMINAL
	SKIPN PTYJFN(I)		;IS THERE A JOB HERE
	  POPJ P,		;NO, TYPE NOTHING
	SETOM TOFLAG		;SAY SOMETHING WAS TYPED
	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,.PRIOU		;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,.PRIOU		
	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 [SKIPE RDJFN	;READING FROM A FILE?
		JRST PTYTP5	;YES, DISREGARD TTY INPUT
		SETZM IGNORF	;NO, THEN EXIT NOW
		SETOM NOINT	;DON'T ALLOW ANY MORE PTY INTERRUPTS
		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,.PRIOU		
	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,.PRIOU	
	      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>)  
	SKIPE NORFS		;ERROR DUE TO NO RESIDENT FREE SPACE
	ERRMES (<? Insufficient system resources - no resident free space>)
				;REPORT CONDITION
	JRST COMLVL

BELL:	NOISE (WHEN OUTPUT WAITING)  ;PARSE NOISE WORDS
	CONFIRM			;CONFIRM COMMAND
	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:	SETZM NORFS		;CLEAR FLAG
	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
	MOVSI A,(GJ%SHT+GJ%ACC)	;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,.PRIOU		;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:	CAIN A,MONX05		;NO RESIDENT FREE SPACE?
	SETOM NORFS		;SET FLAG
	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,A	;NO - SOME OTHER ERROR
		      POP P,A
		      PUSHJ P,CHKLM	;AT LEFT MARGIN?
			PUSHJ P,CRLF	;YES, OUTPUT CRLF
		      CALL TYPERR	;TELL USER ABOUT ERROR
		      JRST .+1]	;REJOIN THE PATH
		MOVE A,PTYTTD(I);TTY DESCRIPTOR
		SOBE		;IS THERE TTY OUTPUT PENDING?
		  PUSHJ P,PTYFIL;YES, READ IN ONE LINE
		PUSH P,[PTYOU6]	;CONTINUATION ADDRESS AFTER INTERRUPT
		SETOM IOWATF	;WAITING FOR INTERRUPT
		MOVEI A,^D1000	;WAIT FOR ONE SECOND
		DISMS
		SETZM IOWATF	;NO LONGER WAITING
		POP P,A		;REMOVE UNWANTED ADDRESS
	PTYOU6:	SETZM WAKEF	;WAKE UP HAS OCCURRED
		POP P,B		;RESTORE REGS
		POP P,A
		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

;TTY INPUT INTERRUPT COMES HERE TO WAKE UP MAIN LEVEL

	SKIPL NOINT		;IS PTY INTERRUPT UNCONDITIONALLY DISALLOWED?
	JRST [ MOVEI A,.FHSLF
	       MOVX B,1B<PTYOCN>
	       IIC		;INITIATE PTY OUTPUT CHECK
	       JRST PTYIN0]	
PTYIN0:	PUSHJ P,ACLOAD		;RESTORE THE ACS
	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			;DISMISS THE INTERRUPT

; CHECK FOR PTY OUTPUT AVAILABLE

CHKPTO:	SETOB I,LSTHDR		;CLEAR LAST HEADER
	SETZM TOFLAG		;INITIALIZE TYPEOUT FLAG
	PUSHJ P,PTOCHK		;PRINT OUT ANY PTY OUTPUT
	SKIPE TOFLAG		;WAS ANYTHING TYPED?
	JRST [	PUSHJ P,CRLF	;YES, PLACE ON LEFT MARGIN
		MOVE A,PMTPR	;PRINT PROMPT
		PUSHJ P,TTSOUT	
		SETZM TOFLAG	;SAY TYPE OVER
		JRST .+1]	
	MOVE A,CMDSBK+.CMBFP	;CHECK FIRST CHARACTER IN COMMAND
	ILDB B,A		;
	SKIPE B			;WAS THERE A CHARACTER?
	JRST [	SETOM NOINT	;YES, DISALLOW UNCONDITIONALLY
		JRST COMSTR]
	SETZM NOINT		;NO, SET TO DISALLOW CONDITIONALLY
	JRST COMSTR		;CONTINUE AT COMMAND LEVEL
	
; TEN SECOND INTERVAL CHECK FOR PTY OUTPUT

PTYOPC:	PUSHJ P,ACSAVE		;SAVE ACS
	SKIPE NOINT		;IS INTERRUPT UNCONDITIONALLY DISALLOWED?
	JRST PTYOP1		;YES
	MOVE A,CMDSBK+.CMBFP	;NO, CHECK FIRST CHARACTER IN COMMAND
	ILDB B,A		;
	SKIPE B			;WAS THERE A CHARACTER?
	JRST PTYOP1		;DISALLOW PTY INTERRUPTS UNCONDITIONALLY
	MOVEI A,CHKPTO		;STORE CONTINUATION ADDRESS
	MOVEM A,RETSAV	
PTYOP1:	SETOM NOINT		;DISALLOW FURTHER INTERRUPTS UNCONDITIONALLY
	MOVE A,[XWD .FHSLF,.TIMEL]  ;RESET ELAPSED TIME OF CHECK
	MOVEI B,^D5000		;FIVE SECONDS TILL NEXT CHECK
	MOVEI C,PTYOCN		;INTERRUPT ON CHECK CHANNEL
	TIMER			
	  ERJMP .+1		;IGNORE ERROR
	PUSHJ P,ACLOAD		;RESTORE ACS
	DEBRK			;DISMISS 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:	NOISE (EXEC LEVEL)	;PARSE NOISE WORDS
	CONFIRM			;CONFIRM COMMAND
	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/DEFAULT-EXEC:/] ;PUSH TO THE DEFAULT EXEC
	GTJFN
	 IFNSK.
	   MOVSI A, (1B2!1B17)
	   HRROI B, [ASCIZ/SYSTEM:EXEC.EXE/] ;NO SUCH THING? TRY SYSTEM: 
	   GTJFN
           JRST NOEXEC		;FAILED AGAIN -  NO EXEC FOUND
         ENDIF.              
	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>+CNTRLC]  ;AND CONTROL-C CHANNEL
	DIC
	MOVNI A,5
	MOVE B,SAVTIW		;PUT TERMINAL INTERRUPT WORDS BACK
	STIW
	MOVEI A,.PRIIN		
	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

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 CMDCNT,1			;COUNT OF CHARACTERS IN COMMAND SO FAR
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 PGMSK,4			;PROGRAM BREAK MASK (USED FOR ONE LINER)
ALC LSTCHR,1			;LAST CHARACTER TYPED
ALC NOFLAG,1			;IF SET, "NO" WAS TYPED
ALC NORFS,1			;FLAG INDICATING NO RESIDENT FREE SPACE
ALC NODEF,1			;IF SET, DEFAULT OF "ALL" DISALLOWED
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 CONDEF,1			;DEFAULT SUBJOB STRING FOR CONNECT
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 JFNIP,1			;JFN ALREADY ACQUIRED IN PARSE
ALC CURENT,1			;INDEX OF CURRENT JOB
ALC NUMFL,1			;SET TO -1 WHEN A NUMBER IS ENTERED
ALC NOINT,1			;SET TO -1 WHEN PTY INTERRUPTS ARE ALLOWED
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
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==50		;STRING LENGTH
	MAXSTC==STRNGL*5-1
ALC STRING,STRNGL		;TEMP STRING
ALC LNEPTR,1			;BYTE POINTER TO START OF TEXT
ALC LNESTR,STRNGL		;STRING FOR SINGLE LINE COMMAND

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

	MAXARG==^D50		;MAXIMUM NUMBER OF ARGUMENTS
ALC ARGS,MAXARG			;ARGUMENT BLOCK
ALC ARGCNT,1			;NUMBRER OF ARGUMENTS

	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
	1,,COMCC		;2
CTLCHN==2			;CONTROL-C CHANNEL
	1,,TYPIN		;3
TINCHN==3
	1,,PTYOPC		;4
PTYOCN==4			;PTY OUTPUT CHECK CHANNEL
	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<CTLCHN>+1B<TINCHN>+1B<TRPCHN>+1B<PTYOCN>+1B9+1B11+1B15+1B16+1B17+1B18+1B20+7777			;INTERRUPT CHANNELS

LOGBUF:	BLOCK 200		;TEXT BUFFER FOR LOG COMMAND
GETBUF:	BLOCK 200		;BUFFER FOR GET COMMAND FILENAME


CBUFSZ==400			;COMMAND BUFFER SIZE
ABUFSZ==50			;ATOM BUFFER SIZE

CMDSBK:	CM%RAI+CM%XIF+COM0	;COMMAND STATE BLOCK
	.PRIIN,,.PRIOU		
	-1,,[ASCIZ "PTYCON> "]	
	-1,,CMDBUF		
	-1,,CMDBUF		
	5*CBUFSZ-1		
	0			
	-1,,ATMBUF		
	5*ABUFSZ-1		
	GTJBLK			

SNBK:	FLDBK. (.CMKEY,CM%HPP,NAMTBL,<a subjob name,>,,[BRMSK. (KEYB0.,KEYB1.,KEYB2.,KEYB3.,,<->)],NBLK)
				;SUBJOB NAME BLOCK FOR COMMAND PARSE

NBLK:	FLDDB. (.CMNUX,<CM%HPP+CM%SDH>,^D10,<a subjob number>)
				;NUMBER BLOCK FOR COMMAND PARSE

CBLK:	FLDBK. (.CMKEY,CM%HPP,CMDTBL,<a command,>,,[BRMSK. (KEYB0.,KEYB1.,KEYB2.,KEYB3.,,<->)],SNBK)
				;COMMAND BLOCK FOR COMMAND PARSE


SBLK:	FLDDB. (.CMUQS,,PGMSK)  ;FUNCTION BLOCK FOR STRING INPUT

NAMTBL:	1,,MAXPTY+1
	[ASCIZ "ALL"],,0	;ALLOW ALL AS A SUBJOB NAME
	BLOCK MAXPTY		;TABLE OF SUBJOB NAMES

CMDBUF:	BLOCK CBUFSZ		;COMMAND BUFFER
ATMBUF:	BLOCK ABUFSZ		;ATOM BUFFER
GTJBLK:	BLOCK 17		;GTJFN BLOCK

PMTPR:	-1,,[ASCIZ "PTYCON> "]	;POINTER TO PROMPT


	END <3,,ENTVEC>