Trailing-Edge
-
PDP-10 Archives
-
tops10_tools_bb-fp64b-sb
-
10,7/kill/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==132 ;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,['LOGIN '] ;
TRNA ;YES, PROCEED
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