Google
 

Trailing-Edge - PDP-10 Archives - BB-F494Z-DD_1986 - 10,7/kill.mac
There are 6 other files named kill.mac in the archive. Click here to see a list.
	TITLE	KILL	PROGRAM TO STOP AND KILL USER JOBS
	SUBTTL	DAVID I. BELL/DIB/TARL



;THIS PROGRAM IS INTENDED TO LET USERS KILL THEIR OWN JOBS
;WITHOUT HAVING TO ASK AN OPERATOR TO DO IT.  KILL MAKES THE
;NECESSARY PRIVILEGE CHECKS, AND IF IT IS SAFE TO DO SO, IT
;WILL PROCEED TO STOP, DETACH, ATTACH, OR KILL OTHER JOBS FOR
;THE USER.  IN ADDITION, IT HAS FUNCTIONS WHICH ALLOW THE USER
;TO SEND MESSAGES TO OTHER JOBS OF HIS.



	TWOSEG	400000			;THIS IS PURE CODE
	SEARCH	JOBDAT,UUOSYM,MACTEN	;GET DEFINITIONS
	.DIREC	.XTABM			;NICE MACROS
	SALL				;EVEN NICER MACROS


	VMAJOR==13	;MAJOR VERSION
	VMINOR==1	;MINOR VERSION
	VEDIT==131	;EDIT NUMBER
	VWHO==0		;WHO LAST EDITED
	VERSION==BYTE(3)VWHO(9)VMAJOR(6)VMINOR(18)VEDIT
	TMPVER==1000	;VERSION OF TMPCOR FORMAT WE HANDLE



;THE ACCUMULATORS:


	F=0		;FLAGS
	T1=1		;TEMPORARY ACS
	T2=2
	T3=3
	T4=4
	P1=5		;PERMANENT ACS
	P2=6
	P3=7
	J=10		;JOB WE ARE CURRENTLY PROCESSING
	JS=11		;JOB STATUS BITS FOR A JOB
	IO=12		;CHANNEL NUMBER OF PRESENT PTY
	C=13		;CHARACTER HOLDING
	P=17		;PUSH-DOWN STACK
;FLAGS IN RH OF F  (KILL'S OWN FLAGS SET ONLY BY US) :


	FR.CCL==1	;COMMANDS ARE COMING FROM A CCL FILE
	FR.OPR==2	;WE ARE PRIVILEGED AND CAN KILL ANYBODY
	FR.DET==4	;WE ARE DETACHED OR IN MONITOR MODE
	FR.ATT==10	;WE HAVE ATTACHED A JOB TO OUR TTY
	FR.XIT==20	;WE HAVE BEEN GIVEN THE EXIT FUNCTION
	FR.HLP==40	;WE HAVE ALREADY GIVEN THE HELP MESSAGE
	FR.FND==100	;A JOB WAS FOUND TO PROCESS
	FR.SCH==200	;WE ARE RUNNING THE SCHEDULER
	FR.WLD==400	;THE FNDJOB ROUTINE IS RETURNING MULTIPLE JOBS
	FR.ERR==1000	;INDICATES THE FNDSTS ROUTINE FAILED
	FR.NDS==2000	;WE NEED TO CALL THE SCHEDULER LATER
	FR.MEA==4000	;DO DESIRED ACTIONS MEANLY
	FR.FND==10000	;A JOB WAS FOUND TO PROCESS
	FR.PHY==20000	;DO RUN UUO PHYSICAL ONLY
	FR.UMA==40000	;ATTACH JOB IN USER MODE



;FLAGS IN LH OF F (SET BY THE USER FOR US) :


	FL.SUP==1B0	;SUPPRESS ALL OUTPUT TO THE TTY
	FL.TCR==1B3	;WE ARE TO WRITE A TMPCOR FILE CONTAINING ERROR
			;CODES IF ANY ERRORS OCCUR
	FL.IMP==1B5	;ONLY OUTPUT IMPORTANT MESSAGES TO TTY (ERRORS)
;FLAG BITS THAT CAN BE SPECIFIED IN THE INDIVIDUAL FUNCTION BLOCKS:


	FF.PHY==1B0	;DO RUN UUO PHYSICAL ONLY
	FF.DOT==1B1	;FOR SENDING MESSAGES, OUTPUT "MONITOR DOTS"
	FF.UMA==1B2	;FOR ATTACH FUNCTION, ATTACH JOB IN USER MODE



;USEFUL OPDEFS:


	OPDEF	CALL	[PUSHJ P,]	;SUBROUTINE CALL
	OPDEF	RET	[POPJ P,]	;RETURN
	OPDEF	RETSKP	[JRST CPOPJ1]	;SKIP RETURN
	OPDEF	PJRST	[JRST]		;STANDARD
	OPDEF	PUTCHR	[CALL CHROUT]	;OUTPUT CHAR TO TTY
	OPDEF	REREAD	[SETOM RRFLAG]	;REREAD LAST CHAR
	OPDEF	GETCHR	[CALL TTYIN]	;GET A CHAR FROM THE TTY

	OPDEF	TELUUO	[1B8]		;OUTPUT A MESSAGE IF NOT SUPPRESSED
	OPDEF	ERRUUO	[2B8]		;OUTPUT MESSAGE, AND TERMINATE PROCESS
	OPDEF	DIEUUO	[3B8]		;OUTPUT MESSAGE, AND QUIT PROGRAM



;I/O CHANNELS:


	CH.PTY==0		;CHANNEL FOR THE FIRST PTY
				;*** THIS MUST BE CHANNEL 0 ***
				;CHANNELS FOR OTHER PTYS FOLLOW IN ORDER

	CH.DSK==CH.PTY+PTYNUM	;CHANNEL FOR READING CCL FILE
;IMPORTANT MONITOR CONSTANTS:


	JSWRUN==1B0	;BIT IN JBTSTS - PROGRAM IS RUNNING
	JSWCMW==1B1	;BIT IN JBTSTS - JOB IS IN A COMMAND WAIT
	JSWJCT==1B17	;BIT IN JBTSTS - PROGRAM IS JACCT'D




;MONITOR CONSTANTS USED ONLY FOR "SYSTATS":


	JSWSWP==1B7	;BIT IN JBTSTS - JOB IS SWAPPED OUT
	JSWCLK==1B18	;BIT IN JBTSTS - CLOCK REQUEST IS IN
	JSWDCM==1B20	;BIT IN JBTSTS - USER TYPED "DCORE"
	JSWOPW==1B22	;BIT IN JBTSTS - JOB IS IN AN OPERATOR WAIT
	JSWRUP==1B26	;BIT IN JBTSTS - RUN UUO IS IN PROGRESS
	DEVIOS==2	;OFFSET IN A DDB FOR THE DEVIOS WORD
	DEVIOW==1B17	;BIT IN DEVIOS WORD - DEVICE IS IN AN I/O WAIT
	DEVOUT==1B0	;BIT IN DEVIOS WORD - I/O WAIT IS FOR OUTPUT



;OTHER CONSTANTS:


	JB.RUN==1B17		;"MADE UP" BIT IN JS, JOB IS RUNNING
	JB.CMW==1B16		;"MADE UP" BIT IN JS, JOB IS IN COMMAND WAIT
	JB.TTY==777777		;"MADE UP" FIELD IN JS, TERMINAL IOINDEX
	VL.ALL==400000		;ARGUMENT - ALL JOBS
	VL.DET==400001		;ARGUMENT - ALL DETACHED JOBS
	VL.OWN==400002		;ARGUMENT - ALL TERMINALS OWNED BY A JOB
	VL.REM==400003		;ARGUMENT - ALL REMOTE JOBS
	STS.LO==1B0		;STATUS BIT FOR A JOB STORED IN LH OF ACTION
				;TABLE - WE ARE CRUMPING A LOGGED OUT JOB
				;INSTEAD OF A LOGGED IN JOB.  MUST BE SIGN BIT.
	STS.AT==1B1		;JOB IS ON A TTY BECAUSE WE JUST ATTACHED
				;IT TO ONE OF OUR PTYS.
	SUBTTL	DEFAULT PARAMETERS AND CONDITIONALS


DEFINE	ND(SYM,VAL),<IFNDEF SYM,<SYM==VAL>>	;MAKE THINGS EASY




;CONDITIONALS AND PARAMETERS:


	ND	FTPOKE,-1	;ON TO POKE ON JACCT IF WE NEED TO
	ND	FTHALT,-1	;ON IF MONITOR CAN DO FRCUUO FUNCTION
				;'HALT' (603 MONITOR)
	ND	FTOWNER,-1	;ON IF ONE USER CAN KILL ANOTHER USER
				;IF HE IS THE "OWNER" OF THE OTHER ACCT'S
				;FILES.  OFF IF PPNS MUST EXACTLY MATCH
	ND	FTBATCH,0	;ON IF A USER IS ALLOWED TO KILL A BATCH
				;JOB. OFF IF NOT ALLOWED TO EVER DO IT.
	ND	MYNAME,'KILL  '	;THE NAME OF THIS PROGRAM
	ND	PDLSIZ,^D30	;SIZE OF MAIN STACK
	ND	STKSIZ,^D35	;SIZE OF STACKS FOR EACH PROCESS
	ND	PTYNUM,^D10	;MAXIMUM NUMBER OF PTYS WE USE AT ONCE
	ND	JOBMAX,^D511	;MAX JOB NUMBER WE EXPECT
	ND	TCRLEN,1000	;MAXIMUM SIZE OF CCL FILE
	ND	DAESLP,^D500	;MILLISECONDS TO WAIT BETWEEN DAEMON CHECKS
	ND	PSTTRY,^D40	;TIMES TO TRY TO STOP PTY JOB
	ND	PSTSLP,^D500	;MILLISECONDS BETWEEN ATTEMPTS
	ND	RUNSLP,^D2000	;MILLISECONDS TO WAIT FOR A STOPPED JOB
				;ON A PTY TO START RUNNING WHEN LOGGING OUT
	ND	KJOTRY,^D120	;NUMBER OF LOOPS TO WAIT FOR LOGGING OUT
	ND	KJOSLP,^D500	;MILLISECONDS BETWEEN CHECKS
	ND	ALCTRY,^D60	;TRIES TO GET A FREE PTY
	ND	ALCSLP,^D1000	;MILLISECONDS BETWEEN ATTEMPTS
	ND	STPTRY,^D150	;TOTAL TRIES TO TRY TO STOP A JOB ON A TTY
	ND	STPSLP,^D500	;MILLISECONDS TO SLEEP BETWEEN ATTEMPTS
	ND	STPIWH,^D130	;TRIES LEFT WHEN USE 'HALT' IF IN TI WAIT
	ND	STPHLT,^D40	;TRIES LEFT WHEN ALWAYS USE 'HALT'
	ND	ZAPSLP,^D750	;TIME TO WAIT FOR NON-LOGGED IN JOB TO QUIT
				;AFTER IT IS KNOWN TO BE "STOPPED"
	ND	ERROFS,^D101	;STARTING ERROR CODE FOR COMMON ERRORS
	ND	DIEOFS,1	;STARTING ERROR CODE FOR FATAL ERRORS
	ND	TMPSIZ,^D32	;MAXIMUM WORDS IN TMPCOR ERROR FILE
	SUBTTL	RANDOM MACROS



	IF1,<			;ALL THE MACROS GO IN FIRST PASS



	DEFINE	CERROR(TEXT),<		;;MACRO FOR SCANNING ERRORS
	MOVEI	T1,[ASCIZ/TEXT/]	;;GET THE PROPER ERROR TEXT
	JRST	ERRFIN			;;THEN GO TYPE IT
>


	DEFINE	CTL(CHAR),<"CHAR"-100>	;;MAKE DESIRED CONTROL CHAR



	DEFINE	TEXT(STRING),<	;;FOR ASCII TEXT WITHOUT BINARY LISTING
	XLIST
	ASCIZ	@STRING@
	LIST
>



;STILL IN IF1 CONDITIONAL
	SUBTTL	MACRO TO DEFINE THE FUNCTIONS




;THE FOLLOWING MACRO DEFINES ALL THE FUNCTIONS.  THERE ARE FOUR
;ARGUMENTS FOR THE DEFINITION OF THE MACRO:
;
;	MNEMONIC, PRIORITY, LENGTH, COMMAND
;
;"MNEMONIC" IS THE 3-LETTER COMBINATION UNIQUE TO THIS FUNCTION WHICH
;   IDENTIFIES THAT FUNCTION.
;"PRIORITY" DETERMINES THE ORDER THE FUNCTIONS ARE EXECUTED IN, LOWER
;   LETTERED FUNCTIONS FIRST.  IF 2 FUNCTIONS HAVE THE SAME PRIORITY, THEN
;   THE ORDER IS UNIMPORTANT.  IF TWO OR MORE LETTERS APPEAR, THEN THIS
;   FUNCTION WILL BE CALLED ONCE FOR EACH PRIORITY.
;"LENGTH" IS THE LENGTH OF THE ARGUMENT BLOCK IN THE TMPCOR REPRESENTATION
;   INCLUDING THE FUNCTION CODE ITSELF.  ZERO MEANS THE LENGTH ISN'T FIXED,
;   AND THAT THE LENGTH OF THE BLOCK WILL BE COMPUTED BY A SUBROUTINE.
;"COMMAND" IF PRESENT, IS THE USER-TYPED COMMAND AVAILABLE FROM THE TTY.
;   IF NOT PRESENT, THERE IS NO COMMAND FOR THIS FUNCTION.
;
;*** WARNING:  ADD NEW FUNCTIONS ONLY AT THE END OF THE LIST, AND REPLACE
;ANY FUNCTION TO BE REMOVED WITH A NO-OP FUNCTION, BECAUSE THE ORDER OF
;THE DEFINITIONS IS USED TO GENERATE THE FUNCTION CODES.



	DEFINE	FUNCTIONS,<

	XX	END,A,1		;;(00) TERMINATE LIST OF FUNCTIONS
	XX	FLG,A,1		;;(01) SET PARAMETERS
	XX	STP,C,3,STOP	;;(02) STOP A JOB
	XX	DET,C,3,DETACH	;;(03) DETACH A JOB
	XX	KIL,C,3,KILL	;;(04) LOG OUT A JOB
	XX	ZAP,C,2,ZAP	;;(05) ZAP A NOT LOGGED IN DETACHED JOB
	XX	ATT,F,3,ATTACH	;;(06) ATTACH A JOB TO OUR TTY
	XX	LST,E,3,LIST	;;(07) LIST ALL JOBS OF A PPN
	XX	HLP,A,1,HELP	;;(10) TYPE OUT THE HELP MESSAGE
	XX	NOT,CEF,3,NOT	;;(11) PERFORM NO ACTION FOR THIS JOB
	XX	RET,D,1		;;(12) ATTACH BACK TO TTY WE DETACHED FROM
	XX	RUN,A,7		;;(13) RUN A PROGRAM
	XX	XIT,A,1,EXIT	;;(14) EXIT WHEN ALL DONE
	XX	MSG,B,0		;;(15) OUTPUT SOME TEXT
	XX	MEA,A,1,MEAN	;;(16) BE MEAN WHEN DOING ACTIONS
>




;STILL IN IF1 CONDITIONAL
	SUBTTL	MACROS FOR THE LUUOS



;THE FOLLOWING MACROS ARE USED IN CREATING THE ACTIONS OF
;THE LUUOS.  THEY ARE PRETTY OBVIOUS:



	DEFINE	TELL(TEXT),<
	TELUUO	[ASCIZ	\TEXT
\]
>

	DEFINE	ERROR(CODE),<
	ERRUUO	E..'CODE
>

	DEFINE	DIE(CODE),<
	DIEUUO	D..'CODE
>


;MACRO TO DEFINE ERROR CODES FOR FATAL AND DIE MACROS:


	DEFINE	ECODE(MNEM,TEXT),<

E..'MNEM:	EXP	[ASCIZ	\? TEXT
\]
>

	DEFINE	DCODE(MNEM,TEXT),<

D..'MNEM:	EXP	[ASCIZ	\TEXT
\]
>



>		;END OF HUGE IF1 CONDITIONAL
	SUBTTL	INITIALIZATION




;HERE TO BEGIN THE PROGRAM.  WE SEE IF WE ARE BEING CONTROLLED
;BY ANOTHER KILL, AND IF SO WE PROCEED TO LOG OUT (THAT IS HOW
;KILL LOGS OFF A JOB, BY MAKING IT RUN KILL ON A PTY).  IF NOT
;THEN WE LOOK FOR A CCL FILE IF WE WERE RUN WITH AN OFFSET.  IF
;FOUND, WE TAKE COMMANDS FROM IT.  IF NOT FOUND, OR IF RUN WITH
;NO OFFSET, WE ACCEPT COMMANDS FROM THE TTY.



KILL:	TDZA	F,F		;SET NO CCL RUN
	MOVX	F,FR.CCL	;REMEMBER THIS IS A CCL RUN
	RESET			;CLEAR ALL I/O
	MOVE	P,[IOWD PDLSIZ,PDL]	;SET UP PUSHDOWN STACK
	MOVE	T1,[CALL UUO]	;GET LUUO DISPATCH INSTRUCTION
	MOVEM	T1,.JB41	;AND STORE IT AWAY
	CALL	INICOR		;GO INITIALIZE CORE SOME
	CALL	SETTRP		;SETUP ^C TRAP NOW
	GETPPN	T1,		;GET MY PPN
	 JFCL			;STUPID SKIP
	MOVEM	T1,MYPPN	;SAVE IT AWAY FOR LATER
	PJOB	J,		;GET MY JOB
	MOVEM	J,MYJOB		;SAVE IT
	CTLJOB	J,		;SEE IF I AM CONTROLLED BY SOMEONE
	 DIE	CUF		;FAILED
	JUMPLE	J,REGRUN	;NOT CONTROLLED, STANDARD THING
	MOVE	T1,[MYNAME]	;GET MY NAME
	CALL	SYSPRG		;IS CONTROLLING JOB RUNNING ME?
	 JRST	REGRUN		;NO, THEN THIS IS A NORMAL RUN
	JRST	LOGOFF		;YES, THEN WE ARE TO LOG OUT
;HERE WHEN WE ARE NOT BEING CONTROLLED BY ANOTHER KILL JOB:



REGRUN:	MOVE	T1,[%CNSJN]	;SET UP
	GETTAB	T1,		;FIND OUT THE NUMBER OF JOBS
	 DIE	GTF		;CAN'T
	MOVEI	T1,-1(T1)	;GET THE HIGHEST LEGAL JOB NUMBER
	CAILE	T1,JOBMAX	;LARGER THAN MAXIMUM WE WERE BUILT FOR?
	 DIE	TMJ		;YES, DIE THEN
	MOVEM	T1,HGHJOB	;IT'S OK, STORE IT
	MOVE	T1,[%CNPTY]	;NOW GET SET
	GETTAB	T1,		;TO FIND OUT PTY PARAMETERS
	 DIE	GTF		;CAN'T
	HLRZ	T1,T1		;GET TTY NUMBER OF THE FIRST PTY
	MOVEM	T1,PTYTTY	;SAVE IT FOR LATER
	MOVE	T1,[%CNLNP]	;NOW GET SET
	GETTAB	T1,		;FIND OUT NUMBER OF TTYS
	 DIE	GTF		;CAN'T
	HLRE	T1,T1		;GET JUST - NUMBER OF TTYS
	MOVN	T1,T1		;GET + NUMBER OF TTYS
	SUBI	T1,1		;CREATE HIGHEST TTY NUMBER
	MOVEM	T1,HGHTTY	;SAVE IT FOR LATER
	MOVE	T1,[%CNTIC]	;GET READY
	GETTAB	T1,		;FIND THE NUMBER OF TICKS IN A SECOND
	 DIE	GTF		;FAILED
	MOVEM	T1,TICSEC	;SAVE IT
	CALL	CHKOPR		;SEE IF I CAN HAVE PRIVILEGES
	 TXO	F,FR.OPR	;YES, REMEMBER WE HAVE THEM
	CALL	GETCCL		;SEE IF THERE ARE CCL COMMANDS
	 JRST	GOTCMD		;YES, SKIP COMMAND SCANNING AND DO THEM
;	JRST	CMMD		;NO, FALL INTO COMMAND CODE
	SUBTTL	ROUTINE TO GET COMMANDS FROM THE TTY



;THIS ROUTINE IS GOTTEN TO IF WE WERE NOT RUN ON A RUNOFFSET OF 1, OR
;IF WE FAILED TO READ IN A CCL FILE.  WE INPUT COMMANDS FROM THE TTY,
;AND CONVERT THEM TO THE FORMAT USED FOR THE CCL FILE.  WHEN THE LINE
;IS DONE, WE THEN GRUNGE ON THE BINARY DATA WE MADE.
;AT THE START OF EVERY COMMAND, CORE IS INITIALIZED.
;
;IN THIS ROUTINE, WE USE THE PERMANENT AC'S AS FOLLOWS:
;
;	P1 = ADDRESS IN TMPCOR STORAGE FOR NEXT WORD
;	P2 = FUNCTION CODE OF THE PRESENT COMMAND
;	P3 IS UNUSED.



CMMD:	ANDX	F,FR.OPR	;ONLY LEAVE THIS FLAG SET
	MOVEI	T1,"*"		;GET THE STANDARD PROMPT
	TXNE	F,FR.OPR	;ARE WE PRIVILEGED?
	MOVEI	T1,"#"		;YES, GET A DIFFERENT PROMPT THEN
	OUTCHR	T1		;OUTPUT THE PROMPT
	MOVE	P,[IOWD	PDLSIZ,PDL]	;RESET PUSH-DOWN POINTER
	CALL	INICOR		;GO ZERO IMPORTANT DATA
	MOVEI	P1,TCRDAT	;POINT TO TMPCOR AREA
	MOVSI	T1,TMPVER	;GET TMPCOR VERSION WITH NO FLAGS
	CALL	PUTWRD		;STORE AS FIRST WORD OF DATA

GETSWT:	CALL	SIXIN		;INPUT A COMMAND
	CAIE	C," "		;A SPACE FOLLOWING?
	CAIN	C,12		;OR AN END OF LINE?
	SKIPA	T2,[IOWD <FNCHGH+1>,CMDFNC]	;YES, SETUP TO SEARCH COMMAND
	JRST	ILLCHS		;NO, ILLEGAL, GO COMPLAIN
	JUMPE	T1,BLKLIN	;IF NO SWITCH GO SEE IF A BLANK LINE
	CALL	MATCH		;WAS ONE, SEARCH THE COMMAND TABLE
	 JRST	ILLSWT		;NOT FOUND OR ILLEGAL, COMPLAIN
	MOVE	P2,T2		;SAVE THE FUNCTION CODE
	CALL	@CMDDSP(T2)	;GO READ ARGUMENTS AND STORE THEM
	JRST	GETSWT		;THEN GET A NEW COMMAND


BLKLIN:	CALL	EATLIN		;ALL DONE, EAT UP THE LINE
	CAIGE	P1,TCRDAT+2	;ANY COMMANDS GIVEN?
	JRST	CMMD		;NO, GO ASK AGAIN FOR SOME
	OUTSTR	[ASCIZ/
/]				;GOT SOMETHING, SPACE DOWN THEN
	JRST	GOTCMD		;AND THEN GO PROCESS THE COMMANDS
	SUBTTL	SUBROUTINES TO PROCESS THE VARIOUS COMMANDS



;THESE ROUTINES ARE CALLED WHEN A COMMAND NEEDS TO BE PROCESSED.  WE
;COLLECT ALL ARGUMENTS IT NEEDS, IF IT NEEDS ANY, AND STORE THE PROPER
;THINGS INTO OUR TMPCOR BUFFER FOR LATER EXECUTION, ALL THE TIME CHECKING
;FOR AN OVERFLOW OF THE BUFFER.  CALL IS:
;
;	MOVEI	P2,FUNCTION	;SETUP FUNCTION CODE
;	MOVEI	P1,POINTER	;AND POINTER INTO TMPCOR BUFFER
;	CALL	CMDXXX		;CALL ROUTINE FOR COMMAND XXX
;	(RETURN)		;SUCCESSFUL, RETURN
;
;ON RETURN, P1 HAS BEEN UPDATED AND THE COMMAND IS STORED IN THE BUFFER.




;HERE FOR COMMANDS WHICH TAKE NO ARGUMENTS.  ALL THAT IS STORED IS
;THE FUNCTION CODE:


CMDHLP:	CMDXIT:	CMDMEA:		;THESE FUNCTIONS COME HERE

SCN0:	CALL	PUTFNC		;STORE THE FUNCTION CODE
	CALL	GETARG		;SEE IF AN ARGUMENT IS FOLLOWING
	 RET			;NO, THEN ALL DONE
	JRST	EXTRAA		;YES, THEN WE HAVE AN ERROR



;HERE FOR FUNCTIONS WHICH ACCEPT ONLY A JOB NUMBER AS AN ARGUMENT,
;SO THAT ONLY TWO WORDS ARE NEEDED FOR STORAGE:


CMDZAP:				;THESE COMMANDS COME HERE

SCN1:	CALL	GETARG		;GET THE ARGUMENT
	 JRST	NULARG		;ERROR IF NONE THERE
SCN1L:	CALL	PUTFNC		;STORE THE FUNCTION CODE
	SKIPE	ARG2		;WAS A PPN GIVEN?
	JRST	UNEEDA		;YES, COMPLAIN BECAUSE IT IS UNNEEDED
	MOVE	T1,ARG1		;GET THE ARGUMENT HE GAVE
	CALL	PUTWRD		;STORE IT IN BUFFER
	CALL	GETARG		;LOOK FOR ANOTHER ARGUMENT
	 RET			;NO MORE
	JRST	SCN1L		;OK, STORE THIS ONE TOO
;HERE FOR COMMANDS WHICH ACCEPT JOB NUMBERS WITH OPTIONAL PPNS.
;THERFORE THREE WORDS OF STORAGE ARE USED:


CMDNOT:	CMDSTP:	CMDDET:	CMDKIL:	CMDATT:		;THESE COMMANDS COME HERE

SCN2:	CALL	GETARG		;GET THE ARGUMENT
	 JRST	NULARG		;ERROR IF ONE NOT GIVEN
