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),> ;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 ,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, , .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 ;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 ;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 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,>> ;;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 ,< EXP SIXBIT /CMMD/ ;COMMAND CMMD > IFB ,< EXP 0 ;NO COMMAND FOR FUNCTION MNEM > > CMDFNC: FUNCTIONS ;THE NAMES OF THE COMMANDS DEFINE XX(MNEM,PRI,LEN,CMMD),< IFNB ,< EXP CMD'MNEM ;DISPATCH ADDRESS FOR COMMAND CMMD > IFB ,< 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