Trailing-Edge
-
PDP-10 Archives
-
bb-jr93e-bb
-
7,6/ap018/batcon.x18
There is 1 other file named batcon.x18 in the archive. Click here to see a list.
TITLE BATCON - GALAXY-10 Batch controller
SUBTTL C.D.O'Toole, D.P.Mastrovito /CDO/DPM 12-SEP-85
;
;
; COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1986,1987.
; ALL RIGHTS RESERVED.
;
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH BATMAC ;BATCON SYMBOLS
SEARCH GLXMAC ;GALAXY SYMBOLS
SEARCH QSRMAC ;QUASAR SYMBOLS
SEARCH ORNMAC ;ORION SYMBOLS
PROLOG (BATCON) ;SET UP
%%.BAT==:%%.BAT ;FORCE VERSION INTO SYMBOL TABLE
TOPS10 <IF1,<PRINTX [Assembling GALAXY-10 BATCON]>>
TOPS20 <IF1,<PRINTX [Assembling GALAXY-20 BATCON]>>
GLOB <LOGERR>
LOC <.JBVER==:137>
EXP %%.BAT ;BATCON VERSION NUMBER
RELOC 0
COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1971,1987. ALL RIGHTS RESERVED.
\;END COPYRIGHT MACRO
SUBTTL Table of contents
; TABLE OF CONTENTS FOR BATCON
;
;
; SECTION PAGE
; 1. Table of contents......................................... 2
; 2. BATCON Data Base.......................................... 3
; 3. Popular ITEXT blocks...................................... 4
; 4. Program initialization and reentry........................ 5
; 5. Job scheduler
; 5.1 Toplevel.......................................... 6
; 5.2 Fast batch shutdown............................... 8
; 5.3 Clock queue control............................... 9
; 5.4 Checkpoint........................................ 12
; 5.5 Message processing................................ 14
; 6. IPCF/Operator/QUASAR interface
; 6.1 IPCF interrupts................................... 15
; 6.2 Hello and goodbye................................. 16
; 6.3 IPCF message processing........................... 17
; 6.4 Message tables.................................... 18
; 6.5 Validate messages................................. 20
; 6.6 Initialize stream block........................... 21
; 6.7 Message block processing.......................... 22
; 6.8 QUASAR communication.............................. 23
; 6.9 Ask for operator response......................... 25
; 6.10 Unknown message................................... 26
; 6.11 QUASAR message #5 (NEXTJOB)....................... 27
; 6.12 QUASAR message #6 (ABORT)......................... 29
; 6.13 QUASAR message #22 (SETUP)........................ 30
; 6.14 QUASAR message #60 (ALLOCATION)................... 33
; 6.15 ORION message #200004 (PAUSE)..................... 34
; 6.16 ORION message #200005 (CONTINUE).................. 35
; 6.17 ORION message #200012 (RESPONSE).................. 36
; 6.18 ORION message #200025 (REQUEUE)................... 37
; 6.19 ORION message #200026 (CANCEL).................... 38
; 6.20 ORION message #200035 (SEND)...................... 40
; 6.21 ORION message #200036 (EXAMINE)................... 41
; 6.22 ACK message #700000............................... 42
; 7. STPPRC - Batch step processor............................. 44
; 8. JOBPRC - Process a Batch stream........................... 45
; 9. BATCON initialization
; 9.1 System independant code........................... 46
; 9.2 TOPS-10 code...................................... 47
; 9.3 TOPS-20 code...................................... 48
; 10. Batch generated commands
; 10.1 Buffer management................................. 49
; 10.2 TOPS-10 Login..................................... 51
; 10.3 TOPS-20 Login..................................... 54
; 10.4 Kill a job........................................ 56
; 10.5 CLOSE/DUMP........................................ 58
; 11. Batch WTO/WTOR
; 11.1 Initialization and character storage.............. 59
; 11.2 IPCF page setup................................... 60
; 11.3 Write To OPR (WTO)................................ 61
; 11.4 Write To OPR with a Response (WTOR)............... 62
; 11.5 Get operator response to a WTOR................... 63
; 12. Response buffer support................................... 64
; 13. Batch error handling
; 13.1 Error, operator, dialogue, or quote checking...... 65
; 13.2 LOGIN error analysis.............................. 66
; 14. MDA interface............................................. 67
; 15. MODIFY interface.......................................... 68
; 16. End of job processing..................................... 69
; 17. JOBINI - Initialize job processing........................ 70
; 18. TIMERR - Time limit exceeded.............................. 71
; 19. Stream termination
; 19.1 Dismiss job....................................... 73
; 19.2 Build release message............................. 74
; 19.3 Data base cleanup................................. 75
; 20. IOWAIT - Wait for I/O completion.......................... 76
; 21. Random Little Routines.................................... 77
; 22. DELSPL - Delete spooled input files....................... 78
; 23. Get job status............................................ 79
; 24. LUUO handler.............................................. 80
; 25. PTY interrupt handler..................................... 81
; 26. ERRTAB EXPAND ERROR TABLE VALUES......................... 82
; 27. Literals.................................................. 83
; 28. End....................................................... 84
SUBTTL BATCON Data Base
; Global data
;
LOWDAT:! ;BEGINING OF BLOCK TO CLEAR ON START UP
G$PDL:: BLOCK TPSIZE ;TOP LEVEL PUSH DOWN LIST
G$IB:: BLOCK IB.SZ ;GLXLIB INITIALIZATION BLOCK
G$PIB:: BLOCK PB.MNS ;GLXLIB PID BLOCK
G$SAB:: BLOCK SAB.SZ ;GLXLIB IPCF SEND ARGUMENT BLOCK
G$MDA:: BLOCK 1 ;MDA FLAG
G$UDT:: BLOCK 1 ;DATE/TIME OF LAST SCHEDULER PASS
G$CPU:: BLOCK 1 ;CPU TYPE CODE
G$MADR:: BLOCK 1 ;MESSAGE ADDRESS
G$MIDX:: BLOCK 1 ;INDEX INTO MESSAGE TABLES
G$MBLK:: BLOCK 1 ;MESSAGE BLOCK POINTER
G$MARG:: BLOCK 1 ;MESSAGE ARGUMENT COUNT
G$CORE:: BLOCK 1 ;FLAG WORD FOR CORE CHECKING
G$NODE:: BLOCK 1 ;BATCON'S NODE
G$SPLD:: BLOCK 1 ;SPOOLED PPN OR DIRECTORY NUMBER
G$PTYF:: BLOCK 1 ;FIRST PTY IN THE SYSTEM
G$PTYN:: BLOCK 1 ;NUMBER OF PTYS IN THE SYSTEM
G$TIME:: BLOCK 2 ;ASCIZ TIME FOR TIME STAMPS
G$STRM:: BLOCK JOBMAX ;STREAM INDEX BLOCK
G$BASE:: BLOCK JOBMAX ;STREAM DATA BASE POINTERS
G$FAIR:: BLOCK 1 ;FAIRNESS COUNT
G$FFLG:: BLOCK 1 ;FAIRNESS COUNT EXPIRED FLAG
G$KILL:: BLOCK 1 ;KILL ALL JOBS FLAG
G$PSCN:: BLOCK 1 ;PRESCAN FLAG
G$HACT:: BLOCK 1 ;HIGHEST STREAM NUMBER ACTIVE
G$SACT:: BLOCK 1 ;NUMBER OF ACTIVE STREAMS
G$TMTX:: BLOCK 2 ;ASCIZ TIME TEXT BUFFER
G$TPTR:: BLOCK 1 ;TEMPORARY BYTE POINTER
G$TCTR:: BLOCK 1 ;TEMPORARY BYTE COUNT
G$KSYS:: BLOCK 1 ;NON-ZERO IF KSYS IN PROGRESS
G$BUDT:: BLOCK 1 ;UDT WHEN TO SAY GOODBYE IF IDLE
G$SSET:: BLOCK 1 ;NUMBER OF STREAMS SETUP
; Local data
;
WTOCNT: BLOCK 1 ;WTO BYTE COUNTER
WTOPTR: BLOCK 1 ;WTO BYTE POINTER
MAX <RSU.SZ!REL.BL!STU.SZ!REQ.SZ!CHE.SZ>
MSGADR: BLOCK MAXSIZ ;MESSAGE DATA AREA
SLPTIM: BLOCK 1 ;TIME TO SLEEP
CLKQUE: BLOCK 1 ;CLOCK REQUEST QUEUE ID
CLKEID: BLOCK 1 ;CLOCK QUEUE ENTRY ID COUNTER
TOPS10 < ;TOPS-10 ONLY
VECTOR:! ;BEGINING OF INTERRUPT VECTOR BLOCKS
VECIPC: BLOCK 4 ;IPCF INTERRUPT BLOCK
ENDVEC==.-1 ;END OF INTERRUPT VECTORS
OPRPPN: BLOCK 1 ;OPERATOR PPN
KSYZBG:! ;START OF KSYS DATA TO ZERO
KSYCNT: BLOCK 1 ;COUNT OF JOBS TO KILL
KSYSSC: BLOCK 1 ;COUNT OF KSYS STREAMS SETUP
KSYUSE: BLOCK 1 ;COUNT OF KSYS STREAMS IN USE
KSYREQ: BLOCK 1 ;FAKE REQUEST-ID
KSYNAM: BLOCK 1 ;LAST LOG FILE NAME
KSYJLO: BLOCK 1 ;COUNT OF JOBS LOGGED OFF
KSYJLE: BLOCK 1 ;COUNT OF JOBS LOGGED OFF WITH ERRORS
KSYMAP: BLOCK <^D512/^D36> ;KSYS BIT MAP
KSYLEN==.-KSYMAP ;LENGTH OF BIT MAP
KSYZND:! ;END OF KSYS DATA TO ZERO
> ;END OF TOPS-10 CONDITIONAL
TOPS20 < ;TOPS-20 ONLY
LEVTAB: BLOCK 3 ;INTERRUPT LEVEL PCS
CHNTAB: BLOCK ^D36 ;INTERRUPT CHANNEL TABLE
INTRP1: BLOCK 1 ;INTERRUPT LEVEL 1 PC
INTRP2: BLOCK 1 ;INTERRUPT LEVEL 2 PC
INTRP3: BLOCK 1 ;INTERRUPT LEVEL 3 PC
JSTBLK: BLOCK .JIMAX ;GETJI JSYS JOB STATUS BLOCK
> ;END OF TOPS-20 CONDITIONAL
LASLOW:! ;END OF BLOCK TO CLEAR ON START UP
SUBTTL Popular ITEXT blocks
; Output job information contained in .JQJBB(R)
;
JIBTXT:: ITEXT (<^R/.JQJBB(R)/^M^J>)
; Output <number> for WTOR messages
;
NUMBER:: ITEXT (<^7/[.CHLAB]/number^7/[.CHRAB]/>)
SUBTTL Program initialization and reentry
BATCON: JFCL ;NO CCL ENTRY
RESET ;STOP I/O
MOVE P,[IOWD TPSIZE,G$PDL] ;SET UP THE PDL
SETZM LOWDAT ;CLEAR THE FIRST DATA WORD
MOVE S1,[LOWDAT,,LOWDAT+1] ;SET UP BLT
BLT S1,LASLOW-1 ;CLEAR THE REST OF THE DATA SECTION
; Build the IB
;
MOVE S1,['BATCON'] ;OUR NAME
MOVEM S1,G$IB+IB.PRG ;STORE IT
MOVX S1,IP.STP ;SEND STOPCODES TO ORION
SKIPE DEBUGW ;DEBUGGING?
MOVX S1,IB.NPF ;YES - NO STOPCODES TO ORION, NO PFH
MOVEM S1,G$IB+IB.FLG ;STORE IN FLAG WORD
MOVEI S1,G$PIB ;POINT TO PID BLOCK
MOVEM S1,G$IB+IB.PIB ;STORE IT
TOPS10 <MOVEI S1,VECTOR> ;TOPS-10 PSI INTERRUPT VECTOR ADDRESS
TOPS20 <MOVE S1,[LEVTAB,,CHNTAB]> ;TOPS-20 PSI INTERRUPT TABLES
MOVEM S1,G$IB+IB.INT ;STORE IT
; Build the PIB
;
MOVX S1,INSVL.(PB.MNS,PB.LEN) ;GET BLOCK LENGTH
MOVEM S1,G$PIB+PB.HDR ;STORE IT
MOVX S1,IP.PSI ;ENABLE FOR IPCF PSI
MOVEM S1,G$PIB+PB.FLG ;SET FLAGS
MOVX S1,<INSVL.(SNDMAX,IP.SQT)!INSVL.(RCVMAX,IP.RQT)> ;IPCF QUOTAS
MOVEM S1,G$PIB+PB.SYS ;STORE THEM
TOPS10 <MOVX S1,INSVL.(VECIPC-VECTOR,IP.CHN)> ;TOPS-10 IPCF PSI VECTOR
TOPS20 <MOVX S1,INSVL.(IPCCHN,IP.CHN)> ;TOPS-20 IPCF INTERRUPT CHANNEL
MOVEM S1,G$PIB+PB.INT ;STORE IT
MOVEI S1,IB.SZ ;GET LENGTH OF BLOCK
MOVEI S2,G$IB ;GET ADDRESS OF BLOCK
PUSHJ P,I%INIT## ;INITIALIZE GLXLIB
PUSHJ P,B$INIT ;INITIALIZE BATCON
PUSHJ P,U$INIT## ;INITIALIZE CUSTOMER CODE
JRST TOPLVL ;ENTER JOB SCHEDULER
REENTER:SETOM G$KILL ;SHUTDOWN BATCH SYSTEM
TOPS10 <JRSTF @.JBOPC##> ;RETURN
TOPS20 <JRST TOPLVL> ;HOPE WE WERE STOPPED IN A SAFE PLACE
SUBTTL Job scheduler -- Toplevel
TOPLVL: PUSHJ P,KILCHK ;SEE IF WE MUST KILL ALL JOBS
PUSHJ P,U$SCHD## ;PROCESS CUSTOMER SCHEDULER STUFF
PUSHJ P,IPCF ;PROCESS IPCF MESSAGES
TOPL.1: SETZM G$FFLG ;CLEAR FAIRNESS EXPIRED FLAG
SKIPLE KSYCNT ;KSYS IN PROGRESS?
PUSHJ P,KSYSCD ;YES--SCHEDULE SOME JOBS
MOVX S,.INFIN ;A LARGE NUMBER INCASE NONE ACTIVE
SKIPN G$SACT ;ANY STREAMS ACTIVE?
JRST STEXIT ;NO - WAIT A WHILE
PUSHJ P,CLKCHK ;COUNTDOWN THE CLOCK REQUEST QUEUE
SETZ S, ;START WITH STREAM 0
TOPL.2: SKIPL R,G$BASE(S) ;GET DATA BASE ADDRESS AND STREAM FLAGS
JRST STEXIT ;STREAM NOT ACTIVE
MOVE F,.JREGS+F(R) ;LOAD STREAM FLAGS
PUSHJ P,JOBCHK ;CHECK FOR JOB'S EXISTANCE
PUSHJ P,CHKPNT ;DO CHECKPOINT IF NEEDED
PUSHJ P,PROMES ;PROCESS ANY OPERATION MESSAGES
MOVEM F,.JREGS+F(R) ;UPDATE FLAG WORD
MOVEM R,G$BASE(S) ;FLAGS HERE TOO
TXZE R,RL.MSP ;MESSAGE TO PROCESS?
JRST TOPL.3 ;YES - THEN PROCESS IT NOW
TXNE R,RL.STP!RL.OPR!RL.NSC!RL.ACK ;STOPPED, OPR/ACK WAIT, NO SCHED?
JRST STEXIT ;YES TO EITHER - IGNORE STREAM
MOVEM R,G$BASE(S) ;UPDATE RELOCATION
TOPL.3: HRLZI 0,.JREGS+1(R) ;SET UP BLT
HRRI 0,1 ;START WITH AC 1
BLT 0,14 ;LOAD ACS 1 - 14
MOVE 0,.JREGS(R) ;LOAD AC 0
MOVE 17,.JREGS+17(R) ;RELOAD AC 17
POPJ P, ;RETURN TO INTERRUPTED PROCESS
; Return from process (switch to BATCON's context).
;
QTS:: MOVEM R,G$BASE(S) ;STORE STREAM RELOCATION
MOVEM 0,.JREGS(R) ;SAVE AC 0
HRLZI 0,1 ;START WITH AC 1
HRRI 0,.JREGS+1(R) ;SET UP BLT
BLT 0,.JREGS+17(R) ;SAVE THE ACS
MOVE P,[IOWD TPSIZE,G$PDL] ;RESET BATCON'S PDL
; Here to exit from the stream
; *** Note ***
; STEXIT must be called by JRST STEXIT after CLRSTR is called since the
; stream stack (and data base) has been destroyed.
;
STEXIT: CAMGE S,G$HACT ;CHECKED ALL STREAMS YET?
AOJA S,TOPL.2 ;NO - TRY THE NEXT
AOSG G$PSCN ;DONE WITH A PRESCAN?
JRST TOPLVL ;YES - THEN NO TIME TO REST
SETZM G$PSCN ;INSURE WE DON'T ATTEMPT A PRESCAN
SKIPG G$FFLG ;FAIRNESS COUNT EXPIRE DURING JOB SCAN?
PUSHJ P,TSLEEP ;ZZZZZZ
JRST TOPLVL ;BACK TO TOP LEVEL
SUBTTL Job scheduler -- Fast batch shutdown
; Set up to kill all jobs if necessary (G$KILL non-zero).
; This routine will set the fast KJOB bit (RL.FKJ) and cause BATCON to
; kill the stream on the next pass. No attempt is made to send release
; messages to QUASAR, nor is any attempt made to recover from batch errors
; such as a job not in monitor mode or not logging out.
;
KILCHK: SKIPN G$KILL ;WANT TO KILL ALL JOBS?
POPJ P, ;NO - JUST RETURN
MOVEI S,0 ;START WITH STREAM 0
KILC.1: SKIPGE R,G$BASE(S) ;GET DATA BASE ADDRESS AND STREAM FLAGS
TXOE R,RL.FKJ ;NEED TO DO ANYTHING?
JRST KILC.2 ;NO - ON TO THE NEXT ONE
HRLI T1,-.JPSIZ ;RESET THE STREAM PDL
HRRI T1,.JPLST-1(R) ;...
PUSH T1,[B$CLOS] ;POINT TO THE CLOSE JOB ROUTINE
MOVEM T1,.JREGS+P(R) ;SAVE AS STREAM AC 'P'
TXZ R,RL.OPR!RL.STP!RL.JIE!RL.DIA ;CLEAR BATCH STREAM FLAGS
MOVX T1,FL.NER ;GET NOERROR BIT
IORM T1,.JREGS+F(R) ;SET IT
TXZ R,RL.OPR!RL.STP!RL.JIE!RL.DIA!RL.NLG ;CLEAR LOTS OF FLAGS
MOVEM R,G$BASE(S) ;UPDATE STATUS
KILC.2: CAMGE S,G$HACT ;CHECKED ALL STREAMS YET?
AOJA S,KILC.1 ;NO - LOOP
SETZM G$PSCN ;FORGET ANY PRESCAN REQUESTS
POPJ P, ;RETURN
SUBTTL Job scheduler -- Clock queue control
; Create a clock request
; Call: MOVE T1,event code,,time in seconds
; MOVE T2,dispatch address
; MOVE T3,context
; PUSHJ P,B$CLKR
; PUSHJ P,B$CLKB ;AUTOMATICALLY SET UP T3 WITH -1 (BATCON)
; PUSHJ P,B$CLKS ;AUTOMATICALLY SET UP T3 WITH C(S) (STREAM)
;
; On return, .JBCLK(R):= event code,,clock queue entry ID
;
B$CLKS::SKIPA T3,S ;INDICATE STREAM CONTEXT
B$CLKB::HRLOI T3,-1 ;INDICATE BATCON'S CONTEXT
B$CLKR::MOVE T4,T1 ;GET EVENT CODE AND SLEEP TIME
LOAD S1,T1,CQ.TIM ;GET TIME IN SECONDS
ASHC S1,-21 ;POSITION FRACTION
DIV S1,[^D24*^D60*^D60] ;DIVIDE BY SECONDS PER DAY
CAILE S2,<^D24*^D60*^D60>/2 ;OVER HALF TO THE NEXT?
AOS S1 ;YES - INCREMENT THE UDT
MOVE T1,S1 ;SAVE UDT IN A SAFE PLACE
$CALL I%NOW ;GET CURRENT DATE/TIME
ADD T1,S1 ;MAKE IT THE WAKEUP DATE/TIME
MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%FIRST ;GET THE FIRST ENTRY
JRST CLKR.2 ;JUMP THE FIRST TIME THROUGH
CLKR.1: MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%NEXT ;GET THE NEXT ENTRY
CLKR.2: JUMPT CLKR.3 ;ONWARD IF NO ERRORS
MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
MOVEI S2,.CQLEN ;GET CLOCK QUEUE ENTRY LENGTH
$CALL L%CENT ;CREATE AN ENTRY AFTER THE CURRENT ONE
JRST CLKR.4 ;CONTINUE
CLKR.3: CAML T1,.CQTIM(S2) ;LESS THAN THE CURRENT ENTRY?
JRST CLKR.1 ;YES - TRY THE NEXT ENTRY
MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
MOVEI S2,.CQLEN ;GET CLOCK QUEUE ENTRY LENGTH
$CALL L%CBFR ;CREATE AN ENTRY BEFORE THE CURRENT ONE
CLKR.4: MOVEM T1,.CQTIM(S2) ;SAVE UDT WAKEUP TIME
MOVEM T2,.CQADR(S2) ;SAVE DISPATCH ADDRESS
MOVEM T3,.CQCTX(S2) ;SAVE CONTEXT AFTER WAKEUP
MOVEM T4,.CQEVN(S2) ;SAVE EVENT CODE AND SLEEP TIME
AOS S1,CLKEID ;GET A NEW CLOCK QUEUE ENTRY ID
HRRZM S1,.CQEID(S2) ;SAVE IT
JUMPL T3,CLKR.5 ;CHECK FOR BATCON'S CONTEXT
MOVE S1,T4 ;GET THE EVENT CODE
HRR S1,.CQEID(S2) ;GET THE ENTRY ID
SKIPGE T4,G$BASE(T3) ;GET STREAM RELOCATION
MOVEM S1,.JBCLK(T4) ;SET UP CLOCK QUEUE DATA WORD
TXNN S1,CQ.NSC ;TURN OFF SCHEDULING FOR THIS STREAM?
JRST CLKR.5 ;NO
MOVX S1,RL.NSC ;GET NO SCHEDULE FLAG
IORM S1,G$BASE(T3) ;UPDATE RELOCATION WORD
CAMN T3,S ;CURRENT STREAM?
TXO R,RL.NSC ;YES
CLKR.5: PUSHJ P,CLKTIM ;COMPUTE NEW SLEEP TIME
POPJ P, ;RETURN
; Kill a clock request
; Call: MOVE T1,clock queue entry ID
; PUSHJ P,B$CLKK
;
B$CLKK::HRRZS T1 ;MAKE SURE IT'S ONLY THE ENTRY ID
MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%FIRST ;GET THE FIRST ENTRY
JRST CLKK.2 ;JUMP THE FIRST TIME THROUGH
CLKK.1: MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%NEXT ;GET THE NEXT ENTRY
CLKK.2: JUMPF .POPJ ;RETURN OF END OF LINKED LIST
CAME T1,.CQEID(S2) ;FOUND THE ENTRY?
JRST CLKK.1 ;NO - TRY ANOTHER ONE
CLKDEL: SKIPGE S1,.CQCTX(S2) ;STREAM CONTEXT?
JRST CLKK.3 ;NO
SKIPGE S2,G$BASE(S1) ;GET STREAM RELOCATION
SETZM .JBCLK(S2) ;CLEAR CLOCK QUEUE DATA WORD
TXZ S2,RL.NSC ;CLEAR NO SCHEDULE FLAG
MOVEM S2,G$BASE(S1) ;UPDATE RELOCATION WORD
CLKK.3: MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%DENT ;DELETE THE ENTRY
POPJ P, ;RETURN
CLKCHK: SETZM SLPTIM ;CLEAR SLEEP TIME
$CALL I%NOW ;GET CURRENT UDT
MOVEM S1,G$UDT ;SAVE IT
$TEXT (<-1,,G$TIME>,<^C/G$UDT/^0>) ;CREATE ASCIZ TIME STAMP
MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%FIRST ;GET THE FIRST ENTRY
JRST CLKC.2 ;ONWARD
CLKC.1: MOVE S1,CLKQUE ;GET THE CLOCK QUEUE ID
$CALL L%NEXT ;GET THE NEXT ENTRY
CLKC.2: JUMPF .POPJ ;END OF LINKED LIST
MOVE S1,.CQTIM(S2) ;GET UDT FOR THIS ENTRY
CAMG S1,G$UDT ;TIME TO PROCESS THIS REQUEST?
HRRZS .CQEVN(S2) ;YES - CLEAR PENDING EVENT CODE
LOAD S1,.CQEVN(S2),CQ.EVN ;GET THE PENDING EVENT CODE
CAIL S1,.CQMIN ;RANGE CHECK
CAILE S1,.CQMAX ; THE EVENT TYPE
JRST CLKC.6 ;ILLEGAL - DON'T DO EVENT CHECKING
SKIPGE S,.CQCTX(S2) ;NEED TO SETUP STREAM STATUS?
JRST CLKC.3 ;NO
SKIPL R,G$BASE(S) ;SET UP STREAM RELOCATION
JRST CLKC.5 ;NOT ACTIVE
PUSHJ P,P$STAT## ;UPDATE JOB STATUS
MOVEM J,.JREGS+J(R) ;SAVE FOR LATER
CLKC.3: PUSHJ P,@CLKTAB(S1) ;CHECK IT OUT
JRST CLKC.6 ;EVENT NOT SATISFIED YET
JUMPL S,CLKC.4 ;CHECK FOR BATCON'S CONTEXT
MOVE S1,.JREGS+P(R) ;GET STREAM'S STACK
SKIPE .CQADR(S2) ;NEED TO PUSH A DISPATCH ADDRESS?
PUSH S1,.CQADR(S2) ;YES - DO IT
MOVEM S1,.JREGS+P(R) ;UPDATE STREAM'S STACK POINTER
JRST CLKC.5 ;ONWARD
CLKC.4: PUSH P,S2 ;SAVE FROM DESTRUCTION
PUSHJ P,@.CQADR(S2) ;DISPATCH IN BATCON'S CONTEXT
POP P,S2 ;RESTORE CLOCK QUEUE ENTRY ADDRESS
CLKC.5: PUSHJ P,CLKDEL ;DELETE THE ENTRY
JRST CLKC.1 ;TRY THE NEXT ONE
CLKC.6: SKIPN SLPTIM ;COMPUTED A SLEEP TIME YET?
PUSHJ P,CLKTIM ;NO - DO IT NOW
JRST CLKC.1 ;YES
; Clock queue event dispatch table
;
CLKTAB: EXP EVNHNG ;(00) HUNG TIMER
EXP EVNLGI ;(01) LOGIN
EXP EVNLGO ;(02) LOGOUT
EXP EVNHLT ;(03) HALT
EVNHNG: MOVE S1,.CQTIM(S2) ;GET UDT FOR THIS ENTRY
CAMG S1,G$UDT ;TIME TO PROCESS IT?
AOS (P) ;YES
POPJ P, ;RETURN
EVNLGI: TXNE J,JL.ULI ;IS A JOB LOGGED IN?
EVNHLT: TXNN J,JL.UML ;IN MONITOR MODE?
AOS (P) ;YES
POPJ P, ;RETURN
EVNLGO: TXNN R,RL.FKJ ;FAST KJOB?
TXNN J,JL.ULI ;LOGGED OUT?
AOS (P) ;YES
POPJ P, ;RETURN
; Compute the time to sleep
; Call: MOVE S2, clock queue entry address
; PUSHJ P,CLKTIM
;
; On return, SLPTIM:= updated sleep time
;
CLKTIM: PUSH P,S2 ;SAVE FROM DESTRUCTION
MOVE S1,.CQTIM(S2) ;GET WAKEUP UDT
SUB S1,G$UDT ;GET OFFSET FROM NOW
MULI S1,<^D24*^D60*^D60> ;MULTIPLY BY NUMBER OF SECS/DAY
ASHC S1,21 ;POSITION RESULT
SKIPE SLPTIM ;ZERO?
CAMG S1,SLPTIM ;GREATER THAN THE CURRENT ONE?
MOVEM S1,SLPTIM ;SAVE IT
POP P,S2 ;RESTORE S2
POPJ P, ;RETURN
SUBTTL Job scheduler -- Timed sleep
TSLEEP: SKIPLE S1,G$BUDT ;CARE ABOUT ACTVIITY?
SKIPE G$SACT ;ANY ACTIVE STREAMS?
JRST [SOJL S1,TSLP.2 ;JUMP IF DON'T CARE
MOVEI S1,1 ;WE CARE, BUT THERE'S ACTIVITIY
MOVEM S1,G$BUDT ;RESET G$BUDT
JRST TSLP.2]
SOJE S1,TSLP.1 ;JUMP IF TIME NEEDS TO BE SET
$CALL I%NOW ;GET CURRENT TIME
CAMGE S1,G$BUDT ;TIME TO SAY GOODBYE?
JRST TSLP.2 ;NOT YET
PJRST IDLBYE ;YES, GO SAY GOODBYE AND LOGOUT
TSLP.1: $CALL I%NOW ;GET CURRENT TIME
ADD S1,[EXP IDLMIN*^D60*^D3];COMPUTE TIME TO SAY GOODBYE
MOVEM S1,G$BUDT ;SAVE IT FOR CHECKING LATER
TSLP.2: MOVEI S1,IZTIME ;GET INACTIVE TIME MAXIMUM
SKIPE G$SACT ;STREAMS ACTIVE?
MOVEI S1,AZTIME ;NO, GET ACTIVE SLEEP TIME MAXIMUM
SKIPN S2,SLPTIM ;GET COMPUTED SLEEP TIME
MOVE S2,S1 ;NO CLOCK REQUESTS
CAMLE S1,S2 ;WHICH IS SMALLER?
MOVE S1,S2 ;USE THE COMPUTED VALUE
TOPS10 <TXO S1,HB.RPT> ;WAKE ON PTY ACTIVITY
$CALL I%SLP ;ZZZZZZ
POPJ P, ;RETURN
SUBTTL Job scheduler -- Job check
JOBCHK: TXNN R,RL.LGI!RL.KJB ;LOGGING IN OR OUT?
TXNE F,FL.UKJ ;USER REQUEST KJOB?
POPJ P, ;MAYBE THERE ISN'T A JOB (THATS OK)
PUSHJ P,P$STAT## ;GET JOB STATUS
TXNE J,JL.ULI!JL.UJA ;JOB STILL THERE?
POPJ P, ;ALL'S WELL
TXZ R,RL.STP!RL.OPR!RL.NSC!RL.ACK ;MAKE JOB RUNABLE
MOVE S1,.JREGS+P(R) ;GET STREAM'S STACK
PUSH S1,[B$GONE] ;START STREAM HERE
MOVEM S1,.JREGS+P(R) ;REPLACE STACK
POPJ P, ;RETURN
SUBTTL Job scheduler -- Checkpoint
CHKPNT: TXNE F,FL.KST ;KSYS STREAM?
POPJ P, ;YES--DON'T TALK TO QUASAR
SKIPN .JBSPS(R) ;IGNORE IF STEP HEADER SCAN
TXNE R,RL.KJB!RL.ACK!RL.OPR ;LOGGING OUT OR ACKS PENDING?
POPJ P, ;THEN DO NOTHING
SKIPL S1,.JBCHK(R) ;STREAM REQUEST CHECKPOINTING?
CAML S1,G$UDT ;BATCON REQUEST CHECKPOINTING?
POPJ P, ;NO TO EITHER - RETURN
PUSHJ P,L$CHKP## ;CHECKPOINT THE LOG
PUSHJ P,CHKINI ;INITIALIZE CHECKPOINT MESSAGE
PUSHJ P,CHKJOB ;CHECK JOB STATUS
JRST CHKP.S ;NO NEED TO GO ON
MOVE S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVX S2,JI.PRG ;GET PROGRAM NAME
PUSHJ P,I%JINF ;GET JOB INFO
SKIPE S2 ;NO NAME..IGNORE THIS STATUS
$TEXT (CHKTYO,< Running ^W/S2/^A>)
SKIPE S1,.JLLBL(R) ;CHECK IF HAD LABEL
TLNN S1,770000 ;WAS IT A LABEL
SKIPA ;NO..IGNORE LABEL
$TEXT (CHKTYO,< Last label: ^W/S1/^A>)
MOVE S1,.JBJNO(R) ;GET JOB NUMBER
MOVX S2,JI.RTM ;GET THE RUNTIME
PUSHJ P,I%JINF ;GET THE JOB INFO
MOVE S1,S2 ;PLACE VALUE IN S1
PUSHJ P,B$MTIM ;CONVERT TO READABLE TEXT
$TEXT (CHKTYO,< Runtime ^T/G$TMTX/^A>)
CHKP.S: MOVX S1,.CHNUL ;GET A <NUL>
PUSHJ P,CHKTYO ;STORE IT
HRRZ S1,.JBSPW(R) ;GET LAST ADDRESS
SUBI S1,-1(P1) ;COMPUTE THE LENGTH
STORE S1,.MSTYP(P1),MS.CNT ;SAVE THE MESSAGE COUNT
PJRST B$SEND ;SEND MESSAGE TO QUASAR AND RETURN
; INITIALIZE CHECKPOINT MESSAGE AND TEXT POINTERS
;
CHKINI: MOVEI S1,CHE.SZ ;GET MESSAGE SIZE
PUSHJ P,B$SQSR ;SET UP MESSAGE
MOVE P1,S2 ;PLACE MESSAGE ADDRESS IN P1
MOVX S1,.QOCHE ;MESSAGE TYPE
STORE S1,.MSTYP(P1),MS.TYP ;SAVE TYPE IN MESSAGE
TXNN F,FL.CHK ;STREAM REQUEST CHECKPOINTING?
JRST CHKI.1 ;NO
MOVE S1,.JQITN(R) ;GET STREAM'S ITN
MOVEM S1,.JOACK(R) ;USE IT AS THE ACK CODE
MOVEM S1,.MSCOD(P1) ;SAVE IN MESSAGE TO QUASAR TOO
MOVX S1,MF.ACK ;GET THE ACK BIT
MOVEM S1,.MSFLG(P1) ;STORE IN FLAG WORD
TXO R,RL.ACK ;REMEMBER TO WAIT FOR AN ACK
CHKI.1: XMOVEI S1,CHE.ST(P1) ;POINT TO STATUS AREA
TXO S1,<POINT 7,0> ;MAKE A BYTE POINTER
MOVEM S1,.JBSPW(R) ;STORE FOR LATER
MOVX S1,CH.FST ;SEND STATUS CODE
TXZE F,FL.CHK ;WANT CHECKPOINT UPDATED ON DISK?
TXO S1,CH.FCH ;YES - TELL QUASAR
MOVEM S1,CHE.FL(P1) ;UPDATE FLAG WORD
MOVE S1,.JQITN(R) ;THE TASK NAME
MOVEM S1,CHE.IT(P1) ;STORE
HRLI S1,.JBCRQ(R) ;CHECKPOINT/REQUEUE INFORMATION
HRRI S1,CHE.IN(P1) ;INTO THE MESSAGE
BLT S1,CHE.IN+<EQCKSZ-1>(P1) ;MOVE ALL THE WORDS
MOVE S1,G$UDT ;GET CURRENT TIME
ADDI S1,CKTIME*3 ;GET NEXT TIME TO CHECKPOINT
MOVEM S1,.JBCHK(R) ;REMEMBER IT
POPJ P, ;RETURN
; CHECK JOB STATUS
;
CHKJOB: MOVEI S1,[ITEXT (<Job ^D/.JBJNO(R)/>)] ;DEFAULT
SKIPG S2,.JBJNO(R) ;GET JOB NUMBER (IF ANY)
MOVEI S1,[ITEXT (<Job being set up by BATCON>)]
STORE S2,CHE.FL(P1),CH.JBN ;STORE IT
$TEXT (CHKTYO,< ^I/(S1)/^A>) ;DISPLAY SOMETHING
SKIPLE .JBJNO(R) ;HAVE A JOB?
AOS (P) ;YES
POPJ P, ;RETURN
; STORE AN ASCII CHARACTER IN THE CHECKPOINT MESSAGE
;
CHKTYO: IDPB S1,.JBSPW(R) ;STORE CHARACTER
$RETT ;RETURN
SUBTTL Job scheduler -- Message processing
; Process operator action messages
;
PROMES: SKIPE .JOVAL(R) ;HAVE AN OPERATOR/QUASAR MESSAGE?
TXNE R,RL.KJB!RL.MIP ;LOGGING OUT OR MESSAGE IN PROGRESS?
POPJ P, ;YES - THEN ALL DONE
TXO R,RL.MIP ;FLAG MESSAGE IN PROGRESS
PROM.1: MOVE S1,.JOFLG(R) ;GET FLAGS
TXNE S1,B.STCN ;STOP OR CONTINUE?
JRST PROM.4 ;YES - SPECIAL CASE OF DEFER REQUEST
TXNE S1,B.DEFR ;DEFER FOR STREAM CONTEXT?
JRST PROM.3 ;YES
PROM.2: PUSHJ P,@.JOPRC(R) ;PROCESS MESSAGE
TXZ R,RL.MIP ;CLEAR MESSAGE IN PROGRESS
SETZM .JOVAL(R) ;INDICATE MESSAGE PROCESSED
POPJ P, ;RETURN
PROM.3: TXZ R,RL.OPR!RL.STP!RL.JIE!RL.DIA ;CLEAR LOTS OF FLAGS
TXZ F,FL.NER!FL.SIL ;CLEAR MORE FLAGS
PROM.4: TXO R,RL.MIP!RL.MSP ;SET MESSAGE IN PROGRESS
MOVEM F,.JREGS+F(R) ;RESTORE FLAG AC
MOVEM R,G$BASE(S) ;RESTORE DATA BASE AC
MOVE S1,.JREGS+P(R) ;GET PROCESS STACK AC
PUSH S1,.JOPRC(R) ;PLACE ROUTINE ADDR ON STACK
MOVEM S1,.JREGS+P(R) ;SAVE STACK FOR PROCESS
POPJ P, ;RETURN
SUBTTL Job scheduler -- KSYS routines
TOPS10 <
; Schedule jobs for KSYS
; Call: PUSHJ P,KSYSCD
KSYSCD: SKIPG KSYCNT ;COUNT EXPIRED?
POPJ P, ;YES--NOTHING TO DO
$SAVE <P1,P2,P3,P4> ;SAVE SOME ACS
MOVSI P1,-KSYLEN ;START WITH FIRST WORD IN BIT MAP
KSYSC1: SKIPN P2,KSYMAP(P1) ;GET A MAP ENTRY
JRST KSYSC4 ;EMPTY
JFFO P2,.+1 ;FIND FIRST
MOVN P4,P3 ;NEGATE
MOVSI P2,400000 ;GET A BIT
LSH P2,(P4) ;POSITION
HRRZ S1,P1 ;GET MAP INDEX
IMULI S1,^D36 ;COMPUTE STARTING JOB NUMBER IN WORD
ADDI S1,(P3) ;PLUS REMAINDER GETS JOB NUMBER
MOVE S,[-JOBMAX+KSYSTR,,KSYSTR] ;POINTER TO START OF KSYS STREAMS
KSYSC2: SKIPLE R,G$BASE(S) ;ACTIVE?
JRST KSYSC3 ;NO--USE THIS ONE
AOBJN S,KSYSC2 ;KEEP SEARCHING
POPJ P, ;NONE AVAILABLE RIGHT NOW
KSYSC3: HRRZS S ;KEEP ONLY STREAM NUMBER
MOVEM S1,.JBJNO(R) ;SAVE
ANDCAM P2,KSYMAP(P1) ;CLEAR BIT IN MAP FOR THIS JOB
SOS KSYCNT ;COUNT DOWN NUMBER OF JOBS TO KILL
AOS KSYUSE ;COUNT THE KSYS STREAM IN USE
PUSHJ P,KSYFIR ;FIREUP THE STREAM
POPJ P, ;RETURN
KSYSC4: AOBJN P1,KSYSC1 ;LOOP
POPJ P, ;RETURN
; Fireup a KSYS stream
KSYFIR: $SAVE <P1> ;SAVE P1
MOVE T1,.JQOBJ+OBJ.TY(R) ;SAVE OBJECT TYPE
MOVE T2,.JQOBJ+OBJ.UN(R) ;SAVE UNIT/STREAM NUMBER
MOVE T3,.JQOBJ+OBJ.ND(R) ;SAVE NODE NUMBER OR NAME
MOVE T4,.JBJNO(R) ;SAVE JOB NUMBER
HRLZ S1,R ;GET START ADDRESS OF DATA BASE
HRRI S1,1(R) ;MAKE A BLT POINTER
SETZM (R) ;CLEAR THE FIRST WORD
BLT S1,.JSIZE-1(R) ;CLEAR THE DATA BASE
MOVEM T1,.JQOBJ+OBJ.TY(R) ;RESTORE OBJECT TYPE
MOVEM T2,.JQOBJ+OBJ.UN(R) ;RESTORE UNIT/STREAM NUMBER
MOVEM T3,.JQOBJ+OBJ.ND(R) ;RESTORE NODE NUMBER OR NAME
MOVEM T4,.JBJNO(R) ;RESTORE JOB NUMBER
$CALL M%GPAG ;GET A PAGE
MOVEM S1,.JSCMD(R) ;STORE FOR COMMAND PARSING
; Internal job name
MOVE S1,G$UDT ;A GOOR RANDOM NUMBER
MOVEM S1,.JQITN(R) ;SAVE
; Job information block
MOVE S1,['KSYS '] ;JOB NAME
MOVEM S1,.JQJBB+JIB.JN(R) ;SAVE
MOVE S1,.JQITN(R) ;GET ITN
ADDI S1,1 ;DON'T ALLOW ZERO
ANDI S1,7777 ;MASK DOWN INTO LEGAL RANGE
STORE S1,.JQJBB+JIB.SQ(R),EQ.SEQ ;SET SEQUENCE NUMBER
MOVE S1,.JBJNO(R) ;GET JOB NUMBER
MOVEI S2,JI.USR ;WANT THE PPN
$CALL I%JINF ;ASK THE GLXLIB
JUMPF KSYJ.X ;JOB GONE AWAY
MOVEM S2,.JQJBB+JIB.US(R) ;SAVE PPN
AOS S1,KSYREQ ;GET FAKE REQUEST-ID
MOVEM S1,.JQJBB+JIB.ID(R) ;SAVE
HRLZ S1,.JBJNO(R) ;GET JOB NUMBER
HRRI S1,.GTNM1 ;WANT FIRST HALF OF NAME
GETTAB S1, ;ASK MONITOR
SETZ S1, ;???
MOVEM S1,.JQJBB+JIB.NM+0(R) ;SAVE WORD 1
HRLZ S1,.JBJNO(R) ;GET JOB NUMBER
HRRI S1,.GTNM2 ;WANT SECOND HALF OF NAME
GETTAB S1, ;ASK MONITOR
SETZ S1, ;???
MOVEM S1,.JQJBB+JIB.NM+1(R) ;SAVE WORD 2
; Limit words
MOVEI S1,%EQUNO ;/UNIQUE:NO
STOLIM S1,.JQLIM(R),UNIQ
MOVEI S1,%EQRNO ;/RESTART:NO
STOLIM S1,.JQLIM(R),REST
MOVEI S1,1 ;/OPRINT:YES
STOLIM S1,.JQLIM(R),OINT
MOVEI S1,%EQOLE ;/OUTPUT:ERROR
STOLIM S1,.JQLIM(R),OUTP
MOVEI S1,0 ;/DEPEND:0
STOLIM S1,.JQLIM(R),DEPN
MOVX S1,INPCOR ;/CORE
STOLIM S1,.JQLIM(R),CORE
MOVEI S1,<^D5*^D60> ;/TIME
STOLIM S1,.JQLIM(R),TIME
MOVE S1,G$NODE ;/DESTINATION
STOLIM S1,.JQLIM(R),ONOD
MOVEI S1,%BSPOL ;/BATLOG:SPOOL
STOLIM S1,.JQLIM(R),BLOG
; Output location
MOVE S1,G$NODE ;USE BATCON'S NODE
MOVEM S1,.JQLOC(R) ;SAVE IT
; Checkpoint information
MOVSI S1,.JBCRQ(R) ;START ADDRESS
HRRI S1,.JBCRQ+1(R) ;BUILD BLT AC
SETZM .JBCRQ(R) ;CLEAR FIRST WORD
BLT S1,.JBCRQ+EQCKSZ-1(R) ;CLEAR ENTIRE BLOCK
; Account string
MOVE S1,[.ACTRD,,T1] ;SET UP UUO AC
MOVEI T1,2 ;TWO WORDS FOLLOWING
MOVE T2,.JBJNO(R) ;COPY JOB NUMBER
MOVEI T3,.JQACT(R) ;WHERE TO PUT IT
ACCT. S1, ;READ ACCOUNT STRING
SETZM .JQACT(R) ;IGNORE ERRORS
; PPN
MOVE S1,.JQJBB+JIB.US(R) ;GET FROM JIB BLOCK
MOVEM S1,.JQPPN(R) ;COPY IT
; Path
MOVEM S1,.JQPAT+0(R) ;SAVE PPN AS PATH
; Control file
; Log file
MOVSI S1,KSYLFP ;POINT TO PROTOTYPE FP
HRRI S1,.JQLFP(R) ;WHERE TO PUT IT
BLT S1,.JQLFP+FPXSIZ-1(R) ;COPY
KSYF.1: PUSHJ P,L$GENL## ;GENERATE A LOG FILE NAME
MOVE S1,.JQLFD+.FDNAM(R) ;GET LOG FILE NAME
CAMN S1,KSYNAM ;SAME AS LAST (NOT UNIQUE)?
JRST KSYF.1 ;TRY AGAIN
MOVEM S1,KSYNAM ;SAVE FOR NEXT TIME
; Miscellaneous
MOVX F,FL.INI+FL.KST ;SET INITIAL F FLAGS
PUSHJ P,U$FIRE## ;DO CUSTOMER STUFF
HRRZS R ;MAKE SURE NO JUNK IN LH
IORX R,RL.INI ;SET INITIAL BATCH STREAM FLAGS
MOVEM R,G$BASE(S) ;STORE JOB RELOCATION AC
MOVEM F,.JREGS+F(R) ;STORE IT
PUSHJ P,P$OPEN## ;OPEN A PTY
JUMPF KSYF.2 ;DID WE DO IT?
CAMLE S,G$HACT ;IS THIS NOW THE HIGHEST ACTIVE STREAM
MOVEM S,G$HACT ;YES, SET NEW VALUE
HRLI T1,-.JPSIZ ;BUILD PDL FOR THE STREAM
HRRI T1,.JPLST-1(R)
PUSH T1,[JOBPRC] ;START STREAM AT THE JOB PROCESSOR
MOVEM T1,.JREGS+P(R) ;SAVE AS PROCESSOR REGISTER P
AOS G$SACT ;ADD ANOTHER JOB
POPJ P, ;RETURN TO DISPATCHER
KSYF.2: $WTO (<Batch error>,<No PTYs available>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
MOVX T1,%RSUNA ;SET UP 'STREAM UNAVAILABLE'
MOVEI T2,E.NJOB ;NO JOBS AVAILABLE CODE
MOVX T3,%SFULL ;SYSTEM FULL
TXO R,RL.SHT ;LITE THE SHUTDOWN AT EOJ BIT
PUSHJ P,SETUPR ;SEND RESPONSE TO QUASAR
JRST B$CLOS ;DISMISS JOB
; Prototype KSYS log file FP
KSYLFP: $BUILD (FPXSIZ) ;SIZE OF BLOCK
$SET (.FPLEN,FPMSIZ) ;LENGTH
$SET (.FPINF,FP.FFF,.FPFAS) ;/FILE:ASCII
$SET (.FPINF,FP.FPF,%FPLAS) ;/PRINT:ASCII
$SET (.FPINF,FP.FSP,1) ;/SPACING:1
$SET (.FPINF,FP.DEL,1) ;/DISPOSE:DELETE
$SET (.FPINF,FP.SPL,1) ;SPOOLED FILE
$SET (.FPONM,,0) ;ORIGINAL FILE NAME
$SET (.FPOXT,,0) ;ORIGINAL EXTENSION
$EOB ;END OF BLOCK
KSYFIN: MOVEI T1,KSYFT1 ;POINT TO NORMAL COMPLETION TEXT
MOVEI T2,[ASCIZ |jobs|] ;ASSUME MORE THAN ONE
MOVE S1,KSYJLO ;GET COUNT
CAIN S1,1 ;JUST ONE?
MOVEI T2,[ASCIZ |job|] ;YES
MOVEI T3,[ASCIZ |errors|] ;ASSUME MORE THAN ONE
MOVE S2,KSYJLE ;GET COUNT
CAIN T3,1 ;JUST ONE?
MOVEI T2,[ASCIZ |error|] ;YES
SKIPE T3 ;ANY ERRORS?
MOVEI T1,KSYFT2 ;YES--USE DIFFERENT TEXT
$WTO (<KSYS processing completed>,,,<$WTFLG(WT.SJI)>)
SETZM G$KSYS ;CLEAR KSYS IN PROGRESS
POPJ P, ;RETURN
KSYFT1: ITEXT (<^D/KSYJLO/ ^T/(T2)/ logged off>)
KSYFT2: ITEXT (<^D/KSYJLO/ ^T/(T2)/ logged off; ^D/KSYJLE/ ^T/(T3)/ had errors>)
> ;END TOPS-10 CONDITIONAL
SUBTTL IPCF/Operator/QUASAR interface -- IPCF interrupts
; IPCF interrupt level handler
;
IPCINT: $BGINT IPCLVL ;SWITCH TO IPCF INTERRUPT LEVEL
$CALL C%INTR ;NOTIFY THE LIBRARY WE HAVE A MESSAGE
$DEBRK ;RETURN FROM INTERRUPT
SUBTTL IPCF/Operator/QUASAR interface -- Hello and goodbye
; Send GOODBYE message and LOGOUT
;
IDLBYE: MOVX T3,IDLMIN ;GET MINUTES OF IDLENESS
SKIPA T2,[EXP IDLTXT] ;GET ADDRESS OF ITEXT FOR WTO
SHTBYE: MOVEI T2,SHTTXT
PUSHJ P,GOODBY ;SAY GOODBYE TO QUASAR
$WTO (<BATCON logging out>,<^I/(T2)/>,,$WTFLG(WT.SJI))
$CALL I%KJOB ;GO LOGOUT
STOPCD (CNL,HALT,,<Could not logout. Call to I%KJOB failed>)
IDLTXT: ITEXT (<All streams have been idle for ^D/T3/ minutes>)
SHTTXT: ITEXT (<All streams have been shut down>)
; Send GOODBYE message to QUASAR
;
GOODBY: TDZA T1,T1 ;INDICATE SIGNING OFF
; Send HELLO message to QUASAR
;
HELLO: SETO T1, ;INDICATE SIGNING ON
MOVEI S1,HEL.SZ ;GET MESSAGE SIZE
PUSHJ P,B$SQSR ;SETUP QUASAR MESSAGE
MOVX S1,<INSVL.(.QOHEL,MS.TYP)!INSVL.(HEL.SZ,MS.CNT)>
MOVEM S1,.MSTYP(S2) ;STORE MESSAGE TYPE AND SIZE
MOVE S1,['BATCON'] ;GET OUR NAME
MOVEM S1,HEL.NM(S2) ;STORE IT
MOVX S1,<INSVL.(%%.QSR,HEFVER)> ;GET QUASAR VERSION NUMBER
SKIPN T1 ;WHAT ARE WE DOING?
TXO S1,HEFBYE ;SIGNING OFF
MOVEM S1,HEL.FL(S2) ;STORE IT
MOVX S1,<INSVL.(1,HENNOT)!INSVL.(DEFMJB,HENMAX)>
MOVEM S1,HEL.NO(S2) ;STORE # OBJECT TYPES AND UNITS/STREAMS
MOVX S1,.OTBAT ;GET BATCH OBJECT TYPE
MOVEM S1,HEL.OB(S2) ;STORE IT
PUSHJ P,B$SEND ;GREET QUASAR
POPJ P, ;AND RETURN
SUBTTL IPCF/Operator/QUASAR interface -- IPCF message processing
IPCF: $CALL C%RECV ;TRY TO RECEIVE A MESSAGE
JUMPF .POPJ ;NONE THERE - RETURN
LOAD S2,MDB.SI(S1) ;GET SYSTEM PID INFO
TXZN S2,SI.FLG ;FROM SYSTEM PID
JRST IPCF.X ;NOT FROM SYSTEM PID - IGNORE IT
LOAD T1,S2,SI.IDX ;GET SYSTEM PID INDEX
CAIE T1,SP.QSR ;IS IT FROM QUASAR
CAIN T1,SP.OPR ;IS IT FROM ORION
SKIPA ;YES
JRST IPCF.X ;NOT FROM QUASAR OR ORION - IGNORE IT
LOAD S1,MDB.MS(S1),MD.ADR ;GET MESSAGE ADDRESS
PUSHJ P,B$SBLK ;SET UP FOR MESSAGE BLOCK PROCESSING
LOAD T1,.MSTYP(S1),MS.TYP ;GET MESSAGE TYPE
MOVSI S1,-NUMMSG ;NUMBER OF MESSAGES
IPCF.1: CAMN T1,MSGTAB(S1) ;A MATCH?
JRST IPCF.2 ;YES
AOBJN S1,IPCF.1 ;LOOP AND TRY ANOTHER
MOVEI S1,0 ;NO MATCH - MAYBE AN ACK
IPCF.2: HRRZM S1,G$MIDX ;SAVE INDEX FOR LATER
PUSHJ P,U$IPCF## ;CALL CUSTOMER USER EXIT ROUTINES
JRST IPCF.X ;FAILED - ABORT PROCESSING
PUSHJ P,VALMSG ;VALIDATE MESSAGE
JRST IPCF.X ;BAD MESSAGE
MOVE S1,G$MIDX ;GET INDEX INTO MESSAGE TABLES
PUSHJ P,@MSGPRC(S1) ;PROCESS THE MESSAGE
IPCF.X: $CALL C%REL ;RELEASE THE MESSAGE
SKIPN G$PSCN ;NEED TO PROCESS PRESCAN STREAM?
JRST IPCF ;NO - GET ANOTHER MESSAGE
POPJ P, ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- Message tables
; Macros to build the paralell message tables
; The arguments to the $ macro are used in the following ways:
; TYPE message type
; SUBR subroutine to process the message
; OBJ index into the message of the object block (-1 means no check)
;
DEFINE $MSG,<
$ ( 0, UNKMSG, -1) ;?????? UNKNOWN MESSAGES
$ (.QONEX, NEXTJB, .EQROB) ;QUASAR NEXTJOB
$ (.QOABO, ABORT , ABO.TY) ;QUASAR USER CANCEL
$ (.QOSUP, SETUP , -1) ;QUASAR SETUP JOB
$ (.QOALC, ALLOC , -1) ;QUASAR PRE-ALLOCATION
TOPS10 <
$ (.QOKSY, KSYS , -1) ;QUASAR KSYS
>
$ (.OMPAU, PAUSE , .OROBJ) ;ORION STOP
$ (.OMCON, CONTIN, .OROBJ) ;ORION CONTINUE
$ (.OMRSP, RESPON, -1) ;ORION RESPONSE TO WTOR
$ (.OMREQ, REQUE , .OROBJ) ;ORION REQUEUE
$ (.OMCAN, CANCEL, .OROBJ) ;ORION CANCEL
$ (.OMSND, SEND , .OROBJ) ;ORION SEND
$ (.OMSHC, EXAMIN, .OROBJ) ;ORION EXAMINE
$ (MT.TXT, ACK , -1) ;ACKS
>
DEFINE $ (TYPE,SUBR,OBJ),<EXP TYPE>
MSGTAB::$MSG
NUMMSG==.-MSGTAB
DEFINE $ (TYPE,SUBR,OBJ),<EXP SUBR>
MSGPRC::$MSG
DEFINE $ (TYPE,SUBR,OBJ),<EXP OBJ>
MSGOBJ::$MSG
SUBTTL IPCF/Operator/QUASAR interface -- Validate messages
; Validate IPCF messages
; Call: PUSHJ P,VALMSG
; <NON-SKIP> ;ILLEGAL MESSAGE
; <SKIP> ;MESSAGE OK
;
; On sucessful return, S:= stream index and R:= stream relocation
;
VALMSG: MOVE S1,G$MIDX ;GET MESSAGE INDEX
SKIPGE MSGOBJ(S1) ;NEED TO VALIDATE MESSAGE?
JRST .POPJ1 ;NO
MOVE S2,MSGTAB(S1) ;GET MESSAGE TYPE
CAIGE S2,.OMTXT ;RANGE CHECK
CAIGE S2,.OMOFF ;FOR ORION MESSAGE TYPE
JRST VALM.2 ;NO
VALM.1: PUSHJ P,B$GBLK ;GET A MESSAGE BLOCK
JRST VALM.E ;NO MORE - ERROR
CAIE T1,.OROBJ ;IS THIS THE OBJECT BLOCK???
JRST VALM.1 ;NO - GET THE NEXT MSG BLOCK
MOVE S2,T3 ;GET THE BLOCK DATA ADDRESS IN S1.
JRST VALM.3 ;GO FIND THE OBJECT BLOCK
VALM.2: MOVE S2,MSGOBJ(S1) ;GET OBJECT BLOCK OFFSET
ADD S2,G$MADR ;ADD MESSAGE ADDRESS
VALM.3: MOVE T1,.ROBTY(S2) ;GET OBJECT TYPE
MOVE T2,.ROBAT(S2) ;GET UNIT NUMBER
MOVE T3,.ROBND(S2) ;AND NODE NUMBER
MOVEI S,0 ;CLEAR STREAM INDEX
VALM.4: SKIPN R,G$BASE(S) ;GET STREAM RELOCATION
JRST VALM.5 ;NOT SETUP
CAMN T1,.JQOBJ+.ROBTY(R) ;COMPARE OBJECT TYPE
CAME T2,.JQOBJ+.ROBAT(R) ;COMPARE UNIT NUMBER
JRST VALM.5 ;NO MATCH
CAMN T3,.JQOBJ+.ROBND(R) ;COMPARE NODE NUMBER
JRST .POPJ1 ;MESSAGE SEEMS OK - RETURN
VALM.5: CAIGE S,DEFMJB ;CHECKED ALL STREAMS YET?
AOJA S,VALM.4 ;NO - LOOP
VALM.E: $WTO (<BATCON Error>,<Invalid object block: type = ^O/T1/, unit/stream = ^O/T2/, node = ^N/T3/>)
POPJ P, ;TAKE ERROR RETURN
SUBTTL IPCF/Operator/QUASAR interface -- Initialize stream block
; Initialize operator/QUASAR message block in stream data base
; Call: MOVEI S1,[ASCIZ |message text|]
; MOVE S2,processor address
; PUSHJ P,B$IMSG
; <NON-SKIP> ;MESSAGE PENDING
; <SKIP> ;MESSAGE BLOCK SETUP
;
B$IMSG::SKIPN .JOVAL(R) ;HAVE A VALID MESSAGE?
JRST IMSG.1 ;NO
$WTO (<^T/@.JONAM(R)/ pending; ^T/(S1)/ ignored>,,.JQOBJ(R))
POPJ P, ;RETURN
IMSG.1: SETOM .JOVAL(R) ;INDICATE A VALID MESSAGE
SETZM .JOFLG(R) ;CLEAR FLAG WORD
MOVEM S1,.JONAM(R) ;STORE TEXT ADDRESS
MOVEM S2,.JOPRC(R) ;STORE PROCESSOR ADDRESS
MOVSI S1,.JOMSG(R) ;START OF MESSAGE BUFFER
HRRI S1,.JOMSG+1(R) ;MAKE A BLT POINTER
SETZM .JOMSG(R) ;CLEAR FIRST WORD
BLT S1,.JOMSG+IPCSIZ-1(R) ;CLEAR ENTIRE BUFFER
MOVE S1,G$MADR ;GET MESSAGE ADDRESS
LOAD S2,.MSTYP(S1),MS.CNT ;GET MESSAGE LENGTH
CAILE S2,IPCSIZ-1 ;OVERFLOW?
MOVEI S2,IPCSIZ-1 ;YES
STORE S2,.MSTYP(S1),MS.CNT ;UPDATE
HRLZ S1,G$MADR ;GET MESSAGE ADDRESS
HRRI S1,.JOMSG(R) ;PUT IT THERE
ADDI S2,.JOMSG(R) ;COMPUTE END ADDRESS
BLT S1,-1(S2) ;COPY MESSAGE
JRST .POPJ1 ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- Message block processing
; Set up message block processing
; Call: MOVE S1,message address
; PUSHJ P,B$SETM
;
; On return, G$MADR and G$MBLK will be set up and B$GBLK may be called.
;
; All ACs preserved
;
B$SBLK::$SAVE <P1> ;SAVE P1
MOVEM S1,G$MADR ;REMEMBER MESSAGE ADDRESS FOR LATER
MOVEI P1,.OHDRS+ARG.HD(S1) ;POINT TO FIRST BLOCK ADDRESS
MOVEM P1,G$MBLK ;REMEMBER IT TOO
MOVE P1,.OARGC(S1) ;GET ARGUMENT COUNT
MOVEM P1,G$MARG ;STORE IT
POPJ P, ;RETURN
; Get the next block of a message
; Call: PUSHJ P,B$GBLK
; <NON-SKIP> ;END OF MESSAGE
; <SKIP> ;NEXT BLOCK FOUND
;
; On error return, T1, T2 and T3 left unchanged
; On sucessful return, T1:= type, T2:= length, T3:= data address
;
; AC usage: Destroys S1
;
B$GBLK::MOVE S1,G$MADR ;GET MESSAGE ADDRESS
SOSGE G$MARG ;SUBTRACT 1 FROM THE BLOCK COUNT
POPJ P, ;ERROR RETURN IF NO MORE
MOVE S1,G$MBLK ;GET THE PREVIOUS BLOCK ADDRESS
LOAD T1,ARG.HD(S1),AR.TYP ;GET THE BLOCK TYPE
LOAD T2,ARG.HD(S1),AR.LEN ;GET THE BLOCK LENGTH
MOVEI T3,ARG.DA(S1) ;GET THE BLOCK DATA ADDRESS
ADD S1,T2 ;POINT TO THE NEXT MESSAGE BLOCK
MOVEM S1,G$MBLK ;SAVE IT FOR THE NEXT CALL
JRST .POPJ1 ;RETURN SUCESSFUL
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR communication
; Setup message to QUASAR
; Call: MOVE S1,# words
; PUSHJ P,B$SQSR
;
; On return, S2:= message address
;
B$SQSR::MOVE S2,[MSGADR,,MSGADR+1] ;SET UP BLT
SETZM MSGADR ;CLEAR THE FIRST WORD
BLT S2,MSGADR-1(S1) ;CLEAR THE ENTIRE BLOCK
MOVEI S2,MSGADR ;GET MESSAGE ADDRESS AGAIN
STORE S2,G$SAB+SAB.MS ;STORE THE MESSAGE ADDRESS IN SAB
POPJ P, ;RETURN
; Send an IPCF message to QUASAR
; Call: PUSHJ P,B$SEND
;
B$SEND::SETZM G$SAB+SAB.PD ;NO PID
LOAD S1,@G$SAB+SAB.MS,MS.CNT ;GET THE MESSAGE COUNT
STORE S1,G$SAB+SAB.LN ;STORE IT
MOVX S1,<SI.FLG+<INSVL.(SI.IDX,SP.QSR)>> ;USE SPECIAL PID INDEX
MOVEM S1,G$SAB+SAB.SI ;STORE IT
MOVEI S1,SAB.SZ ;SIZE OF BLOCK IN S1
MOVEI S2,G$SAB ;ADDRESS OF BLOCK
$CALL C%SEND ;SEND TO QUASAR
SKIPT ;CHECK FOR ERRORS
SKIPN G$KILL ;KILLING ALL JOBS?
POPJ P, ;RETURN
STOPCD (SQF,HALT,,<Send failure to QUASAR>)
; Update stream status in QUASAR
; Call: MOVE T1,status code
; PUSHJ P,B$UPDA
;
B$UPDA::MOVEI S1,STU.SZ ;GET STATUS SIZE
PUSHJ P,B$SQSR ;SETUP MESSAGE TO QUASAR
MOVEM T1,STU.CD(S2) ;SAVE THE CODE
MOVE S1,[STU.SZ,,.QOSTU] ;GET HEADER WORD
MOVEM S1,.MSTYP(S2) ;STORE IN MESSAGE
MOVSI S1,.JQOBJ(R) ;GET SOURCE TYPE FROM STREAM
HRRI S1,STU.RB(S2) ;DESTINATION,,RESPONSE TYPE
BLT S1,STU.RB+OBJ.SZ-1(S2) ;MOVE TYPE,UNIT,NUMBER
PJRST B$SEND ;SEND TO QUASAR AND RETURN
SUBTTL IPCF/Operator/QUASAR interface -- Ask for operator response
; Ask for operator response
; Call: MOVE S1,address of type ITEXT block
; MOVE S2,address of main ITEXT block
; MOVE T1,address of table of responses
; PUSHJ P,B$OPER
;
; On return, S1:= index into response table
;
B$OPER::MOVEM S1,.JOTYP(R) ;STORE TYPE ITEXT BLOCK ADDRESS
MOVEM S2,.JOTXT(R) ;STORE MAIN ITEXT BLOCK ADDRESS
MOVEM T1,.JOTBL(R) ;STORE RESPONSE TABLE POINTER
MOVEI T1,%OREWT ;GET OPERATOR RESPONSE WAIT CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
OPER.1: MOVE S1,.JQITN(R) ;GET THE REQUEST ITN
MOVEM S1,.JOACK(R) ;SAVE AS THE ACK CODE
$WTOR (<^I/@.JOTYP(R)/>,<^I/JIBTXT/^I/@.JOTXT(R)/>,.JQOBJ(R),.JOACK(R),<$WTNOD(.JQLOC(R))>)
TXO R,RL.OPR ;MARK AS WAITING FOR OPERATOR RESPONSE
PUSHJ P,QTS ;WAIT FOR OEPRATOR TO ANSWER
SKIPN S1,.JOTBL(R) ;POINT TO RESPONSE TABLE (IF ONE GIVEN)
POPJ P, ;WILL ACCEPT ANY TEXT - RETURN
HRROI S2,.JORSP(R) ;POINT TO RESPONSE FROM OPERATOR
$CALL S%TBLK ;SCAN THE TABLE FOR A MATCH
TXNE S2,TL%NOM ;GOT ONE?
JRST OPER.1 ;NO - TRY AGAIN
PUSH P,S1 ;SAVE INDEX
MOVX T1,%RESET ;GET NORMAL OPERATION CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
POP P,S1 ;RESTORE S1
POPJ P, ;RETURN WITH TABLE INDEX IN S1
SUBTTL IPCF/Operator/QUASAR interface -- Unknown message
UNKMSG: MOVE S1,G$MADR ;GET MESSAGE ADDRESS
$WTO (<BATCON Error>,<^I/UNKTXT/>)
POPJ P, ;RETURN
UNKTXT: ITEXT (< Unknown IPCF message
Message header: ^O12R0/.MSTYP(S1)/, ^O12R0/.MSFLG(S1)/, ^O12R0/.MSCOD(S1)/>)
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR message #5 (NEXTJOB)
NEXTJB: TXNN R,RL.ACT ;STREAM ALREADY ACTIVE?
JRST NEXT.1 ;GOT IT
MOVX T1,%RSUNA ;NOT SETUP..TRY AGAIN
MOVEI T2,E.STRA ;STREAM ALREADY ACTIVE
SETZM T3 ;CLEAR STATUS CODE AC
PJRST SETUPF ;NOTIFY QUASAR OF THE SETUP FAILURE
NEXT.1: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
PUSHJ P,FIREUP ;FIREUP STREAM
POPJ P, ;RETURN
; Fireup a job for processing
;
FIREUP: MOVE T1,.JQOBJ+OBJ.TY(R) ;SAVE OBJECT TYPE
MOVE T2,.JQOBJ+OBJ.UN(R) ;SAVE UNIT/STREAM NUMBER
MOVE T3,.JQOBJ+OBJ.ND(R) ;SAVE NODE NUMBER OR NAME
HRLZ S1,R ;GET START ADDRESS OF DATA BASE
HRRI S1,1(R) ;MAKE A BLT POINTER
SETZM (R) ;CLEAR THE FIRST WORD
BLT S1,.JSIZE-1(R) ;CLEAR THE DATA BASE
MOVEM T1,.JQOBJ+OBJ.TY(R) ;RESTORE OBJECT TYPE
MOVEM T2,.JQOBJ+OBJ.UN(R) ;RESTORE UNIT/STREAM NUMBER
MOVEM T3,.JQOBJ+OBJ.ND(R) ;RESTORE NODE NUMBER OR NAME
$CALL M%GPAG ;GET A PAGE
MOVEM S1,.JSCMD(R) ;STORE FOR COMMAND PARSING
; Internal job name
MOVE S1,.EQITN(P1) ;GET THE ITN FOR THE JOB
MOVEM S1,.JQITN(R) ;PLACE IN DATA BASE
; Job information block
HRLI S1,.EQJBB(P1) ;START OF JOB INFO BLOCK
HRRI S1,.JQJBB(R) ;END OF JOB INFO BLOCK
BLT S1,.JQJBB+JIBSIZ-1(R) ;MOVE THE BLOCK
; Limit words
HRLI S1,.EQLIM(P1) ;GET START OF LIMIT WORDS
HRRI S1,.JQLIM(R) ;GET DESTINATION OF LIMIT WORDS
BLT S1,.JQLIM+EQLMSZ-1(R) ;MOVE THE LIMIT WORDS
; Output location
GETLIM S1,.JQLIM(R),ONOD ;GET THE OUTPUT/LOCATION NODE
MOVEM S1,.JQLOC(R) ;SAVE AS THE LOCATION
; Checkpoint information
HRLI S1,.EQCHK(P1) ;GET ADDRESS OF CHECKPOINT WORDS
HRRI S1,.JBCRQ(R) ;GET DESTINATION FOR WORDS
BLT S1,.JBCRQ+EQCKSZ-1(R) ;SAVE THEM IN DATA BASE
; Account string
HRLI S1,.EQACT(P1) ;GET ADDRESS OF ACCOUNT STRING
HRRI S1,.JQACT(R) ;GET DESTINATION FOR STRING
BLT S1,.JQACT+10-1(R) ;SAVE ACCOUNT STRING
LOAD T2,.EQLEN(P1),EQ.LOH ;GET LENGTH OF THE REQUEST HEADER
TOPS20 < ;TOPS-20 ONLY
; SPRINT input set handle
MOVE S1,.EQSIS(P1) ;GET SPRINT SPOOL WORD
MOVEM S1,.JQSIS(R) ;SAVE WORD
; User name
HRLI S1,.EQOWN(P1) ;GET USER NAME
HRRI S1,.JQNAM(R) ;DESTINATION FOR USER NAME
BLT S1,.JQNAM+10-1(R) ;MOVE THE NAME
; Connected directory
HRLI S1,.EQCON(P1) ;GET CONNECTED DIRECTORY
HRRI S1,.JQCON(R) ;DESTINATION FOR CONN. DIR
BLT S1,.JQCON+12-1(R) ;SAVE CONNECTED DIRECTORY
> ;END OF TOPS-20 CONDITIONAL
TOPS10 < ;TOPS-10 ONLY
; User PPN
MOVE S1,.EQOID(P1) ;GET PPN INFO
MOVEM S1,.JQPPN(R) ;SAVE PPN
; Path
CAIGE T2,.EQPSZ ;ENOUGH ROOM FOR THE PATH SPEC
JRST FIRE.0 ;NO, DON'T BOTHER COPYING IT
HRLI S1,.EQPAT(P1) ;WHERE IT IS IF PRESENT
HRRI S1,.JQPAT(R) ;INTO INTERNAL BLOCK
BLT S1,.JQPAT+5(R) ;MOVE IT ALL
> ;END OF TOPS-10 CONDITIONAL
; Control file
FIRE.0: ADDI T2,(P1) ;FIND FILE PARAMETERS FOR THE CTL FILE
HRLZ S1,T2 ;GET FP ADDRESS IN THE EQ
HRRI S1,.JQCFP(R) ;GET FP ADDRESS IN THE JOB DATA BASE
LOAD S2,.FPLEN(T2),FP.LEN ;GET LENGTH OF FP IN THE EQ
ADDI S2,.JQCFP(R) ;COMPUTE END ADDRESS TO BLT
BLT S1,-1(S2) ;COPY THE CONTROL FILE FP
LOAD T3,.FPLEN(T2),FP.LEN ;FIND THE FILE DESCRIPTOR
ADDI T3,(T2) ;AS MESSAGE+LENGTH OF HEADER+LENGTH OF PARMS
LOAD T4,.FDLEN(T3),FD.LEN ;SIZE OF THE DESCRIPTOR
ADDI T4,.JQCFD-1(R) ;END OF THE BLT
HRLI T1,0(T3) ;THE CTL FILE STRUCTURE
HRRI T1,.JQCFD(R) ;WHERE FNDCTL WANTS IT
BLT T1,0(T4) ;COPY ALL AND SFD'S IF THERE
LOAD T4,.FDLEN(T3),FD.LEN ;GET FD SIZE AGAIN
ADDI T3,(T4) ;C = LOG FILE PARAMETERS
; Log file
HRLZ S1,T3 ;GET FP ADDRESS IN THE EQ
HRRI S1,.JQLFP(R) ;GET FP ADDRESS IN THE JOB DATA BASE
LOAD S2,.FPLEN(T3),FP.LEN ;GET LENGTH OF FP IN THE EQ
ADDI S2,.JQLFP(R) ;COMPUTE END ADDRESS TO BLT
BLT S1,-1(S2) ;COPY THE CONTROL FILE FP
LOAD T4,.FPLEN(T3),FP.LEN ;SIZE OF LOG FILE PARM HEADER
ADDI T4,(T3) ;POINT TO LOG FILE DESCRIPTOR
LOAD T3,.FDLEN(T4),FD.LEN ;SIZE OF LOG FILE FD
ADDI T3,.JQLFD-1(R) ;LAST LOCATION TO MOVE TO
HRLI T1,0(T4) ;THE LOG FILE NOW
HRRI T1,.JQLFD(R) ;WHERE THE ROUTINES WANT IT
BLT T1,0(T3) ;MOVE THE FULL SPEC
; Miscellaneous
PUSHJ P,U$FIRE## ;DO CUSTOMER STUFF
HRRZS R ;MAKE SURE NO JUNK IN LH
IORX R,RL.INI ;SET INITIAL BATCH STREAM FLAGS
MOVEM R,G$BASE(S) ;STORE JOB RELOCATION AC
MOVX F,FL.INI ;SET INITIAL F FLAGS
MOVEM F,.JREGS+F(R) ;STORE IT
SETOM .JBJNO(R) ;MARK NO JOB YET
MOVE S1,G$STRM(S) ;GET THE STREAM NUMBER
CAIN S1,PSCSTR ;IS IT THE PRESCAN STREAM?
POPJ P, ;YES - JUST RETURN
FIRE.1: AOS G$SACT ;ANOTHER STREAM IN USE
PUSHJ P,P$OPEN## ;OPEN A PTY
JUMPF FIRE.2 ;DID WE DO IT?
CAMLE S,G$HACT ;IS THIS NOW THE HIGHEST ACTIVE STREAM
MOVEM S,G$HACT ;YES, SET NEW VALUE
HRLI T1,-.JPSIZ ;BUILD PDL FOR THE STREAM
HRRI T1,.JPLST-1(R)
PUSH T1,[JOBPRC] ;START STREAM AT THE JOB PROCESSOR
MOVEM T1,.JREGS+P(R) ;SAVE AS PROCESSOR REGISTER P
POPJ P, ;RETURN TO DISPATCHER
FIRE.2: $WTO (<Batch error>,<No PTYs available - job requeued>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
MOVX T1,%RSUNA ;SET UP 'STREAM UNAVAILABLE'
MOVEI T2,E.NJOB ;NO JOBS AVAILABLE CODE
MOVX T3,%SFULL ;SYSTEM FULL
TXO R,RL.SHT ;LITE THE SHUTDOWN AT EOJ BIT
PUSHJ P,SETUPR ;SEND RESPONSE TO QUASAR
SETOM .JBCHK(R) ;NO CHECKPOINT NEEDED
JRST B$CLOS ;DISMISS JOB
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR message #6 (ABORT)
ABORT: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVE S1,ABO.IT(P1) ;GET ITN FOR STREAM
CAME S1,.JQITN(R) ;IS IT SAME JOB
POPJ P, ;NO,,IGNORE IT
MOVEI S1,[ASCIZ |CANCEL|] ;MESSAGE NAME
MOVEI S2,ABOJOB ;PROCESSOR ADDRESS
PUSHJ P,B$IMSG ;SET UP OPERATOR/QUASAR MESSAGE
POPJ P, ;ONE ALREADY THERE - RETURN
MOVX S1,B.DEFR ;GET DEFERRED FLAG
IORM S1,.JOFLG(R) ;STORE IT
MOVX T1,%CNCLG ;GET CANCEL CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
$WTOJ (<Cancel request queued by user ^P/ABO.ID(P1)/>,<^R/.JQJBB(R)/>,.JQOBJ(R))
POPJ P, ;RETURN
; Routine executed in stream context to abort the job.
;
ABOJOB: PUSHJ P,P$STOP## ;STOP THE PTY
MOVEI S1,.JOMSG(R) ;GET MESSAGE ADDRESS
$IDENT (CANCEL,<? Job canceled by user ^P/ABO.ID(S1)/>)
PUSHJ P,B$RTYO ;ECHO THE RESPONSE BUFFER
TXZ R,RL.JIE ;AVOID THE CLOSE/DUMP
TXO F,FL.UHE!FL.TXT ;AN UNEXPECTED CONDITION, TEXT AVAIL
$TEXT (<-1,,.JWTOP(R)>,<Job canceled by user ^P/ABO.ID(S1)/^0>)
JRST CLOSJB ;DISMISS THE JOB
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR message #22 (SETUP)
SETUP: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
LOAD S1,SUP.FL(P1) ;GET FLAGS
TXNE S1,SUFSHT ;SHUTTING DOWN STREAM?
JRST SHUTDN ;YES
MOVX S1,-1 ;-1 MEANS WE WANT A FREE STREAM
PUSHJ P,FSTREA ;SEE IF CAN FIND ONE
JUMPF SETE.1 ;NONE AVAILABLE
MOVE S,S1 ;GET STREAM
LOAD S1,SUP.UN(P1),RO.UNI ;GET UNIT/STREAM NUMBER
MOVEM S1,G$STRM(S) ;SAVE STREAM NUMBER IN TABLE
MOVEI S1,.JPAGS ;# PAGES NEEDED FOR THE DATA BASE
$CALL M%AQNP ;GET A PAGE FOR THE DATA BASE
MOVEI R,(S1) ;PUT THE PAGE NUMBER IN R
PG2ADR R ;CONVERT PAGE TO ADDRESS
HRRZM R,G$BASE(S) ;SAVE FOR THE DISPATCHER
MOVSI S1,SUP.TY(P1) ;BATCH OBJECT TYPE
HRRI S1,.JQOBJ(R) ;PLACE IN DATA BASE
BLT S1,.JQOBJ+OBJ.SZ-1(R) ;MOVE THE BLOCK
MOVX T1,%RSUOK ;GOOD RETURN FOR SETUP
SETZB T2,T3 ;CLEAR MESSAGE AND STATUS CODE
PUSHJ P,SETUPS ;SEND SUCESSFUL SETUP MESSAGE TO QUASAR
AOS G$SSET ;BUMP SETUP COUNTER
POPJ P, ;RETURN
SETE.1: MOVX T1,%RSUDE ;CAN NOT SETUP,,DO NOT TRY AGAIN
MOVEI T2,E.NSTR ;NO FREE STREAMS
SETZM T3 ;CLEAR STATUS CODE AC
PJRST SETUPF ;NOTIFY QUASAR OF THE SETUP FAILURE
; Shutdown message
;
SHUTDN: LOAD S1,SUP.UN(P1),RO.UNI ;GET STREAM NUMBER
PUSHJ P,FSTREA ;FIND THE STREAM
JUMPF .POPJ ;EH?
MOVE S,S1 ;GET STREAM INDEX
SHUT.1: SETOM G$STRM(S) ;MARK STREAM AVAILABLE
HRRZ S2,G$BASE(S) ;GET STREAM RELOCATION ADDRESS
SETZM G$BASE(S) ;CLEAR STREAM ENTRY
ADR2PG S2 ;CONVERT TO PAGE NUMBER
MOVEI S1,.JPAGS ;NUMBER TO RELEASE
$CALL M%RLNP ;RELEASE IT
TXNE F,FL.KST ;KSYS STREAM?
SOS KSYSSC ;YES--COUNT DOWN # STREAMS SETUP
SOSG G$SSET ;DECREMENT SETUP STREAM COUNT
SKIPE G$BUDT ;NO MORE. ARE WE A %STCMD PROCESSOR?
POPJ P, ;NO, RETURN
PJRST SHTBYE ;YES, GO SAY GOODBYE AND LOGOUT
; Here on SETUP failure
;
SETUPF: $WTO (<BATCON error>,<^I/JIBTXT/^I/@ERRTAB(T2)/>,.JQOBJ(R))
TXO R,RL.SHT ;LITE THE SHUTDOWN AT EOJ BIT
JRST SETUPR ;SEND RESPONSE TO QUASAR
; Here on sucessful SETUP
;
SETUPS: $WTO (<Started>,,.JQOBJ(R))
SETUPR: TXNE F,FL.KST ;KSYS STREAM
POPJ P, ;YES--DON'T TALK TO QUASAR
MOVEI S1,RSU.SZ ;GET THE MESSAGE SIZE
PUSHJ P,B$SQSR ;SETUP MESSAGE TO QUASAR
MOVEM T3,RSU.CD(S2) ;SAVE THE CODE
MOVEM T1,RSU.CO(S2) ;STORE IN MESSAGE
MOVE S1,[RSU.SZ,,.QORSU] ;GET HEADER WORD
MOVEM S1,.MSTYP(S2) ;STORE IN MESSAGE
MOVSI S1,.JQOBJ(R) ;GET SOURCE TYPE FROM STREAM
HRRI S1,RSU.TY(S2) ;DESTINATION,,RESPONSE TYPE
BLT S1,RSU.NO(S2) ;MOVE TYPE,UNIT,NUMBER
PUSHJ P,B$SEND ;SEND TO QUASAR
POPJ P, ;RETURN
;FIND A STREAM ROUTINE
;CALLED WITH S1 STREAM TO LOCATE ....-1...FREE STREAM
FSTREA: MOVSI S2,-JOBMAX ;GET MAX NUMBER OF JOBS
FSTR.1: MOVE T1,G$STRM(S2) ;GET FIRST STREAM VALUE
CAMN T1,S1 ;CHECK IF MATCH
JRST FSTR.2 ;YES ,,,MATCH
AOBJN S2,FSTR.1 ;TRY NEXT ENTRY
$RETF ;CAN'T FIND ENTRY
FSTR.2: HRRZ S1,S2 ;RELATIVE STREAM INDEX
$RETT ;RETURN TRUE
POPJ P, ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR message #60 (ALLOCATION)
ALLOC: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVEI S,PSCSTR ;GET PRESCAN STREAM NUMBER
SKIPL G$STRM(S) ;DATA BASE ALLOCATED YET?
JRST ALLO.1 ;YES
MOVX S1,.JPAGS ;NUMBER OF PAGES IN A JOB'S DATA BASE
$CALL M%AQNP ;GET SOME PAGES
MOVEI R,(S1) ;PUT THE PAGE NUMBER IN R
PG2ADR R ;CONVERT TO ADDRESS
HRRZM R,G$BASE(S) ;STORE PAGE POINTER
MOVE S1,.EQROB+.ROBTY(P1) ;GET OBJECT TYPE
MOVEM S1,.JQOBJ+OBJ.TY(R) ;STORE IT
MOVEI S1,PSCSTR ;PRESCAN STREAM NUMBER
MOVEM S1,G$STRM(S) ;STORE IT
MOVE S1,.EQROB+.ROBND(P1) ;GET NODE
MOVEM S1,.JQOBJ+OBJ.ND(R) ;STORE IT
JRST ALLO.2 ;ONWARD
ALLO.1: HRRZ R,G$BASE(S) ;GET RELOCATION
ALLO.2: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVE S1,.EQROB+.ROBTY(P1) ;GET OBJECT TYPE
MOVEI S,PSCSTR ;GET PRESCAN STREAM NUMBER
HRRZ R,G$BASE(S) ;GET RELOCATION FOR STREAM
PUSHJ P,FIREUP ;FIRE UP A BATCH STREAM
HRLI S1,-.JPSIZ ;BUILD THE PDL FOR THE STREAM
HRRI S1,.JPLST-1(R) ;STACK STARTS HERE
PUSH S1,[STPPRC] ;BEGIN AT THE STEP PROCESSOR
MOVEM S1,.JREGS+P(R) ;STORE STREAM'S AC 'P'
SETOM .JBSPS(R) ;INDICATE STEP HEADER SCAN ONLY
AOS G$SACT ;ADD ANOTHER JOB
CAMLE S,G$HACT ;COULD THIS STREAM BE THE NEW G$HACT?
MOVEM S,G$HACT ;YES - STORE STREAM INDEX
SETOM G$PSCN ;INDICATE PRESCAN SETUP
POPJ P, ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- QUASAR message #66 (KSYS)
TOPS10 <
KSYS: MOVE S1,[KSYZBG,,KSYZBG+1] ;SET UP BLT
SETZM KSYZBG ;CLEAR FIRST WORD
BLT S1,KSYZND ;CLEAR ALL KSYS DATA
MOVEI S1,777777-^D512 ;STARTING FAKE REQUEST-ID
MOVEM S1,KSYREQ ;SAVE
SETOM G$KSYS ;FLAG KSYS IN PROGRESS
PUSHJ P,KSYJOB ;FIND ALL THE JOBS TO KILL
SKIPN KSYCNT ;ANY JOBS?
PJRST KSYFIN ;NO--TYPE COMPLETION TEXT AND RETURN
PUSHJ P,KSYSET ;SETUP ALL KSYS STREAMS
POPJ P, ;LET THE SCHEDULER DO THE REST
; Here to find all the jobs to kill
; Call: PUSHJ P,KSYJOB
;
; On return all jobs to be killed will be marked in the bit map
; (KSYMAP) and the number of jobs marked will be set in KSYCNT.
KSYJOB: $SAVE <P1,P2> ;SAVE SOME ACS
MOVE T1,[KSYMAP,,KSYMAP+1] ;SET UP BLT
SETZM KSYMAP ;CLEAR FIRST WORD
BLT T1,KSYMAP+KSYLEN-1 ;CLEAR OUT BIT MAP
SETZM KSYCNT ;INIT COUNT OF JOBS TO KILL
SETZM KSYJLO ;CLEAR COUNT OF JOBS LOGGED OFF
MOVE P1,[%NSHJB] ;START WITH THE HIGHEST
GETTAB P1, ; LOGGED IN JOB
MOVEI P1,^D511 ;ASSUME THE MAX
KSYJ.1:
; CHECK THE PPN
MOVEI S1,(P1) ;GET JOB NUMBER
MOVEI S2,JI.USR ;WANT THE PPN
$CALL I%JINF ;ASK THE GLXLIB
JUMPF KSYJ.X ;JOB GONE AWAY
CAMN S2,OPRPPN ;OPERATOR?
JRST KSYJ.X ;YES--LEAVE HIM ALONE
; CHECK THE LINE
MOVEI S1,(P1) ;GET JOB NUMBER
MOVEI S2,JI.TNO ;WANT LINE NUMBER
$CALL I%JINF ;ASK THE GLXLIB
JUMPF KSYJ.X ;JOB GONE AWAY
JUMPL S2,KSYJ.3 ;ALREADY DETACHED
TRO S2,.UXTRM ;ADD UDX OFFSET
GETLCH S2 ;GET LINE CHARACTERISTICS
TXNN S2,GL.ITY ;PTY?
JRST KSYJ.2 ;NO
; CHECK FOR BATCON OR MIC CONTROLLED PTYS
MOVEI S1,.GTLIM ;BATCH LIMIT TABLE
HRL S1,P ;INCLUDE JOB NUMBER
GETTAB S1, ;GET BAT LIMIT WORD
MOVEI S1,0 ;SHOULDNT FAIL
TXNE S1,JB.LBT ;BATCH (BATCON OR MIC)?
JRST KSYJ.X ;YES--LEAVE THEM ALONE
KSYJ.2: TXNN S2,GL.DSL!GL.REM ;DATASET OR REMOTE?
JRST KSYJ.X ;NO--TRY SOMEONE ELSE
ANDI S2,UX.UNT ;KEEP ONLY THE LINE NUMBER
HRLZS S2 ;MAKE IT LINE#,,JOB 0
ATTACH S2, ;DETACH JOB
JRST KSYJ.X ;??
KSYJ.3: MOVSI T1,400000 ;GET A BIT
MOVEI T2,(P1) ;AND THE JOB IN QUESTION
IDIVI T2,^D36 ;COMPUTE BIT MAP WORD
MOVNS T3 ;NEGATE
LSH T1,(T3) ;POSITION BIT
IORM T1,KSYMAP(T2) ;SAVE IT AWAY
AOS KSYCNT ;COUNT THE JOB
KSYJ.X: SOJG P1,KSYJ.1 ;LOOP FOR ALL JOBS
POPJ P, ;AND RETURN
; Routine to do a special KSYS stream setup
; Call: PUSHJ P,KSYSET
; <NON-SKIP> ;NONE AVAILABLE RIGHT NOW
; <SKIP> ;STREAM SETUP
KSYSET: $SAVE <P1,P2> ;SAVE P1 AND P2
MOVE P1,[-JOBMAX+KSYSTR,,KSYSTR] ;POINTER TO START OF KSYS STREAMS
MOVE P2,KSYCNT ;GET NUMBER IF JOBS TO KILL
KSYSE1: SKIPL G$STRM(P1) ;STREAM IN USE?
JRST KSYSE2 ;YES--KEEP LOOKING
HRRZ S,P1 ;GET STREAM NUMBER IN S
MOVEM S,G$STRM(S) ;SAVE IN TABLE
MOVEI S1,.JPAGS ;# PAGES NEEDED FOR THE DATA BASE
$CALL M%AQNP ;GET A PAGE FOR THE DATA BASE
MOVEI R,(S1) ;PUT THE PAGE NUMBER IN R
PG2ADR R ;CONVERT PAGE TO ADDRESS
HRRZM R,G$BASE(S) ;SAVE FOR THE DISPATCHER
MOVEI S1,.OTBAT ;OBJECT TYPE = BATCH STREAM
MOVEM S1,.JQOBJ+OBJ.TY(R) ;SAVE
MOVE S1,G$STRM(S) ;GET STREAM NUMBER
MOVEM S1,.JQOBJ+OBJ.UN(R) ;SAVE
MOVE S1,G$NODE ;GET BATCON'S NODE
MOVEM S1,.JQOBJ+OBJ.ND(R) ;SAVE
AOS KSYSSC ;COUNT THE STREAM SETUP
$WTO (<KSYS stream started>,,.JQOBJ(R))
; MOVX T1,%RSUOK ;GOOD RETURN FOR SETUP
; SETZB T2,T3 ;CLEAR MESSAGE AND STATUS CODE
; PUSHJ P,SETUPR ;SEND SUCESSFUL SETUP MESSAGE TO QUASAR
SOSLE P2 ;COUNT DOWN
KSYSE2: AOBJN P1,KSYSE1 ;LOOP UNTIL ALL KSYS STREAMS SETUP
POPJ P, ;RETURN
; Routine to simply queue up the log file
KSYQUE: $SAVE <P1,P2> ;SAVE P1 AND P2
$CALL M%GPAG ;GET A PAGE FOR MESSAGE
MOVE P1,S1 ;COPY TO A SAFE PLACE
MOVEI S1,.QOCQE ;MESSAGE TYPE IS SHORT CREATE
STORE S1,.MSTYP(P1),MS.TYP ;STORE IT
MOVEI P2,.OHDRS(P1) ;POINT TO EMPTY SLOT
; Queue type
MOVE S1,[2,,.QCQUE] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVEI S1,.OTLPT ;OBJECT TYPE LPT
MOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,2 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Filespec
MOVSI S1,.JQLFD+ARG.DA(R) ;ADDRESS OF FD
HRRI S1,ARG.DA(P2) ;WHERE TO PUT IT
BLT S1,FDXSIZ-ARG.DA-1(P2) ;COPY FD
MOVE S1,[FDXSIZ-ARG.DA,,.QCFIL] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
HLRZS S1 ;GET BLOCK LENGTH
ADDI P2,(S1) ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; File format
MOVE S1,[2,,.QCPTP] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVEI S1,.FPFAS ;ASCII
MOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,2 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Output disposition
MOVE S1,[2,,.QCODP] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVEI S1,%DELETE ;DELETE AFTER PRINTING
MOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,2 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Account string
MOVE S1,[10,,.QCACT] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVSI S1,.JQACT(R) ;POINT TO ACCT STRING
HRRI S1,ARG.DA(P2) ;WHERE TO PUT IT
BLT S1,ARG.DA+10-1(P2) ;COPY
ADDI P2,10 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; User name
MOVE S1,[3,,.QCNAM] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
DMOVE S1,.JQJBB+JIB.NM(R) ;GET TWO WORDS
DMOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,3 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; PPN
MOVE S1,[2,,.QCOID] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVE S1,.JQPPN(R) ;GET THE PPN
MOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,2 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Job name
MOVE S1,[2,,.QCJBN] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVE S1,['KSYS '] ;GET OBVIOUS NAME
MOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,2 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Note
MOVE S1,[3,,.QCNTE] ;LENGTH,,BLOCK TYPE
MOVEM S1,ARG.HD(P2) ;SAVE
MOVE S1,['LOGOUT'] ;WORD 1
MOVE S2,[' ERROR'] ;WORD 2
DMOVEM S1,ARG.DA(P2) ;SAVE
ADDI P2,3 ;ADVANCE
AOS .OARGC(P1) ;COUNT ARGUMENTS
; Finish up
MOVEI S1,(P2) ;GET LAST FREE ADDR IN MESSAGE
SUBI S1,(P1) ;COMPUTE LENGTH
STORE S1,.MSTYP(P1),MS.CNT ;STORE IN MESSAGE
MOVEM P1,G$SAB+SAB.MS ;STORE PAGE ADDRESS
MOVEI S1,PAGSIZ ;GET THE MESSAGE SIZE
STORE S1,G$SAB+SAB.LN ;STORE IT
MOVEI S1,SAB.SZ ;GET SAB SIZE
MOVEI S2,G$SAB ;GET SAB ADDRESS
$CALL C%SEND ;SEND MESSAGE TO QUASAR
JUMPT .POPJ ;RETURN IF NO ERRORS
MOVE S1,G$SAB+SAB.MS ;ELSE GET BACK PAGE ADDRESS
$CALL M%RPAG ;DESTROY THE PAGE
$WTO (<BATCON error>,<^I/KSYQTX/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
POPJ P, ;AND RETURN
KSYQTX: ITEXT (<Can't spool KSYS log file: ^F/.JQLFD(R)/>)
> ;END TOPS-10 CONDITIONAL
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200004 (PAUSE)
PAUSE: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
SETZ S1, ;CLEAR AC
TXNE R,RL.STP ;ALREADY STOPPED?
MOVEI S1,[ASCIZ |Already stopped|] ;YES
TXNE R,RL.LGI ;LOGGING IN
MOVEI S1,[ASCIZ |Logging in|] ;YES
TXNE R,RL.KJB ;LOGGING OUT?
MOVEI S1,[ASCIZ |Logging out|] ;YES
JUMPE S1,PAUS.1 ;CHECK FOR ERRORS
$ACK (<^T/(S1)/>,,<.JQOBJ(R)>,<.MSCOD(P1)>) ;COMPLAIN
POPJ P, ;RETURN
PAUS.1: MOVEI S1,[ASCIZ |STOP|] ;MESSAGE NAME
MOVEI S2,STOPJB ;PROCESSOR ADDRESS
PUSHJ P,B$IMSG ;SET UP OPERATOR/QUASAR MESSAGE
POPJ P, ;ONE ALREADY THERE - RETURN
MOVX S1,B.STCN!B.DEFR ;GET SOME FLAGS
IORM S1,.JOFLG(R) ;STORE IT
$ACK (<Stop request queued>,,<.JQOBJ(R)>,.MSCOD(P1))
POPJ P, ;RETURN
; Routine executed in stream context to stop the job.
;
STOPJB: TXO F,FL.SCC ;SEND ^C TO STOP THE JOB
PUSHJ P,P$STOP## ;PUT AT MONITOR LEVEL
$IDENT (OPERAT,<[Job stopped by the operator]>)
SETOM .JLTIM(R) ;MARK TIME STAMP NEEDED
MOVX T1,%STOPD ;GET STOPPED CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
$WTOJ (<Stopped>,<^R/.JQJBB(R)/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
TXO R,RL.STP ;STREAM STOPPED
TXZ R,RL.MIP ;CLEAR MESSAGE IN PROGRESS
SETZM .JOVAL(R) ;CLEAR VALID MESSAGE FLAG
JRST QTS ;WAIT FOR CONTINUE
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200005 (CONTINUE)
CONTIN: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
TXNE R,RL.STP ;JOB STOPPED?
JRST CONT.1 ;YES
$ACK (<Not stopped>,,<.JQOBJ(R)>,<.MSCOD(P1)>) ;COMPLAIN
POPJ P, ;RETURN
CONT.1: MOVEI S1,[ASCIZ |CONTINUE|] ;MESSAGE NAME
MOVEI S2,CONTJB ;PROCESSOR ADDRESS
PUSHJ P,B$IMSG ;SET UP OPERATOR/QUASAR MESSAGE
POPJ P, ;ONE ALREADY THERE - RETURN
MOVX S1,B.STCN!B.DEFR ;GET SOME FLAGS
IORM S1,.JOFLG(R) ;STORE IT
POPJ P, ;RETURN
; Routine executed in stream context to continue the job.
;
CONTJB: TXZE R,RL.STP ;SHOULE WE CONTINUE JOB?
TXNN F,FL.SCC ;SENT ^C TO JOB?
JRST CONTJ1 ;NO TO EITHER
$IDENT (OPERAT,<[Job continued by the operator]>)
PUSHJ P,L$LSTP## ;PUT A TIME STAMP IN THE LOG FILE
MOVX S1,MONCHR ;GET THE MONITOR PROMPT CHARACTER
PUSHJ P,L$OUTC## ;LOG IT
PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
$TEXT (B$CPUT,<CONTINUE^M>) ;CONTINUE THE JOB
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
CONTJ1: MOVX T1,%RESET ;GET NORMAL OPERATION CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
$ACK (<Continued>,,<.JQOBJ(R)>,<.JOMSG+.MSCOD(R)>)
TXZ R,RL.MIP ;CLEAR MESSAGE IN PROGRESS
SETZM .JOVAL(R) ;CLEAR VALID MESSAGE FLAG
JRST QTS ;CONTEXT SWITCH INCASE IN OPERATOR WAIT
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200012 (RESPONSE)
RESPON: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVE S1,.MSCOD(P1) ;GET ACK CODE (STREAM ITN)
MOVEI S,0 ;CLEAR STREAM INDEX
RESP.1: SKIPL R,G$BASE(S) ;GET STREAM RELOCATION
JRST RESP.2 ;NOT SETUP
CAMN S1,.JOACK(R) ;CHECK THE ACK CODE
JRST RESP.3 ;FOUND IT
RESP.2: CAMGE S,G$HACT ;CHECKED ALL STREAMS YET?
AOJA S,RESP.1 ;NO - LOOP
POPJ P, ;RETURN
RESP.3: SETZM .JOACK(R) ;CLEAR ACK CODE
TXZN R,RL.OPR!RL.DIA ;CLEAR OPR RESPONSE WAIT, DIALOGUE MODE
POPJ P, ;NOT WAITING
MOVE S1,P1 ;POINT TO MESSAGE
PUSHJ P,B$SBLK ;SETUP FOR BLOCK PARSING
RESP.4: PUSHJ P,B$GBLK ;GET A BLOCK
POPJ P, ;CAN'T
CAIE T1,.CMTXT ;LOOKING FOR TEXT
JRST RESP.4 ;TRY ANOTHER
HRLZ S1,T3 ;GET ADDRESS OF TEXT
HRRI S1,.JORSP(R) ;WANT IT TO GO HERE
MOVE S2,T2 ;GET SIZE OF BLOCK
CAILE S2,<RSPSIZ/5>+1 ;WILL IT FIT IN THE BUFFER?
MOVEI S2,<RSPSIZ/5>+1 ;NO - TAKE ONLY WHAT WE CAN HANDLE
ADDI S2,.JORSP(R) ;COMPUTE END ADDRESS
BLT S1,-1(S2) ;COPY TEXT
MOVEM R,G$BASE(S) ;RESTORE R
POPJ P, ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200025 (REQUEUE)
REQUE: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVEI S1,[ASCIZ |REQUEUE|] ;MESSAGE NAME
MOVEI S2,REQJOB ;PROCESSOR ADDRESS
PUSHJ P,B$IMSG ;SET UP OPERATOR/QUASAR MESSAGE
POPJ P, ;ONE ALREADY THERE - RETURN
MOVX S1,B.DEFR ;GET DEFERRED FLAG
IORM S1,.JOFLG(R) ;STORE IT
MOVX T1,%REQUE ;GET REQUEUE CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
$ACK (<Requeue request queued>,,<.JQOBJ(R)>,.MSCOD(P1))
POPJ P, ;RETURN
; Routine executed in stream context to requeue the job.
;
REQJOB: TXO R,RL.REQ ;MARK JOB AS REQUEUED
MOVEI P1,[ASCIZ |No reason given|] ;DEFAULT REASON
MOVEI S1,.JOMSG(R) ;GET MESSAGE ADDRESS
PUSHJ P,B$SBLK ;SET UP BLOCK STUFF
REQJ.1: PUSHJ P,B$GBLK ;GET A BLOCK
JRST REQJ.2 ;NO MORE
CAIE T1,.ORREA ;REASON FIELD
JRST REQJ.1 ;NO - KEEP LOOKING
MOVE P1,T3 ;GET ADDRESS OF REASON
JRST REQJ.1 ;CHECK NEXT ARGUMENT
REQJ.2: $IDENT (OPERAT,<[Job requeued by the operator]>)
MOVE S1,[$IDENT (OPERAT,<; ^A>)] ;GET INSTRUCTION TO STAMP LINE
MOVE S2,P1 ;GET BYTE POINTER
PUSHJ P,L$COPY## ;COPY TEXT INTO THE LOG FILE
PUSHJ P,L$CRLF## ;ADD A CRLF
MOVX S1,RQ.HBO ;HELD BY OPERATOR FOR REQUEUE
MOVEM S1,.JBRQF(R) ;SAVE REQUEUE FLAG WORD
MOVX S1,<BA.ORQ!BA.JOB> ;OPERATOR REQUEUE
IORM S1,.JBCRQ(R) ;SAVE IN CHECKPOINT WORDS
PJRST B$CLOS ;DISMISS JOB
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200026 (CANCEL)
CANCEL: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVEI S1,[ASCIZ |ABORT|] ;MESSAGE NAME
MOVEI S2,CANJOB ;PROCESSOR ADDRESS
PUSHJ P,B$IMSG ;SET UP OPERATOR/QUASAR MESSAGE
POPJ P, ;ONE ALREADY THERE - RETURN
MOVX S1,B.DEFR ;GET DEFERRED FLAG
IORM S1,.JOFLG(R) ;STORE IT
MOVX T1,%CNCLG ;GET CANCEL CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
$ACK (<Abort request queued>,,<.JQOBJ(R)>,.MSCOD(P1))
POPJ P, ;RETURN
; Routine executed in stream context to cancel the job.
;
CANJOB: PUSHJ P,P$STOP## ;^C THE PTY
MOVX P1,.CNERR ;DEFAULT TO ERROR PROCESSING
MOVEI P2,[ASCIZ |No reason given|] ;DEFAULT REASON
MOVEI S1,.JOMSG(R) ;GET MESSAGE ADDRESS
PUSHJ P,B$SBLK ;SET UP BLOCK STUFF
CANJ.1: PUSHJ P,B$GBLK ;GET A BLOCK
JRST CANJ.2 ;NO MORE
CAIN T1,.CANTY ;TYPE FIELD
JRST CANJ.5 ;YES..PROCESS TYPE
CAIN T1,.ORREA ;REASON FIELD
JRST CANJ.6 ;YES..SETUP POINTER
JRST CANJ.1 ;KEEP LOOKING
CANJ.2: HRRZ S1,CANCTB-1(P1) ;GET THE TEXT FOR ERROR TYPE
$IDENT (OPERAT,<? Job aborted by the operator (^T/(S1)/)>)
MOVE S1,[$IDENT (OPERAT,<; ^A>)] ;GET INSTRUCTION TO STAMP LINE
MOVE S2,P2 ;GET BYTE POINTER
PUSHJ P,L$COPY## ;COPY TEXT INTO THE LOG FILE
PUSHJ P,L$CRLF## ;ADD A CRLF
TXO F,FL.TXT ;MESSAGE TEXT AVAILABLE
$TEXT (<-1,,.JWTOP(R)>,<Job aborted by the operator; ^T/(P2)/^0>)
TXZ R,RL.JIE!RL.FLS ;CLEAR JOB IN ERROR AND FLUSH JOB
CAIE P1,.CNERR ;/ERROR?
JRST CANJ.3 ;NO
TXZ R,RL.MSP!RL.MIP ;CLEAR MESSAGE FLAGS
SETZM .JOVAL(R) ;CLEAR VALID MESSAGE INDICATOR
TXO R,RL.JIE ;SET JOB IN ERROR
MOVX T1,%RESET ;GET NEW STATUS
PUSHJ P,B$UPDA ;TELL QUASAR
POPJ P, ;AND RETURN TO NORMAL JOB LOOP
CANJ.3: CAIE P1,.CNNER ;/NOERROR?
JRST CANJ.4 ;NO
TXO R,RL.FLS ;SET FLUSH JOB BIT
TXZA F,FL.UHE ;CLEAR UNHANDLED ERROR CONDITION
CANJ.4: TXO F,FL.UHE ;/PURGE - SET UNHANDLED ERROR CONDITION
JRST B$CLOS ;DISMISS THE JOB
; Process disposition type
;
CANJ.5: SKIPLE P1,(T3) ;GET DISPOSITION TYPE
CAILE P1,.CNPRG ;IS IT WITHIN RANGE?
MOVEI P1,.CNERR ;ASSUME ERROR PROCESSING
JRST CANJ.1 ;CHECK NEXT ARGUMENT
; Process /REASON
;
CANJ.6: MOVE P2,T3 ;GET ADDRESS OF REASON
JRST CANJ.1 ;CHECK NEXT ARGUMENT
; Table of cancel options and flags
;
CANCTB: EXP [ASCIZ/with error processing/]
EXP [ASCIZ/with no error processing/]
EXP [ASCIZ/purged/]
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200035 (SEND)
SEND: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
PUSHJ P,B$GBLK ;FIND A BLOCK
JRST SEND.1 ;CAN'T
CAIE T1,.CMTXT ;IS IT TEXT?
JRST SEND.1 ;NO
MOVE P2,T3 ;COPY TO A SAFER PLACE
HRLI P2,(POINT 7,) ;MAKE A BYTE POINTER
SEND.1: ILDB S1,P2 ;GET A CHARACTER, < (MATCH BRACKETS)
JUMPE S1,SEND.E ;END OF TEXT - BAD MESSAGE
CAIE S1,">" ;END OF JUNK?
JRST SEND.1 ;NO - KEEP LOOKING
$IDENT (OPERAT,<[Message from operator]>) ;IDENTIFY LINE
MOVE S1,[$IDENT (OPERAT,<; ^A>)] ;GET INSTRUCTION TO STAMP LINE
MOVE S2,P2 ;GET BYTE POINTER
PUSHJ P,L$COPY## ;COPY TEXT INTO THE LOG FILE
MOVE S1,[$IDENT (OPERAT,<[End of operator message]>)]
MOVE S2,[POINT 7,[BYTE (7) .CHCRT,.CHLFD,0,0,0]]
PUSHJ P,L$COPY ;PUT IN LOG FILE
SETOM .JLTIM(R) ;SAY WE NEED TIME STAMP
$ACK (<Send completed>,,<.JQOBJ(R)>,.MSCOD(P1))
POPJ P, ;RETURN
SEND.E: $ACK (<BATCON error>,<Invalid SEND message from ORION>,<.JQOBJ(R)>,.MSCOD(P1))
POPJ P, ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- ORION message #200036 (EXAMINE)
EXAMIN: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
$CALL M%GPAG ;GET A PAGE
MOVE P2,S1 ;SAVE THE PAGE ADDRESS
MOVEI S1,WTOSIZ ;GET MESSAGE SPACE LEAVING ROOM FOR ACK
MOVEM S1,WTOCNT ;SAVE THE COUNT
HRRI S1,(P2) ;POINT TO THE PAGE
HRLI S1,(POINT 7,) ;MAKE BYTE POINTER
MOVEM S1,WTOPTR ;SAVE THE POINTER
SKIPN .JCIFN(R) ;IS THE CONTROL FILE OPEN?
JRST EXAME1 ;NO,,EXIT WITH ERROR
PUSHJ P,B$GBLK ;FIND A BLOCK
JRST EXAME4 ;CAN'T
CAIE T1,.SHCLN ;IS IT /LINES?
JRST EXAME4 ;NO
MOVE P3,(T3) ;GET /LINES VALUE
SUBI P3,1 ;ACCOUNT FOR THE IN-CORE COMMAND LINE
PUSHJ P,C$SPOS## ;SAVE POSITION OF CTL FILE
$TEXT (WTODAT,<*** Input from ^F/.JQCFD(R)/ ***^M^J^T/.JSCTL(R)/^A>)
EXAM.1: MOVE S1,.JCIFN(R) ;GET IFN
$CALL F%IBYT ;GET A BYTE
JUMPF EXAME2 ;EXIT EXAMIN ERROR
JUMPE S2,EXAM.1 ;SKIP NULLS
MOVE S1,S2 ;PLACE NUMBER IN S1
PUSHJ P,WTODAT ;OUTPUT BYTE TO MESSAGE
JUMPF EXAME3 ;ERROR ..TERMINATES MESSAGE
CAIG S2,.CHFFD ;CHECK IF GREATER THAN FF
CAIGE S2,.CHLFD ;CHECK IF LINE FEED
JRST EXAM.1 ;NO GET NEXT CHARACTER
SOJG P3,EXAM.1 ;WANT MORE...GO TO EXAM.1
EXAM.2: PUSHJ P,EXAMAC ;SEND AC AND MESSAGE TO ORION
EXAM.3: PUSHJ P,C$RPOS## ;REPOSITION THE CTL FILE
$RETIT ;ALL DONE IF IT WORKED
MOVE S1,.JREGS+P(R) ;GET THE STREAM STACK
PUSH S1,[B$ABORT] ;WHERE TO RESUME EXECUTION
MOVEM S1,.JREGS+P(R) ;SAVE UPDATED STACK POINTER
TXZ R,RL.STP!RL.OPR!RL.NSC!RL.ACK ;CLEAR FLAGS WHICH WOULD PREVENT
MOVEM R,.JREGS+R(R) ; RUNNING THIS STREAM AT TOPLVL
POPJ P, ;RETURN, WILL ABORT IN STREAM CONTEXT
EXAME1: $TEXT (WTODAT,<Control file ^F/.JQCFD(R)/ not open^A>)
PJRST EXAMAC ;SEND AC TO ORION
EXAME2: $TEXT (WTODAT,<^M^J *** End of File ***^A>)
JRST EXAM.2 ;FINISH OUT EXAMIN COMMAND
EXAME3: MOVEI S1,^D15*5 ;GET EXTRA ROOM
MOVEM S1,WTOCNT ;SAVE THE COUNT
$TEXT (WTODAT,< *** End of Show Data Page ***^A>)
JRST EXAM.2 ;SEND AND REPOSITION
EXAME4: $TEXT (WTODAT,<Invalid Show Control-File command>)
JRST EXAM.2 ;FINISH OFF THE COMMAND
EXAMAC: $ACK (<Show control file>,<^I/JIBTXT/^T/(P2)/>,.JQOBJ(R),.MSCOD(P1),<$WTJBN(.JBJNO(R))>)
MOVE S1,P2 ;GET THE PAGE
$CALL M%RPAG ;RELEASE THE PAGE
POPJ P, ;RETURN
WTODAT: SOSG WTOCNT ;DECREMENT COUNT
$RETF ;ABORT AND RETURN
IDPB S1,WTOPTR ;DEPOSIT BYTE
$RETT ;RETURN
SUBTTL IPCF/Operator/QUASAR interface -- ACK message #700000
ACK: MOVE P1,G$MADR ;GET MESSAGE ADDRESS
MOVX S2,MF.NOM ;GET THE 'NO MESSAGE' BIT
SKIPE S1,.MSCOD(P1) ;GET ACK CODE (IF ANY)
TDNN S2,.MSFLG(P1) ;ALL GOOD ACKS HAVE THIS BIT SET
JRST ACKTXT ;MUST BE SOME JUNK TEXT ACK
MOVEI S,0 ;CLEAR STREAM INDEX
ACK.1: SKIPL R,G$BASE(S) ;GET STREAM RELOCATION
JRST ACK.2 ;NOT SETUP
CAMN S1,.JOACK(R) ;CHECK THE ACK CODE
JRST ACK.3 ;FOUND IT
ACK.2: CAMGE S,G$HACT ;CHECKED ALL STREAMS YET?
AOJA S,ACK.1 ;NO - LOOP
POPJ P, ;RETURN
ACK.3: SETZM .JOACK(R) ;CLEAR ACK CODE
TXZ R,RL.ACK ;CLEAR WAITING FOR ACK BIT
MOVEM R,G$BASE(S) ;UPDATE STREAM FLAGS
POPJ P, ;RETURN
; Text ACKs
;
ACKTXT: MOVE S1,G$MADR ;GET MESSAGE ADDRESS
SKIPE .OARGC(S1) ;QUASAR SNIFFING AROUND?
$WTO(<BATCON Error>,<Unexpected text message - ^T/.OHDRS+ARG.DA(S1)/>)
POPJ P, ;RETURN
; Find new G$HACT stream
;
FHIACT: PUSH P,S ;SAVE THE CURRENT STREAM NUMBER
SKIPL G$BASE(S) ;IS STREAM ACTIVE?
SOJG S,.-1 ;NO - TRY ANOTHER
MOVEM S,G$HACT ;STORE STREAM NUMBER OR -1
POP P,S ;RESTORE CURRENT STREAM NUMBER
$RETT ;RETURN
SUBTTL STPPRC - Batch step processor
STPPRC::SETZM .JSSTP(R) ;CLEAR STEP LINE COUNTER
SKIPN .JBSPS(R) ;DOING ONLY A STEP HEADER SCAN?
JRST STPP.4 ;NO - CALLED FROM JOB PROCESSOR
PUSHJ P,C$OPEN## ;OPEN THE CONTROL FILE
PUSHJ P,C$READ## ;READ THE FIRST LINE
JUMPF CLOSJB ;EOF
CAXN S1,STPCHR ;IS IT THE MAGIC STEP HEADER CHARACTER?
JRST STPP.4 ;YES
STPP.1: PUSHJ P,B$EOJ ;FORCE END OF HEADER PROCESSING
JRST CLOSJB ;DISMISS JOB
STPP.2: TXNE R,RL.JIE ;JOB IN ERROR?
JRST HDRERR ;YES - ABORT IT
SKIPGE .JSSTP(R) ;END OF STEP?
JRST HDRXIT ;YES
STPP.3: PUSHJ P,C$READ## ;READ A LINE FROM THE CONTROL FILE
JUMPF CLOSJB ;END OF FILE
CAIN S1,.CHCRT ;BLANK LINE?
JRST STPP.3 ;YES - IGNORE IT
CAIE S1,";" ;OLD STYLE COMMENT?
CAIN S1,"!" ;NEW STYLE COMMENT?
JRST STPP.4 ;YES
CAXE S1,STPCHR ;STEP DELIMITER CHARACTER?
JRST HDRSSE ;ERROR - GO FINISH UP
STPP.4: PUSHJ P,C$STEP## ;PARSE PARAMETER LINES
JUMPF HDRERR ;PARSE ERRORS
JRST STPP.2 ;BACK FOR ANOTHER COMMAND
; Header syntax error
;
HDRSSE: $IDENT (HEADER,<^T/.JSCTL(R)/^A>) ;ECHO THE LINE IN ERROR
$IDENT (BATSSE,<? Step header syntax error>)
; Common header scan error code
;
HDRERR: TXO F,FL.UHE ;CALL IT AN UNHANDLED ERROR CONDITION
TXO R,RL.JIE ;JOB IN ERROR IF IT GOT THIS FAR
PUSHJ P,B$EOJ ;FORCE END OF HEADER PROCESSING
MOVE S1,.JLSTP(R) ;GET $STEP LABEL
CAMN S1,[-1] ;WAS IT A SPECIAL $STEP ERROR?
SETZM .JLSTP(R) ;YES
SKIPN S1 ;WAS $STEP LINE MISSING?
$IDENT (BATMSL,<? Missing $STEP line in header>)
SOSLE .JSSTP(R) ;ADJUST COUNT OF LINES PROCESSED
$IDENT (HEADER,<[^D/.JSSTP(R)/ lines processed in step ^W/.JLSTP(R)/ header]>)
$IDENT (BATBJC,<[Batch job canceled]>)
; Header scan exit
;
HDRXIT: TXNN R,RL.JIE ;JOB IN ERROR?
SKIPE .JBSPS(R) ;OR DOING ONLY A STEP HEADER SCAN?
JRST CLOSJB ;YES - DISMISS THE JOB
POPJ P, ;NO - RETURN TO JOB PROCESSOR
SUBTTL JOBPRC - Process a Batch stream
; JOBPRC will do the following:
; a) Open the control file
; b) Open the log file
; c) Put a header on the log file
; d) LOGIN a job
; e) Perform post LOGIN job setup
; f) Initialize job processing
; g) Enter job processor loop
;
JOBPRC: PUSHJ P,U$STJB## ;HANDLE SPECIAL STARTUP PROCESSING
PUSHJ P,C$FILE## ;FIX UP THE CTL FILESPEC
MOVEI T1,FILTX1 ;ASSUME NORMAL BATCH JOB
TXNE F,FL.KST ;KSYS STREAM?
MOVEI T1,FILTX2 ;YES
$WTOJ (<Begin>,<^I/JIBTXT/^I/(T1)/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
PUSHJ P,L$HEAD## ;PREPARE A LOG FILE HEADER
PUSHJ P,L$OPEN## ;OPEN THE LOG FILE
PUSHJ P,C$OPEN## ;OPEN THE CONTROL FILE
PUSHJ P,CHKPNT ;CHECKPOINT JOB
PUSHJ P,LOGINJ ;LOGIN THE JOB
PUSHJ P,JOBINI ;INITIALIZE JOB PROCESSING
TXNE F,FL.KST ;KSYS STREAM?
PJRST B$CLOS ;YES--TERMINATE NOW
TXNE R,RL.ACK ;MUST WE WAIT FOR INITIAL ACK?
PUSHJ P,QTS ;YES, MUST BE NORESTARTABLE
JRST HONORJ ;ENTER JOB PROCESSING LOOP
FILTX1: ITEXT (<Control file: ^F/.JQCFD(R)/^M^JLog file: ^F/.JQLFD(R)/>)
FILTX2: ITEXT (<Log file: ^F/.JQLFD(R)/>)
; Here to honor a job's input request
;
HONORJ: PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
TXNN J,JL.UJA ;IS THE JOB STILL THERE?
PJRST B$GONE ;NO
TXNE R,RL.NLG ;LOG FILE OUTPUT ERROR?
PUSHJ P,L$IOER## ;YES
TXNE F,FL.TLE ;WAS TIME LIMIT EXCEEDED?
PUSHJ P,TIMERR ;YES - TRY TO GIVE MORE TIME
TXNE R,RL.DIA ;JOB IN DIALOGUE MODE?
PUSHJ P,REDOPR ;YES
PUSHJ P,U$HNRJ## ;PROCESS SPECIAL CUSTOMER CHECKING
JRST B$CLOS ;DISMISS JOB IF ERROR OCCURS
TXZE F,FL.RCL ;RE-EAT COMMAND LINE?
JRST HONOR1 ;YES
PUSHJ P,C$READ## ;NO - READ A LINE FROM THE CONTROL FILE
JUMPF CLOSJB ;END OF FILE?
HONOR1: PUSHJ P,C$SCAN## ;SCAN AND PROCESS A COMMAND
JRST HONORJ ;LOOP
SUBTTL BATCON initialization -- System independant code
B$INIT: MOVE S1,[PUSHJ P,UUOCON] ;LOCAL UUO HANDLER
MOVEM S1,.JB41## ;SET IT UP
SETOM G$STRM ;SET UP STREAM INDEX BLOCK
MOVX S1,<G$STRM,,G$STRM+1> ; BY PUTTING -1 IN EACH WORD
BLT S1,G$STRM+JOBMAX-1 ; TO INDICATE STREAM NOT IN USE
MOVX S1,INPCOR ;GET CORE FLAG
MOVEM S1,G$CORE ;REMEMBER FOR LATER
SETZM G$MDA ;ASSUME NO MDA SUPPORT
$CALL L%CLST ;CREATE A LINKED LIST
MOVEM S1,CLKQUE ; FOR THE CLOCK REQUEST QUEUE
$CALL .CPUTY ;GET CPU TYPE
MOVEM S1,G$CPU ;SAVE IT
; Get our node number
SETO S1, ;-1 MEANS US
MOVX S2,JI.LOC ;FUNCTION CODE
$CALL I%JINF ;GET OUR NODE NUMBER
MOVEM S2,G$NODE ;STORE IT
PUSHJ P,SYSINI ;DO SYSTEM DEPENDANT INITIALIZATION
; Greet QUASAR
PUSHJ P,HELLO ;GREET QUASAR
MOVEI S1,REENTER ;GET REENTER ADDRESS
MOVEM S1,.JBREN## ;SET IT UP
POPJ P, ;RETURN
SUBTTL BATCON initialization -- TOPS-10 code
; TOPS-10 initialization
;
TOPS10 < ;TOPS-10 ONLY
SYSINI: MOVX S1,OPTYP% ;GET OUR OBJECT PROCESSOR TYPE
SETOM G$BUDT ;ASSUME %ONCE (SHOULDN'T BE, BUT..)
SKIPE DEBUGW ;DEBUGGING?
JRST SYSI.0 ;YES
CAXN S1,%DEMND ;"FIRED UP" WHEN JOB TO DO?
AOSA G$BUDT ;YES, MAKE G$BUDT +1
CAXN S1,%STCMD ;NO, "FIRED UP" ON START COMMAND?
AOS G$BUDT ;YES, MAKE G$BUDT 0
SYSI.0: SETO S1, ;-1 MEANS US
WAKE S1, ;THIS GUARANTEES US A OUR FIRST WAKE UP
JFCL ;WON'T FAIL
MOVE S1,[%LDFFA] ;GET OPERATOR PPN
GETTAB S1, ;FROM THE MONITOR
MOVE S1,[1,,2] ;DEFAULT
MOVEM S1,OPRPPN ;SAVE
MOVE S1,[%LDQUE] ;GET QUEUE PPN
GETTAB S1, ;FROM THE MONITOR
MOVE S1,[3,,3] ;DEFAULT TO THE USUAL
MOVEM S1,G$SPLD ;STORE IT
MOVE S1,[%CNPTY] ;GET SYSTEM PTY CONFIGURATION
GETTAB S1, ;FROM THE MONITOR
SETZ S1, ;CAN'T
HLRZM S1,G$PTYF ;STORE FIRST PTY
HRRZM S1,G$PTYN ;STORE NUMBER OF PTYS
; Set up the interrupt system
MOVX S1,<VECTOR,,VECTOR+1> ;SET UP A BLT POINTER
SETZM VECTOR ;CLEAR THE FIRST WORD
BLT S1,ENDVEC ;CLEAR THE INTERRUPT DATA
MOVEI S1,IPCINT ;GET ADDRESS OF IPCF INTERRUPT ROUTINE
MOVEM S1,VECIPC+.PSVNP ;STORE IN VECTOR
HRREI T1,.PCIPC ;IPCF CONDITION CODE
MOVSI T2,<VECIPC-VECTOR> ;VECTOR OFFSET
MOVSI T3,IPCLVL ;GET IPCF PRIORITY LEVEL
MOVX S1,PS.FAC+T1 ;FUNCTION CODE TO ADD THE CONDITION
PISYS. S1, ;ADD IT
STOPCD (CEI,HALT,,<Can't enable interrupts>) ;++ CAN'T CONTINUE
$CALL I%ION ;TURN ON THE INTERRUPT SYSTEM
MOVE S1,[%CNST2] ;GET SECOND MONITOR STATES WORD
GETTAB S1, ;READ IT
SETZ S1, ;CAN'T
TXNE S1,ST%MDA ;MONITOR SUPPORT MDA?
SETOM G$MDA ;YES
HRROI S1,.GTPPN ;GET OUR PPN
GETTAB S1, ;GET OUR PPN
JFCL ;CAN'T
CAME S1,[1,,2] ;ARE WE GODLY?
SETZM G$MDA ;NO - THEN NO MDA
SKIPN G$MDA ;ARE WE GONNA SUPPORT MDA?
POPJ P, ;NO - ALL DONE
SYSI.1: MOVX S1,SP.MDA ;GET SPECIAL PID INDEX
$CALL C%RPRM ;ASK THE LIBRARY FOR THE MDA PID
JUMPT .POPJ ;GOT IT
MOVEI S1,5 ;5 SECONDS
$CALL I%SLP ;ZZZZZZ
JRST SYSI.1 ;TRY AGAIN
> ;END OF TOPS-10 CONDITIONAL
SUBTTL BATCON initialization -- TOPS-20 code
; TOPS-10 initialization
;
TOPS20 < ;TOPS-20 ONLY
SYSINI: MOVX S1,RC%EMO ;EXACT MATCH ONLY
HRROI S2,[ASCIZ |PS:[SPOOL]|] ;DIRECTORY NAME
RCDIR ;GET THE DIRECTORY NUMBER
MOVEM T1,G$SPLD ;STORE IT
MOVX S1,'PTYPAR' ;GET SOME PTY PARAMETERS
SYSGT ;FROM THE MONITOR
HRRZM S1,G$PTYF ;SAVE FIRST PTY NUMBER
HLRZM S1,G$PTYN ;SAVE THE NUMBER OF PTYS IN THE SYSTEM
MOVX S1,.MSIIC ;BYPASS MOUNT COUNTS
MSTR ;DO THE FUNCTION
ERJMP .+1 ;IGNODE ERRORS
MOVX S1,.FHSLF ;GET OUR PROCESS HANDLE
MOVEI S2,104 ;GET THE DESIRED QUEUE
SPRIW ;SET PRIORITY WORD FOR OUR JOB
ERJMP .+1 ;IGNORE ERRORS
; Set up the interrupt system
MOVEI S1,INTRP1 ;GET INTERRUPT LEVEL 1 PC
MOVEM S1,LEVTAB ;STORE IT
MOVEI S1,INTRP2 ;GET INTERRUPT LEVEL 2 PC
MOVEM S1,LEVTAB+1 ;STORE IT
MOVEI S1,INTRP3 ;GET INTERRUPT LEVEL 3 PC
MOVEM S1,LEVTAB+2 ;STORE IT
MOVX S1,<IPCLVL,,IPCINT> ;GET INTERRUPT LEVEL FOR IPCF
MOVEM S1,CHNTAB+IPCCHN ;SET UP CHANNEL
MOVX S1,<PTYLVL,,PTYINT> ;GET INTERRUPT LEVEL FOR PTYS
MOVEM S1,CHNTAB+PTYCHN ;SET UP CHANNEL
MOVEM S1,CHNTAB+PTYCHN+1 ;PTYS NEED TWO
CIS ;CLEAR INTERRUPT SYSTEM
$CALL I%ION ;TURN IT ON
MOVX S1,.FHSLF ;GET OUR PROCESS HANDLE
MOVX S2,INTMSK ;GET MASK OF CHANNELS TO ACTIVATE
AIC ;ACTIVATE THOSE CHANNELS
POPJ P, ;RETURN
> ;END OF TOPS-20 CONDITIONAL
SUBTTL Batch generated commands -- Buffer management
; Set up the byte pointer and byte count for Batch generated commands
;
B$CINI::MOVX S1,CTLSIZ ;GET THE NUMBER OF CHARACTERS ALLOWED
MOVEM S1,.JSCTC(R) ;STORE IT
HRLI S1,.JSCTL(R) ;BUILD A BLT POINTER
HRRI S1,.JSCTL+1(R) ;TO CLEAR THE COMMAND BUFFER
SETZM .JSCTL(R) ;CLEAR THE FIRST WORD
BLT S1,.JSCTL+<CTLSIZ/5>(R) ;ZAP THE REMAINDER
; SET UP THE BYTE POINTER TO THE IN-CORE COMMAND BUFFER
;
B$SETB::MOVEM S1,.JSCTB(R) ;SAVE S1
MOVE S1,[POINT 7,.JSCTL(R)] ;GET BYTE POINTER TO TEXT BUFFER
EXCH S1,.JSCTB(R) ;STORE IT AND RESTORE S1
POPJ P, ;RETURN SUCESSFUL
; Put a quoted character into the command buffer
;
B$CQUO::CAIN S1,"""" ;IS IT A DOUBLE QUOTE?
PUSHJ P,B$CPUT ;OUTPUT AN EXTRA - FALL INTO B$CPUT
; Put a character into the command buffer
;
B$CPUT::SOSG .JSCTC(R) ;COUNT CHARACTERS
$RETF ;BUFFER FULL
IDPB S1,.JSCTB(R) ;STORE CHARACTER
$RETT ;RETURN SUCESSFUL
; Transfer the contents of the command buffer pointed to by .JSCTB(R)
; to the PTY
;
B$XFER::ILDB S1,.JSCTB(R) ;GET A CHARACTER
JUMPE S1,XFER.3 ;DONE IF WE ENCOUNTER A <NUL>
CAXE S1,.CHCRT ;A CARRIAGE RETURN?
JRST XFER.1 ;NOPE
TXO F,FL.CTP ;REMEMBER A <CR> SEEN
TXZN F,FL.SUP ;SUPRESS EOL CHARACTERS?
JRST XFER.1 ;NO TO EITHER
ILDB S1,.JSCTB(R) ;EAT THE LINE FEED FOLLOWING <CR>
XFER.1: CAXE S1,.CHLFD ;END OF LINE?
JRST XFER.2 ;YES - IGNORE <LF> AND FINISH UP
TXZE F,FL.CTP ;CARRIAGE RETURN PRECEED THE LINE FEED?
JRST XFER.3 ;YES - IGNORE THE LINE FEED
XFER.2: PUSHJ P,P$OCHR## ;SEND CHARACTER TO THE PTY
JRST B$XFER ;LOOP UNTIL END OF LINE
XFER.3: SETOM .JPEOL(R) ;REMEMBER END OF LINE SENT
TXO F,FL.ECH ;GET READY FOR ECHO LINE
PJRST P$OBUF## ;FORCE OUT PTY BUFFERS AND RETURN
SUBTTL Batch generated commands -- TOPS-10 Login
TOPS10 < ;TOPS-10 ONLY
; TOPS-10 Login
;
LOGINJ: SETOM .JLTIM(R) ;FORCE A TIME STAMP
PUSHJ P,P$CTLC## ;SEND A CONTROL-C
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
PUSHJ P,P$TERM## ;SET UP PTY'S TERMINAL CHARACTERISTICS
TXNE F,FL.KST ;KSYS STREAM?
JRST ATTJOB ;YES--DO AN ATTACH INSTEAD
PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
$TEXT (B$CPUT,<LOGIN ^A>) ;SEND LOGIN COMMAND
MOVE S1,.JQPPN(R) ;GET THE PPN
SKIPN .JQPAT(R) ;IS THERE ONE IN THE PATH SPEC?
MOVEM S1,.JQPAT(R) ;NO - PUT ONE THERE
CAME S1,.JQPAT(R) ;ARE THE PPNS THE SAME?
$TEXT (B$CPUT,<^O/.JQPPN(R),LHMASK/,^O/.JQPPN(R),RHMASK/ ^A>)
$TEXT (B$CPUT,<[^O/.JQPAT(R),LHMASK/,^O/.JQPAT(R),RHMASK/^A>)
MOVEI T1,.JQPAT+1(R) ;GET STARTING ADDRESS OF PATH
HRLI T1,-5 ;SFD COUNTER
LGN1: SKIPN (T1) ;HAVE AN SFD?
TDZA T1,T1 ;NO - END OF PATH
$TEXT (B$CPUT,<,^W/(T1)/^A>) ;SEND THE SFD
AOBJN T1,LGN1 ;LOOP FOR ENTIRE PATH
$TEXT (B$CPUT,<] -^M^A>) ;TERMINATE PPN OR PATH
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION AND RETURN
PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
; Batch parameters
$TEXT (LGNCHR,</BATCH:(^A>) ;START BATCH SWITCHES
GETLIM T1,.JQLIM(R),OINT ;GET OPRINT VALUE
CAIN T1,.OPINN ;NO INTERVENTION?
SKIPA T1,['NO '] ;YES - HE SAID NO
HRLZI T1,'YES' ;NO - HE SAID YES
$TEXT (LGNCHR,<INTERVENTION:^W/T1/,NAME:"^A>)
$TEXT (LGNQUO,<^W/.JQJBB+JIB.JN(R)/^A>)
$TEXT (LGNCHR,<",SEQUENCE:^D/.JQJBB+JIB.SQ(R),JB.SEQ/^A>)
$TEXT (LGNCHR,<,STREAM:^O/.JQOBJ+OBJ.UN(R)/^A>)
$TEXT (LGNCHR,<,REQUESTID:^D/.JQJBB+JIB.ID(R)/)^A>)
; Accounting parameters
$TEXT (LGNCHR,</ACCOUNT:"^A>)
$TEXT (LGNQUO,<^T/.JQACT(R)/^A>)
$TEXT (LGNCHR,<"/NAME:"^A>)
$TEXT (LGNQUO,<^W6/.JQJBB+JIB.NM(R)/^W/.JQJBB+JIB.NM+1(R)/^A>)
MOVEI S1,"""" ;TERMINATE NAME STRING
PUSHJ P,LGNCHR ;TERMINATE COMMAND
; Job parameters
LGN2: GETLIM T1,.JQLIM(R),OPTN ;GET BATCH OPTION NAME
SKIPE T1 ;HAVE ONE?
$TEXT (LGNCHR,</OPTION:^W/T1/^A>)
GETLIM T1,.JQLIM(R),CORE ;GET CORE LIMIT
SKIPE G$CORE ;CHECKING CORE LIMITS?
$TEXT (LGNCHR,</CORE:^D/T1/P^A>)
GETLIM T1,.JQLIM(R),TIME ;GET TIME LIMIT
$TEXT (LGNCHR,</DEFER/LOCATE:^O/.JQLOC(R)//SPOOL:ALL/TIME:^D/T1/^A>)
PUSHJ P,U$LOGI## ;APPEND SPECIAL CUSTOMER SWITCHES
MOVEI S1,.CHCRT ;GET A CARRIAGE RETURN
PUSHJ P,LGNCHR ;TERMINATE COMMAND
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION AND RETURN
JRST LOGSET ;GO DO POST LOGIN SETUP
; Here to attach to the job
ATTJOB: MOVE S1,.JPTTY(R) ;GET PTY'S UDX
ANDI S1,UX.UNT ;KEEP JUST THE LINE NUMBER
HRLZS S1 ;PUT IN LH
HRR S1,.JBJNO(R) ;GET JOB NUMBER
TXO S1,AT.UMM ;PUT IN MONITOR MODE
ATTACH S1, ;DO IT
PJRST B$GONE ;TOO BAD
$IDENT (BATCH,<^7/[MONCHR]/ATTACH ^D/.JBJNO(R)/ ^P/.JQPPN(R)/>)
MOVE T1,['HALT '] ;BE MEAN
MOVE T2,.JBJNO(R) ;GET JOB NUMBER
MOVE S1,[2,,T1] ;SET UP UUO AC
FRCUUO S1, ;STOP JOB
PUSHJ P,P$CTLC## ;SEND A SINGLE CONTROL-C TO HALT JOB
PUSHJ P,IOWAIT ;EAT OUTPUT
POPJ P, ;RETURN
; TOPS-10 post LOGIN setup
;
LOGSET: TXNE J,JL.ULI ;IS A JOB LOGGED IN?
TXNE R,RL.JIE ;DID LOGIN FAIL?
PUSHJ P,ANALYZ ;NOT LOGGED IN - ANALYZE THE ERROR
PUSHJ P,CHKPNT ;CHECKPOINT JOB
PUSHJ P,P$TERM## ;SET UP PTY'S TERMINAL CHARACTERISTICS
PUSHJ P,U$PLGN## ;DO SPECIAL POST-LOGIN PROCESSING
JRST B$CLOS ;SOMETHING WRONG - DISMISS JOB
POPJ P, ;RETURN
; Special character sticker routines for LOGIN command line processing.
; These must be used instead of B$CPUT/B$CQUO to cause continuation line
; processing to happen.
LGNQUO: CAIN S1,"""" ;DOUBLE QUOTE?
PUSHJ P,LGNCHR ;YES--OUTPUT TWO
LGNCHR: PUSH P,S1 ;SAVE CHARACTER
PUSH P,S2 ;SAVE JUNK
MOVEI S1,CTLSIZ+2 ;BUFFER SIZE + "-" AND <CR>
SUB S1,.JSCTC(R) ;COMPUTE CHARACTERS STORED
IDIVI S1,^D80 ;SEE HOW MANY CHARACTER ON LINE
JUMPN S2,LGNC.1 ;TIME FOR A CONTINUATION LINE?
MOVEI S1,"-" ;CHARACTER
PUSHJ P,LGNC.2 ;STORE
MOVEI S1,.CHCRT ;CARRIAGE RETURN
PUSHJ P,LGNC.2 ;STORE
LGNC.1: POP P,S2 ;RESTORE JUNK
POP P,S1 ;RESTORE CHARACTER
LGNC.2: SOSG .JSCTC(R) ;COUNT CHARACTERS
$RETF ;BUFFER FULL
IDPB S1,.JSCTB(R) ;STORE CHARACTER
$RETT ;RETURN SUCESSFUL
> ;END OF TOPS-10 CONDITIONAL
SUBTTL Batch generated commands -- TOPS-20 Login
TOPS20 < ;TOPS-20 ONLY
; TOPS-20 Login
;
LOGINJ: SETOM .JPEOL(R) ;FAKE OUT IN CASE OF PROBLEMS
PUSHJ P,P$CTLC## ;SEND A CONTROL-C
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
PUSHJ P,P$TERM## ;SET UP PTY'S TERMINAL CHARACTERISTICS
TXNE R,RL.JIE ;JOB IN ERROR (? FULL)
PJRST ANLY.2 ;YES - REQUEUE THE JOB
LGN: PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
GETLIM T1,.JQLIM(R),TIME ;GET TIME LIMIT
$TEXT (B$CPUT,<SET TIME-LIMIT ^D/T1/^M^A>)
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
TXNE R,RL.JIE ;JOB IN ERROR?
PUSHJ P,ANALYZ ;YES..ANALYZE THE ERROR
PUSHJ P,SETLOC ;SETUP LOCATION
MOVE S1,[POINT 7,.JQACT(R)] ;GET BYTE POINTER TO ACCT STRING
LGN1: ILDB S2,S1 ;GET A CHARACTER
JUMPE S2,LGN2 ;END OF STRING?
CAIGE S2,176 ;RANGE CHECK
CAIGE S2," " ; IT FOR LEGALITY
JRST LGNERR ;NO GOOD
JRST LGN1 ;LOOP
LGN2: PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
$TEXT (B$CPUT,<LOGIN ^T/.JQNAM(R)/ FOO ^T/.JQACT(R)/^A>)
PUSHJ P,U$LOGI## ;APPEND SPECIAL CUSTOMER SWITCHES
MOVX S1,.CHCRT ;GET A CARRIAGE RETURN
PUSHJ P,B$CPUT ;TERMINATE COMMAND
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION AND RETURN
JRST LOGSET ;DO POST LOGIN PROCESSING
LGNERR: ANDI S2,37 ;MAKE SURE NO JUNK (SORRY RUBOUT)
ADDI S2,"@" ;MAKE IT READABLE
$IDENT (BATICA,<? ^I/LGNTXT/>)
$WTOJ (<Batch error>,<^R/.JQJBB(R)/^I/LGNTXT/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
JRST B$ABORT ;DISMISS THE JOB
LGNTXT: ITEXT (<Illegal character "^^^7/S2/" in account string; job canceled>)
; TOPS-20 post LOGIN setup
; The following job parameters are set:
; a) Mount count on connected directory's structure
; b) CONNECT to requested directory
; c) Batch stream number
;
LOGSET: TXNE J,JL.ULI ;IS A JOB LOGGED IN?
TXNE R,RL.JIE ;DID LOGIN FAIL?
PUSHJ P,ANALYZ ;NOT LOGGED IN - ANALYZE THE ERROR
PUSHJ P,P$TERM## ;SET UP PTY'S TERMINAL CHARACTERISTICS
TXO R,RL.DRT ;DELAY THE RESPONSE BUFFER OUTPUT
MOVX S1,.MSIMC ;FUNCTION CODE TO INCREMENT MOUNT COUNT
HRLI S1,2 ;2 WORD BLOCK
MOVEI S2,T1 ;POINT TO BLOCK
HRROI T1,.JQCON(R) ;POINT TO THE CONNECTED DIRECTORY
MOVE T2,.JBJNO(R) ;GET THE JOB NUMBER
MSTR ;CHANGE MOUNT COUNT
ERJMP .+1 ;IGNORE FOR NOW
MOVX S1,AC%CON+3 ;FLAGS,,LENGTH IN 1
MOVEI S2,T1 ;ADR IN 2
HRROI T1,.JQCON(R) ;ADR POINTS TO STR-DIR STRING
HRROI T2,[ASCIZ / /] ;ADR+1 POINTS TO PSW (DUMMY)
HRRZ T3,.JBJNO(R) ;ADR+2 POINTS TO JOB NUMBER
ACCES ;CONNECT THE JOB
ERJMP .+2 ;DON'T WAIT IF IT FAILED
PUSHJ P,IOWAIT ;GET RESPONSE FROM ACCES JSYS
HRRZ S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVEI S2,.SJDFS ;SET DEFAULT SPOOLING
MOVEI T1,.SJSPD ;A = S2 + 1, SET DEFERRED
SETJB ;SET IT FOR THE JOB
ERJMP .+1 ;IGNORE THE ERROR..
HRRZ S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVEI S2,.SJBAT ;SET BATCH INFO
SETZM T1 ;CLEAR DATA WORD
MOVE T2,.JQOBJ+OBJ.UN(R) ;GET STREAM NUMBER
STORE T2,T1,OB%BSN ;SAVE BATCH STREAM NUMBER IN WORD
TXO T1,OB%BSS ;SET THE STREAM SET FLAG
GETLIM T2,.JQLIM(R),OINT ;GET THE OPERATOR INTERVENTION VALUE
CAXE T2,.OPINN ;WAS NO INTERVENTION SPECIFIED?
JRST LOGS.1 ;NO - IGNORE THIS FUNCTION
MOVX T2,.OBNWR ;TURN OFF THE CAPABILITY
STORE T2,T1,OB%WTO ;STORE IN ARGUMENT BLOCK
LOGS.1: SETJB ;SET BATCH PARAMETERS
ERJMP .+1 ;IGNORE ERRORS
PUSHJ P,U$PLGN## ;DO SPECIAL POST-LOGIN PROCESSING
JRST B$CLOS ;SOMETHING WRONG - DISMISS JOB
POPJ P, ;RETURN
> ;END OF TOPS-20 CONDITIONAL
SUBTTL Batch generated commands -- Kill a job
B$KJOB::TXNE R,RL.DRT ;RESPONSE BUFFER OUTPUT DELAYED?
PUSHJ P,B$RTYO ;YES - DUMP IT NOW
PUSHJ P,P$STAT## ;GET JOB'S STATUS
TXNN J,JL.ULI ;IS JOB LOGGED IN?
$RETT ;NO - RETURN
TXNE R,RL.FKJ ;FAST KJOB REQUESTED?
$IDENT (ABORT,<? Job aborted due to batch system shutdown>)
TXZ F,FL.SIL ;CLEAR SILENCE SO LOG FILE SHOWS ALL
PUSHJ P,P$STOP## ;PUT THE JOB IN MONITOR MODE
PUSHJ P,U$KJOB## ;DO ANY SPECIAL PRE-KJOB PROCESSING
KJOB.1: PUSHJ P,P$STOP## ;PUT THE JOB IN MONITOR MODE
TXNN J,JL.ULI ;IS THE JOB STILL THERE?
$RETT ;NO - RETURN
TXO R,RL.KJB ;MARK ON THE WAY OUT
TOPS10 < ;TOPS-10 ONLY
MOVEI S1,"""" ;GET A QUOTE
MOVEM S1,.JBOCH(R) ;SET AS DIALOGUE MODE SIGNAL
MOVEI S1,"?" ;GET A QUESTION MARK
MOVEM S1,.JBECH(R) ;SET AS ERROR CHARACTER
PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
$IDENT (BATCH,<^7/[MONCHR]/KJOB/BATCH>) ;FAKE KJOB COMMAND IN THE LOG
MOVE TF,[2,,S1] ;SET UP UUO
MOVE S1,[SIXBIT/KJOB/] ;COMMAND TO FORCE
MOVE S2,.JBJNO(R) ;GET JOB NUMBER
FRCUUO TF, ;FORCE THE KJOB COMMAND
JFCL ;CAN'T
> ;END OF TOPS-10 CONDITIONAL
TOPS20 < ;TOPS-20 ONLY
$IDENT (BATCH,<^7/[MONCHR]/LOGOUT>) ;FAKE LOGOUT COMMAND IN THE LOG
SETOM .JLTIM(R) ;FORCE A TIME STAMP
MOVE S1,.JBJNO(R) ;GET THE JOB NUMBER
LGOUT ;KILL THE JOB
JFCL ;IGNORE ERRORS FOR NOW
> ;END OF TOPS-20 CONDITIONAL
MOVE S1,G$CPU ;GET CPU TYPE
MOVEI T1,KJTIME ;GET KJOB TIME
CAIN S1,%KS10 ;A SLOW MACHING?
LSH T1,1 ;YES - MULTIPLY BY 2
HRLI T1,.CQLGO ;EVENT CODE IS LOGOUT
MOVEI T2,0 ;NO DISPATCH
PUSHJ P,B$CLKS ;MAKE A CLOCK REQUEST
PUSHJ P,QTS ;WAIT A WHILE CUZ THE -20 IS SO SLOW
KJOB.2: PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
TXNN R,RL.FKJ ;FAST KJOB?
TXNN J,JL.ULI ;DID THE JOB GO AWAY?
POPJ P, ;YES TO EITHER - RETURN
MOVEI S1,LGOTYP ;GET ADDRESS OF TYPE ITEXT BLOCK
MOVEI S2,LGOTXT ;GET ADDRESS OF MAIN ITEXT BLOCK
MOVEI T1,LGOTAB ;GET ADDRESS OF RESPONSE TABLE
PUSHJ P,B$OPER ;ASK THE OPERATOR FOR HELP
JRST KJOB.1 ;SEE IF THE JOB IS STILL THERE
LGOTYP: ITEXT (<Batch error>)
LGOTXT: ITEXT (<Unable to log out job ^D/.JBJNO(R)/.
Type 'RESPOND ^I/NUMBER/ PROCEED' to try again or kill the job>)
LGOTAB: $STAB
KEYTAB (0,<PROCEED>)
$ETAB
SUBTTL Batch generated commands -- CLOSE/DUMP
; Check to see if CLOSE/DUMP commands are necessary
; *** Note ***
; This routine will not use B$CINI/B$XFER routines for sending the CLOSE/DUMP
; commands since this will destroy the contents of .JSCTL(R). .JSCTL(R) must
; be preserced for DUMP output.
;
B$DUMP::TXNN R,RL.JIE ;JOB IN ERROR?
POPJ P, ;NO - JUST RETURN
TXO F,FL.UHE ;SET AN UNEXPECTED ERROR CONDITION
TXNN J,JL.ULI ;JOB LOGGED IN?
POPJ P, ;NO
$IDENT (BATCH,<^7/[MONCHR]/DUMP^A>) ;FAKE DUMP COMMAND IN THE LOG FILE
PUSHJ P,.DUMP## ;FORCE A DUMP BATCH COMMAND
JFCL ;IGNORE ERRORS
PUSHJ P,B$RTYO ;ECHO THE RESPONSE BUFFER
PUSHJ P,P$STOP## ;STOP THE JOB
TOPS10 < ;TOPS-10 ONLY
PUSHJ P,B$RTYO ;ECHO THE RESPONSE BUFFER
$TEXT (P$OCHR##,<CLOSE^M^A>) ;SEND THE CLOSE COMMAND
PUSHJ P,P$OBUF## ;FORCE OUT PTY BUFFERS
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
PUSHJ P,P$STOP## ;MAKE SURE THE JOB IS STOPPED
> ;END OF TOPS-10 CONDITIONAL
POPJ P, ;RETURN
SUBTTL Batch WTO/WTOR -- Initialization and character storage
; Initialize the WTO/WTOR buffer
;
B$WINI::MOVE S1,[POINT 7,.JWTOP(R)] ;GET BYTE POINTER
MOVEM S1,.JWPTR(R) ;STORE IT
MOVX S1,CTLSIZ ;GET THE MAXIMUM NUMBER OF CHARACTERS
MOVEM S1,.JWCNT(R) ;STORE IT
POPJ P, ;RETURN
; Store a character in the WTO/WTOR buffer
;
B$WPUT::SOSLE .JWCNT(R) ;COUNT CHARACTERS
IDPB S1,.JWPTR(R) ;DEPOSIT CHARACTER IF ROOM IN BUFFER
POPJ P, ;RETURN
; End WTO/WTOR buffer
;
B$WEOL::PUSH P,S1 ;SAVE S1
MOVX S1,.CHNUL ;GET A <NUL>
IDPB S1,.JWPTR(R) ;END THE LINE
SETOM .JWCNT(R) ;NO MORE ROOM IN BUFFER
POP P,S1 ;RESTORE S1
POPJ P, ;RETURN
SUBTTL Batch WTO/WTOR -- Write To OPR
; Write To OPR (WTO)
;
B$WTO:: PUSHJ P,B$WEOL ;TERMINATE THE BUFFER
$WTO (<Message from batch user>,<^I/JIBTXT/^T/.JWTOP(R)/>,.JQOBJ(R),<$WTJBN(.JBJNO(R)),$WTNOD(.JQLOC(R))>)
POPJ P, ;RETURN
; Write To OPR with a Response (WTOR)
;
B$WTOR::PUSHJ P,B$WEOL ;TERMINATE THE BUFFER
MOVE S1,.JQITN(R) ;GET OUR ITN
MOVEM S1,.JOACK(R) ;USE IT AS THE ACK CODE
$WTOR (<Message from batch user>,<^I/JIBTXT/^T/.JWTOP(R)/>,.JQOBJ(R),.JOACK(R),<$WTJBN(.JBJNO(R)),$WTNOD(.JQLOC(R))>)
POPJ P, ;RETURN
SUBTTL Batch WTO/WTOR -- Get operator response to a WTOR
; Put job in operator wait and get response
;
B$WRSP::TXO R,RL.OPR ;MARK WAITING FOR THE OPERATOR
MOVX T1,%OREWT ;STATUE CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
PUSHJ P,QTS ;WAIT FOR OPERATOR RESPONSE
MOVX T1,%RESET ;RESET STATUS
PUSHJ P,B$UPDA ;UPDATE QUASAR
SETZM .JBCHK(R) ;FORCE A CHECKPOINT
PUSHJ P,P$STAT## ;GET THE JOB STATUS
MOVE T1,[POINT 7,.JORSP(R)] ;POINT TO RESPONSE BUFFER
MOVE S2,[POINT 7,.JWFOP(R)] ;BYTE POINTER TO DESTINATION
WRSP.1: ILDB S1,T1 ;GET A CHARACTER
IDPB S1,S2 ;PUT A CHARACTER
CAME S2,[POINT 7,.JWFOP+<CTLSIZ/5>(R),27] ;BUFFER FULL?
JUMPN S1,WRSP.1 ;NO - LOOP UNLESS END OF TEXT
WRSP.2: MOVEI S1,.CHNUL ;END THE STRING
IDPB S1,S2 ;STORE <NUL>
POPJ P, ;RETURN
SUBTTL Response buffer support
; Store a character in the response buffer
;
B$RPUT::MOVE S2,.JBRBP(R) ;GET BYTE POINTER
CAME S2,[POINT 7,.JBRSP+PTYBLK-3-1(R),27] ;BUFFER OVERFLOW?
IDPB S1,.JBRBP(R) ;NO - STORE CHARACTER
POPJ P, ;RETURN
; Mark EOL in response buffer
;
B$REOL::MOVEI S1,.CHNUL ;GET A <NUL>
IDPB S1,.JBRBP(R) ;END RESPONSE BUFFER
; Reset response buffer byte pointer
;
B$RINI::MOVE S1,[POINT 7,.JBRSP(R)] ;GET POINTER TO START OF BUFFER
MOVEM S1,.JBRBP(R) ;RESET BYTE POINTER
POPJ P, ;RETURN
; Output the response buffer to the log file
;
B$RTYO::TXNN F,FL.SIL ;DON'T ECHO BUFFER IF SILENCE IN EFFECT
$IDENT (BATCH,<^T/.JBRSP(R)/^A>) ;IDENTITY AND ECHO RESPONSE BUFFER
POPJ P, ;RETURN
SUBTTL Batch error handling -- Error, operator, dialogue, or quote checking
; This routine is called only when the first character in a line has been input.
; It will check for an error condition (either "?" or as set by the last ERROR
; command) or an operator signal (either a double quote or as set by the last
; OPERATOR command). In the case of an error, if (nnn) immediately follows the
; error character, nnn is stored in .JBECD(R) for later analysis.
;
B$ECHK::TXNE J,JL.UNE ;IS THE PTY SET TO A NO ECHO STATE?
TXZ F,FL.ECH ;YES - READ WHAT WE THOUGHT WAS ECHO
TXZE F,FL.ECH ;IS THIS CHARACTER ECHO?
POPJ P, ;YES - THEN DON'T DO ANY CHECKING
CAIE S1,"?" ;IS IT THE STANDARD ERROR FLAG?
JRST ECHK.1 ;NO - LOOK FURTHER
TXO R,RL.JIE ;SET JOB IN ERROR BIT
TXNN R,RL.LGI ;LOGGING IN?
TXNE F,FL.UKJ ; OR USER REQUESTED KJOB?
JRST ECHK.1 ;YES - SKIP TIME LIMIT EXCEEDED CHECK
PUSHJ P,GJTIML ;GET THE JOB'S REMAINING TIME LIMIT
JUMPG S2,ECHK.2 ;TIME LIMIT EXCEEDED?
TXOA F,FL.TLE ;YES
ECHK.1: TXNE F,FL.NER ;IS NOERROR IN EFFECT?
JRST ECHK.2 ;YES - CHECK FOR OPERATOR CHARACTER
CAMN S1,.JBECH(R) ;OR USER ERROR CHARACTER ENCOUNTERED
TXO R,RL.JIE ;YES TO EITHER - MARK JOB IN ERROR
ECHK.2: CAMN S1,.JBOCH(R) ;WAS THE OPERATOR CHARACTER SEEN?
TXO R,RL.DIA ;YES - MARK DIALOGUE MODE
CAIN S1,"""" ;Was a quote seen?
TXO R,RL.QTS ;YES - REMEMBER IT
TXNE F,FL.TLE ;WAS TIME LIMIT EXCEEDED?
POPJ P, ;YES - RETURN NOW
TXNE F,FL.NER ;IS NOERROR IN EFFECT?
TXZ R,RL.JIE ;YES - MAKE SURE JOB IN ERROR CLEARED
TXNE R,RL.JIE ;JOB IN ERROR?
TXNN R,RL.LGI ;AND WAS JOB LOGGING IN?
POPJ P, ;NO - JUST RETURN
SKIPE .JBECD(R) ;BEEN HERE BEFORE?
POPJ P, ;YES - THEN JUST RETURN
ECHK.3: PUSHJ P,L$PLOG## ;LOG THE ERROR CHARACTER
PUSHJ P,P$NXTC## ;GET THE NEXT CHARACTER
CAIE S1,"(" ;START OF SPECIAL ERROR CODE?
POPJ P, ;NO - JUST RETURN
ECHK.4: PUSHJ P,L$PLOG## ;LOG THE CHARACTER
PUSHJ P,P$NXTC## ;GET THE NEXT CHARACTER
CAIG S1,"9" ;RANGE CHECK THE DIGIT
CAIGE S1,"0" ;0 THROUGH 9 ALLOWED
POPJ P, ;NOT A DIGIT - EXIT LOOP
MOVE S2,.JBECD(R) ;GET THE ERROR CODE
IMULI S2,^D10 ;SHIFT NUMBER
ADDI S2,-"0"(S1) ;ADD IN THIS DIGIT
MOVEM S2,.JBECD(R) ;REPLACE CODE
JRST ECHK.4 ;LOOP FOR ANOTHER
SUBTTL Batch error handling -- LOGIN error analysis
ANALYZ: TXNE J,JL.ULI ;IS THIS JOB LOGGED IN NOW?
$RETT ;YES - THATS INCONSISTANT
TOPS10 < ;TOPS-10 ONLY
SKIPLE S1,.JBECD(R) ;GET THE ERROR CODE FROM LOGIN
CAILE S1,5 ;WE ONLY KNOW ABOUT 1-5
MOVEI S1,5 ;ASSUME RANDOM ERROR AND REQUEUE JOB
JRST @[ANLY.1 ;(1) CANCEL JOB
ANLY.1 ;(2) CANCEL JOB
ANLY.1 ;(3) CANCEL JOB
ANLY.2 ;(4) REQUEUE JOB AND SHUTDOWN STREAM
ANLY.3]-1(S1) ;(5) REQUEUE JOB
> ;END OF TOPS-10 CONDITIONAL
TOPS20 < ;TOPS-20 ONLY
MOVX S1,EQ.IAS ;GET THE INVALID ACCOUNT BIT
TDNE S1,.JQJBB+JIB.SQ(R) ;DID QUASAR SET IT?
JRST ANLY.1 ;YES - CANCEL THE JOB
JRST ANLY.2 ;NO - REQUEUE THE JOB
> ;END OF TOPS-20 CONDITIONAL
; Cancel job
;
ANLY.1: $IDENT (BATBJC,<? Batch job has been canceled - LOGIN failure>)
$WTO (<Batch error>,<LOGIN failed - job canceled>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
TXO F,FL.UHE!FL.TXT ;CALL IT AN UNHANDLED ERROR CONDITION
$TEXT (<-1,,.JWTOP(R)>,<LOGIN failure^0>)
JRST B$ABOR ;ABORT THE JOB
; Requeue job and shutdown stream
;
ANLY.2: $IDENT (BATJRQ,<[Job requeued by BATCON]>)
$WTO (<Batch error>,<Cannot LOGIN jobs - job requeued>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
MOVX T1,%RSUNA ;SET UP 'STREAM UNAVAILABLE'
MOVEI T2,E.NJOB ;NO JOBS AVAILABLE CODE
MOVX T3,%SFULL ;SYSTEM FULL
TXO R,RL.SHT ;LITE THE SHUTDOWN AT EOJ BIT
PUSHJ P,SETUPR ;SEND RESPONSE TO QUASAR
JRST B$CLOS ;DISMISS JOB
; Requeue job
;
ANLY.3: $IDENT (BATJRQ,<[Job requeued by BATCON]>)
$WTO (<Batch error>,<Requeue requested by LOGIN>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
TXO R,RL.REQ ;MARK JOB AS BEING REQUEUED
MOVEI S1,REQTIM ;GET DEFAULT REQUEUE TIME
STORE S1,.JBRQF(R),RQ.TIM ;SAVE IT
MOVEI T1,%REQUE ;GET REQUEUE CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
JRST B$CLOS ;DISMISS JOB
SUBTTL MDA interface
; Get an MDA page if we don't already have one (S1:= page address)
;
B$MDAP::SKIPE S1,.JMDAP(R) ;ALREADY HAVE A PAGE?
POPJ P, ;YES - JUST RETURN
$CALL M%GPAG ;GET A PAGE FOR MESSAGE
MOVEM S1,.JMDAP(R) ;STORE PAGE ADDRESS
MOVX S2,.QOPRM ;MESSAGE TYPE IS PRE-MOUNT
STORE S2,.MSTYP(S1),MS.TYP ;STORE IT
MOVX S2,.MMHSZ ;MESSAGE SIZE
STORE S2,.MSTYP(S1),MS.CNT ;STORE IT
LOAD S2,.JQJBB+JIB.ID(R) ;GET REQUEST ID
STORE S2,.OFLAG(S1),PR.RID ;STORE IT
MOVEI S2,.MMHSZ(S1) ;POINT TO EMPTY SLOT
MOVEM S2,.JMDAF(R) ;STORE FIRST FREE POINTER
POPJ P, ;RETURN
; Send any ALLOCATE/MOUNT requests to QUASAR
;
B$MDAR::PUSHJ P,B$MDAP ;GET MDA PAGE IF NECESSADY
MOVX S2,PR.NON ;GET NOTHING IN MESSAGE BIT
SKIPN .MMARC(S1) ;ANYTHING ADDED TO THE BLOCK?
IORM S2,.OFLAG(S1) ;STORE BIT
MOVEM S1,G$SAB+SAB.MS ;STORE PAGE ADDRESS
MOVX S1,PAGSIZ ;GET THE MESSAGE SIZE
STORE S1,G$SAB+SAB.LN ;STORE IT
MOVX S1,SAB.SZ ;GET SAB SIZE
MOVEI S2,G$SAB ;GET SAB ADDRESS
$CALL C%SEND ;SEND MESSAGE TO QUASAR
SKIPT ;MESSAGE SENT OK?
$CALL M%RPAG ;NO - DESTROY THE PAGE
SETZM .JMDAP(R) ;CLEAR PAGE NUMBER
POPJ P, ;RETURN SUCESSFUL
SUBTTL MODIFY interface
; Get a MODIFY page if we don't already have one (S1:= page address)
;
B$MODP::SKIPE S1,.JMODP(R) ;HAVE A MODIFY PAGE YET?
POPJ P, ;YES - RETURN WITH S1 SET UP
$CALL M%GPAG ;GET A PAGE FOR MESSAGE
MOVEM S1,.JMODP(R) ;STORE PAGE ADDRESS
MOVX S2,.QOMOD ;MESSAGE TYPE IS MODIFY QUEUE ENTRY
STORE S2,.MSTYP(S1),MS.TYP ;STORE IT
MOVEI S2,NMAJPM+NINPPM+MOD.SZ ;GET BLOCK LENGTH
STORE S2,.MSTYP(S1),MS.CNT ;STORE IT
MOVX S2,.OTBAT ;OBJECT TYPE
MOVEM S2,MOD.OT(S1) ;STORE IT
LOAD S2,.JQJBB+JIB.ID(R) ;GET REQUEST ID
STORE S2,MOD.RQ+.RDBRQ(S1) ;STORE IT
MOVEI S1,MOD.FG(S1) ;POINT TO FIRST FREE WORD
MOVE S2,[.GPMAJ,,NMAJPM] ;SET UP GROUP MODIFY BLOCK
MOVEM S2,MOD.GN(S1) ;STORE MAJOR MODIFY HEADER
SETOM MOD.GE(S1) ;DEFAULT THE FIRST ENTRY
HRLZI S2,MOD.GE(S1) ;GET SOURCE ADDRESS
HRRI S2,MOD.GE+1(S1) ;GET DESTINATION ADDRESS
BLT S2,MOD.GE+NMAJPM(S1) ;SET THE WHOLE MESS TO -1
ADDI S1,NMAJPM ;POINT TO START OF NEXT BLOCK
MOVE S2,[.GPQUE,,NINPPM] ;SET UP GROUP MODIFY BLOCK
MOVEM S2,MOD.GN(S1) ;STORE QUEUE DEPENDANT MODIFY HEADER
SETOM MOD.GE(S1) ;DEFAULT THE FIRST ENTRY
HRLZI S2,MOD.GE(S1) ;GET SOURCE ADDRESS
HRRI S2,MOD.GE+1(S1) ;GET DESTINATION ADDRESS
BLT S2,MOD.GN+NINPPM-1(S1) ;SET TO -1
MOVE S1,.JMODP(R) ;RELOAD PAGE ADDRESS
POPJ P, ;RETURN
; Send MODIFY request to QUASAR
;
B$MODR::SKIPN S1,.JMODP(R) ;GET MDA REQUEST PAGE
$RETT ;NO MODIFY TO SEND
SKIPN .JMODC(R) ;ANY MODIFIES IN THIS REQUEST?
JRST MODR.1 ;NO
MOVEM S1,G$SAB+SAB.MS ;STORE PAGE ADDRESS
MOVX S1,PAGSIZ ;GET THE MESSAGE SIZE
STORE S1,G$SAB+SAB.LN ;STORE IT
MOVX S1,SAB.SZ ;GET SAB SIZE
MOVEI S2,G$SAB ;GET SAB ADDRESS
$CALL C%SEND ;SEND MESSAGE TO QUASAR
JUMPT MODR.2 ;ANY ERRORS?
$WTO(<BATCON Error>,<MODIFY failed for request ^D/.JQJBB+JIB.ID(R)/>)
MODR.1: MOVE S1,.JMODP(R) ;GET PAGE NUMBER
$CALL M%RPAG ;DESTROY THE PAGE
MODR.2: SETZM .JMODP(R) ;CLEAR SO WE DON'T HAVE PROBLEMS LATER
POPJ P, ;AND RETURN
SUBTTL End of job processing
; Here on end of job (step) header
;
B$EOJ:: TXOE F,FL.EOJ ;PROCESS EOJ STUFF ALREADY?
POPJ P, ;YES - THEN JUST RETURN
TXNN R,RL.JIE ;IS THE JOB IN ERROR?
SETOM .JSSTP(R) ;NO - INDICATE END OF STEP
SKIPN .JBSPS(R) ;DOING ONLY STEP HEADER SCAN?
POPJ P, ;NO - RETURN
PUSHJ P,B$MODR ;PROCESS ANY MODIFY REQUESTS
SKIPE G$MDA ;MDA TURNED ON?
PUSHJ P,B$MDAR ;YES - SEND ANY MDA REQUESTS
POPJ P, ;RETURN
SUBTTL JOBINI - Initialize job processing
JOBINI: TXNE F,FL.KST ;KSYS STREAM?
JRST JOBI.K ;YES
SETOM .JSSPP(R) ;ALLOW US TO PROCESS ONLY 1 STEP
TXZ R,RL.LGI ;CLEAR LOGIN SEQUENCE NOW
SKIPN S1,.JBCRQ(R) ;IS THERE CHKPNT/REQUEUE INFORMATION?
JRST JOBI.1 ;NO - SEE IF RESTARTABLE
TXNN S1,BA.JOB ;BETTER BE SET
JRST JOBI.E ;ELSE WE'RE IN TROUBLE
TXNE S1,BA.ORQ!BA.URQ!BA.CHK ;ANY REQ OR CHKPNT
JRST JOBI.2 ;YES,,CHECK FOR CHECKPOINT RESTART
GETLIM S2,.JQLIM(R),REST ;GET RESTART DATA
CAIE S2,%EQRNO ;IS IT RESTARTABLE
JRST JOBI.2 ;TREAT IT AS RESTARTABLE
;USER MODIFIED AFTER CRASH
; BUT BEFORE RESTART
$IDENT (BATJNR,<? Job canceled after a restart - it is not restartable^A>)
$WTO (<Batch error>,<Job canceled after a restart; it is not restartable>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
SETZM .JBCHK(R) ;FORCE A CHECKPOINT
TXO F,FL.LSL ;LIST SKIPPED LINES
PJRST LABFIN## ;FIND %FIN AND CONTINUE FROM THERE
JOBI.1: MOVX S1,<BA.JOB> ;GET SEEN JOB FLAG
IORM S1,.JBCRQ(R) ;UPDATE FLAG WORD
TXO F,FL.CHK ;UPDATE CHECKPOINT
JOBI.2: SETZM .JBCHK(R) ;FORCE A CHECKPOINT
PUSHJ P,C$READ## ;READ A LINE FROM THE CONTROL FILE
JUMPF CLOSJB ;END OF FILE?
CAXE S1,STPCHR ;START OF A STEP?
JRST JOBI.3 ;NO - RESET TO BEGING OF FILE
PUSHJ P,STPPRC ;YES - CALL THE STEP HEADER PROCESSOR
JUMPF CLOSJB ;ERRORS DURING SCAN?
JRST JOBI.4 ;GO SEARCH FOR STARTING POINT
JOBI.3: TXO F,FL.RCL ;RE-EAT THE COMMAND LINE
JOBI.4: PUSHJ P,C$STRT## ;SEARCH FOR STARTING POINT IN CTL FILE
POPJ P, ;RETURN
JOBI.K: $IDENT (BATKSY,<[Beginning KSYS processing]^A>)
POPJ P, ;RETURN
JOBI.E: $IDENT (BATUJR,<? ^I/JOBTXT/>)
$WTOJ (<BATCON error>,<^R/.JQJBB(R)/^I/JOBTXT/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
JRST B$ABORT ;DISMISS THE JOB
JOBTXT: ITEXT (<Unrecognized job restart type ^O/S1/; job canceled>)
SUBTTL TIMERR - Time limit exceeded
; Here on time limit exceeded errors
;
TIMERR::TXON F,FL.%XT ;EXTRA TIME ALREADY GIVEN?
JRST TIME.1 ;NO
$WTO (<Batch error>,<^I/JIBTXT/^I/TIMTX0/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
$IDENT (BATTLE,<? ^I/TIMTX0/>) ;MAKE A LOG ENTRY
TXO F,FL.TXT ;MESSAGE TEXT AVAILABLE
$TEXT (<-1,,.JWTOP(R)>,<Time limit exceeded^0>)
JRST B$ABOR ;ABORT THE JOB
TIME.1: PUSHJ P,C$READ## ;ADVANCE BEYOND LINE CAUSING THE ERROR
PUSHJ P,LABTER## ;SEARCH FOR LABEL %TERR
PUSHJ P,P$STOP## ;YES - PUT JOB IN MONITOR MODE
TXZ R,RL.JIE ;CLEAR ERROR CONDITION
GETLIM S2,.JQLIM(R),TIME ;GET TIME LIMIT
IMULI S2,%EXTRA ;COMPUTE EXTRA TIME TO BE GIVEN
IDIVI S2,^D100 ;AS A PERCENTAGE OF THE ORIGINAL LIMIT
CAIGE S2,%EXTRA ;TOO MUCH?
MOVX S2,%EXTRA ;YES - ADJUST IT
PUSH P,S2 ;SAVE TIME
MOVE S1,S2 ;COPY IT
PUSHJ P,B$STIM ;TRANSLATE TO READABLE TEXT
POP P,S2 ;RESTORE TIME TO SET
TOPS10 < ;TOPS-10 ONLY
MOVX T1,<2,,S1> ;SET UP AC
HRRZ S1,J ;GET THE JOB NUMBER
HRLI S2,.STTLM ;FUNCTION TO SET TIME LIMIT
JBSET. T1, ;SET NEW TIME LIMIT
JRST TIME.E ;CAN'T
JRST TIME.2 ;NO ERRORS
> ;END OF TOPS-10 CONDITIONAL
TOPS20 < ;TOPS-20 ONLY
PUSH P,S2 ;SAVE TIME IN SECONDS
PUSHJ P,B$CINI ;SET UP THE COMMAND BUFFER
$TEXT (B$CPUT,<SET TIME-LIMIT ^D/S2/>) ;ISSUE COMMAND
PUSHJ P,B$SETB ;RESET THE BYTE POINTER
PUSHJ P,B$XFER ;TRANSFER THE LINE TO THE PTY
PUSHJ P,IOWAIT ;WAIT FOR I/O COMPLETION
POP P,S2 ;RESTORE TIME
TXNE R,RL.JIE ;JOB IN ERROR?
JRST TIME.E ;YES
> ;END OF TOPS-20 CONDITIONAL
TIME.2: $WTO (<Batch error>,<^I/JIBTXT/^I/TIMTX2/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
$IDENT (BATAXT,<[^I/TIMTX2/]>) ;MAKE A LOG ENTRY
TXZ F,FL.TLE ;CLEAR TIME LIMIT EXCEEDED CONDITION
TXO F,FL.RCL ;RE-EAT COMMAND LINE
POPJ P, ;RETURN
TIME.E: $WTO (<BATCON error>,<^I/JIBTXT/^T/TIMTX1/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
$IDENT (BATCST,<? ^I/TIMTX1/>) ;MAKE LOG ENTRY
JRST B$ABOR ;ABORT JOB
TIMTX0: ITEXT (<Time limit exceeded after allowing extra time; job canceled>)
TIMTX1: ITEXT (<Cannot set time limit; job canceled>)
TIMTX2: ITEXT (<Time limit exceeded; allowing ^T/G$TMTX/ extra time>)
;HERE WHEN DIALOGUE MODE IS IN EFFECT, READ FROM THE OPERATOR
REDOPR: PUSHJ P,B$WTOR ;WRITE TO OPR AND WAIT FOR RESPONSE
PUSHJ P,B$WRSP ;GET THE OPERATOR RESPONSE
TXNN J,JL.UJA ;IS THE JOB STILL THERE?
JRST B$GONE ;NO
TXNE R,RL.DIA ;JOB STILL WAITING?
JRST REDOPR ;YES - TRY AGAIN
PUSH P,F ;SAVE FLAGS IN CASE THE JOB IS SILENCED
TXZ F,FL.SIL ;CLEAR SILENCE SO LINES WILL GO TO LOG
$IDENT (OPERAT,<Operator response:^A>)
PUSHJ P,B$RTYO ;DUMP THE RESPONSE BUFFER
MOVE S2,[POINT 7,.JWFOP(R)] ;BYTE POINTER TO STRING
SETZ T1, ;CLEAR PREVIOUS CHARACTER SAVER
RDOPR1: ILDB S1,S2 ;GET A CHARACTER
JUMPE S1,RDOPR2 ;DONE IF ENCOUNTER A <NUL>
CAXN S1,.CHLFD ;A LINE FEED?
CAXE T1,.CHCRT ;PREVIOUS CHARACTER A CARRIAGE RETURN?
PUSHJ P,P$OCHR## ;SEND CHARACTER TO THE PTY
MOVE T1,S1 ;SAVE AS PREVIOUS CHARACTER
JRST RDOPR1 ;LOOP FOR ANOTHER
RDOPR2: MOVX S1,.CHCRT ;LOAD A CARRIAGE RETURN
SKIPL .JPEOL(R) ;END OF LINE YET?
PUSHJ P,P$OCHR## ;NO - FORCE ONE
PUSHJ P,P$OBUF## ;SEND THE TEXT TO THE PTY
POP P,S1 ;RESTORE OLD F
TXNE S1,FL.SIL ;WAS SILENCE IN EFFECT?
TXO F,FL.SIL ;YES - SET IT AGAIN
PUSHJ P,P$OBUF## ;OUTPUT THE PTY BUFFER
SETOM .JPEOL(R) ;MARK EOL SENT
TXO F,FL.RCL ;RE-EAT THE COMMAND LINE
POPJ P, ;RETURN
SUBTTL Stream termination -- Dismiss job
; Here to abort the job and update QUASAR
;
B$ABOR::SKIPE .JBSPS(R) ;STEP HEADER SCAN PROCESSING ONLY?
JRST B$CLOS ;YES
MOVEI T1,%CNCLG ;GET CANCEL CODE
PUSHJ P,B$UPDA ;UPDATE QUASAR
JRST B$CLOS ;DISMISS THE JOB
; Here when the job disappears (probably some ATTACHed to it)
;
B$GONE::SKIPN .JBSPS(R) ;STEP HEADER SCAN PROCESSING ONLY?
TXNE R,RL.LGI!RL.KJB ;LOGGING IN OR OUT?
JRST B$CLOS ;THEN IT COULD DISAPPEAR UNEXPECTEDLY
TXNE F,FL.UKJ ;USER REQUEST KJOB?
JRST B$CLOS ;YES
$WTO (<Batch error>,<^I/JIBTXT/^I/GONTXT/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
$IDENT (BATNBC,<% ^I/GONTXT/>) ;LOG IT
JRST B$CLOS ;TERMINATE JOB
GONTXT: ITEXT (<Job ^D/.JBJNO(R)/ no longer under BATCON's control; job canceled>)
; Here to dismiss a job (release or requeue)
;
B$CLOS::
CLOSJB::PUSHJ P,CHKPNT ;CHECKPOINT IF NECESSARY
TXNE R,RL.FKJ ;FAST KJOB?
JRST CLOS.0 ;YES - DON'T TALK TO ANYONE
SKIPE .JOACK(R) ;A PENDING WTOR?
$KWTOR (.JOACK(R)) ;KILL IT
PUSHJ P,B$EOJ ;PROCESS END OF JOB (STEP) HEADER
CLOS.0: TXNN J,JL.UJA ;IS A JOB REALLY THERE?
JRST CLOS.1 ;NO
TXNE R,RL.KJB ;WHAT ARE WE DOING HERE?
JRST CLOS.2 ;DON'T DO ANOTHER KJOB
TXNN R,RL.FKJ ;FAST KJOB?
PUSHJ P,B$DUMP ;NO - SEE IF A CLOSE/DUMP IS NEEDED
PUSHJ P,B$KJOB ;KILL THE JOB
TXNE F,FL.KST ;KSYS STREAM?
TXNN R,RL.JIE ;AND JOB IN ERROR?
SKIPA ;NO TO EITHER
AOS KSYJLE ;COUNT THE ERROR
CLOS.1: TXNE R,RL.REQ ;JOB BEING REQUEUED?
JRST CLOS.2 ;YES - DON'T DELETE CTL FILE
SKIPE .JBSPS(R) ;DOING ONLY STEP HEADER PROCESSING?
JRST CLOS.S ;YES
TXNN R,RL.FLS ;FLUSHING THE JOB?
PUSHJ P,C$DISP## ;DISPOSE OF THE CONTROL FILE (MAYBE)
CLOS.2: PUSHJ P,P$CLOS## ;CLOSE THE PTY
PUSHJ P,C$CLOS## ;CLOSE THE CONTROL FILE
PUSHJ P,L$CLOS## ;CLOSE THE LOG FILE
PUSHJ P,U$CLOS## ;DO ANY SPECIAL POST-KJOB PROCESSING
TXNE R,RL.FKJ ;FAST KJOB?
JRST CLOS.F ;YES - SKIP ALL OTHER STUFF
TXNE R,RL.REQ ;JOB BEING REQUEUED?
JRST CLOS.R ;YES - SEND REQUEUE MESSAGE
PUSHJ P,DELSPL ;DELETE SPOOLED FILES (TOPS-20 ONLY)
PUSHJ P,RELMSG ;BUILD RELEASE MESSAGE
CLOS.5: $WTOJ (<End>,<^R/.JQJBB(R)/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
PUSHJ P,CLRSTR ;CLEAN UP STREAM
TXNE F,FL.KST ;KSYS STREAM?
JRST STEXIT ;YES--DONE
TXNN R,RL.SHT ;SHUTTING DOWN STREAM?
PUSHJ P,B$SEND ;NO - SEND RELEASE MESSAGE TO QUASAR
JRST STEXIT ;EXIT FROM STREAM
CLOS.S: PUSHJ P,C$CLOS## ;CLOSE THE CONTROL FILE
CLOS.F: PUSHJ P,CLRSTR ;CLEAN UP STREAM DATA BASE
JRST STEXIT ;EXIT FROM STREAM
CLOS.R: MOVX S1,REQ.SZ ;REQUEUE MESSAGE SIZE
PUSHJ P,B$SQSR ;SET UP MESSAGE TO QUASAR
MOVE S1,[REQ.SZ,,.QOREQ] ;HEADER WORD
MOVEM S1,.MSTYP(S2) ;SAVE IN MESSAGE
MOVE S1,.JBRQF(R) ;GET REQUEUE FLAG WORD
TXNE S1,RQ.TIM ;SAVE A TIME SET?
TXZA S1,RQ.HBO ;YES - MAKE SURE HOLD BIT OFF
TXO S1,RQ.HBO ;ELSE LITE THE HOLD BIT
MOVEM S1,REQ.FL(S2) ;SAVE IN REQUEUE FLAG WORD
MOVE S1,.JQITN(R) ;THE TASK NAME
MOVEM S1,REQ.IT(S2) ;STORE
HRLI S1,.JBCRQ(R) ;CHECKPOINT/REQUEUE INFORMATION
HRRI S1,REQ.IN(S2) ;INTO THE MESSAGE
BLT S1,REQ.IN+<EQCKSZ-1>(S2) ;MOVE ALL THE WORDS
PUSHJ P,B$SEND ;SEND IT TO QUASAR
$WTOJ (<Requeue>,<^R/.JQJBB(R)/>,.JQOBJ(R),<$WTNOD(.JQLOC(R))>)
PUSHJ P,CLRSTR ;CLEAN UP STREAM
PJRST STEXIT ;EXIT FROM STREAM
SUBTTL Stream termination -- Build release message
; Build release message
;
RELMSG: TXNE F,FL.KST ;KSYS STREAM?
JRST RELM.6 ;YES--SKIP NORMAL RELEASE STUFF
MOVEI S1,REL.FD ;GET MINIMUM RELEASE MESSAGE
PUSHJ P,B$SQSR ;SET UP MESSAGE TO QUASAR
MOVX S1,<INSVL.(REL.FD,MS.CNT)!INSVL.(.QOREL,MS.TYP)>
MOVEM S1,.MSTYP(S2) ;STORE LENGTH AND TYPE
MOVE S1,.JQITN(R) ;GET ITN
MOVEM S1,REL.IT(S2) ;STORE IT
MOVEI S1,0 ;CLEAR FLAG BITS
TXNE F,FL.UHE ;UNHANDLED ERROR?
TXO S1,RF.ABO ;YES--LIGHT ABORTED BIT
MOVEM S1,REL.FL(S2) ;STORE FLAGS
TXNN F,FL.TXT ;COPY .JWTOP TEXT?
JRST RELM.3 ;NO
MOVE S1,[POINT 7,.JWTOP(R)] ;YES--SETUP INITIAL POINTER
MOVE T1,[POINT 7,REL.TX(S2)] ;AND DESTINATION
REML.1: ILDB T2,S1 ;GET A CHAR
CAIE T2,.CHLFD ;STOP ON <LF>
CAIN T2,.CHCRT ;STOP ON <CR>
JRST RELM.2 ;YES
JUMPE T2,RELM.2 ;OR NULL
IDPB T2,T1 ;STORE
JRST REML.1 ;LOOP FOR ALL
RELM.2: MOVEI T2,.CHNUL ;GET A NULL
IDPB T2,T1 ;STORE
RELM.3: SKIPG S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVEI S1,0 ;JOB WAS NEVER LOGGED IN
MOVE T1,.JQLFP+.FPINF(R) ;GET THE LOG FILE BITS
TXNE T1,FP.DEL ;DELETE IT?
TXO S1,RL.DLG ;YES
TXNE T1,FP.SPL ;WAS IT SPOOLED?
TXO S1,RL.SPL!RL.DLG ;YES
MOVEM S1,REL.BJ(S2) ;STORE FLAGS AND JOB NUMBER
RELM.4: GETLIM S1,.JQLIM(R),OUTP ;GET /OUTPUT VALUE
TXNN R,RL.FLS ;FLUSHING THE JOB?
CAIN S1,%EQONL ;OR WAS IT /OUTPUT:NOLOG
JRST RELM.7 ;YES TO EITHER - DON'T QUEUE LOG
TXNE F,FL.UHE ;WAS THERE AN UNHANDLED ERROR?
CAIE S1,%EQOLE ;AND /OUTPUT:ERROR SPECIFIED?
CAIN S1,%EQOLG ;NO TO ERROR STUFF, WAS IT /OUTPUT:LOG?
JRST RELM.5 ;YES TO ONE OF THOSE - QUEUE LOG FILE
JRST RELM.7 ;DON'T QUEUE LOG IF WE GET THIS FAR
RELM.5: TXNE F,FL.NUL ;LOG FILE WRITTEN TO NUL:?
POPJ P, ;YES - THEN ALL DONE
HRLI S1,.JQLFD(R) ;GET LOG FILE FD ADDRESS
HRRI S1,REL.FD(S2) ;GET DESTINATION ADDRESS
LOAD T1,.JQLFD+.FDLEN(R),FD.LEN ;GET FD LENGTH
LOAD T2,.MSTYP(S2),MS.CNT ;GET MESSAGE LENGTH
ADD T2,T1 ;COMPUTE NEW LENGTH
STORE T2,.MSTYP(S2),MS.CNT ;STORE IT
ADDI T1,-1(S1) ;COMPUTE END ADDRESS OF BLT
BLT S1,0(T1) ;COPY LOG FILE FD
POPJ P, ;RETURN
RELM.6: TXNE R,RL.JIE ;JOB IN ERROR?
PJRST KSYQUE ;YES--QUEUE UP LOG FILE /DISP:DEL
JRST RELM.8 ;ELSE DELETE IT
RELM.7: MOVX S1,RL.SPL!RL.DLG ;GET SPOOLED AND DELETE LOG FILE BIT
TDNE S1,REL.BJ(S2) ;DID WE SET IT?
RELM.8: PUSHJ P,L$DLET## ;YES - DELETE THE LOG FILE
POPJ P, ;RETURN
SUBTTL Stream termination -- Data base cleanup
; This routine is called only from CLOSJB
;
CLRSTR: TXNN F,FL.KST ;KSYS STREAM?
JRST CLRS.1 ;NO
MOVE S1,KSYSSC ;GET COUNT OF STREAMS SETUP
SOS S2,KSYUSE ;COUNT DOWN KSYS STREAMS IN USE
SUBI S1,(S2) ;COMPUTE STREAMS FREE NOW
CAMLE S1,KSYCNT ;ENOUGH LEFT TO HANDLE THE OVERFLOW?
TXO R,RL.SHT ;YES--SHUT DOWN THIS STREAM
JUMPN S2,CLRS.1 ;SHUTTING DOWN LAST KSYS STREAM?
PUSHJ P,KSYFIN ;YES--TELL THE OPERATOR WE'VE FINISHED
CLRS.1: MOVE S1,[IOWD TPSIZE,G$PDL] ;GET TOP LEVEL PDL FIRST
PUSH S1,(P) ;PLACE RETURN ADDRESS ON STACK
MOVE P,S1 ;GET NEW STACK POINTER
SOS G$SACT ;DECREMENT THE STREAM COUNT
CAMN S,G$HACT ;WAS STREAM THE HIGHEST ACTIVE
PUSHJ P,FHIACT ;YES, FIND NEW G$HACT
SKIPE S1,.JMDAP(R) ;GET MDA PAGE (IF ANY)
$CALL M%RPAG ;RELEASE IT
SKIPE S1,.JMODP(R) ;GET MODIFY PAGE (IF ANY)
$CALL M%RPAG ;RELEASE IT
MOVEI S1,1 ;1 PAGE
MOVE S2,.JSCMD(R) ;GET ADDRESS OF COMMAND PARSE PAGE
ADR2PG S2 ;CONVERT TO PAGE NUMBER
SKIPE S2 ;MAKE SURE WE REALLY HAD IT
$CALL M%RLNP ;RELEASE IT
TXNE R,RL.SHT ;SHUTTING DOWN STREAM?
PJRST SHUT.1 ;YES - DO IT NOW
TLZ R,777777 ;CLEAR INITIAL SETTINGS
MOVEM R,G$BASE(S) ;UPDATE STREAM RELOCATION AND FLAGS
POPJ P, ;RETURN
SUBTTL Time text generation
; Convert time to ASCIZ text
; Call: MOVE S1, time
; PUSHJ P,B$MTIM ;TIME IN MILLISECONDS
; PUSHJ P,B$STIM ;TIME IN SECONDS
;
; On return, G$TMTX:= contains the ASCIZ time text
;
B$MTIM::IDIVI S1,^D1000 ;CONVERT TO SECONDS
B$STIM::$SAVE <P1,P2,P3> ;SAVE SOME ACS
MOVE P1,S1 ;GET TIME IN MILLISECONDS
IDIVI P1,^D3600 ;P1:= HOURS
IDIVI P2,^D60 ;P2:= MINUTES, P3:= SECONDS
$TEXT (<-1,,G$TMTX>,<^D/P1/:^D2R0/P2/:^D2R0/P3/^0>) ;HH:MM:SS
POPJ P, ;RETURN
SUBTTL IOWAIT - Wait for I/O completion
IOWAIT::PUSHJ P,P$STAT## ;GET THE JOB STATUS
TXNE J,JL.UOA ;OUTPUT AVAILABLE?
JRST IOWA.2 ;YES
TXNE J,JL.UDI!JL.UHI ;PTY READY FOR MORE INPUT?
JRST IOWA.3 ;YES
IOWA.1: PUSHJ P,QTS ;WAIT FOR SOME PTY ACTIVITY
JRST IOWAIT ;TRY AGAIN
IOWA.2: PUSHJ P,P$READ## ;READ A LINE FROM THE PTY
JRST IOWAIT ;GO CHECK STATUS
IOWA.3: TXNE F,FL.SIL ;BATCH JOB SILENCED?
SETOM .JLTIM(R) ;YES - KEEP OUTPUT ALIGNED
SKIPE .JBCLK(R) ;CLOCK/EVENT REQUEST PENDING?
JRST IOWA.1 ;YES - WAIT A WHILE
POPJ P, ;RETURN
SUBTTL Random Little Routines
; Get job's remaining time limit
;
GJTIML:
TOPS10 < ;TOPS-10 ONLY
HRLZ S2,.JBJNO(R) ;GET THE JOB NUMBER
HRRI S2,.GTLIM ;AND THE BATCH LIMIT TABLE
GETTAB S2, ;READ THE JOB'S LIMIT WORD
MOVX S2,-1 ;CAN'T - GIVE THE GUY A BREAK
ANDX S2,JB.LTM ;KEEP ONLY THE TIME LIMIT
POPJ P, ;RETURN
> ;END OF TOPS-10 CONDITIONAL
TOPS20 < ;TOPS-20 ONLY
PUSH P,S1 ;SAVE S1
PUSH P,T1 ;AND T1
MOVE S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVX S2,<-1,,T1> ;RETURN 1 WORD IN S2
MOVX T1,.JIRTL ;FUNCTION CODE
GETJI ;READ THE JOB'S TIME LIMIT
MOVX S2,-1 ;GIVE THE GUY A BREAK
MOVE S2,T1 ;GET TIME LIMIT
POP P,T1 ;RESTORE T1
POP P,S1 ;AND S1
POPJ P, ;RETURN
> ;END OF TOPS-20 CONDITIONAL
; Set job location on TOPS-20
;
TOPS20 <
SETLOC: MOVE S1,.JQLOC(R) ;GET THE OUTPUT NODE
CAMN S1,G$NODE ;IS IT SAME AS MINE?
POPJ P, ;YES..JUST RETURN
SETZB T3,T4 ;CLEAR T3 AND T4
MOVE T1,[POINT 6,.JQLOC(R)] ;GET THE LOCATION
MOVE T2,[POINT 7,T3] ;PLACE TO STORE STRING
MOVEI P1,6 ;MAXIMUM LENGTH
SETL.1: ILDB S2,T1 ;GET A BYTE
JUMPE S2,SETL.2 ;O.K. SET THE LOCATION
ADDI S2,40 ;CONVERT TO ASCII CHARACTER
IDPB S2,T2 ;SAVE THE BYTE
SOJG P1,SETL.1 ;CHECK NUMBER OF CHARACTERS
SETL.2: MOVE S1,.JBJNO(R) ;GET THE JOB NUMBER
MOVX S2,.SJLLO ;SETUP LOCATION
HRROI T1,T3 ;GET STRING
SETJB ;SET IT UP
ERJMP .+1 ;IGNORE ERROR FOR NOW
POPJ P, ;RETURN
>;END TOPS20
SUBTTL DELSPL - Delete spooled input files
; This routine is not needed for TOPS-10. For TOPS-20, files named
; DSK:<SPOOL>CDR-xxx.CDyyy.* are deleted. "xxx" is the user's directory
; and "yyyy" is a string maje of the job name concatenated with 4 random
; characters currently passed by SPRINT in .JQSIS(R).
;
; *** Note ***
; The call to DELSPL must follow the call to C$CLOS in CLOSJB since it uses
; .JQCFD(R) for deleting spooled files.
;
DELSPL:
TOPS10 <POPJ P,> ;NOT NEEDED FOR TOPS-10
TOPS20 < ;TOPS-20 ONLY
SKIPN .JQSIS(R) ;IS THERE A SPOOLED INPUT NAME?
POPJ P, ;NO, JUST RETURN
$TEXT (<-1,,.JQCFD(R)>,<PS:[SPOOL]CDR-^O/.JQJBB+JIB.US(R),RHMASK/.^W/.JQSIS(R)/.*^0>)
MOVX S1,GJ%OLD!GJ%IFG!GJ%SHT ;LOAD GTJFN BITS
HRROI S2,.JQCFD(R) ;POINT TO FILE-NAME
GTJFN ;GET A JFN
POPJ P, ;FAILED, RETURN
MOVE T1,S1 ;SAVE THE JFN
JRST DELS.2 ;JUMP INTO THE LOOP
DELS.1: GNJFN ;GET THE NEXT FILE
JRST DELS.3 ;DONE EXPUNGE THE AREA
DELS.2: TLZ S1,-1 ;CLEAR LEFT HALF OF JFN WORD
TXO S1,DF%NRJ ;DONT RELEASE THE JFN
DELF ;DELETE THE FILE
JFCL ;IGNORE THE ERROR
MOVE S1,T1 ;RELOAD INDEXABLE JFN
JRST DELS.1 ;GET THE NEXT ONE
DELS.3: MOVEI S1,0 ;NO SPECIAL FLAGS
MOVE S2,G$SPLD ;GET DIRECTORY NUMBER OF PS:[SPOOL]
DELDF ;EXPUNGE IT
ERJMP .+1 ;IGNORE ERROR..
POPJ P, ;AND RETURN
> ;END OF TOPS-20 CONDITIONAL
SUBTTL LUUO handler
UUOCON: PUSH P,S1 ;SAVE S1
LDB S1,[POINT 9,.JBUUO##,8] ;GET OPCODE
CAXLE S1,UUOMAX ;RANGE CHECK IT
STOPCD (IBU,HALT,,<Illegal BATCON UUO>)
PUSHJ P,@UUOTAB-1(S1) ;DISPATCH
POP P,S1 ;RESTORE S1
POPJ P, ;RETURN
; UUO dispatch table
;
UUOTAB: IDENTX ;IDENTIFY A LOG FILE LINE
IDHDRX ;IDENTIFY A LOG FILE HEADER LINE
UUOMAX==.-UUOTAB ;NUMBER OF KNOWN UUOS
; Identify a log file line
;
IDENTX: SKIPN .JLTIM(R) ;NEED TO END THE PREVIOUS LINE?
PUSHJ P,L$CRLF## ;YES - SEND A CRLF TO THE LOG
SETZM .JLTIM(R) ;CLEAR TIME STAMP NEEDED FLAG
MOVE S1,-1(P) ;GET SAVED AC CONTENTS
$TEXT (L$PLOG##,<^T/G$TIME/^I/@.JBUUO/>) ;OUTPUT LINE IDENTIFIER
POPJ P, ;RETURN
; Identify a log file header line
;
IDHDRX: MOVE S1,-1(P) ;GET SAVED AC CONTENTS
$TEXT (L$PHDR##,<^T/G$TIME/^I/@.JBUUO/>) ;OUTPUT LINE IDENTIFIER
POPJ P, ;RETURN
SUBTTL PTY interrupt handler
; This seemingly useless routine will actually make the TOPS-20 DISMS JSYS
; act in a reasonable manor when a PTY interrupt is received during the sleep.
; The problem is that the DISMS JSYS doesn't get terminated when an interrupt
; is received.
;
TOPS20 < ;TOPS-20 ONLY
PTYINT: $BGINT PTYLVL ;SWITCH TO PTY INTERRUPT LEVEL
$DEBRK ;RETURN FROM INTERRUPT
> ;END OF TOPS-20 CONDITIONAL
SUBTTL ERRTAB EXPAND ERROR TABLE VALUES
DEFINE X(A,B),< EXP [ITEXT (<B>)]>
ERRTAB: MSGBLD ;BUILD MESSAGE TABLE
SUBTTL Literals
LIT
SUBTTL End
END BATCON ;A GOOD PLACE TO START