SCN2L:	CALL	PUTFNC		;STORE THE FUNCTION CODE
	MOVE	T1,ARG1		;GET THE FIRST ARGUMENT
	CALL	PUTWRD		;STORE IT
	MOVE	T1,ARG2		;GET THE SECOND ARGUMENT
	CALL	PUTWRD		;STORE IT TOO
	CALL	GETARG		;LOOK FOR ANOTHER ARGUMENT
	 RET			;NO MORE
	JRST	SCN2L		;OK, GO STORE IT TOO




;HERE FOR COMMANDS WHICH ACCEPT BOTH JOB AND PPNS, WITHOUT COMPLAINING IF
;NONE WAS SPECIFIED.  IN THIS CASE, THE ARGUMENTS ARE ASSUMED TO BE *[*,*].


CMDLST:				;THIS COMMAND COMES HERE

SCN2A:	CALL	GETARG		;GO GET AN ARGUMENT IF THERE
	 SKIPA	T1,MYPPN	;NONE, GET MY PPN
	JRST	SCN2L		;WAS ONE, THEN STORE IT
	MOVEM	T1,ARG2		;ACT LIKE IT WAS TYPED
	JRST	SCN2L		;AND PROCEED
;ROUTINE TO STORE A WORD IN THE TMPCOR BUFFER, WHILE CHECKING FOR
;OVERFLOWS, AND ALSO UPDATING P1.  CALL IS:
;
;	MOVE	T1,WORD		;GET THE WORD TO BE STORED
;	CALL	PUTWRD		;GO PUT IT AWAY
;	(RETURN)		;DID IT
;
;USES NO AC'S, AC P1 IS INCREMENTED BY 1.



PUTFNC:	HRRZ	T1,P2		;GET FUNCTION CODE WITH NO FLAGS
PUTWRD:	CAIL	P1,TCRDAT+TCRLEN	;ANY MORE ROOM?
	JRST	OVFARG		;NO, GO COMPLAIN HE TYPED TOO MUCH
	MOVEM	T1,(P1)		;YES, STORE THE WORD AWAY
	AOJA	P1,CPOPJ	;INCREMENT P1 AND RETURN
	SUBTTL	SUBROUTINE TO READ ONE ARGUMENT FOR A COMMAND


;THIS ROUTINE IS CALLED AFTER A FUNCTION IS TYPED IN, TO LOOK FOR THE
;NEXT ARGUMENT FOR THE FUNCTION.  EXAMPLES OF ARGUMENTS ARE:
;
;	12, 14[1,2], #47, #23[*,10], *, 12-24, 10-14[*,*]
;
;WE LEAVE THE FIRST CHARACTER FOLLOWING THE ARGUMENT READY TO BE READ.
;ARGUMENTS ARE STORED IN LOCATION ARG1 AND ARG2 AS FOLLOWS:
;  ARG1/	JOB, <JOB1,,JOB2>, .UXTRM+TTY, VL.ALL, OR VL.DET
;  ARG2/	PPN OR 0
;
;	CALL	GETARG		;GO INPUT AN ARGUMENT
;	 (NONE RETURN)		;NONE THERE, IS A COMMAND OR END OF LINE
;	(GOT ONE RETURN)	;THERE IS ONE, AND WE HAVE THE ARGS
;
;WE USE AC'S   T1, T2, T3, T4,  AND  C.




GETARG:	MOVX	T1,VL.ALL	;ASSUME WANTS ALL JOBS AT FIRST
	MOVEM	T1,ARG1		;SO STORE THAT
	CALL	DECINZ		;SEE IF A JOB NUMBER WAS SPECIFIED
	JUMPL	T2,JOBARG	;PROCEED IF TRUE
	GETCHR			;WASN'T A JOB NUMBER, GET NEXT CHAR
	CAIN	C,","		;THE DELIMITER CHARACTER?
	JRST	GETARG		;YES, EAT IT AND KEEP LOOKING
	CAIN	C,"*"		;WANT TO DO ALL JOBS?
	JRST	ALLARG		;YES, SKIP ON
	CAIN	C,"#"		;WANTS TO SPECIFY A TERMINAL NUMBER?
	JRST	TTYARG		;YES, GO HANDLE THAT
	CALL	ALFNUM		;SEE IF THIS IS A COMMAND
	 CAIN	C,12		;OR AN END OF LINE
	JRST	RPOPJ		;YES, GIVE A NON-SKIP RETURN
	REREAD			;PUT IT BACK
	CAIE	C,"["		;SPECIFYING A PPN WITHOUT JOB OR TTY?
	JRST	ILLCHA		;NO, JUST PLAIN JUNK AS ARGUMENT
	CAIE	P2,FN.LST	;LIST FUNCTION?
	CAIN	P2,FN.NOT	;OR NOT FUNCTION?
	JRST	ALLARG		;YES, ALLOW MISSING JOB NUMBER
	JRST	NEEDJB		;FOR OTHERS, COMPLAIN
;HERE WHEN THE ARGUMENT IS A TTY NUMBER:


TTYARG:	CALL	OCTIN		;GO LOOK FOR AN OCTAL NUMBER
	CAIE	C,"8"		;USER TRYING TO SNEAK IN DECIMAL DIGITS?
	CAIN	C,"9"
	JRST	ILARGT		;YES, COMPLAIN
	JUMPL	T2,TTYARN	;PROCEED IF GOT ONE
	CAIN	C,"D"		;WANTS DETACHED JOBS?
	MOVEI	T1,VL.DET	;YES, GET CODE
	CAIN	C,"R"		;WANTS REMOTE JOBS?
	MOVEI	T1,VL.REM	;YES, GET CODE
	JUMPE	T1,ILARGT	;IF NOT ONE OF THEM, FAIL
	GETCHR			;EAT THE CHARACTER
	JRST	HAVARG		;AND PROCEED

TTYARN:	SKIPL	T1		;IS THE NUMBER IN RANGE?
	CAMLE	T1,HGHTTY
	JRST	ILARGT		;OUT OF LEGAL TTY RANGE, COMPLAIN
	ADDI	T1,.UXTRM	;MAKE A TTY I/O INDEX
	JRST	HAVARG		;AND GO STORE IT AND GET PPN




;HERE WHEN THE ARGUMENT IS A JOB NUMBER:


JOBARG:	SKIPLE	T4,T1		;RANGE CHECK IT
	CAMLE	T4,HGHJOB	;BEFORE ACCEPTING IT
	JRST	ILARGJ		;LOSE
	CAIE	C,"-"		;WANTS TO SPECIFY A RANGE?
	JRST	ONEARG		;NO, SKIP ON
	GETCHR			;YES, EAT THE DASH
	CALL	DECIN		;THEN READ SECOND JOB NUMBER
	SKIPLE	T1		;RANGE CHECK IT ALSO
	CAMLE	T1,HGHJOB	;BEFORE USING IT
	JRST	ILARGJ		;IT'S BAD
	CAMN	T1,T4		;A RANGE OF JUST ONE JOB?
ONEARG:	SKIPA	T1,T4		;YES, GET SINGLE JOB NUMBER READY
	HRL	T1,T4		;OR BUILD RANGE OF JOBS
;HERE TO STORE THE FIRST ARGUMENT, AND GET THE PPN IF ANY WAS THERE:


HAVARG:	MOVEM	T1,ARG1		;SAVE AWAY THE JOB OR TTY OR -1
ALLARG:	CALL	PPNIN		;LOOK FOR A PPN IMMEDIATLY FOLLOWING
	JUMPN	T1,ILLPPN	;IF ONE GIVEN, BUT BAD FORMAT, DIE
	MOVEM	T1,ARG2		;GOOD PPN GIVEN (OR NONE), SAVE IT
	GETCHR			;GET THE NEXT CHARACTER NOW
	CAIN	C,12		;NOW AT THE END OF A LINE?
	JRST	RPOPJ1		;YES, RESTORE IT AND GIVE OK RETURN
	CAIE	C," "		;ARGUMENT FOLLOWED BY A SPACE?
	CAIN	C,","		;OR FOLLOWED BY A COMMA?
	RETSKP			;YES, EAT IT UP AND GIVE OK RETURN
	JRST	ILLCHA		;ILLEGAL CHARACTER IN ARGUMENT
	SUBTTL	ERRORS FROM COMMAND SCANNING


;THESE ARE ERROR MESSAGES GIVEN TO THE USER WHEN SCANING THE COMMAND
;LINE AND FINDING INCORRECT STUFF GIVEN.  IT IS OK TO JUST OUTSTR THESE
;MESSAGES, SINCE WE CAN ONLY GET HERE IF COMMANDS WERE TYPED IN ON THE
;USER'S TTY, NEVER FROM A CCL FILE.  ALL ROUTINES RETURN TO INPUT A NEW
;COMMAND WHEN DONE.



OVFARG:	CERROR	Storage buffer overflowed
NULARG:	CERROR	Missing argument
ILARGJ:	CERROR	Illegal job number given
ILARGT:	CERROR	Illegal tty number given
ILLPPN:	CERROR	Illegal PPN given
EXTRAA:	CERROR	No argument is required
UNEEDA:	CERROR	Ppn is not required
NEEDJB:	CERROR	<Must specify job, tty, or "*">



;HERE FOR FINISHING UP THE COMMON EASY TO EXPLAIN ERRORS


ERRFIN:	CALL	EATLIN		;EAT UP THE REST OF THE BAD LINE
	CLRBFI			;EAT ALL INPUT
	OUTSTR	[ASCIZ/
? /]				;OUTPUT PRELIMINARY TEXT
	OUTSTR	(T1)		;OUTPUT THE ERROR MESSAGE
	OUTSTR	[ASCIZ/ for "/]	;GIVE MORE TEXT
	MOVE	T1,CMDFNC(P2)	;GET THE COMMAND NAME
	CALL	SIXOUT		;OUTPUT THE COMMAND NAME
	OUTSTR	[ASCIZ/" command

/]				;FINISH THE TEXT
	JRST	CMMD		;AND THEN GET A NEW COMMAND
;NOW THE ROUTINES FOR THE HARDER TO EXPLAIN ERRORS:




ILLCHS:	SKIPA	T1,[[ASCIZ/a command/]]	;;SET UP TEXT
ILLCHA:	MOVEI	T1,[ASCIZ/an argument/]	;OR OTHER TEXT
	MOVEI	T2,(C)		;GET A COPY OF THE BAD CHAR
	CALL	EATLIN		;THEN EAT THE REST OF THE LINE
	CLRBFI			;DESTROY THE INPUT BUFFER
	OUTSTR	[ASCIZ/
? Illegal character "/]			;START OFF ERROR
	CAIL	T2," "		;IS CHAR A CONTROL CHAR?
	JRST	ILLCHX		;NO, NO SPECIAL OUTPUT
	OUTCHR	["^"]		;YES, GIVE THE UP-ARROW
	ADDI	T2,100		;AND CONVERT TO CORRESPONDING LETTER
ILLCHX:	OUTCHR	T2		;OUTPUT CHAR
	OUTSTR	[ASCIZ/" found while reading /]	;MORE TEXT
	OUTSTR	(T1)		;GIVE THE PROPER TEXT
	OUTSTR	[ASCIZ/

/]				;THEN SPACE DOWN
	JRST	CMMD		;AND GET A NEW COMMAND






ILLSWT:	CALL	EATLIN		;GOBBLE UP THE PRESENT LINE
	CLRBFI			;THEN WIPE OUT INPUT BUFFER
	SKIPE	T2		;WAS THE COMMAND UNKNOWN?
	OUTSTR	[ASCIZ/
? Unknown command "/]		;YES, TELL HIM
	SKIPN	T2		;HOW ABOUT AMBIGUOUS?
	OUTSTR	[ASCIZ/
? Ambiguous command "/]		;YES, TELL HIM THAT INSTEAD
	CALL	SIXOUT		;OUTPUT IT
	OUTSTR	[ASCIZ/" - type "HELP" for help

/]				;TYPE MORE
	JRST	CMMD		;THEN GET NEW COMMANDS
	SUBTTL	ROUTINE TO PROCESS TMPCOR COMMANDS


;THIS CODE IS REACHED DIRECTLY FROM THE INPUT OF A CCL FILE, OR
;INDIRECTLY AFTER THE USER'S TTY COMMANDS HAVE BEEN CONVERTED TO
;BINARY FORM.  WE SCAN THE TMPCOR DATA IN SEVERAL PASSES, DOING
;THE FUNCTIONS WHICH IT IS NOW TIME FOR.  THIS IS THE HEART OF THE
;PROG.  WHEN DONE, WE RETURN TO GET A NEW COMMAND, OR EXIT.
;
;THE PERMANENT AC'S ARE USED IN THIS ROUTINE AS FOLLOWS:
;
;	P1 = PRIORITY MASK.  SHIFTED FOR EACH PRIORITY.  FUNCTIONS ARE
;		HANDLED WHEN THEIR MASK MATCHES THE CURRENT MASK.
;
;	P2 = POINTER INTO THE TMPCOR DATA.  ALWAYS POINTS TO THE FUNCTION
;		PRESENTLY BEING LOOKED AT
;
;	P3 = THE CURRENT FUNCTION CODE BEING LOOKED AT



GOTCMD:	ANDX	F,FR.OPR!FR.CCL	;ONLY LEAVE THESE FLAGS SET
	SETZM	ERRPTR		;INITIALIZE THE ERROR POINTER
	SETZM	ERRCNT		;AND THE COUNT OF ERRORS
	HLRZ	T1,TCRDAT	;GET VERSION OF TMPCOR DATA
	CAIE	T1,TMPVER	;CORRECT?
	 DIE	CWV		;NOPE
	MOVEI	P1,1		;INITIALIZE THE PRIORITY MASK


CLSLOP:	MOVEI	P2,TCRDAT+1	;SET UP POINTER TO TMPCOR AREA
	MOVE	T1,[ACTION,,ACTION+1]	;GET READY
	SETZM	ACTION		;TO CLEAR THE ACTION TABLE
	BLT	T1,ACTION+JOBMAX-1	;MAKE SURE NO ACTIONS REMAIN
FNCLOP:	CAILE	P2,TCRDAT+TCRLEN	;ARE WE OUTSIDE OF THE TMPCOR AREA?
	JRST	CLSNXT		;YES, GO DO NEXT CLASS NOW
	HRRZ	P3,(P2)		;GET THE NEXT FUNCTION TO PERFORM
	JUMPE	P3,CLSNXT	;IF ZERO, THEN DONE, DO NEXT CLASS
	CAILE	P3,FNCHGH	;IS IT A LEGAL FUNCTION?
	 DIE	IFN		;NO, ILLEGAL FUNCTION NUMBER
	TDNE	P1,PRIFNC(P3)	;TIME TO DO THIS FUNCTION?
	CALL	@DSPFNC(P3)	;YES, THEN GO DISPATCH TO IT
	SKIPL	T1,LENFNC(P3)	;GRAB THE LENGTH OF THE ARGUMENT BLOCK
	ADD	P2,T1		;IF A CONSTANT, ADD IT TO POINTER
	SKIPGE	T1		;SEE IF NOT CONSTANT
	CALL	(T1)		;YES, CALL ROUTINE TO MOVE POINTER FOR US
	JRST	FNCLOP		;AND LOOK AT NEXT FUNCTION


CLSNXT:	TXZE	F,FR.NDS	;SCHEDULER NEED TO RUN?
	CALL	SCHEDG		;YES, LET IT DO WORK THEN
	LSH	P1,1		;SHIFT OVER FOR NEXT PRIORITY
	CAIG	P1,PRIMAX	;DID ALL THE PRIORITIES YET?
	JRST	CLSLOP		;NO, MAKE ANOTHER PASS WITH NEW PRIORITY
				;YES, FALL INTO CODE TO FINISH UP
;HERE WHEN ALL FUNCTIONS ARE FINISHED



KILDON:	TXNE	F,FR.CCL	;WERE WE RUN FROM A CCL FILE?
	JRST	CCLFIN		;YES, GO DO DIFFERENT STUFF
	TXNE	F,FR.XIT	;WERE WE TOLD TO EXIT WHEN ALL DONE?
	JRST	KILXIT		;YES, GO QUIT
	TXNE	F,FR.ATT	;DID WE ATTACH A USER TO OUR TTY?
	JRST	LOGOFF		;YES, THEN LOG OUT
	OUTSTR	[ASCIZ/
/]				;NO, THEN SPACE DOWN
	JRST	CMMD		;AND GET A NEW COMMAND


CCLFIN:	MOVE	T1,ERRCNT	;GET COUNT OF ERRORS WE HAD
	HRRM	T1,.JBERR	;SAVE IT FOR PROGS TO READ LATER
	JUMPE	T1,NOERRS	;JUMP IF NO ERRORS AT ALL
	TXNE	F,FL.TCR	;USER NOT EVER WANT ERROR FILE?
	SKIPN	RUNBLK		;OR WE ARE NOT GOING TO RUN ANYTHING?
	JRST	NOERRS		;YES, DON'T WRITE ONE THEN
	CALL	WRTERR		;NO, THEN GO WRITE ERROR FILE

NOERRS:	SKIPE	RUNBLK		;WERE WE GIVEN A RUN UUO TO DO?
	JRST	RUNUUO		;YES, GO DO THAT
	TXNN	F,FR.XIT	;NO, WERE WE TOLD TO EXIT?
	TXNN	F,FR.ATT	;OR DID WE NOT ATTACH A JOB?
	JRST	KILXIT		;YES, THEN JUST EXIT
	JRST	LOGOFF		;NO, THEN LOG OUT


RUNUUO:	MOVE	T1,[RUN T2,]	;GET A RUN UUO
	TXNE	F,FR.PHY	;USER WANT IT DONE PHYSICAL ONLY?
	TXO	T1,UU.PHY	;YES, SET THE BIT
	MOVS	T2,RUNBLK	;GET THE RUNOFFSET FOR THE RUN
	HRRI	T2,RUNBLK+1	;AND ADDRESS OF THE RUN BLOCK
	XCT	T1		;DO THE RUN UUO
	 TXNN	F,FR.XIT	;IT FAILED, USER WANTS TO EXIT?
	JRST	LOGOFF		;NO, THEN GO LOG OUT
	OUTSTR	[ASCIZ/
? Run uuo failed to user program
/]				;YES, THEN COMPLAIN ABOUT THE FAILURE
	JRST	KILXIT		;AND GO EXIT
	SUBTTL	ROUTINES CALLED BY THE FUNCTIONS



;THE FOLLOWING ROUTINES ARE CALLED TO PROCESS (OR AT LEAST SET UP)
;THE FUNCTIONS AS THEY NEED TO BE DONE.  ALL ARE CALLED BY CALL ROUTINE
;AND RETURN WITH A RET.  ALL THE TEMP AC'S ARE USED.




DSPXIT:	TXOA	F,FR.XIT	;REMEMBER TO EXIT WHEN ALL DONE
DSPFLG:	HLL	F,(P2)		;SET THE FLAGS AS THE USER WANTS
DSPEND:	RET			;AND THEN RETURN


DSPRUN:	MOVE	T1,(P2)		;GET FLAGS
	TXNE	T1,FF.PHY	;WANT PHYSICAL ONLY RUN?
	TXOA	F,FR.PHY	;YES, REMEMBER THAT
	TXZ	F,FR.PHY	;NO, THEN CLEAR IT
	MOVSI	T1,1(P2)	;SET UP ADDRESS TO BLT FROM
	IORI	T1,RUNBLK	;AND ADDRESS TO BLT TO
	BLT	T1,RUNBLK+6	;COPY THE RUN BLOCK TO SAFE AREA
	RET			;AND THEN RETURN


DSPATT:	MOVE	T1,(P2)		;GET FLAGS
	TXNN	T1,FF.UMA	;WANT ATTACHES IN USER MODE?
	TXZA	F,FR.UMA	;NO, CLEAR BIT
	TXO	F,FR.UMA	;YES, SET BIT FOR LATER
	MOVEI	T1,DOATT	;GET ADDRESS OF ATTACH ROUTINE
	PJRST	SETLGI		;AND SET FOR REQUIRED JOBS


DSPSTP:	MOVEI	T1,DOSTOP	;GET FUNCTION DISPATCH ADDRESS
	PJRST	SETLGI		;AND GO PROCESS IT


DSPKIL:	MOVEI	T1,DOKILL	;GET ADDRESS OF ROUTINE
	PJRST	SETLGI		;AND GO SET IT FOR JOBS


DSPDET:	MOVEI	T1,DODET	;GET ADDRESS FOR DOING DETACH
	PJRST	SETLGI		;AND GO SETUP ALL JOBS


DSPZAP:	MOVEI	T1,DOZAP	;GET ADDRESS FOR DOING ZAP
	PJRST	SETLGO		;AND SETUP FOR THOSE JOBS
DSPNOT:	MOVE	T1,1(P2)	;SETUP ARGUMENT
	MOVEI	T2,NOTDO	;AND ADDRESS OF ROUTINE
	CALL	FNDJOB		;LOOP OVER ALL SELECTED JOBS
	RET			;DONE


NOTDO:	TXNE	F,FR.WLD	;DOING ONLY A SINGLE JOB?
	SKIPN	2(P2)		;OR NO PPN WAS SPECIFIED?
	JRST	CLRACT		;YES, THEN CLEAR THE ACTION
	MOVSI	T1,(J)		;GET READY
	IORI	T1,.GTPPN	;TO READ PPN OF JOB
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CALL	PPNCHK		;SEE IF JOB HAS RIGHT PPN
	 RET			;NO, LEAVE IT ALONE THEN

CLRACT:	SETZM	ACTION(J)	;CLEAR THE ACTION FOR THE JOB
	SETZM	TIMES(J)	;AND THE TIMES
	SETZM	PPNS(J)		;AND THE PPN
	RET			;AND DO FOR ALL JOBS



DSPMEA:	TXNN	F,FR.OPR	;ARE WE PRIVILEGED?
	 ERROR	MCI		;NO, THEN THIS IS ILLEGAL
	TXO	F,FR.MEA	;YES, REMEMBER TO BE MEAN
	RET			;RETURN
	SUBTTL	ROUTINES TO SETUP ACTIONS ON JOBS



;THESE TWO ROUTINES ARE CALLED TO SETUP AN ACTION ON THE DESIRED JOBS.
;ONE ROUTINE HANDLES THE FUNCTIONS FOR LOGGED-IN JOBS, AND THE OTHER
;FOR LOGGED-OUT JOBS.  WHAT WE DO IS STORE THE ADDRESS OF THE PROPER
;ROUTINE INTO THE ACTION TABLE FOR ALL JOBS WE WERE TOLD TO GET.
;WE ALSO PRIVILEGE CHECK TO SEE IF THE USER CAN REALLY GET THE JOB HE
;SAYS TO GET.  CALLS ARE:
;
;	MOVEI	P2,POINTER	;SETUP POINTER TO DATA AREA
;	MOVEI	P3,FUNCTION	;AND THE FUNCTION
;	MOVEI	T1,ADDRESS	;AND ADDRESS WHERE ACTION IS TO GO
;	CALL	SETLG?		;CALL SETLGI OR SETLGO
;	(RETURN)		;ALL JOBS REQUIRED ARE SET UP
;
;USES AC'S  J, JS, AND ALL TEMP AC'S.



;ROUTINE TO HANDLE LOGGED-IN JOBS:


SETLGI:	CALL	SAVE1		;SAVE AN AC
	MOVEI	P1,(T1)		;AND REMEMBER THE ACTION ADDRESS
	MOVE	T1,1(P2)	;GET ARGUMENT
	MOVEI	T2,LGIDO	;AND ROUTINE TO CALL
	CALL	FNDJOB		;LOOP OVER ALL SELECTED JOBS
	TXNN	F,FR.FND	;DID WE FIND ANY JOBS?
	 ERROR	NJF		;NO, NO SUCH JOBS
	RET			;DONE

LGIDO:	CAMN	J,MYJOB		;TRYING TO HURT MY JOB?
	 ERROR	CHM		;YES, ERROR
	MOVSI	T1,(J)		;GET SET
	IORI	T1,.GTPPN	;TO GET PPN OF JOB
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CALL	PPNCHK		;THIS PPN MATCH PPN IN FUNCTION BLOCK?
	 PJRST	CHKPDM		;NO, GO SEE IF WE DESERVE AN ERROR
	MOVEM	T1,PPNS(J)	;WANT THIS JOB, STORE PPN IN TABLE
	CALL	PRIVCK		;SEE IF I AM PRIVILEGED TO GET THIS GUY
	 ERROR	CHP		;NO, ERROR
				;IF YES FALL INTO SETFIN ROUTINE
;HERE IF ALLOWED TO DO SOMETHING TO THIS JOB, TO SET IT UP


SETFIN:	MOVSI	T1,(J)		;GET SET
	IORI	T1,.GTJLT	;TO GET TIME JOB INITIALIZED
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;CAN'T
	MOVEM	T1,TIMES(J)	;STORE THE TIME
	MOVEM	P1,ACTION(J)	;AND STORE THE ACTION TO BE DONE
	TXO	F,FR.NDS!FR.FND	;SCHEDULER NEEDED AND FOUND JOB TO ACT ON
	RET			;AND RETURN





;ROUTINE TO HANDLE LOGGED-OUT JOBS:


SETLGO:	CALL	SAVE1		;SAVE AN AC
	MOVEI	P1,(T1)		;COPY HIS ARGUMENT INTO IT
	TXO	P1,STS.LO	;SET BIT TO SAY DOING LOGGED OUT JOB
	MOVE	T1,1(P2)	;GET THE ARGUMENT
	MOVEI	T2,LGODO	;AND ROUTINE TO CALL
	CALL	FNDJOB		;LOOP OVER ALL SELECTED JOBS
	TXNN	F,FR.FND	;DID WE FIND ANY JOBS?
	 ERROR	NJF		;NO, NO SUCH JOBS
	RET			;DONE


LGODO:	TXNN	JS,JB.ULI	;IS THE JOB LOGGED IN?
	JRST	SETLO1		;NO, PROCEED
	TXNN	F,FR.WLD	;DOING WILDCARD JOBS?
	 ERROR	CZL		;NO, THEN HAVE AN ERROR
	RET			;YES, THEN GO ON TO NEXT JOB


SETLO1:	TXNN	F,FR.MEA	;BEING MEAN?
	TXNN	F,FR.WLD	;DOING A WILD ZAP?
	TXNN	F,FR.OPR	;AND ARE WE THE OPERATOR?
	TXNN	JS,JB.TTY	;OR IS THE JOB DETACHED?
	PJRST	SETFIN		;YES, THEN GO SET THE JOB ACTION
	TXNN	F,FR.WLD	;DOING A MANY JOB LOOP?
	 ERROR	CZD		;NO, THEN IS AN ERROR
	RET			;OTHERWISE JUST RETURN
	SUBTTL	ROUTINE TO LOOP OVER JOBS SELECTED BY AN ARGUMENT



;CALL:
;	MOVE	T1,ARG		;SET UP THE ARGUMENT
;	MOVEI	T2,ROUTINE	;AND ROUTINE TO CALL
;	CALL	FNDJOB		;CALL ROUTINE FOR EVERY SPECIFIED JOB
;	(RETURN)		;ALL DONE
;
;THE SPECIFIED ROUTINE IS CALLED FOR EVERY SELECTED JOB NUMBER, WITH
;AC J CONTAINING THE JOB NUMBER AND JS CONTAINING THE STATUS OF THE JOB.
;ALSO, FR.WLD IS SET IF MULTIPLE JOBS ARE BEING CONSIDERED, AND FR.FND
;IS CLEARED ON THE CALL TO FNDJOB.



FNDJOB:	TXZ	F,FR.FND	;CLEAR SOME FLAGS FIRST
	MOVEM	T2,FNDSUB	;REMEMBER ROUTINE TO CALL
	SETZ	T2,		;ASSUME NO MATCH YET
	CAIN	T1,VL.ALL	;WANTS ALL JOBS?
	MOVEI	T2,CPOPJ	;YES, GET ROUTINE
	CAIN	T1,VL.DET	;WANTS DETACHED JOBS?
	MOVEI	T2,FDRDET	;YES, GET ROUTINE
	CAIN	T1,VL.REM	;WANTS REMOTE JOBS?
	MOVEI	T2,FDRREM	;YES, GET ROUTINE
	MOVEM	T2,FNDDSP	;REMEMBER IT
	JUMPE	T2,FNDJAL	;PROCEED IF NOT ONE OF THEM
	MOVE	T1,HGHJOB	;ONE OF THEM, GET HIGHEST JOB
	HRLI	T1,1		;AND LOWEST JOB
FNDJAL:	TLNE	T1,-1		;SPECIFYING A RANGE OF JOBS?
	JRST	FNDMLT		;YES, GO LOOP OVER THE RANGE
	CAIGE	T1,.UXTRM	;ARGUMENT SEEM LIKE A TTY?
	PJRST	FNDAJB		;NO, GO HANDLE A JOB NUMBER
	MOVEI	T2,-.UXTRM(T1)	;YES, GET JUST THE TTY NUMBER
	CAMLE	T2,HGHTTY	;IS IT LEGAL?
	 ERROR	ITN		;NO, ERROR THEN
	MOVEI	T2,(T1)		;GET COPY OF IOINDEX
	DEVTYP	T1,UU.PHY	;FIND OUT SOME INFO ON THE TTY
	 ERROR	DTF		;CAN'T
	LDB	T1,[POINT 9,T1,26]	;OK, GRAB JOB WHICH OWNS TTY
	SKIPE	T3,T1		;SEE IF TTY IS OWNED BY SOMEONE
	TRMNO.	T3,		;AND SEE IF JOB IS ATTACHED
	 ERROR	NJT		;NO, THEN BAD TTY
	CAIE	T3,(T2)		;IS JOB REALLY ON THAT TTY?
	 ERROR	NJT		;NO, THEN AGAIN IS WRONG
				;YES, THEN FALL INTO ROUTINE TO CHECK JOB
;HERE TO SEE IF A PARTICULAR JOB IS TO BE DONE


FNDAJB:	SKIPE	J,T1		;SEE IF JOB NUMBER IS LEGAL
	CAMLE	J,HGHJOB
	 ERROR	JNI		;NO, IS ILLEGAL
	TXZ	F,FR.WLD	;NOT DOING MULTIPLE JOBS
	CALL	FNDSTS		;GET STATUS OF THE JOB
	TXNE	F,FR.ERR	;ERROR OCCURRED?
	RET			;YES, IGNORE THIS JOB
	TXNN	JS,JB.UJA	;IS JOB ASSIGNED?
	 ERROR	JNA		;NO, ERROR
	CALL	@FNDSUB		;CALL ROUTINE WITH THIS DATA
	RET			;AND RETURN





;HERE WHEN POSSIBLY GIVEN A RANGE OF JOBS:


FNDMLT:	HLRZ	T2,T1		;GET ONE END OF RANGE
	HRRZ	T1,T1		;AND THE OTHER END
	CAMN	T1,T2		;SPECIFYING JUST ONE JOB?
	JRST	FNDAJB		;YES, GO TO OTHER CODE
	CAMLE	T1,T2		;IS RANGE BACKWARDS?
	EXCH	T1,T2		;YES, SWAP TO BE IN ORDER
	SOSL	T1		;BACK OFF ONE AND RANGE CHECK
	CAMLE	T2,HGHJOB	;BEFORE PROCEEDING
	 ERROR	JNI		;NOPE, FAIL
	MOVEM	T1,FNDCNT	;REMEMBER INITIAL JOB NUMBER
	MOVEM	T2,FNDMAX	;AND HIGHEST JOB NUMBER

FNDALN:	AOS	J,FNDCNT	;INCREMENT TO NEXT POSSIBLE JOB
	CAMLE	J,FNDMAX	;REACHED END OF RANGE YET?
	RET			;YES, DONE
	TXO	F,FR.WLD	;REMEMBER DOING WILD SEARCH
	CAMN	J,MYJOB		;IS THIS MY JOB?
	JRST	FNDALN		;YES, IGNORE IT
	CALL	FNDSTS		;NO, GET THE STATUS OF THE JOB
	TXNN	F,FR.ERR	;AN ERROR?
	TXNN	JS,JB.UJA	;OR THE JOB IS NOT IN USE?
	JRST	FNDALN		;YES, GO TO NEXT JOB
	SKIPE	T1,FNDDSP	;ANY ROUTINE TO CALL?
	CALL	(T1)		;YES, SEE IF WE WANT THIS JOB
	 CALL	@FNDSUB		;YES, CALL ROUTINE BACK TO PROCESS JOB
	JRST	FNDALN		;LOOK AT NEXT ONE
;ROUTINES TO DECIDE IF WE SHOULD LOOK AT THIS JOB.  SKIP RETURN IF NO.



FDRDET:	TXNE	JS,JB.TTY	;IS JOB DETACHED?
	AOS	(P)		;NO
	RET			;YES

FDRREM:	TXNN	JS,JB.TTY	;IS JOB DETACHED?
	RETSKP			;YES, THEN IS NOT REMOTE
	MOVEI	T1,(JS)		;GET TERMINAL
	GETLCH	T1		;OBTAIN INFORMATION
	TXNN	T1,GL.REM	;IS THE LINE REMOTE?
	AOS	(P)		;NO
	RET			;YES
	SUBTTL	SUBROUTINES TO DO THE CRUMPING FUNCTIONS



;ALL OF THESE ROUTINES ARE CALLED FROM THE SCHEDULER.  IF AN ERROR OCCURS IN
;THESE ROUTINES, THE OTHER PROCESSES ARE NOT AFFECTED AND WILL CONTINUE
;TO RUN.  ONLY WHEN ALL PROCESSES ARE DONE WILL THE SCHEDULER RETURN.




;HERE TO STOP A JOB:


DOSTOP:	CALL	TTYSTP		;TRY TO STOP HIM IF HE IS ON A TTY
	 JRST	DETSTP		;FAILED, GO SEE WHY
DONSTP:	TELL	Job $1$2 stopped
	RET			;ALL DONE

DETSTP:	TXNE	JS,JB.TTY	;IS HE DETACHED?
	 ERROR	CSJ		;NO, THEN FAILED TO STOP HIM
	CALL	GETPTY		;NOW GET A PTY
	CALL	CHECK		;MAKE SURE CAN STILL CRUMP HIM
	TXNE	JS,JB.TTY	;IN TIME WE WAITED, DID HE ATTACH BACK?
	JRST	[CALL RELPTY	;YES, RELEASE PTY AGAIN
		 JRST DOSTOP]	;AND STOP HIM ON HIS NEW TTY
	CALL	PTYATT		;OK, PUT HIM ON THE PTY
	CALL	PTYSTP		;STOP HIM BY TYPING ^C'S
	 ERROR	CSJ		;CAN'T DO IT, DIE
	JRST	DONSTP		;OK, GO SAY ALL DONE







;HERE TO ZAP A NOT LOGGED IN JOB:


DOZAP:	CALL	CHECK		;SEE IF WE CAN CRUMP ON THIS PERSON
	CALL	GETPTY		;YES, GET A PTY
	CALL	CHECK		;SEE IF STILL CAN CRUMP HIM
	CALL	PTYATT		;YES, ATTACH JOB TO IT
	CALL	PTYSTP		;TRY TO STOP IT (PROBABLY KILLING IT)
	 JFCL			;IF FAILED, HOPE FOR A MIRACLE
	MOVEI	T1,[ASCIZ/KJOB
/]				;GET STRING TO BE TYPED
	CALL	PTYSTR		;KILL THE JOB
	MOVEI	T1,ZAPSLP	;SET UP TO WAIT
	CALL	SCHED		;GIVE TIME FOR JOB TO GO AWAY
	CALL	CHECK		;SEE IF GONE YET
	ERROR	CZJ		;NO, THEN FAILED
;HERE TO ATTACH A JOB TO OUR TTY:


DOATT:	CALL	CHECK		;SEE IF REALLY CAN ATTACH THIS JOB
	AOS	ATTCNT		;YES, ADD 1 TO COUNT OF JOBS WANTING ATTACHING
	SETZ	T1,		;SET UP A SLEEP TIME OF ZERO
	CALL	SCHED		;RUN ALL OTHER PROCESSES BEFORE PROCEEDING
	SOSN	T1,ATTCNT	;DECREMENT COUNT AND SEE IF JUST 1 JOB TO DO
	JRST	ATTHER		;YES, GO DO IT
	JUMPL	T1,CPOPJ	;MULTIPLE JOBS, QUIT IF SOMEONE COMPLAINED
	SETZM	ATTCNT		;NO, THEN IT IS UP TO US, ZAP THE COUNT
	ERROR	MJA		;AND COMPLAIN ABOUT MULTIPLE JOBS

ATTHER:	GETLIN	T1,		;GET MY TTY NAME
	TLNN	T1,-1		;TO SEE IF I AM DETACHED
	 ERROR	IAD		;YES, HARD TO ATTACH WHEN WE ARE DETACHED
	CALL	CHKDET		;OK, SEE IF I AM ALLOWED TO DETACH
	CALL	CHECK		;MAKE SURE HE IS STILL OK
	TXNN	F,FR.MEA	;WANT TO BE MEAN?
	TXNN	JS,JB.TTY	;IS IS THE JOB DETACHED?
	JRST	DOATHR		;YES, CAN PROCEED QUICKLY
	CALL	TTYSTP		;ON A TTY, STOP HIM FIRST
	 JFCL			;FAILED, NOT TOO IMPORTANT
DOATHR:	TELL	Attaching job $1$2
	CALL	CRLF		;TYPE AN EXTRA CRLF
	MOVEI	C,"."		;GET A "MONITOR DOT"
	TXNN	F,FR.UMA	;ATTACH TO ME DONE IN MONITOR MODE?
	PUTCHR			;YES, GIVE THE DOT TOO THEN
	CALL	CHKDET		;MAKE SURE I CAN STILL BE DETACHED
	CALL	CHECK		;AND HE CAN STILL BE ATTACHED
	CALL	TTYATT		;OK, BRING HIM TO MY TTY, DETACHING ME
	TXO	F,FR.ATT	;REMEMBER WE HAVE DONE THIS
	RET			;RETURN
;HERE TO DETACH A JOB FROM ITS TTY:


DODET:	CALL	CHECK		;MAKE SURE CAN GET THIS GUY
	TXNN	JS,JB.TTY	;IS HE ALREADY DETACHED?
	JRST	DONDET		;YES, NOTHING TO DO REALLY
	TXNN	F,FR.MEA	;WANT TO ME MEAN?
	CALL	TTYSTP		;NO, THEN TRY TO STOP THE JOB FIRST
	 JFCL			;FAILED, NOT TOO IMPORTANT
	CALL	DETJOB		;THEN DETACH HIM FROM HIS TTY
DONDET:	TELL	Job $1$2 detached
	RET			;DONE






;HERE TO KILL OFF A JOB WHICH IS LOGGED IN:


DOKILL:	CALL	CHECK		;SEE IF CAN CRUMP ON THE USER
	CALL	DAECHK		;CHECK FOR DAEMON
	CALL	GETPTY		;GO GET A PTY NOW
	CALL	CHECK		;AND SEE IF WE CAN STILL GET HIM
	TXNN	JS,JB.TTY	;IS HE DETACHED?
	JRST	DETKIL		;YES, SKIP THE TTY STUFF THEN
	CALL	TTYSTP		;TRY TO STOP THE USER
	 JFCL			;FAILED, HOPE PTY STOPPING ROUTINE WORKS
DETKIL:	CALL	PTYATT		;NOW PUT THE USER ON OUR PTY
	CALL	PTYSTP		;TRY ONCE MORE TO STOP HIM IF IT IS NEEDED
	 ERROR	JIS		;IF CAN'T DO IT, THEN COMPLAIN AND DIE
	PJRST	KJOB		;AND GO TRY TO LOG HIM OUT
	SUBTTL	ROUTINE TO LOG OUT THIS JOB



;WE GET HERE WHEN IT IS DESIRED THAT WE LOG OURSELVES OUT.  THIS
;IS BECAUSE WE WERE ON A PTY CONTROLLED BY KILL, OR THE USER'S
;RUN UUO BACK TO SOMETHING DIED, OR WE JUST GOT DONE ATTACHING A
;JOB TO THE USER'S TTY.  WE NEVER RETURN FROM HERE



LOGOFF:	MOVE	T1,[.TCRDD,,LGODEL]	;SET UP TO DELETE TMPCOR
	TMPCOR	T1,			;DO IT
	 JFCL				;NOT THAT IMPORTANT YET
	MOVE	T1,[.TCRWF,,LGOWRT]	;NOW SET UP TO WRITE LGO FILE
	TMPCOR	T1,			;DO IT
	 TELL	Unable to write TMPCOR file for LOGOUT - proceeding anyway
	SETZM	.JBSA		;ALLOW NO RESTARTS NOW
	MOVEI	T1,1		;NOW SHRINK LOW SEG ALL WE CAN
	CORE	T1,		;SO .R KILL HUGE  WILL NOT BLOW US UP
	 JFCL			;WE TRIED
	MOVEI	T1,LGORNB	;SET UP FOR THE RUN
	RUN	T1,UU.PHY	;TRY TO RUN LOGOUT NOW
	 OUTSTR	[ASCIZ/? RUN uuo to LOGOUT failed !!!!
/]				;CAN'T !! TELL HIM
	EXIT			;THEN EXIT FOR GOOD




LGOWRT:	SIXBIT	/LGO/		;NAME FOR LOGOUT'S TMPCOR FILE
	IOWD	LGOLEN,LGOTCR	;LENGTH, ADDRESS OF TMPCOR FILE

LGOTCR:	BLOCK	1		;UNUSED WORD HERE
	SIXBIT	/NUL/		;DEVICE FOR LOG FILE
LGODEL:	BLOCK	6		;UNUSED WORDS
	EXP	MYNAME		;FILENAME FOR LOG FILE
	BLOCK	6		;MORE UNUSED WORDS
	EXP	-1		;WHOLE POINT OF WRITING TMPCOR
				;FILE - DO NOT CALL QMANGR FLAG

	LGOLEN==.-LGOTCR	;LENGTH OF TMPCOR FILE TO WRITE



LGORNB:	SIXBIT	/SYS/		;THE RUN BLOCK FOR LOGOUT
	SIXBIT	/LOGOUT/	;WHICH IS RUN FROM SYS, PHYSICAL ONLY
	BLOCK	4		;EXTRA ARGUMENTS NOT NEEDED
	SUBTTL	ROUTINE TO LOG OFF A JOB WHICH IS STOPPED ON A PTY



;THIS ROUTINE IS USED TO LOG OUT A LOGGED IN JOB WHICH HAS BEEN ATTACHED
;TO A PTY OF OURS, AND IS STOPPED.  CALL IS:
;
;	MOVE	J,JOB		;GET JOB NUMBER
;	MOVEI	IO,CHANNEL	;AND CHANNEL OF PTY JOB IS ON
;	CALL	KJOB			;LOG OUT THE JOB
;	(NEVER RETURNS)		;DON'T GET HERE
;
;USES MANY AC'S, AND CAN WAIT A LONG TIME TO FINISH.




KJOB:	CALL	CHECK		;SEE IF CAN STILL CRUMP ON THIS GUY
	CALL	SAVE1		;SAVE ONE AC
	CALL	PTYEAT		;EAT ANY STUFF THAT MAY BE THERE
	MOVE	T1,[%SIQSR]	;GET READY
	GETTAB	T1,		;SEE IF GALAXY IS RUNNING
	 SETZ	T1,		;OLD SYSTEM, NO GALAXY
	SKIPN	T1		;IS SYSTEM RUNNING GALAXY-MODE?
	TROA	T1,LG2TXT	;NO, GET TEXT TO RUN OURSELF
	MOVEI	T1,LG1TXT	;YES, GET TEXT TO RUN LOGOUT DIRECTLY
	CALL	PTYSTR		;SEND IT TO THE PTY
	MOVEI	T1,RUNSLP	;SET UP TO WAIT
	CALL	SCHED		;GIVE PROG A CHANCE TO START RUNNING
	MOVEI	P1,KJOTRY	;SET UP A COUNT FOR WAITING WITH

LGOLOP:	CALL	CHECK		;SEE IF HE IS GONE YET
	CALL	PTYEAT		;NOT YET, EAT ANY OUTPUT THERE
	TXNN	JS,JB.RUN!JB.CMW	;IS THE JOB RUNNING?
	 ERROR	JNR		;NO, JOB IS NOT RUNNING
	TXNE	JS,JB.UDI	;IS PROGRAM IN A TI WAIT?
	 ERROR	TIW		;YES, JOB IS IN A TTY INPUT WAIT
	MOVEI	T1,(IO)		;GET READY
	JOBSTS	T1,		;FIND OUT THE JOBSTS OF JOB ON OUR PTY
	 ERROR	JSF		;CAN'T
	CAIN	J,(T1)		;IS JOB ON THE PTY THE JOB WE WANT?
	JRST	LGOK1		;YES, PROCEED
	CALL	CHECK		;NO, SEE IF STILL THERE (RACE CONDITION)
	ERROR	NOP		;YES, JOB IS NOT ON OUR PTY
LGOK1:	MOVSI	T1,(J)		;GET SET TO GET PROGRAM NAME
	IORI	T1,.GTPRG
	GETTAB	T1,		;FIND IT OUT
	 ERROR	GTF		;FAILED
	CAME	T1,['LOGOUT']	;IS IT THE PROGRAMS WE EXPECT?
	CAMN	T1,[MYNAME]
	JRST	LGOK2		;YES, PROCEED
	CALL	CHECK		;NO, CHECK RACE CONDITION THEN
	 ERROR	NRL		;STILL THERE BUT NOT RUNNING LOGOUT
LGOK2:	SOSG	P1		;STILL HAVE MORE COUNTS LEFT?
	 ERROR	JIS		;NO, THEN JOB IS STUCK RUNNING SOMETHING
	MOVEI	T1,KJOSLP	;STILL OK, SET UP A WAIT
	CALL	SCHED		;WAIT A WHILE
	JRST	LGOLOP		;AND CHECK AGAIN




;TEXT USED TO LOG OUT JOBS RUNNING UNDER A GALAXY SYSTEM.


LG1TXT:	TEXT	<KJOB/N
>



;TEXT USED TO LOG OUT JOBS NOT RUNNING UNDER GALAXY.  THE PURPOSE OF
;RUNNING OURSELF IS: 1) FASTER THAN KJOB, 2) PREVENTS QUEUEING OF FILES


LG2TXT:	TEXT	<DEASSIGN
R KILL
>
	SUBTTL	ROUTINE TO STOP A JOB WHICH ON A REGULAR TTY



;THIS ROUTINE IS USED TO STOP A JOB WHICH IS ON A RANDOM TTY, AND MIGHT
;BE RUNNING STILL.  OUR DUTY IS TO STOP IT, AND ALSO TAKE STEPS TO
;POSSIBLY MAKE THE JOB STAY STOPPED.  WE CLEAR THE INPUT BUFFER OF THE
;TTY, AND CLEAR THE PROGRAM TO RUN VALUE.  CALL IS:
;
;	MOVEI	J,JOB		;SET UP JOB NUMBER TO STOP
;	CALL	TTYSTP		;STOP THE JOB
;	 (FAILED RETURN)	;COULDN'T STOP IT
;	(NORMAL RETURN)		;DID IT
;
;USES AC'S  T1 - T4.




TTYSTP:	PUSH	P,[EXP TRMUSL]	;PUT ROUTINE TO UNSLAVE TTY ON TOP
	CALL	SAVE2		;SAVE A COUPLE OF AC'S
	MOVEI	P1,STPTRY	;SETUP THE COUNT OF TRIES
	TXNE	F,FR.MEA	;WANT TO BE MEAN IN STOPPING JOBS?
	MOVEI	P1,STPHLT	;YES, SET UP SO DON'T ALLOW ^C TRAPPING
	SETZ	P2,		;CLEAR OUR FLAGS

TTYSTL:	CALL	CHECK		;SEE IF CAN STILL CRUMP ON THIS GUY
	CALL	CLRRUN		;CLEAR THE PROGRAM-TO-RUN WORD
	CALL	TRMCLR		;CLEAR TTY'S INPUT BUFFER
	TXNN	JS,JB.RUN!JB.CMW	;JOB STILL RUNNING?
	RETSKP			;NO, THEN GIVE SUCCESSFUL RETURN
	TXNN	JS,JB.TTY	;IS THE JOB ON A TTY?
	RET			;NO, WE CAN DO NOTHING
	SOJL	P1,CPOPJ	;RETURN NOW IF TOO MUCH TIME HAS GONE BY
	TRCE	P2,1		;IS THIS AN EVEN NUMBERED TIME THROUGH?
	JRST	SKPFRC		;NO, SKIP THE FRCUUO THIS TIME
	MOVEI	T1,T2		;SET UP FOR THE FRCUUO
	MOVE	T2,['.HALT ']	;ASSUME WILL BE MILD TO THE JOB

	IFN	FTHALT,<	;IF WE CHECK FOR MEAN HALT
	TXNE	JS,JB.UML	;IS JOB AT MONITOR LEVEL?
	JRST	MEANST		;YES, THEN DO HALT NOW
	CAIGE	P1,STPIWH	;TIME TO CHECK FOR TI STATE?
	TXNN	JS,JB.UDI	;YES, JOB IN TI WAIT?
	CAIGE	P1,STPHLT	;OR IS IT TIME TO BE MEAN ANYWAY?
MEANST:	MOVE	T2,['HALT  ']	;YES, THEN SET UP THE UNTRAPPABLE HALT
>
	MOVEI	T3,(J)		;SETUP THE JOB NUMBER
	FRCUUO	T1,		;DO THE FRCUUO ON THE JOB
	 JFCL			;IGNORE - THEY FAIL RANDOMLY ANYWAY
SKPFRC:	MOVEI	T1,STPSLP	;GET A SLEEP TIME
	CALL	SCHED		;WAIT FOR THE JOB TO RESPOND TO THE HALT
	JRST	TTYSTL		;AND THEN LOOP
	SUBTTL	ROUTINE TO STOP A JOB WHICH IS ON OUR PTY


;THIS ROUTINE STOPS A JOB WHICH WE HAVE JUST ATTACHED TO A PTY OF OURS.
;THIS IS USED MAINLY TO CATCH DETACHED JOBS WHICH WE WANTED TO STOP, BUT
;IT ALSO GIVES US A LAST MINUTE CHANCE TO STOP A JOB WHICH WAS ON A TTY
;BUT WE WEREN'T ABLE TO STOP.  CALL IS:
;
;	MOVE	J,JOB		;GET JOB
;	CALL	PTYSTP		;STOP THE USER NOW
;	 (ERROR RETURN)		;NOT ABLE TO STOP HIM
;	(NORMAL RETURN)		;HE IS NOW STOPPED AND IS ON THE PTY
;
;USES  T1, T2, AND T3.  WE COULD WAIT QUITE A WHILE BEFORE RETURNING.



PTYSTP:	CALL	SAVE2		;SAVE SOME ACS
	MOVEI	P1,PSTTRY	;GET A COUNTER FOR ATTEMPTS
	SETZ	P2,		;AND INITIALIZE FLAGS

PTYSTL:	CALL	CHECK		;SEE IF STILL OK TO CRUMP ON GUY
	CALL	CLRRUN		;YES, CLEAR PROGRAM TO RUN
	CALL	PTYEAT		;EAT UP ANY OUTPUT
	TXNN	JS,JB.RUN!JB.CMW	;IS THE JOB STILL RUNNING?
	RETSKP			;NO, THEN ALL DONE
	SOJL	P1,CPOPJ	;IF TOO MANY TRIES, STOP NOW
	TRCE	P2,1		;WANT TO TRY STOPPING THIS TIME?
	JRST	SKPOUT		;NO, WAIT TILL NEXT TIME
	MOVEI	T1,HLTTXT	;GET ADDRESS OF HALT TEXT
	TRCE	P2,2		;TIME FOR JUST PLAIN ^C'S ?
	MOVEI	T1,CTLCS	;YES, GET THAT STRING INSTEAD
	CALL	PTYSTR		;OUTPUT THEM TO THE JOB
SKPOUT:	MOVEI	T1,PSTSLP	;SET UP TO WAIT
	CALL	SCHED		;WAIT FOR JOB TO STOP
	JRST	PTYSTL		;AND CHECK AGAIN TO STOP IT



CTLCS:	BYTE	(7)3,3,3,3	;A FEW CONTROL-C'S TO OUTPUT

HLTTXT:	ASCIZ	/HALT
/				;COMMAND TO STOP
	SUBTTL	SUBROUTINE TO CLEAR PROGRAM TO RUN FOR A JOB



;THIS CLEARS THE PROGRAM TO RUN FOR A JOB.  WITHOUT THIS BEING CLEARED,
;THERE IS NO WAY THAT WE COULD EVER HOPE TO STOP A JOB TO KILL IT.
;ANY ATTEMPT TO STOP A JOB SHOULD COME RIGHT AFTER THIS CALL TO
;MINIMIZE THE CHANCE THE JOB GETS TO RUN AND SET IT AGAIN!!  CALL IS:
;
;	MOVEI	J,JOB		;GET JOB NUMBER
;	CALL	CLRRUN		;CLEAR THE PROGRAM TO RUN FOR THE JOB
;	(RETURN)		;DID IT
;
;WE IGNORE ANY FAILURE OF THE .JBSET, FOR HOPEFULLY IT DOESN'T MATTER MUCH.
;USES AC'S  T1, T2, AND T3.




CLRRUN:	PUSH	P,P1		;SAVE AC SINCE NEED LOTS
	MOVE	P1,[2,,T1]	;GET POINTER FOR .JBSET
	MOVEI	T1,(J)		;GET JOB TO DO SETUUO FOR
	MOVE	T2,[.STPGM,,T3]	;FUNCTION FOR SETUUO, ADDRESS OF ARGS
	SETZB	T3,T4		;WE WANT TO CLEAR IT
	JBSET.	P1,		;DO THE SETUUO TO CLEAR IT
	 JFCL			;WE TRIED, BUT IT ISN'T *VERY* IMPORTANT
	JRST	PPOPJ		;RESTORE P1 AND RETURN
	SUBTTL	SUBROUTINES TO DO TRMOPS TO JOB'S TTYS



;THESE ROUTINES ARE CALLED WHEN WE ARE ATTEMPTING TO STOP A JOB ON
;A TTY, AND WHEN THE JOB IS FINALLY STOPPED.  WE CLEAR THE TTY'S INPUT
;BUFFER WHEN STOPPING THE JOB, OTHERWISE THE MONITOR WILL RESCAN THE
;LAST COMMAND TYPED, AND THE JOB CAN START UP AGAIN !!  WE UNSLAVE
;THE TERMINAL WHEN THE JOB IS STOPPED, SO THAT THE USER CAN TYPE
;COMMANDS TO IT AGAIN.  CALLS ARE:
;
;	MOVEI	J,JOB		;SETUP JOB NUMBER
;	CALL	TRM???		;CALL ROUTINE TO DO TRMOP
;	(RETURN)		;DID IT, RETURN
;
;WE DO NOT GIVE AN ERROR INDICATION IF THE TRMOP FAILS, FOR HOPEFULLY
;THE ERROR IS NOT THAT IMPORTANT ANYWAY, AND WE MAY WIN REGARDLESS.
;USES AC'S  T1 - T4.




TRMCLR:	MOVEI	T3,(JS)		;GET THE TTY NUMBER
	JUMPE	T3,CPOPJ	;IF NONE, THEN CAN'T CLEAR A BUFFER
	MOVEI	T2,.TOCIB	;SETUP FUNCTION TO CLEAR BUFFER
	MOVE	T1,[2,,T2]	;SETUP ARGUMENT
	TRMOP.	T1,		;CLEAR IT
	 RET			;FAILED, NOT THAT IMPORTANT
	RET			;DID IT, RETURN



TRMUSL:	SKIPA			;IF NORMAL ENTRY, DO NOTHING SPECIAL
	AOS	(P)		;BUT IF CALLED WITH OFFSET, PASS IT ON
	MOVEI	T3,(JS)		;GET THE TTY IOINDEX
	JUMPE	T3,CPOPJ	;IF JOB DETACHED, CAN'T UNSLAVE
	MOVEI	T2,.TOSET+.TOSLV	;SETUP THE SLAVE FUNCTION
	MOVE	T1,[3,,T2]	;SETUP ARGUMENT
	SETZ	T4,		;SET FOR SLAVE TO BE TURNED OFF
	TRMOP.	T1,		;UNSLAVE THE TTY
	 RET			;FAILED, TOO BAD
	RET			;WORKED, GREAT
	SUBTTL	SUBROUTINES TO DO ATTACH UUOS



;THIS SUBROUTINE IS USED TO ATTACH THE DESIRED JOB TO A PTY WE HAD
;PREVIOUSLY OPENED.  CALL IS:
;
;	MOVEI	IO,CHANNEL	;GET CHANNEL OF PTY TO USE
;	MOVEI	J,JOB		;AND JOB NUMBER TO BE ATTACHED
;	CALL	PTYATT		;ATTACH JOB TO OUR PTY
;	(RETURN)		;DID IT
;
;DOES NOT RETURN IF ERROR ENCOUNTERED.  ANY SECURITY CHECKS SHOULD BE
;MADE BEFORE CALLING THIS ROUTINE, AS WE DO NO CHECKING.  USES AC T1.





PTYATT:	MOVEI	T1,[BYTE (7)15,12]	;GET A FEW NICE CHARS
	CALL	PTYSTR		;OUTPUT THEM TO INITIALIZE PTY
	MOVEI	T1,(IO)		;GET CHANNEL TO USE
	IONDX.	T1,UU.PHY	;GET IO INDEX OF THE PTY WE ARE USING
	 ERROR	IUF		;CAN'T
	ANDX	T1,UX.UNT	;KEEP ONLY THE UNIT NUMBER
	ADD	T1,PTYTTY	;CONVERT TO CORRESPONDING TTY NUMBER
	MOVSI	T1,<(AT.UMM)>(T1)   ;PUT IN LEFT HALF, WITH GOOD BIT
	IORI	T1,(J)		;THIS JOB TO OUR PTY'S TTY
	ATTACH	T1,		;DO THE ATTACH
	 ERROR	ATF		;CAN'T
	MOVX	T1,STS.AT	;GET FLAG READY
	IORM	T1,ACTION(J)	;REMEMBER WE ATTACHED JOB TO A PTY
	RET			;THEN RETURN
;ROUTINE TO ATTACH THE DESIRED JOB TO OUR TTY IN EITHER MONITOR MODE
;OR USER MODE AS DETERMINED BY THE USER-SET FLAG FF.UMA, AND THEREBY
;DETACHING OURSELF.  CALL IS:
;
;	MOVEI	J,JOB		;SET UP JOB TO ATTACH HERE
;	CALL	TTYATT		;BRING IT HERE
;	(RETURN)		;OK, WE ARE NOW DETACHED
;
;USES ONLY AC T1.  AS ABOVE, SECURITY CHECKS ARE MADE PREVIOUS TO THE CALL.




TTYATT:	MOVE	T1,MYJOB	;SET UP
	TRMNO.	T1,		;FIND OUT MY TTY NUMBER
	 ERROR	IAD		;CAN'T IF I AM DETACHED
	MOVSI	T1,-.UXTRM(T1)	;PUT TTY NUMBER IN LEFT HALF
	IORI	T1,(J)		;AND HIS JOB NUMBER IN RIGHT HALF
	TXO	T1,AT.UMM	;ASSUME MONITOR MODE WANTED
	TXNE	F,FR.UMA	;WANTS USER MODE INSTEAD?
	TXC	T1,AT.UMM!AT.UUM	;YES, SET THAT
	ATTACH	T1,		;DO THE ATTACH
	 ERROR	ATF		;FAILED
	RET			;ALL DONE, RETURN






;ROUTINE TO DETACH A DESIRED JOB. CALL IS:
;
;	MOVEI	J,JOB		;SET UP JOB NUMBER
;	CALL	DETJOB		;DETACH HIM
;	(RETURN)		;DID IT
;
;USES ONLY AC T1.




DETJOB:	MOVEI	T1,(J)		;GET HIS JOB NUMBER
	TRMNO.	T1,		;AND THEN HIS TTY IO INDEX
	 RET			;HE IS ALREADY DETACHED, RETURN NOW
	MOVSI	T1,-.UXTRM(T1)	;PUT TTY IN LEFT HALF, 0 IN RIGHT HALF
	ATTACH	T1,		;DETACH HIM
	 ERROR	ATF		;FAILED, COMPLAIN
	RET			;SUCCESSFUL, RETURN
	SUBTTL	ROUTINES TO CHECK VALIDITY OF THE CRUMPING FUNCTIONS



;THESE SUBROUTINES ARE CALLED VERY OFTEN TO MAKE SURE THAT THE USER IS
;ABLE TO PROCEED WITH THE STOPPING, KILLING, ETC. FUNCTIONS.  WE MAKE
;SURE THAT HE IS NOT TRYING TO "MUNCH" BY STOPPING OTHER PPN'S JOBS,
;OR RIP OFF A JACCT'D PROGRAM, OR OURSELF, ETC.  CALL IS:
;
;	CALL	ROUTINE		;SEE IF OK TO DO SOMETHING
;	(RETURN)		;YES IT IS
;
;NO RETURN IF THE FUNCTION HAS BEEN DISALLOWED.  USES ALL THE TEMP AC'S.




CHECK:	CALL	EXIST		;SEE IF THE JOB IS STILL THERE, FIRST
	SKIPGE	T1,ACTION(J)	;WERE WE SUPPOSED TO BE KILLING LOGGED IN JOB?
	JRST	CHECKD		;NO, GO CHECK LOGGED OUT JOB THEN
	MOVSI	T2,(J)		;OK, SEE IF PPN HAS CHANGED
	IORI	T2,.GTPPN	;SET UP
	GETTAB	T2,		;FIND IT
	 ERROR	GTF		;CAN'T
	CAMN	T2,PPNS(J)	;SAME AS IT SHOULD BE?
	JRST	CHKBAT		;YES, CONTINUE ONWARD
	CALL	EXIST		;CHECK FOR RACE CONDITION
	ERROR	PHC		;STILL THERE, THEN PPN HAS CHANGED

CHKBAT:	IFE	FTBATCH,<	;THIS CHECK IF CAN'T HURT BATCH JOBS
	TXNE	F,FR.OPR	;ARE WE PRIVILEGED?
	JRST	CHKRST		;YES, SKIP THIS CHECK
	MOVSI	T2,(J)		;GET SET
	IORI	T2,.GTLIM	;TO GET BATCH WORD
	GETTAB	T2,		;GET IT
	 ERROR	GTF		;CAN'T
	TXNN	T2,JB.LBT	;IS HE A BATCH JOB?
	JRST	CHKRST		;NO, CAN PROCEED
	CALL	EXIST		;YES, MAKE SURE SAME JOB THOUGH
	ERROR	CHB		;SAME JOB, CAN'T HURT IT THEN
>
CHKRST:	TXNE	T1,STS.AT	;DID WE ATTACH THE JOB TO A PTY?
	RET			;YES, NO MORE CHECKS BECAUSE COULD BE LOGOUT
	TXNN	F,FR.OPR	;ARE WE PRIVILEGED?
	TXNN	JS,JB.UJC	;OR IS THE PROGRAM NOT JACCT'D?
	RET			;YES, NO PROBLEM THEN
	TXNE	JS,JB.TTY	;IS THE JOB DETACHED?
	TXNE	JS,JB.UML	;OR IN MONITOR MODE?
	RET			;YES, OK SINCE HE COULD STOP IT HIMSELF
	TXNE	JS,JB.RUN	;IS THE PROGRAM RUNNING?
	 ERROR	PIJ		;YES, CAN'T TOUCH IT
	RET			;NO, THEN CAN GET JOB



CHECKD:	TXNE	JS,JB.ULI	;IS IT LOGGED IN?
	 ERROR	CZL		;YES, ERROR
	TXNE	F,FR.OPR	;ARE WE PRIVILEGED?
	RET			;YES, CAN KILL ANY NOT LOGGED IN JOB
	TXNN	T1,STS.AT	;WAS JOB ATTACHED TO A PTY?
	TXNN	JS,JB.TTY	;NO, SEE IF DETACHED THEN
	RET			;ON PTY OR DETACHED, OK
	ERROR	CZD		;ERROR, CAN'T KILL IT WHEN ON A TTY
	SUBTTL	SUBROUTINE TO SEE IF A JOB STILL EXISTS



;THIS ROUTINE IS CALLED OCCASSIONALLY TO CHECK TO SEE IF THE JOB WE
;ARE LOOKING AT HAS GONE AWAY.  EVEN IF ANOTHER DIFFERENT JOB WITH THE
;SAME ACCOUNT LOGS IN BETWEEN CHECKS, WE WILL NOT BE FOOLED, BECAUSE
;THE JOB'S LOGGED-IN-TIME WILL HAVE CHANGED.  CALL IS:
;
;	MOVEI	J,JOB		;SAY WHICH JOB TO CHECK
;	CALL	EXIST		;SEE IF STILL THERE
;	(RETURN)		;YES IT IS
;
;NO RETURN IF JOB HAS GONE AWAY.  ONLY USES AC JS, WHICH HAS THE
;JOB'S STATUS WHEN WE RETURN.





EXIST:	CALL	FNDSTS		;GET THE STATUS OF THE JOB
	TXNN	JS,JB.UJA	;IS THE JOB STILL ASSIGNED?
	JRST	BYEJOB		;NO, GO KILL OURSELF
	MOVEM	JS,TEMP1	;SAVE THE STATUS TEMPORARILY
	MOVSI	JS,(J)		;NOW SET UP
	IORI	JS,.GTJLT	;TO GET TIME JOB INITIALIZED
	GETTAB	JS,		;GET IT
	 ERROR	GTF		;CAN'T
	CAME	JS,TIMES(J)	;IS IT THE SAME AS ORIGINALLY?
	JRST	BYEJOB		;NO, THEN TELL HIM JOB IS GONE
	MOVE	JS,TEMP1	;RESTORE STATUS BITS
	RET			;AND RETURN


BYEJOB:	SKIPL	ACTION(J)	;WAS THE JOB LOGGED IN ORIGINALLY?
	 TELL	Job $1$5 logged out
	SKIPGE	ACTION(J)	;HOW ABOUT LOGGED OUT?
	 TELL	Job $1 zapped
	JRST	SCHEDQ		;NOW GO KILL OURSELF SINCE UNNEEDED ANYMORE
	SUBTTL	ROUTINE TO GET THE JOBSTS OF A JOB



;THIS SUBROUTINE RETURNS IN AC JS THE JOBSTS INFORMATION RETURNED BY
;THE JOBSTS UUO, AND A COUPLE OF OTHER EXTRA BITS WHICH ARE NICE TO
;KNOW.  CALL IS:
;
;	MOVEI	J,JOB		;GET THE JOB
;	CALL	FNDSTS		;GET THE JOB STATUS BITS
;	(RETURN)		;GOT THEM
;
;ONLY AC JS IS USED.  CAN BE CALLED FROM SCHEDULER, OR ELSEWHERE.
;IF ELSEWHERE, FLAG FR.ERR INDICATES WHETHER OR NOT WE FAILED.




FNDSTS:	TXO	F,FR.ERR	;ASSUME FAILURE AT FIRST
	MOVSI	JS,(J)		;SET UP
	GETTAB	JS,		;FIND OUT THE JOB STATUS WORD OF THE JOB
	 ERROR	GTF		;CAN'T DO IT
	ANDCMI	JS,-1		;CLEAR THE RIGHT HALF
	TXNE	JS,JSWRUN	;IS JOB RUNNING?
	TXO	JS,(JB.RUN)	;YES, SET FLAG IN RIGHT HALF OF AC
	TXNE	JS,JSWCMW	;IS JOB IN A COMMAND WAIT?
	TXO	JS,(JB.CMW)	;YES, SET THAT FLAG
	HRLZM	JS,TEMP1	;AND STORE IT
	MOVEI	JS,(J)		;SET UP
	TRMNO.	JS,		;SEE WHETHER THE JOB IS ATTACHED OR NOT
	 SETZ	JS,		;NO, INDICATE THAT
	HRRM	JS,TEMP1	;AND STORE THAT INFO TOO
	MOVNI	JS,(J)		;FINALLY SET UP
	JOBSTS	JS,		;GET THE BITS WE CARE ABOUT
	 ERROR	JSF		;CAN'T
	TXZ	JS,JB.RUN!JB.CMW!JB.TTY	;CLEAR PARTS WE USE
	IOR	JS,TEMP1	;AND THEN PUT IN OUR BITS
	TXZ	F,FR.ERR	;CLEAR ERROR FLAG
	RET			;AND RETURN
	SUBTTL	SUBROUTINE TO SEE IF I AM ALLOWED TO DETACH



;THIS SUBROUTINE IS CALLED TO ENFORCE THE RESTRICTIONS ON DETACHING
;MY OWN JOB WITHOUT PRIVILEGES, THAT IS TO MAKE SURE I AM NOT IN
;MONITOR MODE, AND THAT I AM NOT A BATCH JOB. CALL IS:
;
;	CALL	CHKDET		;GO SEE IF I CAN DETACH
;	(RETURN)		;OK
;
;USES AC T1.




CHKDET:	TXNE	F,FR.OPR	;AM I PRIVILEGED?
	RET			;YES, THEN I CAN DETACH MYSELF
	MOVN	T1,MYJOB	;GET SET
	JOBSTS	T1,		;FIND OUT ABOUT MY OWN JOB
	 ERROR	JSF		;CAN'T
	TXNE	T1,JB.UML	;AM I IN MONITOR MODE?
	 ERROR	CDM		;YES, CAN'T DETACH THEN
	HRROI	T1,.GTLIM	;GET READY TO GET BATCH STATUS WORD
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	TXNE	T1,JB.LBT	;AM I A BATCH JOB?
	 ERROR	CDB		;YES, ERROR
	RET			;NO, THEN SAFE TO DETACH
	SUBTTL	SUBROUTINE TO CHECK PRIVILEGES OF A USER



;THIS ROUTINE IS CALLED TO SEE IF WE ARE ALLOWED TO STOP, ATTACH,
;ETC. ANOTHER JOB.  THIS ALSO CHECKS TO SEE IF WE CAN SEND A
;MESSAGE TO ANOTHER JOB.  CALL IS:
;
;	MOVE	T1,PPN		;GET THE PPN WE ARE TALKING ABOUT
;	CALL	PRIVCK		;CAN I DO SOMETHING TO THAT PPN?
;	 (NO RETURN)		;NO, NOT ALLOWED TO
;	(YES RETURN)		;YES, IT IS OK
;
;USES AC'S  T1 - T4.




PRIVCK:	CAME	T1,MYPPN	;IS THAT PPN MY OWN?
	TXNE	F,FR.OPR	;OR AM I PRIVILEGED?
	RETSKP			;YES, GOOD RETURN

	IFN	FTOWNER,<	;IF NOT, MAYBE OK ANYWAY...
	MOVE	T3,T1		;PUT HIS PPN IN THE RIGHT SPOT
	MOVE	T4,MYPPN	;AND MY OWN PPN TOO
	MOVE	T2,[.ACWRI,,<177>]	;WANT TO SEE IF COULD WRITE A FILE
	MOVEI	T1,T2		;PROTECTED HIGH ON HIS ACCOUNT
	CHKACC	T1,		;ASK MONITOR IF WE COULD
	 RET			;DON'T KNOW, ASSUME NOT
	JUMPE	T1,CPOPJ1	;YES, THEN CAN GET THIS GUY
>
	RET			;NO, THEN GIVE NON-SKIP RETURN
	SUBTTL	ROUTINE TO DETERMINE IF I AM PRIVILEGED



;CALLED TO SEE IF WE ARE THE OPERATOR, OR THE EQUIVALENT.  USED
;TO SET THE FR.OPR FLAG.  SETS JACCT IF IT IS NOT ON AND WE CAN
;POKE IT ON.  CALL:
;
;	CALL	CHKOPR		;SEE IF I AM GOD
;	 (YES RETURN)		;YES, I AM
;	(NO RETURN)		;NO, I AM NOT
;
;USES ONLY AC T1.




CHKOPR:	MOVE	T1,[%LDFFA]	;GET READY
	GETTAB	T1,		;FIND OUT THE PPN OF OPERATORS
	 DIE	GTF		;FAILED
	MOVEM	T1,OPRPPN	;REMEMBER THEIR PPN
	CAMN	T1,MYPPN	;IS THAT MY OWN PPN?
	RET			;YES, I AM GOD
	HRROI	T1,.GTPRV	;GET READY
	GETTAB	T1,		;FIND MY PRIVILEGE WORD
	 DIE	GTF		;CAN'T
	TLNN	T1,(JP.POK)	;DOES HE HAVE POKE PRIVILEGES?
	RETSKP			;NO, THEN NOT GODLY

	IFN	FTPOKE,<	;CODE TO TURN ON JACCT IF NECESSARY
	MOVE	T1,[3,,T2]	;SET UP FOR POSSIBLE POKE
	MOVEI	T2,.GTSLF	;SET UP TO GET LOCATION OF TABLE 0
	GETTAB	T2,		;GET IT
	 DIE	GTF		;FAILED
	ADD	T2,MYJOB	;ADD MY JOB NUMBER AS OFFSET
	MOVEI	T2,(T2)		;USE ONLY ADDRESS PART
	HRROI	T3,.GTSTS	;GET READY
	GETTAB	T3,		;READ MY PRIVILEGE WORD
	 DIE	GTF		;WE LOSE
	MOVE	T4,T3		;COPY OLD VALUE
	TLOE	T4,(JSWJCT)	;ALREADY PRIVILEGED?
	RET			;YES, DON'T HAVE TO POKE
	POKE.	T1,		;NO, THEN POKE ON JACCT
	 TELL	% Unable to POKE privileges on
>
	RET			;GIVE PRIVILEGED RETURN
	SUBTTL	ROUTINE TO CHECK FOR DAEMON




;ROUTINE CALLED WHEN LOGGING OUT JOBS TO SEE IF THIS JOB IS DAEMON.
;IF SO, DELAY KILLING THE JOB UNTIL IT IS THE LAST ONE.  OTHERWISE,
;JOBS CAN'T BE LOGGED OUT BECAUSE DAEMON IS GONE.  RETURNS WHEN IT
;IS SAFE TO PROCEED.



DAECHK:	MOVE	T1,SCDCNT	;GET NUMBER OF PROCESSES
	SOJLE	T1,CPOPJ	;RETURN IF WE ARE THE ONLY ONE
	MOVE	T1,PPNS(J)	;GET PPN OF JOB
	CAME	T1,OPRPPN	;IS THIS THE OPERATOR?
	RET			;NO, DON'T WORRY ABOUT DAEMON
	MOVE	T1,['DAEMON']	;GET NAME TO CHECK FOR
	CALL	SYSPRG		;IS THIS DAEMON?
	 RET			;NO, THEN OK TO PROCEED

DAEWAI:	MOVEI	T1,DAESLP	;GET SLEEP TIME
	CALL	SCHED		;WAIT A BIT
	MOVE	T1,SCDCNT	;GET NUMBER OF PROCESSES LEFT
	SOJG	T1,DAEWAI	;IF MORE THAN US, WAIT SOME MORE
	RET			;WE ARE ALONE, RETURN

	SUBTTL	ROUTINE TO CHECK FOR A PROGRAM FROM SYS:



;SUBROUTINE TO SEE IF A PROGRAM IS RUNNING THE DESIRED PROGRAM WHICH
;IS FROM SYS.  CALL IS:
;
;	MOVE	T1,PROGRAM	;SET UP NAME
;	MOVE	J,JOB		;AND HIS JOB NUMBER
;	CALL	SYSPRG		;SEE IF HE IS RUNNING THAT PROG, FROM SYS:
;	 (NO RETURN)		;NOT THAT PROG OR NOT FROM SYS
;	(YES RETURN)		;YES HE IS
;
;USES AC T2, T1 IS UNCHANGED.



SYSPRG:	MOVSI	T2,(J)		;SET UP
	IORI	T2,.GTPRG	;TO GET PROGRAM NAME
	GETTAB	T2,		;DO IT
	 ERROR	GTF		;MAYBE NOT
	CAME	T1,T2		;IS THIS HIS PROG?
	RET			;NO, NON-SKIP RETURN THEN
	MOVSI	T2,(J)		;YES, NOW GET SET
	IORI	T2,.GTLIM	;TO GET BATCH WORD
	GETTAB	T2,		;GET IT
	 ERROR	GTF		;NOPE
	TXNE	T2,JB.LSY	;IS PROGRAM FROM SYS?
	AOS	(P)		;YES, SET UP FOR SKIP RETURN
	RET			;RETURN
	SUBTTL	SUBROUTINE TO ALLOCATE A CHANNEL AND INIT A PTY



;THIS SUBROUTINE IS CALLED TO ALLOCATE A PTY CHANNEL FOR USE WITH A
;PTY, AND THEN TO INIT THE PTY AND SET UP INPUT AND OUTPUT BUFFERS.
;WE DO THIS IN A COMPLEX ALGORITHM SO THAT THERE IS AS GREAT A CHANCE
;AS POSSIBLE THAT WE WILL SUCCEED.  CALL IS:
;
;	MOVEI	J,JOB		;SETUP WHICH JOB I AM HANDLING
;	CALL	GETPTY		;GO GET A CHANNEL, AND INIT A PTY
;	(RETURN)		;GOT IT
;
;ON RETURN, AC IO CONTAINS THE CHANNEL NUMBER TO BE USED FOR I/O TO
;THE PTY, THE TABLE PTYALC CONTAINS OUR JOB NUMBER IN THAT CHANNEL'S
;SLOT, AND LOCATIONS PTYBIN+C(IO) AND PTYBOT+C(IO) CONTAIN POINTERS
;TO THE INPUT AND OUTPUT BUFFER HEADERS THAT WE WILL USE.
;USES AC'S  T1 - T4.




GETPTY:	CALL	SAVE2		;SAVE A COUPLE OF PERM ACS
	MOVEI	P1,ALCTRY	;SETUP A COUNT OF TRIES TO GET A PTY
	SETZ	P2,		;INITIALIZE FLAGS

ALLOCL:	MOVEI	IO,PTYNUM-1	;START OFF TO SEARCH ALLOCATION TABLE
	SKIPE	PTYALC(IO)	;IS THIS CHANNEL FREE?
	SOJGE	IO,.-1		;NO, KEEP LOOKING
	JUMPGE	IO,ALCYES	;IS NONNEG, DID GET A CHANNEL
	MOVEI	T1,ALCSLP	;SETUP FOR A WAIT
	CALL	SCHED		;GIVE OTHER PROCESSES CHANCE TO RELEASE PTY
	JRST	ALLOCL		;THEN GO CHECK TABLE AGAIN
				;(NO TIMEOUT COUNTER IS NEEDED BECAUSE
				;EVENTUALLY SOME PROCESS MUST FINISH)


;HERE WHEN WE HAVE FOUND A FREE CHANNEL THAT WE CAN USE


ALCYES:	MOVNM	J,PTYALC(IO)	;SET WE HAVE CHANNEL BUT PTY ISN'T INITED
	SKIPN	T1,PTYBIN(IO)	;ALREADY KNOW LOCATION OF SOME BUFFERS?
	PJRST	OPNPTY		;NO, THEN JUST ALLOCATE FROM .JBFF
	PUSH	P,.JBFF		;YES, THEN SAVE REAL .JBFF
	MOVEM	T1,.JBFF	;AND SET KNOWN LOCATION AS NEW .JBFF
	CALL	OPNPTY		;GO BUILD BUFFERS AT KNOWN PLACE
	POP	P,.JBFF		;RESTORE .JBFF TO OLD VALUE
	RET			;AND RETURN SUCCESSFULLY
;HERE FOR SUBROUTINE TO ACTUALLY TRY TO OPEN UP A PTY


OPNPTY:	MOVE	T3,.JBFF	;GET ADDRESS OF INPUT BUFFER HEADER
	HRLI	T3,3(T3)	;AND PUT IN OUTPUT BUFFER HEADER ADDRESS
	MOVEI	T1,^D50(T3)	;GET REASONABLE HIGHEST ADDRESS NEEDED
	CAMGE	T1,.JBREL	;HAVE ENOUGH CORE?
	JRST	PTYOKC		;YES, SKIP THE UUO
	CORE	T1,		;NO, THEN TRY TO GET IT
	 ERROR	CUF		;CAN'T
PTYOKC:	MOVSI	T1,(UU.PHS)	;SETUP ASCII MODE, PHYSICAL ONLY
	MOVSI	T2,'PTY'	;AND DEVICE PTY
	CALL	DOIO		;DO A OPEN
	 OPEN	T1		;OF A PTY, WITH BUFFERS WHERE WE SAID
	 JRST	OPENFL		;FAILED, GO ANALYSE SOME
	HRRZM	T3,PTYBIN(IO)	;OK, STORE INPUT BUFFER HEADER ADDRESS
	HLRZM	T3,PTYBOT(IO)	;AND OUTPUT BUFFER HEADER ADDRESS
	MOVEI	T3,6		;GET TOTAL WORDS USED FOR HEADERS
	ADDM	T3,.JBFF	;AND ADD THAT TO .JBFF
	CALL	DOIO		;NOW BUILD SOME BUFFERS
	 OUTBUF	1		;ONE OUTPUT BUFFER
	CALL	DOIO		;AND ONE INPUT BUFFER
	 INBUF	1
	MOVEM	J,PTYALC(IO)	;SET THAT OUR "JOB" HAS PTY INITED NOW
	RET			;AND THEN RETURN



;HERE IF THE OPEN FAILED, WE MUST SEE HOW MUCH WE CAN WAIT


OPENFL:	MOVEI	T1,PTYNUM-1	;SETUP TO SEARCH ALLOCATION TABLE
	SKIPG	PTYALC(T1)	;THIS CHANNEL HAVE A PTY INITED?
	SOJGE	T1,.-1		;NO, THEN CHECK OTHER CHANNELS
	JUMPGE	T1,WAITPT	;JUMP IF SOMEONE OF US HAS A PTY
	SOSG	P1		;WE HAVE NONE, DECREMENT TIMEOUT COUNT
	 ERROR	CGP		;TIMEOUT, COULDN'T GET A PTY
WAITPT:	MOVEI	T1,ALCSLP	;SET UP TO WAIT A WHILE
	CALL	SCHED		;LET SOMEONE MAKE A PTY AVAILABLE TO US
	JRST	OPNPTY		;AND NOW TRY AGAIN TO GET ONE
	SUBTTL	ROUTINE TO RELEASE A PTY




;THIS ROUTINE IS CALLED TO RELEASE ANY AND ALL PTYS THAT WE EITHER HAVE
;A CHANNEL ALLOCATED FOR, OR ACTUALLY HAVE A PTY OPENED AT THE MOMENT.
;IT IS UP TO THE CALLER TO MAKE SURE NO JOB IS ON THE PTY, IF HE CARES.
;CALL IS:
;
;	MOVEI	J,JOB		;GET JOB WE ARE DOING THIS FOR
;	CALL	RELPTY		;LET GO OF ALL PTYS THIS PROCESS MAY HAVE
;	(RETURN)		;ALL DONE
;
;USES AC'S  T1, T4, AND IO.




RELPTY:	MOVEI	IO,PTYNUM-1	;SET UP FOR A LOOP
	MOVNI	T1,(J)		;GET OUR NEGATIVE JOB NUMBER
RELPTL:	CAMN	T1,PTYALC(IO)	;WAS CHANNEL IN USE, BUT PTY NOT INITED?
	SETZM	PTYALC(IO)	;YES, JUST ZERO THE ENTRY
	CAME	J,PTYALC(IO)	;DID WE HAVE A PTY INITED ON THIS CHANNEL?
	JRST	RELPTN		;NO, GO LOOK AT NEXT CHANNEL
	SETZM	PTYALC(IO)	;YES, CLEAR OUT THE ENTRY
	CALL	DOIO		;DO SOME IO
	 RELEAS			;TO BE SPECIFIC, RELEASE PTY
RELPTN:	SOJGE	IO,RELPTL	;LOOP OVER ALL CHANNELS
	RET			;AND THEN RETURN
	SUBTTL	SUBROUTINE TO OUTPUT A STRING TO A PTY


;THIS ROUTINE IS USED TO OUTPUT A STRING OF CHARACTERS TO A PTY, AND
;TO MAKE SURE THEY ARE OUTPUT (SO THERE IS NO NEED TO "PUNT" ANY CHARS
;WHICH ARE LEFT IN THE BUFFERS).  CALL IS:
;
;	MOVEI	T1,[ASCIZ/STRING/]	;SETUP THE TEXT
;	MOVEI	IO,CHANNEL		;AND CHANNEL FOR PROPER PTY
;	CALL	PTYSTR			;GO OUTPUT STRING
;	(RETURN)			;DID IT
;
;USES AC'S  C, T1, T2, AND T4.



PTYSTR:	HRLI	T1,(POINT 7,)	;MAKE ADDRESS INTO A BYTE POINTER
	MOVE	T2,PTYBOT(IO)	;GET ADDRESS OF OUTPUT BUFFER HEADER
PTYSRX:	ILDB	C,T1		;GET THE NEXT CHARACTER
	JUMPE	C,PTYPNT	;WHEN A NULL PJRST TO OUTPUT ROUTINE
	CALL	PTYOUT		;NOT NULL, GO OUTPUT IT
	JRST	PTYSRX		;AND LOOP


PTYOUT:	SOSG	2(T2)		;COUNT ANOTHER CHARACTER USED
	CALL	PTYPNT		;NO MORE ROOM, OUTPUT THIS BUFFER
	IDPB	C,1(T2)		;NOW HAVE ROOM, STORE CHARACTER
	RET			;AND RETURN


PTYPNT:	CALL	DOIO		;GO DO THE ACTUAL OUTPUT
	 OUT			;AN OUT
	 RET			;GREAT, RETURN NOW
	CALL	DOIO		;FAILED, THEN DO AN INSTRUCTION
	 SETSTS	.IOASC		;SETSTS TO CLEAR ERRORS
	RET			;THEN RETURN
	SUBTTL	SUBROUTINE TO SLURP UP ALL OUTPUT FROM A PTY



;THIS ROUTINE IS CALLED OFTEN SO THAT ANY OUTPUT A PROG ON A PTY OF
;OURS MAY HAVE IS EATEN, AND SO WE CAN PROCEED WITH WHATEVER WE WANT
;TO DO.  CALL IS:
;
;	MOVEI	IO,CHANNEL	;GET CHANNEL PTY IS ON
;	CALL	PTYEAT		;GO EAT UP STUFF
;	(RETURN)		;ALL DONE FOR NOW
;
;USES AC T1.




PTYEAT:	MOVEI	T1,(IO)		;GET SET
	JOBSTS	T1,		;FIND OUT STATUS OF THE PTY
	 ERROR	JSF		;CAN'T
	TXNN	T1,JB.UOA	;ANY OUTPUT FOR US TO EAT?
	RET			;NO, ALL DONE FOR NOW
	CALL	DOIO		;OK, INPUT
	 IN	0		;I.E. READ NEXT BUFFER FROM PTY
	 JRST	PTYEAT		;OK, GO ON UNTIL GOT IT ALL
	CALL	DOIO		;IT FAILED, DO ANOTHER UUO
	 SETSTS	.IOASC		;CLEAR ANY ERRORS WE MAY HAVE HAD
	RET			;AND RETURN FOR NOW
	SUBTTL	SUBROUTINE TO EXECUTE AN I/O INSTRUCTION FOR PTYS



;THIS ROUTINE TAKES A BASIC I/O INSTRUCTION PROVIDED BY THE CALLER
;IN THE NEXT LOCATION FOLLOWING THE CALL, AND PUTS IN THE AC FIELD THE
;PROPER CHANNEL, THEN EXECUTES THE INSTRUCTION.  CALL IS:
;
;	MOVEI	IO,CHANNEL	;SET UP CHANNEL NUMBER OF PTY
;	CALL	DOIO		;DO AN I/O UUO
;	 (INSTRUCTION TO DO)	;THIS IS THE INSTRUCTION TO DO
;	 (NON-SKIP RETURN)	;UUO DID NOT SKIP
;	(SKIP RETURN)		;UUO DID SKIP
;
;USES AC T4.



DOIO:	JUMPE	IO,CPOPJ	;IF CHANNEL ZERO, JUST RETURN AND DO IT
	MOVSI	T4,(IO)		;GET CHANNEL NUMBER
	LSH	T4,5		;POSITION IT IN CHANNEL FIELD
	IOR	T4,@(P)		;ADD IN THE INSTRUCTION TO DO
	AOS	(P)		;SKIP OVER THE INSTRUCTION
	XCT	T4		;PERFORM THE I/O INSTRUCTION
	 RET			;IT GAVE A NON-SKIP, SO SO DO WE
	RETSKP			;IT SKIPPED, GO DO THE SAME
	SUBTTL	THE SCHEDULER FOR THE PROCESSES



;THIS ROUTINE STARTS UP ALL THE PROCESSES WHICH WE WANT TO RUN, AND
;RUNS THEM UNTIL ALL PROCESSES HAVE "KILLED" THEMSELVES.  THEN WE
;RETURN TO WHOEVER CALLED US.  CALL IS:
;
;	(SETUP ACTION TABLE)	;SETUP WHAT TO DO FOR EACH JOB
;				;(THE STARTING ADDRESS OF SOME ROUTINE)
;	CALL	SCHEDG		;GO DO ALL THE PROCESSES
;	(RETURN)		;ALL DONE
;
;ONLY AC'S F, P AND THE PERMANENT AC'S ARE PRESERVED.


SCHEDG:	CALL	SAVE3		;SAVE THE IMPORTANT AC'S
	MOVEM	P,SAVEP		;AND THEN SAVE P FOR THE RETURN LATER
	SETZM	SCDCNT		;ZERO NUMBER OF RUNNING PROCESSES
	MOVE	J,HGHJOB	;GET LARGEST JOB

SCHDGL:	SKIPE	T1,ACTION(J)	;ANY ROUTINE FOR THIS JOB?
	CALL	SCHEDC		;YES, CREATE A PROCESS FOR IT
	SOJG	J,SCHDGL	;NOW LOOP FOR ALL POSSIBLE PROCESSES
	SKIPG	SCDCNT		;ANY PROCESSES TO BE RUN?
	JRST	SCHEQQ		;NO, THEN JUST RETURN
	TXO	F,FR.SCH	;INDICATE WE ARE NOW IN THE SCHEDULER
	JRST	SCHEDS		;AND GO START THINGS GOING




;ROUTINE TO KILL OFF A PROCESS WHICH WANTS TO DIE.  JUST JRST HERE.
;WHEN ALL PROCESSES ARE DEAD, WE RETURN TO ORIGINAL CALLER OF SCHEDG.


SCHEDQ:	CALL	RELPTY		;LET GO OF ANY PTYS WE MAY HAVE HAD
	SETZM	WAITS(J)	;SAY WE NO LONGER EXIST
	SOSLE	SCDCNT		;DECREMENT NUMBER OF PROCESSES RUNNING
	JRST	SCHEDS		;STILL SOME LEFT, GO RUN THEM
SCHEQQ:	MOVE	P,SAVEP		;RESTORE SAVED STACK POINTER
	TXZ	F,FR.SCH	;NO LONGER IN THE SCHEDULER
	RET			;RETURN TO CALLER
	SUBTTL	ROUTINE TO CREATE A PROCESS


;THIS ROUTINE IS CALLED WHEN A NEW PROCESS IS DESIRED.  WE ALLOCATE ROOM
;FROM LOCATION .JBFF (DOING A CORE UUO IF NECESSARY) FOR STORAGE OF THE
;PROCESS'S AC'S, AND PUSH-DOWN STACK.  WE DO NOT ACTUALLY START EXECUTION
;OF THE PROCESS, ONLY SET THINGS UP SO THAT IT WILL BE RUN LATER.  CALL IS:
;
;	MOVEI	J,PROCESS	;SET UP THE PROCESS NUMBER
;	MOVEI	T1,ADDRESS	;SET ADDRESS TO START PROCESS AT
;	CALL	SCHEDC		;GO SET UP THE PROCESS
;	(RETURN)		;ALL READY FOR PROCESS TO GO
;
;USES ALL TEMP ACS



SCHEDC:	MOVE	T4,.JBFF	;GET FIRST FREE LOCATION
	MOVEM	T4,TEMP1	;REMEMBER ADDRESS OF STACK STORAGE
	ADDI	T4,STKSIZ	;MOVE BEYOND THAT AREA
	MOVEM	T4,ACCS(J)	;REMEMBER ADDRESS OF AC STORAGE
	MOVEI	T3,P-T4+1	;GET NUMBER OF ACS WE SAVE
	ADDB	T3,T4		;MOVE BEYOND THAT AREA TOO
	CAMG	T3,.JBREL	;DO WE NEED TO EXPAND CORE?
	JRST	COREOK		;NO, SKIP
	CORE	T3,		;YES, GET AS MUCH AS WE NEED
	 ERROR	UCP		;IF NO CORE, THIS PROCESS LOSES
COREOK:	MOVEM	T4,.JBFF	;SAVE NEW FIRST FREE LOCATION
	SOS	T3,TEMP1	;GET BACK ADDRESS OF STACK MINUS ONE
	HRLI	T3,-STKSIZ	;FINISH IOWD POINTER
	PUSH	T3,[EXP	SCHEDQ]	;PUT PROCESS KILLING ROUTINE ON TOP OF STACK
	PUSH	T3,T1		;AND THEN PUT ON STARTING ADDRESS
	MOVE	T1,ACCS(J)	;GET ADDRESS OF AC STORAGE
	MOVEM	T3,P-T4(T1)	;STORE AWAY THE STACK POINTER
	MOVEM	J,J-T4(T1)	;STORE AWAY PROCESS NUMBER TOO
	SETOM	WAITS(J)	;SAY WE EXIST AND WANT TO RUN RIGHT AWAY
	AOS	SCDCNT		;INCREMENT PROCESS COUNTER
	RET			;DONE
	SUBTTL	ROUTINE TO CHOOSE WHICH PROCESS TO RUN, AND RUN IT


;THIS ROUTINE IS USED TO SWITCH PROCESSES.  WE SAVE THE USER'S
;ACS (INCLUDING HIS PUSH-DOWN POINTER) AND RUN ANOTHER PROCESS IF ONE
;IS WAITING.  IF NOONE WANTS TO RUN RIGHT NOW, WE WAIT UNTIL SOMEONE
;DOES WANT TO RUN.  CALL IS:
;
;	MOVEI	T1,MILLISECONDS	;GET TIME TO WAIT
;	MOVEI	J,PROCESS	;GET MY PROCESS NUMBER
;	CALL	SCHED		;GO SCHEDULE SOMEONE ELSE FOR AWHILE
;	(RETURN)		;OK, MY TURN TO RUN AGAIN
;
;USES AC'S  T1, T2, T3



SCHED:	IMUL	T1,TICSEC	;CONVERT MILLISECONDS TO JIFFIES
	ADDI	T1,^D999	;ROUND UP IF PARTIAL TICKS
	IDIVI	T1,^D1000	;FINALLY GET TICKS
	CALL	GETUPY		;GET THE UPTIME AT PRESENT
	ADD	T1,T2		;ADD TOGETHER TO GET UPTIME HE WANTS
	MOVEM	T1,WAITS(J)	;STORE THE TIME IN THE WAIT TABLE
	MOVE	T3,T1		;COPY TIME IN CASE ONLY ONE PROCESS
	MOVE	T1,SCDCNT	;GET NUMBER OF PROCESSES RUNNING
	SOJE	T1,SCHDWT	;IF ONLY ONE, SKIP LOTS OF WORK
	MOVE	T1,ACCS(J)	;GET ADDRESS OF STORAGE AREA
	MOVSI	T2,T4		;SET UP ADDRESS OF WHERE WE BLT FROM
	IOR	T2,T1		;SET UP ADDRESS TO WHERE WE BLT
	BLT	T2,P-T4(T1)	;SAVE ALL THE ACS

SCHEDS:	MOVEM	J,TEMP1		;SAVE WHICH JOB WE STARTED WITH
	MOVEI	T1,(J)		;GET A COPY FOR OUR USE
	HRLOI	T3,377777	;GET A LARGE VALUE TO INITIALIZE THINGS
	SETO	J,		;INITIALIZE BEST JOB TO RUN TOO

SCHDLP:	SKIPE	T2,WAITS(T1)	;IS THIS PROCESS IN USE?
	CAML	T2,T3		;AND IS IT OLDER THAN BEST SO FAR?
	JRST	SCHDNX		;NO, LOOK AT NEXT ONE
	MOVE	T3,T2		;YES, GET NEW BEST VALUE
	MOVEI	J,(T1)		;AND REMEMBER THE JOB NUMBER
SCHDNX:	ADDI	T1,1		;ADD 1 TO JOB NUMBER
	CAMLE	T1,HGHJOB	;GONE OFF THE TOP?
	SETZ	T1,		;YES, RESTART AT 0
	CAME	T1,TEMP1	;BACK AT ORIGINAL JOB?
	JRST	SCHDLP		;NOT YET, FINISH LOOPING
	JUMPL	J,SCHEQQ	;SHOULDN'T EVER HAPPEN, BUT...
	CALL	SCHDWT		;WAIT REQUIRED TIME BEFORE CONTINUING
	MOVS	T1,ACCS(J)	;GET ADDRESS OF WHERE TO BLT ACS FROM
	HRRI	T1,T4		;AND WHERE THE ACS GO
	BLT	T1,P		;RESTORE THIS PROCESS'S ACS
	RET			;AND RETURN TO HIM
;SUBROUTINE TO WAIT PROPER LENGTH OF TIME WHEN NECESSARY.
;CALLED WITH T3 CONTAINING THE UPTIME IN TICKS WHEN WE CAN RETURN.



SCHDWT:	CALL	GETUPT		;GET THE UPTIME OF THE SYSTEM
	SUB	T2,T3		;SUBTRACT TIME FROM TIME HE WANTED
	JUMPGE	T2,CPOPJ	;IF THAT TIME, RETURN NOW
	MOVM	T1,T2		;GET POSITIVE TICKS TO WAIT
	IMULI	T1,^D1000	;PREPARE TO TURN INTO MILLISECONDS
	IDIV	T1,TICSEC	;DO IT (OR AT LEAST CLOSE)
	JUMPE	T1,CPOPJ	;IF TOO SMALL, RETURN NOW
	HRLI	T1,(HB.RWJ)	;SET THE PROTECTION BITS
	HIBER	T1,		;WAIT AS LONG AS WE HAVE TO
	 DIE	HUF		;HIBER UUO FAILED
	SETZM	UPTIME		;MAKE SURE WE GET A NEW UPTIME
	JRST	SCHDWT		;GO CHECK AGAIN FOR SOMEONE TO RUN




;ROUTINE TO COMPUTE THE UPTIME OF THE SYSTEM IF NOT ALREADY KNOWN.
;IF LOCATION UPTIME IS ZERO, GET DO THE GETTAB OVER AGAIN, OTHERWISE
;WE USE THE OLD VALUE.  ANSWER IN T2.  USES ONLY AC T2.



GETUPT:	SKIPE	T2,UPTIME	;SKIP IF NEED TO REGET UPTIME
	RET			;RETURN IF HAVE IT
GETUPY:	MOVE	T2,[%CNSUP]	;SET UP
	GETTAB	T2,		;GET THE UPTIME RIGHT NOW
	 DIE	GTF		;CAN'T
	MOVEM	T2,UPTIME	;SAVE IT FOR NEXT CALL
	RET			;AND RETURN
	SUBTTL	ROUTINE TO ATTACH BACK TO A TTY



;THIS ROUTINE ALLOWS THE USER'S JOB WHICH IS DETACHED TO COME BACK TO
;THE TTY THAT HE LAST DETACHED FROM.  WE DISALLOW COMING BACK TO PTYS
;BECAUSE OF CERTAIN PROBLEMS IN DOING THAT, AND CAN'T COME BACK TO A
;TTY WHICH IN USE BY ANOTHER JOB.  CALL IS:
;
;	CALL	DSPRET		;GO RETURN BACK TO OLD TTY
;	(RETURN)		;DID IT
;
;USES ALL TEMP AC'S



DSPRET:	GETLIN	T2,		;GET MY TTY'S SIXBIT NAME
	TLNE	T2,-1		;ALREADY ATTACHED?
	RET			;YES, DO NOTHING
	HRLI	T2,'TTY'	;FILL IN MISSING PART OF NAME
	TRNN	T2,-1		;BUT IS RIGHT HALF OF NAME BLANK?
	MOVSI	T2,'CTY'	;YES, CORRECT NAME TO BE CTY
	MOVE	T4,T2		;COPY NAME TO GOOD AC
	IONDX.	T4,UU.PHY	;GET IOINDEX OF TTY
	 ERROR	IUF		;FAILED
	MOVEI	T1,(T4)		;GET A COPY
	GETLCH	T1		;FIND THE STATUS OF THE TTY
	TLNE	T1,(GL.ITY)	;IS IT A PTY?
	 ERROR	CAP		;YES, CAN'T ATTACH BACK TO IT THEN
	MOVE	T1,[UU.PHS+.IOASC]	;SET UP FOR THE OPEN
	SETZ	T3,		;NO BUFFERS
	OPEN	CH.DSK,T1	;TRY TO OPEN THE TTY
	 ERROR	TIU		;CAN'T, THEN ASSUME IT IS IN USE
	HRLOI	T1,<-.UXTRM(AT.UUM)>(T4)   ;SET UP FOR THE ATTACH
	ATTACH	T1,		;PUT ME ON THE TTY
	 ERROR	ATF		;FAILED
	RELEAS	CH.DSK,		;OK, RELEASE THE TTY NOW
	RET			;AND RETURN
	SUBTTL	ROUTINE TO LIST OUT SOME JOBS



;THIS ROUTINE IS CALLED TO TYPE OUT A MINI-SYSTAT OF A JOB, A JOB ON
;A TTY, OR ALL JOBS OF A PPN SO THAT THE USER KNOWS WHICH ONES HAVE
;NOT BEEN CRUMPED, OR DESERVE CRUMPING, ETC.  CALL IS:
;
;	MOVEI	P2,ADDRESS	;SETUP POINTER TO THE FUNCTION
;	CALL	DSPLST		;GO DO A SYSTAT OF THE INDICATED JOBS
;	(RETURN)		;ALL DONE
;
;USES ALL TEMP AC'S, AND J AND JS.




DSPLST:	MOVE	T1,1(P2)	;GET ARGUMENT
	MOVEI	T2,DSPDO	;AND ROUTINE TO CALL
	CALL	FNDJOB		;CALL ROUTINE FOR ALL JOBS
	RET			;DONE

DSPDO:	SKIPN	2(P2)		;WAS A PPN SPECIFIED?
	JRST	LSTSET		;NO, WANT THIS JOB THEN
	MOVSI	T1,(J)		;NOW GET SET
	IORI	T1,.GTPPN	;TO GET THE PPN OF THE JOB
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CALL	PPNCHK		;SEE IF THIS PPN IS DESIRED
	 JRST	CHKPDM		;NO, SEE IF AN ERROR IS IN ORDER

LSTSET:	MOVEI	T1,SYSTAT	;GET ROUTINE
	MOVEM	T1,ACTION(J)	;SET IT UP
	TXO	F,FR.NDS	;NEED SCHEDULER
	RET			;DONE NOW



;HERE WHEN PPN DOES NOT MATCH THE PPN SPECIFIED BY THE USER, TO SEE
;IF THAT IS AN ERROR.  NO ERROR OCCURS IF DOING WILD JOBS.


CHKPDM:	TXNN	F,FR.WLD	;DOING WILD JOBS?
	 ERROR	PDM		;NOT WILD, COMPLAIN ABOUT WRONG PPN
	RET			;YES, FORGET THIS JOB THEN
	SUBTTL	ROUTINE TO OUTPUT SOME TEXT TO USER'S JOBS



;THIS ROUTINE IS CALLED TO OUTPUT SOME TEXT TO A TTY WHICH THE USER
;IS ALLOWED TO SEND TO.  HE CAN SEND TO ANY TTY WHICH IS IN USE BY A JOB
;WHICH WE WOULD BE ABLE TO KILL.  A MESSAGE CAN BE SEND TO A PARTICULAR
;JOB, OR TO A PARTICULAR TTY, OR TO ALL JOBS OF A USER, OR TO ALL TTYS
;BELONGING TO A USER.  IN ADDITION, THE MESSAGES CAN HAVE A "MONITOR
;DOT" APPENDED TO THE END OF THE SENT STRING SO IT IS SIMILAR TO A SEND
;COMMAND.  CALL IS:
;
;	MOVEI	P2,ADDR		;SET UP ADDRESS TO STRING FUNCTION
;	CALL	DSPMSG		;GO SEND A MESSAGE
;	(RETURN)		;ALL DONE
;
;USES ALL TEMP AC'S


DSPMSG:	MOVE	T1,(P2)		;GET FLAGS
	TXNE	T1,FF.DOT	;WANT MONITOR DOTS?
	CALL	DOTSET		;YES, SETUP FOR THEM
	MOVE	T1,1(P2)	;GET USER'S ARGUMENT
	CAIN	T1,VL.OWN	;IS IT FOR ALL TTYS OF A USER?
	PJRST	MSGALL		;YES, GO DO THAT
	MOVEI	T2,MSGDO	;GET ROUTINE TO CALL
	CALL	FNDJOB		;LOOP OVER ALL JOBS
	RET			;DONE

MSGDO:	MOVSI	T1,(J)		;GET SET
	IORI	T1,.GTPPN	;TO GET PPN OF JOB
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;CAN'T
	CALL	PPNCHK		;MATCH THE PPN WE WANT?
	 RET			;NO, IGNORE IT AND DO NEXT ONE
	CALL	PRIVCK		;SEE IF ALLOWED TO SEND TO THE JOB
	 ERROR	CSU		;NOPE, ERROR
	MOVEI	T3,(JS)		;OK, GET THE TTY IOINDEX OF THE JOB
	SKIPE	T3		;WAS THE USER DETACHED?
	PJRST	TXTTRM		;NO, THEN GO SEND TO HIM
	TXNN	F,FR.WLD	;SENDING TO MULTIPLE JOBS?
	 ERROR	JID		;NO, ERROR THEN
	RET			;YES, GO ON TO NEXT JOB
;HERE WHEN WE ARE TO SEND TO ALL OF THE TTYS OWNED BY A USER



MSGALL:	CALL	SAVE1		;SAVE AN AC
	MOVE	P1,HGHTTY	;GET HIGHEST TTY NUMBER FOR LOOP
	ADDI	P1,.UXTRM+1	;MAKE INTO HIGHEST IOINDEX

MSGALN:	SUBI	P1,1		;DECREMENT TO NEXT TTY IOINDEX
	CAIGE	P1,.UXTRM	;DOWN TO THE LAST ONE?
	RET			;YES, RETURN
	PUSH	P,[EXP	MSGALN]	;SET UP FOR THE RETURN LATER
	MOVEI	T1,(P1)		;GET SET
	DEVTYP	T1,UU.PHY	;GET INFO ABOUT THE DEVICE
	 ERROR	DTF		;FAILED
	LDB	J,[POINT 9,T1,26]	;GET JOB NUMBER WHO OWNS TTY
	JUMPE	J,CPOPJ		;IGNORE TTY IF NO JOB USING IT
	MOVSI	T1,(J)		;OK, GET SET
	IORI	T1,.GTPPN	;TO GET PPN OF JOB OWNING TTY
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CALL	PPNCHK		;WANT THE PPN?
	 RET			;NO, GO ON TO NEXT TTY
	CALL	PRIVCK		;SEE IF ALLOWED TO SEND TO JOB
	 ERROR	CSU		;NOPE, ERROR
	MOVEI	T1,(P1)		;YES, GET IOINDEX AGAIN
	GETLCH	T1		;FIND OUT TTY CHARACTERISTICS
	TXNE	T1,GL.ITY	;IS THIS A PTY?
	RET			;YES, DON'T SEND TO IT
	MOVEI	T3,(P1)		;GET IOINDEX READY FOR ROUTINE
	PJRST	TXTTRM		;OUTPUT MESSAGE TO THE TTY
	SUBTTL	ROUTINE TO SETUP CONVERSION OF STRING FOR "MONITOR DOT"



;THIS ROUTINE IS CALLED WHEN IT IS POSSIBLE THAT WE SHOULD APPEND A
;MONITOR DOT AT THE END OF THE USER'S GIVEN STRING.  THIS MONITOR DOT
;WILL BE TYPED OUT IF THE TTY TO SEND THE STRING TO IS IN MONITOR MODE.
;SO THIS WILL CREATE AN ACTION SIMILAR TO THE SEND COMMAND.
;THIS ROUTINE CAN ONLY APPEND A STRING OF 4 OR LESS CHARACTERS TO THE
;USER'S STRING, NOTE THIS IF YOU EVER CHANGE IT!!   CALL IS:
;
;	MOVEI	P2,ADDR		;SETUP ADDRESS OF STRING FUNCTION
;	CALL	DOTSET		;GO SETUP FOR POSSIBLE MONITOR DOTS
;	(RETURN)		;ALL DONE
;
;USES AC'S  T1, T2, AND C.  SETS LOCATIONS  TXEND,TXORG1,TXORG2,TXNEW1,TXNEW2



DOTSET:	MOVEI	T1,3(P2)	;GET ADDRESS OF ACTUAL STRING
	HRLI	T1,(POINT 7,)	;AND CREATE A BYTE POINTER TO IT
	MOVE	T2,T1		;GET A COPY
	ILDB	C,T1		;GRAB THE NEXT CHARACTER OF THE STRING
	JUMPN	C,.-2		;IF NOT YET A NULL KEEP GOING
	HRRZM	T2,TXEND	;OK, SAVE LOCATION OF LAST CHAR
	MOVE	T1,(T2)		;GET WORD CONTAINING LAST CHAR
	MOVEM	T1,TXORG1	;SAVE IT
	MOVEM	T1,TXNEW1	;BOTH PLACES
	MOVE	T1,1(T2)	;GET FOLLOWING WORD ALSO
	MOVEM	T1,TXORG2	;SAVE IT TOO
	MOVEM	T1,TXNEW2	;BOTH PLACES
	HRRI	T2,TXNEW1	;POINT BYTE POINTER TO THE NEW WORDS
	MOVE	T1,[POINT 7,[BYTE (7)15,12,"."]]	;GET STRING
	ILDB	C,T1		;GRAB NEXT CHAR OF STRING
	IDPB	C,T2		;STORE IT IN NEW WORDS
	JUMPN	C,.-2		;LOOP UNTIL STORED THE NULL
	RET			;THEN RETURN
	SUBTTL	ROUTINE TO OUTPUT STRING TO A TTY



;THIS SUBROUTINE IS CALLED TO OUTPUT THE GIVEN ASCIZ STRING TO THE
;REQUIRED TERMINAL.  AS PART OF THE OUTPUT, WE SEE IF A MONITOR DOT
;IS TO BE TYPED, AND IF SO, THE USER'S OUTPUT IS ENDED WITH A DOT
;IF THE TTY WAS IN MONITOR MODE.  CALL IS:
;
;	MOVEI	P2,ADDR		;GET ADDRESS OF STRING FUNCTION
;	MOVEI	T3,TTY IOINDEX	;AND WHICH TTY TO SEND TO
;	MOVEI	J,JOB		;AND THE JOB WHICH OWNS THE TTY
;	CALL	TXTTRM		;OUTPUT IT
;	(RETURN)		;DID IT
;
;IF THE TRMOP FAILS, THE FLAG FR.ERR IS SET.  USES ALL TEMP AC'S.



TXTTRM:	MOVE	T1,(P2)		;GET FLAGS
	TXNE	T1,FF.DOT	;MONITOR DOTS WANTED?
	JRST	TXTNOD		;NO, THEN JUST DO DIRECTLY
	MOVE	T1,[2,,T2]	;SETUP FOR TRMOP.
	MOVEI	T2,.TOCOM	;TO SEE IF TTY IS IN MONITOR MODE
	TRMOP.	T1,		;SEE IF IT IS
	 PJRST	TXTNOD		;FAILED, ASSUME NOT
	JUMPE	T1,TXTNOD	;JUMP IF NOT MONITOR MODE, NO DOT NEEDED
	MOVE	T1,TXEND	;GET ADDRESS OF LAST WORD USED IN STRING
	MOVE	T2,TXNEW1	;GET NEW VERSION OF THAT WORD
	MOVEM	T2,(T1)		;STORE IT
	MOVE	T2,TXNEW2	;AND GET NEXT WORD TOO
	MOVEM	T2,1(T1)	;STORE IT ALSO
	CALL	TXTNOD		;OUTPUT THE TEXT NOW, WITH MONITOR DOT
	MOVE	T1,TXEND	;OK, NOW GET BACK ADDRESS OF END
	MOVE	T2,TXORG1	;GET ORIGINAL WORD BACK
	MOVEM	T2,(T1)		;STORE IT
	MOVE	T2,TXORG2	;AND OTHER ORIGINAL WORD
	MOVEM	T2,1(T1)	;STORE IT ALSO
	RET			;THEN RETURN


TXTNOD:	MOVE	T1,[3,,T2]	;SETUP FOR TRMOP
	MOVEI	T2,.TOOUS	;STRING OUTPUT FUNCTION
	MOVEI	T4,3(P2)	;GET STRING ADDRESS
	TRMOP.	T1,		;OUTPUT IT TO THE TTY
	 ERROR	TUF		;IT FAILED
	RET			;AND RETURN
	SUBTTL	ROUTINES TO ADVANCE TMPCOR POINTER FOR FUNCTIONS




;CALLED FOR THOSE ROUTINES WHICH DO NOT HAVE A CONSTANT BLOCK LENGTH.
;THESE ROUTINES MUST COMPUTE THE LENGTH OF THEIR BLOCK, AND RETURN
;THE NEW POSITION OF THE TMPCOR POINTER.  CALL IS:
;
;	MOVEI	P2,ADDR		;GET POINTER TO TOP OF THIS BLOCK
;	CALL	SIZXXX		;CALL PROPER ROUTINE
;	(RETURN)		;DONE, P2 IS UPDATED.
;
;USES AC'S T1 AND T2 ONLY.  RIGHT NOW ONLY THE MESSAGE FUNCTION HAS
;A VARIABLE LENGTH BLOCK.




SIZMSG:	MOVEI	T1,3(P2)	;GET ADDRESS OF START OF STRING
	HRLI	T1,(POINT 7,)	;MAKE A BYTE POINTER TO IT
	ILDB	T2,T1		;GRAB NEXT BYTE
	JUMPN	T2,.-1		;KEEP GOING UNTIL GET A NULL
	MOVEI	P2,1(T1)	;POINT P2 RIGHT AFTER THAT WORD
	RET			;AND RETURN
	SUBTTL	ROUTINE TO CHECK A PPN TO SEE IF IT MATCHES GIVEN ONE



;ROUTINE TO COMPARE A PPN SUPPLIED IN THE FUNCTION BLOCK WE ARE NOW
;LOOKING AT (IE, AT 2(P2)), WITH A PPN GIVEN BY THE USER IN AC T1.
;USUALLY THE GIVEN PPN IS THAT OF A JOB WE ARE TESTING.  WE DEFAULT
;ZERO HALFS OF A PPN TO OUR OWN, AND DEFAULT -1 HALFS OF A PPN AS
;A WILDCARD.  CALL IS:
;
;	MOVE	T1,PPN		;GET PPN TO BE COMPARED AGAINST
;	CALL	PPNCHK		;SEE IF IT MATCHES THE ONE IN CORE
;	 (NO RETURN)		;NO MATCH
;	(YES RETURN)		;YES, MATCHES SOMEHOW
;
;USES ONLY AC T2.





PPNCHK:	MOVE	T2,2(P2)	;GET THE PPN FROM THE FUNCTION BLOCK
	TLNN	T2,-1		;WAS A PROJECT SUPPLIED?
	HLL	T2,MYPPN	;NO, THEN THROW OUR OWN IN
	TRNN	T2,-1		;WAS A PROGRAMMER GIVEN?
	HRR	T2,MYPPN	;NO, THEN THROW OUR OWN IN
	SETCA	T2,		;COMPLEMENT AC FOR TESTING
	TLCN	T2,-1		;WAS THE PROJECT -1?
	HLL	T2,T1		;YES, THEN FILL IN FROM TEST PPN
	TRCN	T2,-1		;WAS THE PROGRAMMER -1?
	HRR	T2,T1		;YES, THEN FILL IN FROM TEST PPN
	CAMN	T1,T2		;DO PPNS NOW MATCH?
	AOS	(P)		;YES, SKIP RETURN
	RET			;NO, NON-SKIP RETURN
	SUBTTL	LUUO HANDLER



;THIS ROUTINE TAKES CARE OF OUR LUUOS WHICH TYPE MESSAGES, AND ALSO
;RETURN ERROR CODES TO THE USER IF WE WERE RUN FROM CCL ENTRY.
;LUUOS MAY ONLY USE AC'S T1 - T4 UNLESS THEY SAVE THE OTHERS THEMSELVES.
;RECURSION OF LUUOS IS NOT ALLOWED.




UUO:	MOVEM	P,LUUOP		;SAVE POINTER IN CASE NEED THE PC
	MOVEM	T1,SAVET1	;SAVE ALL OF THE TEMP AC'S
	MOVEM	T2,SAVET2
	MOVEM	T3,SAVET3
	MOVEM	T4,SAVET4
	GETLIN	T1,		;GET OUR TTY NAME
	TLNN	T1,-1		;ARE WE DETACHED?
	JRST	NOTYPE		;YES, GO SET FLAG SAYING NO OUTPUT
	MOVN	T1,MYJOB	;NO, THEN GET SET
	JOBSTS	T1,		;TO FIND MY STATUS
	 SETZ	T1,		;NO LOOPING HERE
	TXNN	T1,JB.UML	;ARE WE IN MONITOR MODE?
	TXZA	F,FR.DET	;NO, THEN CLEAR FLAG
NOTYPE:	TXO	F,FR.DET	;YES, PREVENT TYPEOUT
	LDB	T2,[POINT 9,.JBUUO,8]	;GRAB THE OPCODE OF THE UUO
	CAILE	T2,MAXUUO	;IS IT A LEGAL ONE?
	JRST	DIEDS1		;NO, GO GIVE ILLEGAL LUUO ERROR
	HRRZ	T1,.JBUUO	;SETUP THE ARGUMENT FOR CONVENIENCE
	CALL	@UUOTAB-1(T2)		;PROCESS THE LUUO
UUOFIN:	MOVE	T4,SAVET4	;RESTORE THE AC'S WE USED
	MOVE	T3,SAVET3
	MOVE	T2,SAVET2
	MOVE	T1,SAVET1
	RET			;THEN RETURN TO THE CALLER




UUOTAB:	TELDSP		;(1) OUTPUT TEXT
	ERRDSP		;(2) OUTPUT TEXT THEN KILL THE PROCESS
	DIEDSP		;(3) OUTPUT TEXT, THEN KILL OURSELF

	MAXUUO==.-UUOTAB	;MAXIMUM UUO
;THE ACTUAL CODE FOR EACH LUUO FOLLOWS:



TELDSP:	TXNE	F,FL.SUP!FL.IMP	;WANT OUTPUT SUPPRESSED?
	RET			;YES, THEN RETURN
	PJRST	TXTCMD		;OTHERWISE GO OUTPUT IT



ERRDSP:	TXO	F,FR.FND	;REMEMBER A JOB WAS FOUND
	SUBI	T1,ERRSE	;CREATE ERROR CODE
	JUMPL	T1,DIEDS1	;IF NEGATIVE, HAVE AN ILLEGAL LUUO
	ADDI	T1,ERROFS	;CREATE THE REAL ERROR CODE
	MOVEI	T2,(J)		;GET JOB NUMBER AS ARGUMENT
	CALL	SAVERR		;GO SET THE ERROR
	MOVE	T1,@.JBUUO	;GET THE ADDRESS OF THE ERROR TEXT
	CALL	TXTCMD		;OUTPUT THE TEXT
	TXNE	F,FR.SCH	;WERE WE INSIDE THE SCHEDULER?
	JRST	SCHEDQ		;YES, GO KILL OURSELF
	SUB	P,[2,,2]	;NO, THEN SET UP PDL SO GET A RET
	JRST	UUOFIN		;RETURN FROM THE FATAL LUUO



DIEDSP:	SUBI	T1,ERRSD	;CREATE ERROR CODE
	SKIPG	T1		;IS IT A REASONABLE ERROR CODE?
DIEDS1:	SETZB	T1,.JBUUO	;NO, MAKE IT SO
	ADDI	T1,DIEOFS	;CREATE REAL ERROR CODE
	SETO	T2,		;SET -1 AS AN ARGUMENT
	CALL	SAVERR		;GO SAVE THE ERROR
	MOVEI	T1,[ASCIZ/? Fatal error $4 - /]
	CALL	TXTCMD		;OUTPUT THE PRELIMINARY TEXT
	SKIPE	.JBUUO		;KNOW THE ADDRESS OF THE ERROR TEXT?
	SKIPA	T1,@.JBUUO	;YES, GET IT
	MOVEI	T1,ERRSD	;OTHERWISE GET ADDRESS OF ILLEGAL LUUO MESSAGE
	CALL	TXTCMD		;OUTPUT IT
	JRST	KILDON		;AND FINISH UP
	SUBTTL	ERROR CODES FOR THE ERROR AND DIE LUUO'S



;THERE ARE TWO TYPES OF ERRORS.  ONE TERMINATES ONLY THE PROCESS IT
;OCCURS IN WHEN IN THE SCHEDULER, AND GIVES A RET RETURN WHEN NOT
;IN THE SCHEDULER.  THE OTHER KILLS THE WHOLE PROGRAM.
;KEEP THE ORDER OF THE ERRORS CONSTANT, BECAUSE THE ORDER DETERMINES
;THE ERROR CODE RETURNED TO THE USER.



ERRSE:	ECODE	CUF,Can't get core for PTY buffers for job $1$2
	ECODE	CGP,Could not get a PTY to use for $1$2
	ECODE	ATF,ATTACH uuo failed for job $1$2 $4
	ECODE	IUF,IONDX. uuo failed for PTY to use for $1$2 $4
	ECODE	GTF,GETTAB uuo failed while processing job $1$2 $4
	ECODE	JSF,JOBSTS uuo failed for job $1$2 $4
	ECODE	NRL,Job $1$2 is running $3 instead of LOGOUT
	ECODE	JNR,Job $1$2 is stopped instead of logging out
	ECODE	TIW,Job $1$2 has gone into a TI wait running $3
	ECODE	NOP,Job $1$2 is no longer on our PTY
	ECODE	JIS,Couldn't stop job $1$2 running $3
	ECODE	PHC,Job $1$2 has changed PPNs
	ECODE	PIJ,Job $1$2 is running $3 which is JACCT'd
	ECODE	CZL,Can't zap logged in job $1$2
	ECODE	CZD,Can't zap non detached job $1$2
	ECODE	CHM,Job $1 is myself
	ECODE	JNI,Illegal job number given
	ECODE	JNA,Job $1 is not assigned
	ECODE	PDM,PPN of job $1$2 isn't what you specified
	ECODE	CHP,You can not hurt job $1$2
	ECODE	UCP,Unable to create a process for job $1$2
	ECODE	ITN,Illegal TTY number given
	ECODE	DTF,DEVTYP uuo failed
	ECODE	NJT,TTY is not controlling a job
	ECODE	CZJ,Failed to zap job $1$2
	ECODE	CSJ,Failed to stop job $1$2
	ECODE	MJA,Multiple jobs specified for ATTACH function
	ECODE	CAP,Can't attach back to a PTY
	ECODE	TIU,Tty to attach back to is in use
	ECODE	CSU,You can't send messages to job $1$2
	ECODE	CDM,Can't attach job $1$2 since I am in monitor mode
	ECODE	CDB,Can't attach job $1$2 since I am a batch job
	ECODE	IAD,Can't attach job $1$2 since I am detached
	ECODE	CHB,You cannot hurt batch job $1$2
	ECODE	TUF,TRMOP uuo failed to output to job $1$2
	ECODE	JID,Can't output message to detached job $1$2
	ECODE	MCI,You are not privileged to use the MEAN command
	ECODE	NJF,No jobs found
;FINALLY FOR THE ERRORS WHICH KILL THE WHOLE PROGRAM





ERRSD:	DCODE	ILE,Illegal LUUO executed
	DCODE	CUF,CTLJOB uuo failed
	DCODE	GTF,GETTAB uuo failed
	DCODE	IUF,IONDX. uuo failed
	DCODE	IFN,Illegal function number
	DCODE	OFD,OPEN failed for CCL file
	DCODE	IFC,INPUT uuo failed for CCL file
	DCODE	CLE,CCL file LOOKUP error
	DCODE	TMJ,Too many jobs for tables - reassemble with larger MAXJOB
	DCODE	HUF,HIBER uuo failed
	DCODE	CWV,CCL format is not correct version
	SUBTTL	SUBROUTINE TO STORE AWAY AN ERROR



;ROUTINE CALLED TO STORE AWAY INFORMATION ABOUT AN ERROR SO THAT
;IT CAN BE GIVEN TO THE USER LATER.  THE ERROR IS CONTAINED IN TWO
;WORDS, THE FIRST WORD CONTAINING THE ERROR CODE, AND THE SECOND
;WORD CONTAINING SOME ARGUMENT WHICH MIGHT BE OF SOME USE TO THE
;USER.  CALL IS AS FOLLOWS:
;
;	MOVEI	T1,ERROR CODE	;SET UP ERROR CODE
;	MOVE	T2,ARGUMENT	;AND ARGUMENT DESIRED (JOB, TTY, ETC.)
;	CALL	SAVERR		;GO STORE THE ERROR AWAY
;	(RETURN)		;ALL DONE
;
;USES AC'S  T1, T2, AND T3.



SAVERR:	AOS	ERRCNT		;INCREMENT ERROR COUNT
	TXNN	F,FR.CCL	;ARE WE USING CCL COMMANDS?
	RET			;NO, THEN NO POINT IN STORING ERRORS
	MOVEI	T3,2		;GET NUMBER OF WORDS PER ERROR
	ADDB	T3,ERRPTR	;UPDATE POINTER AND GET NEW VALUE
	CAILE	T3,TMPSIZ-1	;ROOM TO STORE THE ERROR?
	RET			;NO, MUST FORGET IT
	MOVEM	T1,ERRBLK-1(T3)	;OK, STORE THE CODE
	MOVEM	T2,ERRBLK(T3)	;AND THE ARGUMENT FOR IT
	RET			;THEN RETURN
	SUBTTL	SUBROUTINE TO WRITE OUT A TMPCOR ERROR FILE



;THIS ROUTINE IS CALLED TO WRITE OUT TO A TMPCOR FILE BY THE NAME OF
;'KIL' ANY ERRORS WHICH WE HAVE ENCOUNTERED.  IF THERE ARE TOO MANY TO
;FIT, THAT IS JUST TOO BAD.  CALL IS:
;
;	CALL	WRTERR		;GO WRITE THE ERRORS IN A FILE
;	(RETURN)		;DID IT
;
;USES ALL TEMP AC'S.



WRTERR:	SETOM	ERRBLK		;SET FIRST WORD OF BLOCK TO -1
	MOVSI	T2,.TCRFS	;GET FREE SPACE
	TMPCOR	T2,		;FROM MONITOR
	 RET			;CAN'T??
	MOVE	T1,ERRCNT	;GET COUNT OF ERRORS
	ADDI	T1,1(T1)	;GET WORDS OF TMPCOR WE WANT TO USE
	CAILE	T2,T1		;LESS THAN MAXIMUM TMPCOR WE CAN HAVE?
	MOVEI	T2,(T1)		;YES, SET TO ONLY ASK THAT MUCH THEN
	MOVNI	T2,(T2)		;MAKE NEGATIVE
	MOVSI	T2,(T2)		;PUT IN LEFT HALF
	IORI	T2,ERRBLK-1	;AND ADDRESS IN RIGHT HALF FOR IOWD
	HLLZ	T1,TCRINB	;PUT IN FILE NAME
	MOVE	T3,[.TCRWF,,T1]	;SET UP
	TMPCOR	T3,		;WRITE AS MANY ERRORS AS WILL FIT
	 TELL	TMPCOR Uuo failed to write error file
	RET			;WON, GREAT
	SUBTTL	TEXT OUTPUT ROUTINES


;THIS ROUTINE IS CALLED TO OUTPUT AN ASCIZ STRING, AND LOOK FOR SPECIAL
;SEQUENCES OF CHARACTERS WHICH PERFORM GOOD FUNCTIONS.  AMONG THESE
;FUNCTIONS ARE THE PC OF THE LUUO, A JOB'S NUMBER, A USER'S PPN, AND
;THE PROGRAM WHICH IS RUNNING.  ALL FUNCTIONS ARE OF THE FORM $N WHERE
;$ IS A DOLLAR SIGN, AND N IS A SINGLE DECIMAL DIGIT.  CALL IS:
;
;	MOVEI	T1,[ASCIZ/STRING/]	;SET UP TEXT
;	CALL	TXTCMD			;GO OUTPUT TEXT ACCORDING TO STRING
;	(RETURN)			;ALL DONE
;
;USES ALL THE TEMP AC'S



TXTCMD:	PUSH	P,P1		;SAVE AWAY A PERM AC
	MOVE	P1,T1		;COPY ADDRESS OF THE STRING
	HRLI	P1,(POINT 7,)	;MAKE A BYTE POINTER TO STRING
TXTCMN:	ILDB	C,P1		;GRAB THE NEXT CHARACTER
TXTCMC:	JUMPE	C,PPOPJ		;IF A NULL ARE ALL DONE
	CAIN	C,"$"		;IS IT A DOLLAR SIGN?
	JRST	TXTCMA		;YES, GO DO A "COMMAND"
	PUTCHR			;NO, THEN OUTPUT NORMAL CHARACTER
	JRST	TXTCMN		;AND LOOP FOR MORE


TXTCMA:	ILDB	C,P1		;GET CHARACTER FOLLOWING DOLLAR SIGN
	CAIL	C,"1"		;IS IT IN RANGE OF A LEGAL COMMAND?
	CAILE	C,"1"+TXTNUM	;WELL?
	JRST	TXTCMC		;NO, THEN TREAT THIS AS NORMAL CHAR
	CALL	@TXTDSP-"1"(C)	;YES, GO PROCESS THE COMMAND
	JRST	TXTCMN		;AND PROCEED WITH NORMAL CHARACTERS


TXTDSP:	TXTJOB			;FUNCTION 1 - TYPE JOB "N"
	TXTUSR			;FUNCTION 2 - TYPE "[PROJ,PROG]" OF JOB
	TXTPRG			;FUNCTION 3 - TYPE "PROGRAM NAME"
	TXTPC			;FUNCTION 4 - TYPE "AT PC N"
	TXTPPN			;FUNCTION 5 - TYPE "[PROJ,PROG]" OF TABLE ENTRY

	TXTNUM==.-TXTDSP	;NUMBER OF FUNCTIONS
;THE FOLLOWING SUBROUTINES ARE CALLED BY THE ABOVE TXTCMD SUBROUTINE
;TO ACTUALLY TYPE OUT THE THINGS WHICH THE FUNCTIONS CALL FOR.
;ANY TEMP AC MIGHT BE USED.  ALL CALLED BY A CALL.


TXTPC:	MOVEI	T1,[ASCIZ/at PC /]	;GET SOME TEXT
	CALL	STROUT		;OUTPUT IT
	HRRZ	T1,LUUOP	;GET PUSHDOWN POINTER WHEN UUO BEGAN
	MOVE	T1,(T1)		;GET ADDRESS WHERE CALL CAME FROM
	MOVEI	T1,-2(T1)	;GENERATE THE REAL PC
	PJRST	OCTOUT		;OUTPUT IT AND RETURN




TXTPRG:	MOVSI	T1,(J)		;SET UP
	IORI	T1,.GTPRG	;TO GET PROGRAM NAME
	GETTAB	T1,		;GET IT
	 SETZ	T1,		;FAILED, MAKE NULL
	JUMPN	T1,SIXOUT	;IF NONZERO, OUTPUT IN SIXBIT
	MOVEI	T1,[ASCIZ/(blank)/]	;OTHERWISE GET THIS STRING
	PJRST	STROUT		;AND OUTPUT THAT



TXTJOB:	MOVEI	T1,(J)		;GET HIS JOB NUMBER
	PJRST	DECOUT		;OUTPUT IT AND RETURN



TXTPPN:	SKIPE	T1,PPNS(J)	;GET PPN FROM TABLE IF THERE
	CAMN	T1,MYPPN	;IS IT MY OWN PPN?
	RET			;YES, THEN DON'T TYPE IT
	PJRST	PPNOUT		;GO OUTPUT PPN



TXTUSR:	MOVSI	T1,(J)		;SET UP
	IORI	T1,.GTPPN	;TO GET THE PPN OF THE JOB
	GETTAB	T1,		;GET IT
	 SETZ	T1,		;FAILED? MAKE ZERO
	CAME	T1,MYPPN	;DOES IT MATCH MY OWN PPN?
	SKIPN	T1		;OR IS IT ZERO?
	RET			;YES, THEN NO NEED TO TYPE IT
;	PJRST	PPNOUT		;NO, THEN FALL INTO PPN OUTPUT
;THE FOLLOWING ROUTINES ARE THE LOW LEVEL OUTPUT ROUTINES TO PERFORM
;THE STANDARD TYPES OF OUTPUT.  ALL CALLED BY A CALL WITH THE ARGUMENT
;IN AC T1.  AC'S  T1 - T4 MAY BE CHANGED.


				;**** FALL HERE FROM PREVIOUS PAGE ****
PPNOUT:	MOVEI	C,"["		;GET A LEADING BRACKET
	MOVE	T4,T1		;SAVE THE PPN AWAY
	PUTCHR			;OUTPUT IT
	HLRZ	T1,T4		;GET THE PROJECT
	CALL	OCTOUT		;OUTPUT IT
	MOVEI	C,","		;GET A COMMA
	PUTCHR			;GIVE IT
	MOVEI	T1,(T4)		;GET THE PROGRAMMER
	CALL	OCTOUT		;OUTPUT IT
	MOVEI	C,"]"		;GET THE TRAILING BRACKET
	PJRST	CHROUT		;OUTPUT IT AND RETURN



OCTOUT:	SKIPA	T3,[^D8]	;SET UP OCTAL
DECOUT:	MOVEI	T3,^D10		;SET UP DECIMAL
NUMOUT:	IDIVI	T1,(T3)		;GET A DIGIT IN T2
	JUMPE	T1,NUMFIN	;ALL DONE?
	HRLM	T2,(P)		;NO, STORE DIGIT
	CALL	NUMOUT		;GET NEXT DIGIT
	HLRZ	T2,(P)		;OK, GET BACK NEXT DIGIT
NUMFIN:	MOVEI	C,"0"(T2)	;MAKE ASCII CHAR
	PJRST	CHROUT		;OUTPUT AND RETURN




SIXOUT:	JUMPE	T1,CPOPJ	;WHEN HAVE NULL WORD ARE DONE
	SETZ	T2,		;CLEAR AN AC
	ROTC	T1,6		;GET NEXT CHAR IN T2
	MOVEI	C," "(T2)	;GET ASCII VALUE
	PUTCHR			;OUTPUT IT
	JRST	SIXOUT		;AND LOOP



SIXFUL:	MOVE	T2,[POINT 6,T1]	;GET A BYTE POINTER READY
SIXFLL:	ILDB	C,T2		;GET NEXT BYTE
	ADDI	C," "		;TURN INTO ASCII
	PUTCHR			;OUTPUT IT
	TLNE	T2,770000	;DID ALL SIX CHARACTERS?
	JRST	SIXFLL		;NO, KEEP GOING
	RET			;YES, DONE
CRLF:	MOVEI	T1,[ASCIZ/
/]				;GET ASCIZ STRING OF A CRLF
				;AND FALL INTO STRING OUTPUT ROUTINE


STROUT:	HRLI	T1,(POINT 7,)	;MAKE A BYTE POINTER
STROUX:	ILDB	C,T1		;GET THE NEXT CHAR
	JUMPE	C,CPOPJ		;QUIT WHEN GET A NULL
	PUTCHR			;OUTPUT IT
	JRST	STROUX		;AND LOOP






;HERE IS THE FINAL RESULT OF ALL THE TTY OUTPUT ROUTINES.  THIS
;ROUTINE IS CALLED TO OUTPUT A CHARACTER TO THE USER'S TTY, IF THAT
;IS POSSIBLE.  CERTAIN CONDITIONS PREVENT ANY OUTPUT.  CALL IS:
;
;	MOVEI	C,CHAR		;SETUP THE CHARACTER
;	CALL	CHROUT		;OUTPUT THE CHARACTER
;	(RETURN)		;ALL DONE
;
;NO AC'S ARE HURT




CHROUT:	TXNE	F,FL.SUP	;USER WANTS OUTPUT SUPPRESSED?
	RET			;YES, RETURN NOW
	TXNN	F,FR.DET	;ARE WE DETACHED?
	OUTCHR	C		;NO, THEN IT IS SAFE TO OUTPUT THE CHAR
	RET			;RETURN
	SUBTTL	TTY INPUT ROUTINES


;SIMPLE ROUTINE TO INPUT NEXT CHAR OF TTY COMMAND INTO AC C.  WE
;PROVIDE FOR RESCANS, AND TRANSLATE CHARACTERS.  CALL IS:
;
;	CALL	TTYIN		;GET THE NEXT CHARACTER
;	(RETURN)		;GOT ONE IN AC C


TTYIN:	AOSE	RRFLAG		;ARE WE TO REREAD A CHARACTER?
	INCHWL	SAVEC		;NO, THEN INPUT NEXT ONE FROM MONITOR
	MOVE	C,SAVEC		;GET CHARACTER INTO C
	CAIN	C,CTL(I)	;IS THE CHAR A TAB?
	MOVEI	C," "		;YES, CONVERT IT TO A SPACE
	CAIL	C," "		;A CONTROL CHARACTER?
	CAILE	C,174		;OR NON-HIGH CHARACTER
	JRST	TTYINC		;NO, GO CHECK FOR END OF LINES
	CAIL	C,"A"+40	;IS IT A LOWER CASE CHARACTER?
	CAILE	C,"Z"+40
	RET			;NO, THEN RETURN WITH IT
	SUBI	C,40		;YES, MAKE IT UPPER CASE
	RET			;THEN RETURN

TTYINC:	CAIE	C,15		;IS THIS A CARRIAGE RETURN?
	CAIN	C,177		;OR A RUBOUT?
	JRST	TTYIN		;YES, EAT IT UP
	CAIN	C,12		;ALREADY A LINE FEED?
	JRST	TTYBK2		;YES, JUST TYPE A CR
	CAIE	C,33		;AN ALTMODE?
	CAIN	C,7		;OR CONTROL-G?
	JRST	TTYBK1		;YES, CONVERT AND TYPE CRLF
	CAIE	C,175		;OLD TYPES OF ALTMODE?
	CAIN	C,176
	JRST	TTYBK1		;YES, CONVERT AND ALSO TYPE CRLF
	CAIE	C,CTL(K)	;A VERTICAL TAB?
	CAIN	C,CTL(L)	;OR A FORM FEED?
	JRST	TTYBK2		;YES, CONVERT AND JUST TYPE CR
	CAIE	C,CTL(Z)	;IS THIS A CONTROL-Z?
	CAIN	C,CTL(C)	;OR A CONTROL-C?
	JRST	KILXIT		;YES, GO EXIT
	CAIE	C,CTL(R)	;LAST STUPID BREAK CHAR?
	RET			;NO, RETURN WITH PROBABLY BAD CHAR

TTYBK1:	SKIPE	RRFLAG		;DON'T TYPE FOR A RESCANNED CHAR
	OUTCHR	[12]		;TYPE A LINEFEED
TTYBK2:	SKIPE	RRFLAG		;SKIP OUTPUT FOR RESCANNED CHAR
	OUTCHR	[15]		;AND A CARRIAGE RETURN
	MOVEI	C,12		;CONVERT EOL TO A LINE FEED
	RET			;THEN RETURN
;SUBROUTINE TO LOOK FOR THE FIRST NON-BLANK CHARACTER.  ALL CHARACTERS
;FROM THE PRESENT CHARACTER TO THE NEXT NON-SPACE OR NON-TAB ARE EATEN
;AND THAT NON-BLANK CHARACTER WILL BE THE NEXT CHARACTER INPUT.  CALL IS:
;
;	CALL	EATSPS		;EAT ALL BLANK CHARS
;	(RETURN)		;ALL DONE
;
;USES ONLY AC C.



EATSPS:	GETCHR			;GET THE NEXT CHARACTER
	CAIE	C," "		;IS THIS A SPACE?
	JRST	RPOPJ		;NO, THEN RETURN
	JRST	EATSPS		;YES, EAT IT AND LOOK AT NEXT CHAR




;ROUTINE TO INPUT A SIXBIT QUANTITY MADE UP OF THE CHARACTERS
;A-Z OR 0-9.  CALL IS:
;
;	CALL	SIXIN		;GET A SIXBIT VALUE
;	(RETURN)		;GOT IN IN AC T1.
;
;BEFORE LOOKING FOR THE WORD, PRECEEDING BLANKS ARE EATEN.
;IF NO SIXBIT WORD EXISTS, THEN T1 WILL BE ZERO.  USES T1 AND T2.



SIXIN:	CALL	EATSPS		;SLURP UP THE BLANKS FIRST
	MOVEI	T2,6		;SET UP A CHAR COUNT
SIXINL:	GETCHR			;INPUT THE NEXT CHARACTER
	CALL	ALFNUM		;IS IT ALPHANUMERIC?
	 JRST	SIXINF		;NO, THEN FINISH UP
	SOJL	T2,SIXINL	;IGNORE THE CHAR IF NO MORE ROOM LEFT
	LSH	T1,6		;IS ROOM, SHIFT OVER
	IORI	T1,-" "(C)	;PUT IN THIS CHAR
	JRST	SIXINL		;THEN GET THE NEXT CHAR

SIXINF:	JUMPLE	T2,RPOPJ	;RETURN IF WORD IS FULL
	IMULI	T2,6		;OTHERWISE SETUP TO JUSTIFY VALUE
	LSH	T1,(T2)		;DO IT
	JRST	RPOPJ		;AND RETURN
;NUMERIC INPUT ROUTINES.  THE FOLLOWING ROUTINES INPUT A NUMBER INTO
;AC T1 IN ANY RADIX DESIRED.  CALL IS:
;
;	CALL	ROUTINE		;GET A NUMBER OF DESIRED RADIX
;	(RETURN)		;GOT IT IN T1
;
;ON RETURN, T2 IS NEGATIVE IF A NUMBER WAS ACTUALLY FOUND, AND
;NONNEGATIVE OTHERWISE.  USES AC'S T1 AND T2.



DECINZ:	CALL	EATSPS		;EAT PRECEEDING SPACES FIRST
DECIN:	SKIPA	T2,[^D10]	;SET UP DECIMAL RADIX
OCTIN:	MOVEI	T2,^D8		;SET UP OCTAL RADIX
NUMIN:	MOVEI	T2,(T2)		;CLEAR LEFT HALF OF T2 AS A FLAG
	SETZ	T1,		;START OFF NUMBER WITH A ZERO
NUMINX:	GETCHR			;GET THE NEXT CHAR
	CAIL	C,"0"		;IS IT A VALID DIGIT?
	CAILE	C,"0"-1(T2)
	JRST	RPOPJ		;NO, RETURN WITH RESULT
	TLOE	T2,400000	;GOT ONE, SET THE FLAG
	IMULI	T1,(T2)		;MAKE ROOM FOR THE NEW DIGIT
	ADDI	T1,-"0"(C)	;ADD IT IN
	JRST	NUMINX		;AND LOOK FOR ANOTHER
;ROUTINE TO EAT ALL CHARACTERS UNTIL THE END OF LINE.  THIS MEANS
;THAT THE NEXT CHAR TO BE INPUT WILL BE THE BEGINNING OF THE NEXT
;LINE.  WE RESCAN FIRST, SO THAT WE NEVER WILL HANG ON THE NEXT LINE.
;CALL IS:
;
;	CALL	EATLIN		;GOBBLE THE REST OF THIS LINE
;	(RETURN)		;DID IT
;
;USES ONLY AC C.



EATLIN:	REREAD			;MAKE SURE WE NEVER HANG FIRST
EATLIX:	GETCHR			;GET THE NEXT CHARACTER
	CAIE	C,12		;IS THIS A BREAK CHARACTER?
	JRST	EATLIX		;NO, KEEP GOING
	RET			;YES, RETURN NOW





;ROUTINE TO DETERMINE IF A CHARACTER IN AC C IS A LETTER OR A DIGIT.
;CALL IS:
;
;	MOVEI	C,CHAR		;GET THE CHAR
;	CALL	ALFNUM		;SEE IF IT IS A LETTER OR A NUMBER
;	 (NO RETURN)		;NO, IT ISN'T
;	(YES RETURN)		;YES, IT SURE IS
;
;USES NO AC'S



ALFNUM:	CAIL	C,"0"		;IS IT LESS THAN A NUMBER?
	CAILE	C,"Z"		;OR GREATER THAN A LETTER?
	RET			;YES, THEN IS NOT ALPHANUMERIC
	CAIGE	C,"A"		;IS IT A LETTER FOR SURE?
	CAIG	C,"9"		;OR A DIGIT FOR SURE?
	AOS	(P)		;YES, THEN GIVE A SKIP RETURN
	RET			;RETURN
	SUBTTL	ROUTINE TO INPUT A WILD PPN



;THIS ROUTINE IS CALLED TO INPUT A PPN WHICH HAS LIMITED WILDCARDS.
;BY THIS IS MEANT A MASK IS NOT RETURNED, INSTEAD A -1 HALFWORD WILL
;MEAN THAT HALF OF THE PPN IS WILD.  USERS OWN PPN IS USED AS DEFAULT
;IF A HALF OF THE PPN IS NOT SUPPLIED.  CALL IS:
;
;	CALL	PPNIN		;INPUT A PPN
;	 (ERROR RETURN)		;NO PPN THERE, OR ELSE BAD FORMAT
;	(NORMAL RETURN)		;GAVE THE PPN IN AC T1
;
;ALL TEMP AC'S ARE USED.  ON AN ERROR, AC T1 IS ZERO IF NO PPN WAS
;TYPED (NO LEADING "["), AND NONZERO IF A PPN WAS THERE BUT HAS BAD
;FORMAT.



PPNIN:	GETCHR			;GET THE FIRST CHAR
	CAIE	C,"["		;START OF THE PPN?
	JRST	PPNER0		;NO, RETURN A ZERO AND NON-SKIP
	CALL	OCTIN		;NOW INPUT THE PROJECT NUMBER
	JSP	T4,PPNLGL	;SEE IF WILD AND SEE IF BAD NUMBER
	HLRZ	T1,MYPPN	;NO PROJECT GIVEN, USE OUR OWN
	MOVSI	T3,(T1)		;SAVE IT FOR LATER
	GETCHR			;NOW GET NEXT CHAR
	CAIE	C,","		;A COMMA FOLLOWING THE PROJECT?
	JRST	PPNER1		;NO, THEN ERROR
	CALL	OCTIN		;NOW INPUT THE PROGRAMMER NUMBER
	JSP	T4,PPNLGL	;SEE IF WILD AND SEE IF LEGAL
	HRRZ	T1,MYPPN	;NO PROGRAMMER GIVEN, USE OUR OWN
	IOR	T1,T3		;NOW PUT IN THE PROJECT
	GETCHR			;GET CHAR AFTER PROGRAMMER
	CAIE	C,"]"		;END OF THE PPN?
	REREAD			;NO, RESTORE CHARACTER
	RETSKP			;SKIP RETURN WITH PPN IN T1
;SUBROUTINE TO SEE IF PROJECT OR PROGRAMMER IS LEGAL, AND TO CHECK
;FOR A WILD PPN.  SKIP RETURN IF NUMBER SUPPLIED, NON-SKIP IF MUST
;BE DEFAULTED.  CALLED WITH JSP T4,PPNLGL, RIGHT AFTER A NUMBER WAS
;ATTEMPTED TO BE READ.



PPNLGL:	JUMPL	T2,PPNLGS	;JUMP IF HE REALLY TYPED A NUMBER
	CAIE	C,"*"		;WAS THE NEXT CHARACTER AN ASTERISK?
	JRST	(T4)		;NO, THEN NON-SKIP FOR DEFAULT VALUE
	GETCHR			;YES, EAT THE ASTERISK UP
	TROA	T1,-1		;WILDCARD, SET NUMBER TO -1
PPNLGS:	CAIGE	T1,-1		;DON'T ALLOW WILDCARD VALUE FOR TYPEIN
	JUMPG	T1,1(T4)	;IF POSITIVE, GOOD RETURN
PPNER1:	TLOA	T1,-1		;SET AC NONZERO TO INDICATE BAD PPN
PPNER0:	SETZ	T1,		;SET AC ZERO TO INDICATE NO PPN THERE
	JRST	RPOPJ		;RESTORE CHARACTER AND RETURN
	SUBTTL	ROUTINE TO SEARCH FOR ABBREVIATED MATCH


;THIS IS THE STANDARD ROUTINE TO SEARCH A TABLE OF SIXBIT WORDS FOR THE
;ONE WHICH MATCHES A GIVEN WORD.  AN EXACT MATCH ALWAYS WINS, WHILE
;AN ABBREVIATED MATCH WINS IF IT IS UNIQUE.  CALL IS:
;
;	MOVE	T1,WORD				;SET UP WORD TO LOOK FOR
;	MOVE	T2,[IOWD  LENGTH,ADDRESS]	;AND A POINTER
;	CALL	MATCH				;GO LOOK FOR THE MATCH
;	 (NO MATCH RETURN)			;NONE, OR TOO MANY
;	(UNIQUE MATCH RETURN)			;GOT INDEX IN T2
;
;ON A SKIP RETURN, A UNIQUE MATCH WAS FOUND, AND T2 CONTAINS THE
;INDEX INTO THE TABLE OF THE MATCH.  ON AN ERROR RETURN, T2 IS ZERO IF
;THERE WERE MULTIPLE MATCHES, AND NONZERO IF NOTHING MATCHED AT ALL.
;T1 IS NEVER CHANGED.  USES AC'S  T2, T3, AND T4.


MATCH:	PUSH	P,P1		;SAVE A PERMANENT AC
	MOVE	P1,T2		;SAVE THE POINTER TO THE TABLE
	MOVN	T2,T1		;SET UP TO GET RIGHTMOST NONZERO BIT
	AND	T2,T1		;LEAVE ONLY THAT BIT
	JFFO	T2,.+1		;GET POSITION IN WORD OF THE BIT
	IDIVI	T3,6		;GET LOCATION IN A SIXBIT BYTE OF BIT
	LSH	T2,-5(T4)	;RIGHT JUSTIFY THE BIT IN THE BYTE
	MOVN	T2,T2		;FINISH MAKING THE MASK
	MOVEI	T3,(P1)		;SAVE THE ADDRESS OF THE TABLE
	JUMPGE	P1,SRCALL	;GIVE UP IF NO TABLE


SRCLOP:	MOVE	T4,1(P1)	;GRAB THE NEXT WORD FROM TABLE
	XOR	T4,T1		;FIND DIFFERENCES BETWEEN IT AND OUR WORD
	JUMPE	T4,[MOVEI   T2,(P1)	;NO DIFFERENCES, GET LOCATION
		    JRST   EXACT]	;AND RETURN INDEX TO USER
	AND	T4,T2		;ZAP DIFFERENCES WE DON'T CARE ABOUT
	JUMPN	T4,SRCNXT	;JUMP IF WASN'T AN ABBREVIATION
	JUMPE	T3,SRCNXT	;JUMP IF ALREADY HAVE TOO MANY MATCHES
	TLNE	T3,-1		;ALREADY HAVE A MATCH?
	TDZA	T3,T3		;YES, ZERO WORD TO SAY HAVE TOO MANY
	HRLI	T3,(P1)		;FIRST ABBREVIATION, SAVE ITS ADDRESS
SRCNXT:	AOBJN	P1,SRCLOP	;GO LOOK AT NEXT WORD


SRCALL:	MOVE	T2,T3		;COPY ARG
	TLNN	T2,-1		;DID WE FIND A UNIQUE MATCH?
	JRST	PPOPJ		;NO, RETURN NON SKIP
	HLRZ	T2,T2		;YES, GET ADDRESS OF THE MATCH
EXACT:	SUBI	T2,(T3)		;SUBTRACT START OF TABLE TO GET INDEX
	JRST	PPOPJ1		;AND RETURN WITH A SKIP
	SUBTTL	ROUTINE TO READ IN A CCL FILE



;CALLED BEFORE COMMAND SCANNING TO SEE IF THERE IS A CCL FILE TO PROCESS.
;RETURNS:
;  +1:	CCL COMMANDS READ IN
;  +2:	NO CCL COMMANDS TO PROCESS



GETCCL:	TXNN	F,FR.CCL	;ENTERED AT CCL ENTRY POINT?
	RETSKP			;NO, THEN NO CCL COMMANDS
	MOVE	T1,[.TCRDF,,TCRINB]	;SETUP TO READ AND DELETE TMPCOR
	TMPCOR	T1,		;TRY TO READ THE TMPCOR FILE
	 SKIPA	T1,[UU.PHS+.IODMP]	;NONE THERE, SETUP FOR DISK
	RET			;GOT IT, RETURN WITH IT
	MOVSI	T2,'DSK'	;WANT DISK, PHYSICAL ONLY
	SETZ	T3,		;BUFFERS NOT NEEDED
	OPEN	CH.DSK,T1	;OPEN THE DISK IN DUMP MODE
	 DIE	OFD		;OPEN UUO FAILED FOR DISK
	MOVEI	T4,3		;SETUP A COUNT
	MOVE	T1,MYJOB	;AND GET MY JOB FOR MAKING SIXBIT JOB NO.
GETCCN:	IDIVI	T1,^D10		;GET A DIGIT OF THE JOB NUMBER
	ADDI	T2,'0'		;MAKE IT SIXBIT
	LSHC	T2,-6		;STORE DIGIT INTO AC T3
	SOJG	T4,GETCCN	;LOOP FOR 3 DIGITS
	HLR	T3,TCRINB	;GET FIRST 3 CHARS OF OUR NAME
	MOVSI	T4,'TMP'	;AND EXTENSION
	MOVE	T2,MYPPN	;DO NOT LOOK AT DEFAULT PATH
	MOVEI	T1,3		;MINIMUM NUMBER OF ARGS
	LOOKUP	CH.DSK,T1	;TRY TO LOOKUP THE .TMP FILE
	 JRST	GETCCF		;FAILED, GO ANALYZE
	CAME	T2,MYPPN	;MONITOR RETURN MY PPN?
	JRST	GETCCE		;NO, THEN GIVE AN ERROR
	INPUT	CH.DSK,DSKIOW	;INPUT 1 BLOCK OF THE FILE
	STATZ	CH.DSK,IO.ERR	;WAS THERE AN INPUT ERROR?
	 DIE	IFC		;YES, INPUT FAILED FOR CCL FILE
	SETZ	T3,		;OK, NOW WE WANT TO DELETE THE FILE
	RENAME	CH.DSK,T1	;TRY TO DO IT
	 JFCL			;IGNORE ANY FAILURE
	RELEAS	CH.DSK,		;LET GO OF DISK NOW
	RET			;AND RETURN
;HERE WHEN WE HAD A LOOKUP ERROR ON THE CCL FILE.



GETCCE:	SETO	T4,		;MAKE SURE WILL THINK THIS IS AN ERROR
GETCCF:	RELEAS	CH.DSK,		;FIRST LET GO OF THE DISK
	MOVEI	T4,(T4)		;GET THE ERROR CODE BY ITSELF
	CAIE	T4,ERFNF%	;IS IT FILE NOT FOUND?
	 DIE	CLE		;NO, CCL FILE LOOKUP ERROR
	TXZ	F,FR.CCL	;CLEAR CCL FILE FLAG
	RETSKP			;AND SKIP RETURN




;THE DATA FOR READING IN THE TMPCOR FILE FOR US.


TCRINB:	EXP	MYNAME&<-1,,0>	;OUR TMPCOR FILE NAME
DSKIOW:	IOWD	TCRLEN,TCRDAT	;AND IS IN THE BUFFER WE HAVE SET UP
	BLOCK	1		;ZERO WORD TO END IOWD FOR DISK INPUT
	SUBTTL	SUBROUTINE TO TYPE OUT A "SYSTAT" OF A JOB



;THIS SUBROUTINE IS USED TO OUTPUT A LINE OF INFORMATION ABOUT A JOB
;TO THE USER'S TTY.  CALLED FROM THE LIST COMMAND FOR ANY JOB WHICH
;SHOULD BE OUTPUT.  CALL IS:
;
;	MOVEI	J,JOB		;GET THE JOB
;	CALL	SYSTAT		;GO TYPE THE LINE
;	(DONE)			;DID IT
;
;USES AC'S  T1 - T4.



SYSTAT:	MOVEI	T1,[ASCIZ/ $1	/]	;GET SET TO OUTPUT JOB AND A TAB
	CALL	TXTCMD		;DO IT
	MOVEI	T1,(J)		;GET READY
	TRMNO.	T1,		;FIND WHICH TTY JOB IS ON
	 SETZ	T1,		;NONE, MAKE ZERO
	JUMPN	T1,NTDET	;JUMP IF ON SOME TTY
	OUTSTR	[ASCIZ/DET/]	;DETACHED, SAY SO
	JRST	NTCTRL		;AND OUTPUT MORE

NTDET:	SUBI	T1,.UXTRM	;REMOVE THE IOINDEX
	CALL	OCTOUT		;OUTPUT TTY NUMBER
	MOVEI	T1,(J)		;GET SET
	CTLJOB	T1,		;SEE IF JOB IS BEING CONTROLLED
	 JRST	NTCTRL		;FAILED, ASSUME NOT
	JUMPLE	T1,NTCTRL	;NO, THEN SKIP OUTPUT
	OUTCHR	["J"]		;OUTPUT A J
	CALL	DECOUT		;THEN OUTPUT THE CONTROLLING JOB

NTCTRL:	OUTCHR	["	"]	;OUTPUT A TAB
	MOVSI	T1,(J)		;GET READY
	IORI	T1,.GTPRG	;TO READ PROGRAM NAME
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CALL	SIXFUL		;TYPE IT
	CALL	STATE		;GET THE STATE OF THE JOB
	CALL	SIXOUT		;OUTPUT IT
	TLNE	T3,(JSWSWP)	;JOB SWAPPED OUT?
	OUTSTR	[ASCIZ/ SW   /]	;YES, TYPE SO
	TLNN	T3,(JSWSWP)	;WELL?
	OUTSTR	[ASCIZ/      /]	;NO, THEN SPACES INSTEAD
	MOVSI	T1,(J)		;SET UP JOB NUMBER
	IORI	T1,.GTNM1	;AND INDEX
	GETTAB	T1,		;FIND FIRST HALF OF USER NAME
	 ERROR	GTF		;FAILED
	CALL	SIXFUL		;OUTPUT IT
	MOVSI	T1,(J)		;ONCE MORE
	IORI	T1,.GTNM2	;SET UP INDEX
	GETTAB	T1,		;FIND SECOND HALF OF USER NAME
	 ERROR	GTF		;FAILED
	CALL	SIXFUL		;OUTPUT IT
	MOVSI	T1,(J)		;NOW GET SET
	IORI	T1,.GTPPN	;TO GET THE PPN OF THE JOB
	GETTAB	T1,		;GET IT
	 ERROR	GTF		;FAILED
	CAMN	T1,OLDPPN	;SAME AS THE PREVIOUS ONE WE DID?
	PJRST	CRLF		;YES, JUST TYPE A CRLF AND RETURN
	MOVEM	T1,OLDPPN	;NO, SAVE IT FOR NEXT TIME
	OUTSTR	[ASCIZ/   /]	;OUTPUT SOME SPACES
	MOVE	T1,OLDPPN	;GET THE JOB'S PPN
	CALL	PPNOUT		;OUTPUT IT
	PJRST	CRLF		;THEN FINISH WITH A CRLF
	SUBTTL	ROUTINE TO RETURN THE STATE OF A JOB



;RETURNS A SIXBIT QUANTITY IN AC T1 TELLING STATE OF A JOB.
;QUANTITY IS OF FORM   SIXBIT/   XX /   WHERE XX IS THE STATE
;IN 2-CHARACTER FORMAT, SUCH AS  SL, ^C, AND RN.  CALLED BY:
;
;	MOVE	J,JOB		;GET WHICH JOB TO DO
;	CALL	STATE		;GO FIND OUR THE STATE OF THE JOB
;	(RETURN)		;GOT IT IN AC T1
;
;USES AC'S  T1 - T3.  STATUS OF JOB IS LEFT IN T3.



STATE:	SKIPE	STTAB		;DO WE HAVE TABLE OF STATES?
	JRST	HAVTAB		;YES, THEN SKIP SOME
	SETZ	T2,		;GET SET TO GENERATE TABLE
GETTBL:	MOVSI	T1,(T2)		;SET UP THE INDEX
	IORI	T1,.GTWSN	;AND TABLE
	GETTAB	T1,		;GET IT
	 JRST	HAVTAB		;WHEN FAIL, ASSUME HAVE ALL OF THEM
	MOVEM	T1,STTAB(T2)	;STORE THIS WORD FOR LATER USE
	AOJA	T2,GETTBL	;THEN TRY TO GET ANOTHER WORD OF IT

HAVTAB:	MOVSI	T3,(J)		;GET SET
	GETTAB	T3,		;FIND OUT THE JOB STATUS WORD OF THE JOB
	 ERROR	GTF		;CAN'T, THEN RETURN WITH AN ERROR
	MOVEI	T1,'^W '	;SET UP IN CASE
	TLNE	T3,(JSWRUN)	;SEE IF RUNNING YET
	MOVEI	T1,'CW '	;YES, THEN DIFFERENT STATE POSSIBLE
	TLNE	T3,(JSWCMW)	;COMMAND IN PROGRESS?
	RET			;YES, RETURN WITH THAT
	MOVEI	T1,'OW '	;SET IN CASE
	TRNE	T3,JSWOPW	;IS IT OPERATOR WAIT?
	RET			;YES, RETURN
	MOVEI	T1,'^D '	;SET UP
	TRNE	T3,JSWDCM	;DAEMON CALLED BY COMMAND?
	RET			;YEP
	MOVEI	T1,'^C '	;SET UP IN CASE
	JUMPGE	T3,CPOPJ	;RETURN WITH ^C IF STOPPED
	MOVEI	T1,'RU '	;SET IN CASE
	TRNE	T3,JSWRUP	;IS A RUN UUO IN PROGRESS?
	RET			;YES, RETURN THAT
	LDB	T1,[POINT 5,T3,14]	;GET THE STATE NOW
	IDIVI	T1,3		;GET WHICH WORD OF TABLE TO USE
	LDB	T1,[POINT 12,STTAB(T1),11
		    POINT 12,STTAB(T1),23
		    POINT 12,STTAB(T1),35](T2)	;GET THE CODE
	LSH	T1,6		;MOVE OVER PROPERLY
	CAIN	T1,'SL '	;IS IT SLEEP STATE?
	TRNE	T3,JSWCLK	;AND IS THERE A CLOCK REQUEST IN?
	SKIPA			;NO
	MOVEI	T1,'HB '	;YES, INDICATE THAT
	CAIE	T1,'TI '	;DO WE HAVE TTY I/O?
	RET			;NO, THEN ARE ALL DONE
	MOVSI	T2,(J)		;YES, NOW GET SET
	IORI	T2,.GTTTY	;TO GET POINTER TO TTY DDB
	GETTAB	T2,		;GET IT
	 JRST	STATTW		;CAN'T, THEN USE TW
	JUMPE	T2,STATTW	;IF ZERO RETURNED USE TW ALSO
	MOVEI	T2,DEVIOS(T2)	;GET ADDRESS OF DEVIOS WORD
	PEEK	T2,		;GET IT
	TLNE	T2,(DEVOUT)	;IS TTY ACTUALLY IN OUTPUT WAIT?
	MOVEI	T1,'TO '	;YES, CHANGE STATE
	TLNN	T2,(DEVIOW)	;IS IT IN ANY WAIT AT ALL?
STATTW:	MOVEI	T1,'TW '	;NO, CHANGE STATE TO INDICATE THAT
	RET			;AND RETURN
	SUBTTL	ROUTINE TO TYPE OUT HELP FILE



;THIS ROUTINE IS CALLED TO TYPE OUT A HELP FILE FROM HLP: OR SYS:
;BY THE NAME OF KILL.HLP.  CALLED BY THE HELP FUNCTION BY:
;
;	CALL	DSPHLP		;GO TYPE HELP
;	(RETURN)		;ALL DONE
;
;USES AC'S  T1 - T4.




DSPHLP:	TXON	F,FR.HLP	;ALREADY TYPED THE HELP MESSAGE?
	TXNE	F,FL.SUP	;OR USER SUPPRESSING OUTPUT?
	RET			;YES, THEN NO HELP OUTPUT
	GETLIN	T1,		;GET MY TTY NAME
	TLNN	T1,-1		;AM I DETACHED?
	RET			;YES, THEN FORGET THE TEXT
	PUSH	P,P1		;SAVE P1
	PUSH	P,.JBFF		;AND PRESENT FIRST FREE
	MOVSI	P1,-HLPTRY	;SET UP AOBJN POINTER



;HERE TO LOOK FOR THE HELP FILE ON THE NEXT DEVICE


HLPNXT:	MOVE	T1,[.IOASC+UU.PHS]	;SET UP PHYSICAL ONLY ASCII MODE
	MOVE	T2,HLPTAB(P1)	;GET THE NEXT DEVICE
	MOVE	T3,(P)		;GET FIRST FREE LOCATION
	MOVEM	T3,.JBFF	;AND RESTORE FOR THIS PASS
	OPEN	CH.DSK,T1	;OPEN UP THE DEVICE
	 JRST	HLPLOP		;FAILED, GO TRY NEXT ONE
	MOVEI	T1,3		;SET UP FOR LOOKUP
	ADDM	T1,.JBFF	;UPDATE .JBFF PAST BUFFER HEADER
	SETZ	T2,		;USE DEFAULT PATH MAYBE
	MOVE	T3,[MYNAME]	;MY NAME
	MOVSI	T4,'HLP'	;AND EXTENSION .HLP
	LOOKUP	CH.DSK,T1	;SEE IF FILE IS THERE
	 JRST	HLPLOP		;CAN'T GET, TRY NEXT THING
	MOVE	T1,(P)		;GET ADDRESS OF BUFFER HEADER
;HERE WHEN FOUND A HELP FILE, TO TYPE IT OUT


HLPCHR:	SOSGE	2(T1)		;ANY MORE CHARS THIS BLOCK?
	JRST	HLPIN		;NO, GO GET NEXT ONE
	ILDB	C,1(T1)		;YES, GET IT
	JUMPE	C,HLPCHR	;IGNORE NULLS
	OUTCHR	C		;OUTPUT THE CHAR
	JRST	HLPCHR		;THEN GET NEXT ONE

HLPIN:	IN	CH.DSK,		;READ THE NEXT BLOCK
	 JRST	HLPCHR		;GOT IT, CONTINUE TYPING
	STATZ	CH.DSK,IO.ERR	;ERROR RETURN, HAVE ANY ERRORS?
	OUTSTR	[ASCIZ/
% INPUT error reading help file
/]				;YES, TELL ABOUT IT


HLPDON:	RELEAS	CH.DSK,		;LET GO OF THE CHANNEL
	POP	P,.JBFF		;RESTORE OLD .JBFF VALUE
	OUTSTR	[ASCIZ/
/]				;LOOK PRETTY
	JRST	PPOPJ		;AND RESTORE P1 AND RETURN



HLPLOP:	AOBJN	P1,HLPNXT	;GO TRY THE NEXT THING
	OUTSTR	[ASCIZ/
% Unable to find any help file, sorry
/]				;TELL HIM WE FAILED
	JRST	HLPDON		;AND GO FINISH UP





HLPTAB:	SIXBIT	/HLP/		;TRY HELP
	SIXBIT	/SYS/		;THEN SYS

	HLPTRY==.-HLPTAB	;NUMBER OF DEVICES TO LOOK FOR
	SUBTTL	ROUTINE TO INITIALIZE CORE




;WE CLEAR ALL THE IMPORTANT DATA AND TABLES, AND RESET .JBFF BACK TO
;THE ORIGINAL VALUE, AND FINALLY DO A CORE UUO TO SHRINK BACK TO A
;REASONABLE SIZE.  CALL IS:
;
;	CALL	INICOR		;GO INITIALIZE CORE
;	(RETURN)		;DID IT
;
;USES ONLY AC T1.




INICOR:	SETZM	ZERBEG		;ZERO FIRST WORD OF AREA
	MOVE	T1,[ZERBEG,,ZERBEG+1]	;GET A BLT POINTER
	BLT	T1,ZEREND	;ZERO REST OF AREA
	HLRZ	T1,.JBSA	;GET ORIGINAL VALUE OF .JBFF
	MOVEM	T1,.JBFF	;AND RESET IT
	ADDI	T1,^D100	;ADD A REASONABLE AMOUNT TO IT
	CAMG	T1,.JBREL	;ARE WE LARGER THAN THAT?
	CORE	T1,		;YES, THEN TRY TO SHRINK DOWN SOME
	 RET			;FAILED, NOT TOO IMPORTANT
	RET			;DID IT, RETURN
	SUBTTL	ROUTINES TO SET UP AND HANDLE ^C TRAPS



;THIS ROUTINE IS CALLED TO SETUP THE ^C TRAP.  THE TRAP IS PRETTY
;IMPORTANT TO PREVENT TIMING PROBLEMS THE MALICIOUS USER MIGHT TRY.
;WHEN WE GET A TRAP, WE JUST DO A RESET AND EXIT, NOTHING FANCY.
;CALL TO SET UP TRAP IS:
;
;	CALL	SETTRP		;GO SETUP FOR ^C TRAPPING
;	(RETURN)		;DID IT
;
;USES ONLY AC T1.



SETTRP:	MOVE	T1,[TRPCOD,,TRPBLK]	;SETUP FOR A BLT
	BLT	T1,TRPBLK+3	;MOVE INTERCEPT BLOCK TO LOW SEG
	MOVEI	T1,TRPBLK	;GET ADDRESS OF THE BLOCK
	MOVEM	T1,.JBINT	;STORE SO MONITOR KNOWS WHERE IT IS
	RET			;THEN RETURN



TRPCOD:	XWD	4,TRAPCC	;4 WORDS, TRAP ADDRESS IS TRAPCC
	EXP	ER.ICC		;ONLY TRAPPING FOR ^C
	BLOCK	2		;PC WORDS




;HERE TO EXIT FROM KILL BY COMMAND, OR IN CASE OF A ^C.


TRAPCC:	SETZM	TRPBLK+2	;ENABLE FOR ANOTHER TRAP
KILXIT:	RESET			;CLEAR ALL IO
	EXIT	1,		;EXIT NICELY
	JRST	KILL		;AND RESTART IF CONTINUED
	SUBTTL	ROUTINES TO SAVE THE AC'S



;THESE ARE STANDARD ROUTINES, SO NO MORE COMMMENT



SAVE3:	EXCH	P1,(P)		;SAVE P1, GET PC OF CALLER
	PUSH	P,P2		;SAVE P2
	PUSH	P,P3		;AND P3
	MOVEM	P1,1(P)		;PUT PC OF CALLER ON STACK
	MOVE	P1,-2(P)	;RESTORE P1
	CALL	@1(P)		;CALL THE USER BACK
	JRST	REST3		;NON-SKIP RETURN
	AOSA	-3(P)		;SKIP RETURN, INCREMENT ORIGINAL PC
REST2S:	AOSA	-2(P)		;INCREMENT PC SO WILL SKIP
REST3:	POP	P,P3		;RESTORE P3
REST2:	POP	P,P2		;AND P2
PPOPJ:	POP	P,P1		;AND FINALLY P1
	RET			;THEN RETURN



SAVE2:	EXCH	P1,(P)		;SAVE P1, GET PC
	PUSH	P,P2		;SAVE P2
	MOVEM	P1,1(P)		;PUT PC ON STACK
	MOVE	P1,-1(P)	;RESTORE P1
	CALL	@1(P)		;CALL USER BACK
	JRST	REST2		;NON-SKIP RETURN, RESTORE ACS AND RETURN
	JRST	REST2S		;SKIP RETURN, RESTORE ACS AND SKIP




SAVE1:	EXCH	P1,(P)		;SAVE P1, GET PC
	MOVEM	P1,1(P)		;PUT PC ON STACK
	MOVE	P1,(P)		;RESTORE P1
	CALL	@1(P)		;CALL USER BACK
	JRST	PPOPJ		;NON-SKIP, GO RESTORE P1 AND RETURN
PPOPJ1:	AOS	-1(P)		;SET UP FOR A SKIP
	JRST	PPOPJ		;RESTORE P1 AND RETURN



RPOPJ1:	AOSA	(P)		;SET UP FOR SKIP RETURN
CPOPJ1:	AOSA	(P)		;SET FOR SKIP
RPOPJ:	REREAD			;SET SO WILL REREAD LAST CHAR
CPOPJ:	RET			;AND THEN RETURN
	SUBTTL	TABLES FOR PROCESSING THE FUNCTIONS AND COMMANDS



;THE FOLLOWING TABLES ARE BUILT BY DEFINING THE MACRO "XX" AS DESIRED,
;AND THEN CALLING THE MACRO "FUNCTIONS" WHICH CONTAINS A LIST OF ALL
;FUNCTIONS.  THIS GENERATES THE DATA.  THE TABLES ARE SELF-EVIDENT:

	XALL		;ALLOW LISTING OF EXPANSIONS




DEFINE	XX(MNEM,PRI,LEN,CMMD),<
	FN.'MNEM==.-PRIFNC	;;DEFINE THE MNEMONIC FOR THIS FUNCTION
	PRIMSK==0		;;INITIALIZE THE MASK TO ZERO
	IRPC	PRI,<PRIMSK==PRIMSK!<1_<"PRI"-"A">>>	;;MAKE MASK
	PRIMAX==PRIMAX!PRIMSK	;;COMPUTE NEW MAXIMUM PRIORITY
	EXP	PRIMSK		;PRIORITY MASK FOR FUNCTION MNEM
>

	PRIMAX==0		;INITIALIZE MAXIMUM PRIORITY


PRIFNC:	FUNCTIONS		;THE PRIORITIES OF EACH FUNCTION


	FNCHGH==.-PRIFNC-1	;THE HIGHEST KNOWN FUNCTION
DEFINE	XX(MNEM,PRI,LEN,CMMD),<
	EXP	DSP'MNEM		;DISPATCH ADDRESS FOR FUNCTION MNEM
>


DSPFNC:	FUNCTIONS		;THE ROUTINES FOR THE FUNCTIONS




DEFINE	XX(MNEM,PRI,LEN,CMMD),<
	IFG	LEN,<
	EXP	LEN		;LENGTH OF ARG BLOCK FOR MNEM
>
	IFLE	LEN,<
	XWD	-1,SIZ'MNEM	;ROUTINE TO COMPUTE LENGTH OF MNEM BLOCK
>
>


LENFNC:	FUNCTIONS		;THE LENGTHS OF THE ARGUMENTS
DEFINE	XX(MNEM,PRI,LEN,CMMD),<
	IFNB	<CMMD>,<
	EXP	SIXBIT	/CMMD/   	;COMMAND CMMD
>
	IFB	<CMMD>,<
	EXP	0			;NO COMMAND FOR FUNCTION MNEM
>
>





CMDFNC:	FUNCTIONS			;THE NAMES OF THE COMMANDS
DEFINE	XX(MNEM,PRI,LEN,CMMD),<
	IFNB	<CMMD>,<
	EXP	CMD'MNEM		;DISPATCH ADDRESS FOR COMMAND CMMD
>
	IFB	<CMMD>,<
	EXP	CPOPJ		;NO COMMAND FOR FUNCTION MNEM
>
>





CMDDSP:	FUNCTIONS		;THE TABLE OF DISPATCHES FOR COMMANDS
	SUBTTL	THE LOW SEGMENT DATA AREA


;ALL THE TABLES AND CONSTANTS NECESSARY FOR KILL.  FIRST WE MUST DUMP
;OUT THE LITERALS:


	XLIST			;LITERALS
	LIT
	LIST

	LOC	.JBVER		;FIRST SET UP VERSION WORD
	EXP	VERSION		;AT .JBVER
	RELOC	0		;THEN BEGIN LOW SEGMENT



;FIRST COMES THE DATA THAT IS NEVER ZEROED WHEN INITIALIZING:


PDL:	BLOCK	PDLSIZ		;MAIN PUSH-DOWN STACK
MYPPN:	BLOCK	1		;MY PPN
MYJOB:	BLOCK	1		;AND MY JOB NUMBER
OPRPPN:	BLOCK	1		;OPERATOR PPN
PTYTTY:	BLOCK	1		;OFFSET FROM PTY NUMBER TO TTY NUMBER
HGHJOB:	BLOCK	1		;THE HIGHEST LEGAL JOB NUMBER
HGHTTY:	BLOCK	1		;THE HIGHEST LEGAL TTY NUMBER
STTAB:	BLOCK	^D20		;ROOM FOR STATE TABLE
TICSEC:	BLOCK	1		;NUMBER OF TICKS IN A SECOND
TRPBLK:	BLOCK	4		;THE ^C INTERCEPT BLOCK




;NOW FOR THE DATA WHICH IS ZEROED ON STARTUP, AND ON EVERY COMMAND:


	ZERBEG==.		;LOCATION WHERE ZEROING IS STARTED


RUNBLK:	BLOCK	7		;RUN UUO BLOCK FOR RUNNING USER'S PROG
TIMES:	BLOCK	JOBMAX		;TIMES WHEN JOBS WERE INITIALIZED
ACTION:	BLOCK	JOBMAX		;ADDRESS OF STARTING ROUTINE FOR A JOB
PPNS:	BLOCK	JOBMAX		;THE PPN OF EACH JOB
PTYALC:	BLOCK	PTYNUM		;THE JOB NUMBER USING EACH CHANNEL
TCRDAT:	BLOCK	TCRLEN+7	;CORE WHERE COMMANDS ARE READ IN IN BINARY
OLDPPN:	BLOCK	1		;PPN LAST TYPED ON LIST OUTPUT
LUUOP:	BLOCK	1		;PUSH-DOWN POINTER AT START OF AN LUUO
ERRPTR:	BLOCK	1		;POINTER INTO ERROR BLOCK
ERRCNT:	BLOCK	1		;NUMBER OF ERRORS STORED IN BLOCK
ERRBLK:	BLOCK	TMPSIZ		;AREA TO STORE ERRORS INTO
FNDCNT:	BLOCK	1		;COUNTER FOR FNDJOB SUBROUTINE
FNDMAX:	BLOCK	1		;HIGHEST JOB TO LOOP OVER
FNDSUB:	BLOCK	1		;ADDRESS TO CALL FROM FNDJOB ROUTINE
FNDDSP:	BLOCK	1		;ROUTINE TO CALL FROM FNDJOB
ARG1:	BLOCK	1		;FIRST PART OF ARGUMENT FROM TTY
ARG2:	BLOCK	1		;SECOND PART OF ARGUMENT FROM TTY
PTYBIN:	BLOCK	PTYNUM		;ADDRESS OF PTY INPUT BUFFER HEADERS
PTYBOT:	BLOCK	PTYNUM		;ADDRESS OF PTY OUTPUT BUFFER HEADERS
SAVET1:	BLOCK	1		;STORAGE FOR THE TEMP AC'S
SAVET2:	BLOCK	1		;WHEN HANDLING A LUUO
SAVET3:	BLOCK	1
SAVET4:	BLOCK	1
SAVEP:	BLOCK	1		;STORAGE FOR PUSH-DOWN POINTER
SAVEC:	BLOCK	1		;THE LAST CHARACTER INPUT
RRFLAG:	BLOCK	1		;-1 IF WE ARE TO REREAD LAST CHAR
TEMP1:	BLOCK	1		;A REAL TEMPORARY STORAGE LOCATION
WAITS:	BLOCK	JOBMAX		;TABLES OF UPTIMES EACH PROCESS WANTS TO
				;START RUNNING AGAIN
ACCS:	BLOCK	JOBMAX		;TABLE OF POINTERS FOR EACH PROCESSES'S
				;AREA FOR ACCUMULATOR STORAGE
ATTCNT:	BLOCK	1		;NUMBER OF JOBS DESIRING TO BE ATTACHED
TXEND:	BLOCK	1		;ADDRESS OF THE LAST CHAR IN STRING
TXORG1:	BLOCK	1		;FIRST WORD TO BE SAVED OF ORIGINAL STRING
TXORG2:	BLOCK	1		;SECOND WORD WHICH IS ORIGINAL TOO
TXNEW1:	BLOCK	1		;MODIFIED WORD OF STRING HAVING MONITOR DOTS
TXNEW2:	BLOCK	1		;SECOND WORD OF STRING WHICH IS MODIFIED
UPTIME:	BLOCK	1		;THE UPTIME OF THE SYSTEM
SCDCNT:	BLOCK	1		;NUMBER OF PROCESSING BEING RUN NOW


	ZEREND==.-1		;LAST LOCATION TO BE ZEROED


	END	KILL