.TITLE BATCH .IDENT /V2.48/ ;******************************************************************* ; ; COMMAND ...BAT PROVIDES QUEUE MANIPULATION COMMANDS FOR THE ; BATCH SYSTEM. THIS TASK PROVIDES THE USER INTERFACE TO THE ; BATCH SYSTEM. RSX11M V3.2 ONLY. ; ; A FULL DESCRIPTION OF THIS TASK IS FOUND IN THE BATCH SYSTEM ; USER'S GUIDE. ; ; THIS VERSION SUPPORTS ANY NUMBER OF BATCH STREAMS. ; ; S.M. THOMPSON DECEMBER 1979 ; ; REVISION HISTORY ; ---------------- ; ; 7/1/80 D.J. STEINFELD ; QUEUE LISTING COMMANDS PRINT OUT "RESTARTABLE" IF ; ; 7/8/80 D.J. STEINFELD ; COMMAND LINE INPUT MODIFIED TO ACCEPT CONTINUATION ; LINES (TOTAL OF 132 CHARS.) ; ; 7/8/80 D.J. STEINFELD ; SAVE/RESTORE FUNCTIONS IMPLEMENTED ; ; 23-APR-82 S.M. THOMPSON ; CHANGED "PRINT$" MACRO TO "PRINT" ; SEVERAL SUBROUTINE NAME CHANGES, REMOVING THE $ ; AS FIRST CHARACTER. ; ; 18-MAY-82 DON'T PRINT ;0 IN LISTINGS IF LATEST VERSION OF ; JOB DESCRIPTION FILE. ; ; 18-JUN-82 CHANGED SIZE OF QUEUE BUFFER FROM 15 TO 25 JOBS ; ; 9-JUL-82 DON'T LOOK FOR IDENT IN INITIAL REGISTERS, TO ; PERMIT PERMANENT INSTALLMENT. ; ; 9-JUL-82 ADD SUPPORT FOR IMPLICIT /HF:1 ON SUBMISSIONS ; FROM WITHIN BATCH JOBS. ; ; 20-JUL-82 MAKE RESUBMISSIONS FROM WITHIN BATCH AT LEAST ; 60 MINUTES LONG (UNLESS PRIVILEGED JOB). ; ;******************************************************************* .PAGE .MCALL CSI$,CSI$SW,CSI$SV,CSI$ND,CSI$1,CSI$2 .MCALL NBOF$L,FDOF$L,QUEDF$ .MCALL GCMLB$,GCML$,FSRSZ$,OPEN$R,OPEN$W,CLOSE$,DELET$ .MCALL FDBDF$,FDAT$A,FDOP$A,NMBLK$,FINIT$ .MCALL EXIT$S,QIOW$,DIR$,PUT$,WSIG$S,STSE$S .MCALL GTIM$S,SPWN$,GLUN$S .MCALL TCBDF$,UCBDF$ QUEDF$ ; DEFINE QUEUE PACKET OFFSETS ; THIS MACRO IS PART OF THE BATCH SYSTEM. ; ALL OTHER MACROS LISTED IN .MCALL DIRECTIVES ; ABOVE ARE STANDARD RSX11M SYSTEM MACROS. TCBDF$ ; DEFINE TASK CONTROL BLOCK OFFSETS UCBDF$ ; DEFINE UCB OFFSETS NBOF$L ; DEFINE FILENAME BLOCK OFFSETS FDOF$L ; DEFINE FILE DESCRIPTOR BLOCK OFFSETS .PAGE P$$ARM = 10. ; IF THIS SYMBOL IS DEFINED, BAT WILL ALLOW THE ; CONSTRUCTION OF A PARAMETER LIST FOR THE ; BATCH JOB. THE VALUE OF P$$ARM IS THE MAXIMUM ; ALLOWED LENGTH OF EACH PARAMETER. ; THIS VERSION ALLOWS FOUR PARAMETERS TO BE ; SPECIFIED. ; THIS SYMBOL SHOULD BE DEFINED ACCORDINGLY IN THE ; SOURCE CODE FOR BATMAN. L$$CNT = 0 ; DEFINE IF LINE COUNTS ARE TO BE USED (SEE THE ; COMMENTS IN THE SOURCE FOR BATMAN.TSK) S$$AVE = 0 ; FOR FUTURE EXPANSION - DON'T DEFINE THIS SYMBOL ;T$$URN = 0 ; DEFINE THIS SYMBOL TO INCLUDE CODE FOR THE ; TURNROUND (/TU) SWITCH. IT DOESN'T WORK RIGHT ; AT THE MOMENT. A$$HLD = 0 ; IF THIS SYMBOL IS DEFINED, A JOB SUBMISSION ; FROM WITHIN A BATCH JOB WILL BE ACCOMPANIED ; BY /HF:1 IF THE /HF AND /HU SWITCHES ARE ; NOT USED. THIS STOPS THE SYSTEM BEING BLOCKED ; UP WITH SHORT JOBS AND GIVES THE LONG ONES ; A CHANCE TO START. M$$60M = 0 ; IF THIS SYMBOL IS DEFINED, ALL NON-PRIVILEGED ; SUBMISSIONS FROM WITHIN A BATCH JOB WILL ; BE FORCED TO AT LEAST A 60 MINUTE LIMIT. MAXDEP = 1 ; MAXIMUM NESTING DEPTH FOR INDIRECT COMMAND FILES MAXJOB = 25. ; NUMBER OF ENTRIES IN LIST BUFFER ; MAXJOB SHOULD BE AT LEAST AS BIG AS THE ; MAXIMUM QUEUE SIZE. IF NOT, QUEUE LISTINGS ; WILL BE INCOMPLETE AND IT WILL NOT BE ; POSSIBLE TO COMPUTE A TURNROUND TIME FOR ; JOBS TOWARDS THE END OF THE QUEUE. PASSIZ = 6 ; SIZE OF PASSWORD FIELD LNKSIZ = 2 ; SIZE OF LINK WORD FIELD IN BYTES MRKSIZ = 2 ; SIZE OF END-BUFFER MARKER COMLUN = 1 ; COMMAND I/O LUN ERRLUN = 2 ; ERROR MESSAGES LUN QIOEFN = 1 ; QIOW$ EVENT FLAG SAVEFN = 5 ; EVENT FLAG FOR SAVE/RESTORE CR = 15 ; CARRIAGE RETURN LF = 12 ; LINEFEED HT = 11 ; HORIZONTAL TAB SPA = 40 ; SPACE DPT = '. ; PERIOD DOLLAR = '$ ; DOLLAR FOR CARRIAGE CONTROL PLUS = '+ ; PLUS FOR CARRIAGE CONTROL SEMI = '; ; SEMICOLON COLON = ': ; COLON TKPS = 60. ; CLOCK FREQUENCY .PAGE CSI$ ; DEFINE CSI OFFSETS .IF GT MAXDEP-1 FSRSZ$ MAXDEP .IFF FSRSZ$ 1. .ENDC DEFSIZ = 1 ; INITIAL SIZE FOR /IM FILE IN BLOCKS EXTSIZ = 1 ; EXTEND SIZE FOR /IM FILE IN BLOCKS $FDB: FDBDF$ ; FDB FOR BATCH JOB FILE FDAT$A R.VAR,FD.CR,,DEFSIZ,EXTSIZ FDOP$A COMLUN,,DEFFNB ; DEFFNB: NMBLK$ BATCH,CMD,,SY,0 ; DEFAULT NAME IS BATCH.CMD .PAGE ; ; MACROS ; .MACRO PRINT MSG,MSGSZ,FLAG MOV MSG,QIOW+Q.IOPL MOV MSGSZ,QIOW+Q.IOPL+2 DIR$ #QIOW .IF IDN , INCB ERRFLG .ENDC .ENDM .MACRO ERROR$ ERR,ERRA,FATAL MOVB F.ERR(R0),R1 MOV ERRA,R0 CALL FCSERR SUB ERR,R0 PRINT ERR,R0,FATAL .ENDM .MACRO JMSG$ JOBNO,M1,M2,NORET .IIF NB JOBNO,MOV JOBNO,R1 .IF B M1 MOV #MSG1,R2 .IFF MOV M1,R2 .ENDC MOV M2,R3 .IF B NORET JMP JBMSG .IFF CALL JBMSG .ENDC .ENDM .MACRO TAB COL MOV #,R1 CALL TTAB .ENDM .PAGE GCML: GCMLB$ MAXDEP,BAT,GCBUF,COMLUN,PUSH,GCBFLN ; GCML I/O BLOCK ***DJS CSIBLK: .BLKB C.SIZE GCBUF: .BLKB 132. ; COMMAND I/O BUFFER ***DJS GCBFLN= .-GCBUF ; COMMAND I/O BUFFER LENGTH ***DJS BUF: .BLKB 132. ; INTERNAL MESSAGE BUFFER ; MUST BE AT LEAST 80. BYTES PUSH: .BLKB <16.*> ; PUSH-DOWN LIST ; ; SWITCH MASK TABLE ; ; *IMPORTANT* DO NOT CHANGE THESE BIT DEFINITIONS WITHOUT ; MAKING A CORRESPONDING CHANGE IN THE SOURCE CODE FOR BATMAN.TSK. ; IN ANY EVENT, THE DEFINITIONS OF 'MRKABO' AND 'MRKEXE' MUST ; NOT BE CHANGED. ; TLMASK = 1 ; /TL (TIME LIMIT) PAMASK = 2 ; /PA (PASSWORD) IMMASK = 4 ; /IM (IMMEDIATE MODE) EVMASK = 10 ; /EV (EXPLICIT VERSION) EXMASK = 20 ; /EX (EXPRESS JOB) TRMASK = 40 ; /TR (TRACE JOB EXECUTION) DEMASK = 100 ; /DE (DELETE COMMAND FILE AT END OF JOB) HFMASK = 200 ; /HF (HOLD FOR SWITCH) HUMASK = 400 ; /HU (HOLD UNTIL SWITCH) LNMASK = 1000 ; /LN (LINE COUNT) RSMASK = 2000 ; /RS (RESTART JOB ON CRASH) KEMASK = 4000 ; /KE (KEEP LOG FILE IN USER DIRECTORY) NOMASK = 10000 ; /NO (DON'T SPOOL LOG FILE PMMASK = 20000 ; /PM (PARAMETER LIST) ; THE REMAINING 2 BITS IN THE MASK WORD ; ARE USED BY BATMAN AND MUST NOT BE USED ; BY BAT FOR SWITCH MASKS. LIMASK = 1 ; /LI (LIST BATCH QUEUE) FUMASK = 2 ; /FU (FULL LISTING) ALMASK = 4 ; /AL (LIST ALL THE QUEUE, NOT JUST MY JOBS) CAMASK = 1 ; /CA (CANCEL JOB) ABMASK = 2 ; /AB (ABORT JOB IF RUNNING) RLMASK = 1 ; /RL (RELEASE JOB FROM HOLD) TUMASK = 1 ; /TU (JOB TURNROUND) SQMASK = 1 ; /SAVE (SAVE QUEUE) RQMASK = 2 ; /RESTORE (RESTORE QUEUE) QSMASK = 4 ; /QUESIZE (QUEUE SIZE) RDMASK = 10 ; /RUNDOWN (PUT QUEUE IN RUNDOWN) RJMASK = 20 ; /RUNJOBS (CLEAR RUNDOWN CONDITION) IDMASK = 40 ; /ID (BATCH VERSION NUMBER) CLMASK = 100 ; /CLOSEDOWN (DON'T ACCEPT NEW JOBS) NXMASK = 200 ; /NEXTJOB (SET NEXT JOB NUMBER) XTMASK = 400 ; /STOP (SET RUNDOWN AND MARK FOR EXIT) MRKABO = 100000 ; FLAG FOR MARK-FOR-ABORT MRKEXE = 40000 ; JOB RUNNING FLAG CANCW: .BLKW 1 ; CANCEL COMMANDS MASK WORD SUBMW: .BLKW 1 ; SUBMIT COMMANDS MASK WORD RELSW: .BLKW 1 ; RELEASE COMMANDS MASK WORD LISTW: .BLKW 1 ; LIST COMMAND MASK WORD TURNW: .BLKW 1 ; TURNROUND COMMAND MASK WORD PRIVF: .BLKW 1 ; PRIVILEGED FUNCTIONS MASK WORD .PAGE ; ; SWITCH DESCRIPTOR TABLE ; SWTBL: CSI$SW TL,TLMASK,SUBMW,,,TLTAB ; JOB SUBMISSION SWITCH CSI$SW PA,PAMASK,SUBMW,,,PATAB ; PASSWORD SUBSWITCH CSI$SW IM,IMMASK,SUBMW,,NEG ; IMMEDIATE MODE SWITCH CSI$SW EV,EVMASK,SUBMW,,NEG ; EXPLICIT VERSION SWITCH CSI$SW TR,TRMASK,SUBMW,,NEG ; TRACE SUBSWITCH CSI$SW DE,DEMASK,SUBMW,,NEG ; DELETION SUBSWITCH CSI$SW HF,HFMASK,SUBMW,,NEG,HFTAB ; HOLD FOR SUBSWITCH CSI$SW HU,HUMASK,SUBMW,,NEG,HUTAB ; HOLD UNTIL SUBSWITCH .IF DF L$$CNT CSI$SW LN,LNMASK,SUBMW,,,LNTAB ; LINE COUNT SWITCH .ENDC CSI$SW EX,EXMASK,SUBMW,,NEG ; EXPRESS JOB SUBSWITCH CSI$SW RS,RSMASK,SUBMW,,NEG ; RESTARTABLE JOB SWITCH CSI$SW KE,KEMASK,SUBMW,,NEG ; KEEP LOG FILE SWITCH CSI$SW NO,NOMASK,SUBMW ; DON'T SPOOL LOG FILE .IF DF P$$ARM .IIF LE P$$ARM .ERROR ; ILLEGAL PARAMETER SIZE (P$$ARM) CSI$SW PM,PMMASK,SUBMW,,NEG,PMTAB ; PARAMETER LIST SWITCH .ENDC ; DF P$$ARM CSI$SW LI,LIMASK,LISTW ; LIST BATCH QUEUE SWITCH CSI$SW FU,FUMASK,LISTW,,NEG ; FULL BATCH QUEUE LIST SWITCH CSI$SW AL,ALMASK,LISTW,,NEG ; LIST THE COMPLETE QUEUE CSI$SW CA,CAMASK,CANCW,,,CATAB ; CANCEL BATCH JOB SWITCH CSI$SW AB,ABMASK,CANCW,,NEG ; ABORT BATCH JOB SUBSWITCH CSI$SW RL,RLMASK,RELSW,,,RLTAB ; RELEASE JOB SUBSWITCH CSI$SW TU,TUMASK,TURNW,,,TUTAB ; TURNROUND SWITCH CSI$SW SAVE,SQMASK,PRIVF,,NEG,,EXACT ; /SAVE CSI$SW RESTORE,RQMASK,PRIVF,,NEG,,EXACT ; /RESTORE CSI$SW QUESIZE,QSMASK,PRIVF,,,MQTAB,EXACT ; /QUESIZE CSI$SW RUNDOWN,RDMASK,PRIVF,,NEG,,EXACT ; /RUNDOWN CSI$SW RUNJOBS,RJMASK,PRIVF,,NEG,,EXACT ; /RUNJOBS CSI$SW ID,IDMASK,PRIVF ; /ID CSI$SW CLOSEDOWN,CLMASK,PRIVF,,NEG,,EXACT ; /CLOSEDOWN CSI$SW NEXTJOB,NXMASK,PRIVF,,,NXTAB,EXACT ; /NEXTJOB CSI$SW STOP,XTMASK,PRIVF,,NEG,,EXACT ; /STOP CSI$ND .PAGE ; ; SWITCH VALUE DESCRIPTOR TABLES ; TLTAB: CSI$SV OCTAL,TIMLIM,2 ; JOB TIME LIMIT CSI$ND CATAB: CSI$SV OCTAL,CAJOB,2 ; CANCEL JOB NUMBER CSI$ND PATAB: CSI$SV ASCII,PSWD,6 ; USER PASSWORD CSI$ND HFTAB: CSI$SV OCTAL,HFTIM,2 ; HOLD FOR CSI$ND HUTAB: CSI$SV DECIMAL,HUHR,2 ; HOLD UNTIL CSI$SV DECIMAL,HUMIN,2 ; CSI$ND .IF DF L$$CNT LNTAB: CSI$SV OCTAL,LINES,2 CSI$ND .ENDC .IF DF P$$ARM PMTAB: CSI$SV ASCII,PARM1,P$$ARM CSI$SV ASCII,PARM2,P$$ARM CSI$SV ASCII,PARM3,P$$ARM CSI$SV ASCII,PARM4,P$$ARM CSI$ND .ENDC RLTAB: CSI$SV OCTAL,RLJOB,2 ; RELEASE CSI$ND .IF DF P$$ARM PARM1: .BLKB ; PARAMETER STORAGE FIELDS PARM2: .BLKB PARM3: .BLKB PARM4: .BLKB .EVEN .ENDC ; DF P$$ARM TUTAB: CSI$SV OCTAL,TUJOB,2 ; TURNROUND CSI$ND MQTAB: CSI$SV OCTAL,QUESIZ,2 ; MAX QUEUE SIZE CSI$ND NXTAB: CSI$SV OCTAL,NXJOB,2 ; NEXT JOB NUMBER CSI$ND TIMLIM: .BLKW 1 ; /TL TIME LIMIT (MINUTES) CAJOB: .BLKW 1 ; /CA JOB NUMBER TUJOB: .BLKW 1 ; /TU JOB NUMBER QUESIZ: .BLKW 1 ; /QUESIZE QUEUE SIZE NXJOB: .BLKW 1 ; /NEXTJOB JOB NUMBER PSWD: .BLKB 8. ; USER PASSWORD ; (6 BYTES FOR PASSWORD, 1 BYTE FOR ; THE READ TERMINATOR, AND 1 BYTE TO ; PRESERVE WORD ALIGNMENT) HFTIM: .BLKW 1 ; "HOLD FOR" TIME HUHR: .BLKW 1 ; "HOLD UNTIL" HOUR HUMIN: .BLKW 1 ; "HOLD UNTIL" MINUTE RLJOB: .BLKW 1 ; /RL JOB NUMBER .IF DF L$$CNT LINES: .WORD 0 ; /LN LINE COUNT .ENDC ; DF L$$CNT HOLDTM: .WORD -1 ; JOB HOLD TIME ; -1 GIVES A DEFAULT OF JOB NOT IN HOLD. PKTADR: .WORD 0 ; DSR CORE BLOCK ADDRESS ; ; NEXT TWO BYTES MUST BE TOGETHER ; PASFLG: .BYTE 0 ; FLAG FOR PASSWORD ACCEPTANCE ERRFLG: .BYTE 0 ; ERROR FLAG CRTFLG: .WORD 0 ; TI: IS A CRT 0=NO,1=YES .PSECT $LBUF$,D LSIZE:: .WORD MAXJOB LIBUF: .BLKB <>+MRKSIZ> ; QUEUE LIST BUFFER .PSECT PRMPT: .BYTE '* ; PROMPT FOR /IM INPUT .PAGE ; ; TEXT MESSAGES ; .NLIST BEX .ENABL LC .IF DF L$$CNT LCNT: .ASCIZ /Lines=/ .ENDC XPRS: .ASCIZ / Express/ RSSTR: .ASCIZ /Restartable/ USED: .ASCIZ / (Used / IDENT: .ASCII /BAT -- Batch version / IDHERE: .ASCII /V2.48 / ; JUST IN CASE WE CAN'T GET THE RIGHT ID IDSZ=.-IDENT QSTR: .ASCIZ /Quesize=/ NXJB: .ASCIZ /Nextjob=/ GETP: .ASCII /Enter Password:/ GETPSZ=.-GETP IMD: .ASCII /Enter commands:/ IMDSZ=.-IMD BATD: MSG1: .ASCII /BAT -- / BATDSZ=.-BATD .ASCIZ /Job / MSG1A: .ASCIZ / removed from hold/ MSG2A: .ASCIZ / marked for abort/ MSG3A: .ASCIZ / accepted/ MSG4: .ASCII /BAT -- Queue is empty/ MSG4SZ=.-MSG4 MSG5: .ASCII /Jobs in queue: / MSG5A: .BLKB 6. MSG6A: .ASCIZ / cancelled/ MSG7: .ASCII /Queue is in Rundown/ MSG7SZ=.-MSG7 MSG8: .ASCII / - No new jobs are being accepted/ MSG8SZ=.-MSG8 .IF DF T$$URN MSG9: .ASCII /BAT -- Can't compute turnround for job / MSG9A: .BLKB 6 MSG10: .ASCII /BAT -- Turnround for job / MSG10A: .BLKB 20. .IFF MSG9: .ASCII /BAT -- Turnround command is withdrawn/ MSG9SZ=.-MSG9 .ENDC ; DF T$$URN MSG11: .ASCII /Listings may be incomplete - too many jobs for buffer/ MSG11S=.-MSG11 .PAGE ; ; ERROR MESSAGES ; ERR1: .ASCII /BAT -- Command input error: code / ERR1A: .BLKB 6. ERR2: .ASCII /BAT -- Can't open command file: FCS / ERR2A: .BLKB 8. ERR3: .ASCII /BAT -- Maximum nesting depth exceeded/ ERR3SZ=.-ERR3 ERR4: .ASCII /BAT -- Command file specification error/ ERR4SZ=.-ERR4 ERR5: .ASCII /BAT -- Command syntax error/ ERR5SZ=.-ERR5 ERR6: .ASCII /BAT -- Invalid job number/ ERR6SZ=.-ERR6 ERR7: .ASCII /BAT -- Cancel switch missing/ ERR7SZ=.-ERR7 ERR8: .ASCII /BAT -- Queue is full/ ERR8SZ=.-ERR8 ERR9: .ASCII /BAT -- Invalid time limit/ ERR9SZ=.-ERR9 ERR10: .ASCII /BAT -- Bad password/ ERR10S=.-ERR10 ERR11: .ASCII /BAT -- Command is ambiguous/ ERR11S=.-ERR11 ERR12: .ASCII /BAT -- Invalid hold specification/ ERR12S=.-ERR12 ERR13: .ASCII /BAT -- Privileged command/ ERR13S=.-ERR13 ERR14: .ASCII /BAT -- Nodes exhausted/ ERR14S=.-ERR14 ERR15: .ASCII /BAT -- Bad directory string/ ERR15S=.-ERR15 ERR17: .ASCII /BAT -- Only a batch job can default the password/ ERR17S=.-ERR17 ERR18: .ASCII /BAT -- Can't open job description file: FCS / ERR18A: .BLKB 6. ERR19: .ASCII /BAT -- Immediate mode illegal within a batch job/ ERR19S=.-ERR19 ERR20: .ASCII %BAT -- I/O error - file deleted: FCS % ERR20A: .BLKB 6. ERR21A: .ASCIZ / is running/ ERR22A: .ASCIZ / not in queue/ ERR23A: .ASCIZ / is not in hold/ ERR24: .ASCII /BAT -- Privilege violation/ ERR24S=.-ERR24 ERR25A: .ASCIZ / is in hold/ ERR26: .ASCII %BAT -- WARNING - /NO switch will be ignored% ERR26S=.-ERR26 .IF DF P$$ARM ERR27: .ASCII /BAT -- Unable to build parameter list/ ERR27S=.-ERR27 .ENDC ERR28: .ASCII /BAT -- Can't accept job - system is closing down/ ERR28SZ=.-ERR28 .IF DF L$$CNT ERR29: .ASCII /BAT -- Invalid line count specification/ ERR29S=.-ERR29 .ENDC ; DF L$$CNT .PAGE .EVEN TIMBUF: .BLKW 8. ; TIME PARAMETERS BUFFER DIRD = TIMBUF ; DIRECTORY STRING DESCRIPTOR ; ; DIRECTIVE PARAMETER BLOCKS ; QIOW: QIOW$ IO.WVB,ERRLUN,QIOEFN,,IOSB,,<0,0,40> IMMEDW: QIOW$ IO.WVB,ERRLUN,QIOEFN,,,, IMMEDR: QIOW$ IO.RVB,ERRLUN,QIOEFN,,IOSB,, ATT: QIOW$ IO.ATT,ERRLUN DET: QIOW$ IO.DET,ERRLUN IOSB: .BLKW 2 ; I/O STATUS BLOCK .IF DF M$$MUP SYSMBR = 54 .IFF SYSMBR = 50 .ENDC .IF DF S$$AVE QSAVE: SPWN$ MCR...,,,1,SYSMBR,SAVEFN,,,QSCMD,QSCMDS,0 QSCMD: .ASCII %RUN LB:[10,25]BATSAVE/TASK=BATSAV% QSCMDS=.-QSCMD QRMSG: .ASCII %BAT -- /RESTORE removed, restore queue with BATREST.TSK% QRMSLN= .-QRMSG .ENDC ; DF S$$AVE .PAGE .SBTTL COMMAND LINE PROCESSING $BATEP:: ; FINIT$ ; GETCM: GCML$ #GCML ; GET COMMAND LINE BCC 15$ ; OK CMPB #GE.EOF,G.ERR(R0) ; END OF TOP LEVEL FILE? BNE 10$ ; NO 7$: EXIT$S ; EXIT 10$: BITB #GE.IOR,G.ERR(R0) ; CMD I/O ERROR? BNE 101$ ; YES BITB #GE.OPR,G.ERR(R0) ; FILE OPEN ERROR? BNE 102$ ; YES BITB #GE.MDE,G.ERR(R0) ; MAX NESTING DEPTH EXCEEDED? BNE 103$ ; YES PRINT #ERR4,#ERR4SZ ; MUST BE FILE SPEC ERROR BR GETCM ; 101$: ERROR$ #ERR1,#ERR1A ; COMMAND INPUT ERROR BR GETCM ; 102$: ERROR$ #ERR2,#ERR2A ; CAN'T OPEN COMMAND FILE BR GETCM ; 103$: PRINT #ERR3,#ERR3SZ ; MAX NESTING DEPTH EXCEEDED BR GETCM ; 15$: MOV G.CMLD(R0),R1 ; GET LENGTH OF COMMAND LINE BEQ GETCM ; GO AGAIN IF ZERO CLR CANCW ; CLEAR MASK WORDS CLR SUBMW ; CLR RELSW ; CLR LISTW ; CLR TURNW ; CLR PRIVF ; CLRB ERRFLG ; CLEAR ERROR FLAG CLR HUHR ; DEFAULT HOLD HOUR TO MIDNIGHT CLR HUMIN ; AND HOLD MINUTE TO THE HOUR CLR HFTIM ; NO DEFAULT HOLD FOR TIME .IF DF L$$CNT MOV #$DFLIN,LINES ; SET DEFAULT LINE LIMIT .ENDC ; DF L$$CNT .IF DF P$$ARM MOV R1,-(SP) ; SAVE COMMAND LINE LENGTH MOV #PARM1,R0 ; GET ADDRESS OF 1ST PARAMETER FIELD CALL CPARM ; ZERO IT OUT MOV #PARM2,R0 ; SIMILARY FOR ALL OTHER FIELDS... CALL CPARM ; MOV #PARM3,R0 ; CALL CPARM ; MOV #PARM4,R0 ; CALL CPARM ; MOV (SP)+,R1 ; RESTORE COMMAND LINE LENGTH .ENDC ; DF P$$ARM CLR CAJOB ; NO DEFAULT JOB NUMBER FOR CANCEL CLR RLJOB ; NO DEFAULT JOB NUMBER FOR RELEASE CLR TUJOB ; NO DEFAULT JOB NUMBER FOR TURNROUND CLR QUESIZ ; DEFAULT FOR /QUESIZE IS DISPLAY QUEUE CLR NXJOB ; DEFAULT FOR /NEXTJOB IS DISPLAY NEXT JOB NUMBER MOV #$TIME,TIMLIM ; SET DEFAULT TIME LIMIT MOV #-1,HOLDTM ; AND JOB NOT IN HOLD CSI$1 #CSIBLK,GCML+G.CMLD+2,R1 ; CHECK SYNTAX BCC 20$ ; SYNTAX IS GOOD 16$: PRINT #ERR5,#ERR5SZ ; SYNTAX ERROR 17$: BITB #FD.TTY,GCML+F.RCTL ; DID CMD COME FROM TI:? BNE 19$ ; YES MOV #DOLLAR,QIOW+Q.IOPL+4 ; SET PROMPT MODE PRINT #BATD,#BATDSZ ; TYPE BAT -- MOV #PLUS,QIOW+Q.IOPL+4 ; SET OVERPRINT PRINT CSIBLK+C.FILD+2,CSIBLK+C.FILD ; TYPE BAD PART MOV #SPA,QIOW+Q.IOPL+4 ; RESET MODE 19$: JMP GETCM ; 20$: CSI$2 #CSIBLK,OUTPUT,#SWTBL ; PARSE JOB FILE SPECIFICATION BCC 30$ ; OK 25$: MOV GCML+G.CMLD,CSIBLK+C.FILD ; POINT TO COMMAND LINE MOV GCML+G.CMLD+2,CSIBLK+C.FILD+2 ; BR 16$ ; TELL USER OF ERROR 30$: BITB #CS.EQU!CS.WLD,CSIBLK+C.STAT ; = SIGN OR WILD CARDS? BNE 25$ ; YES IS ERROR TST CANCW ; ANY CANCEL COMMANDS? BEQ 200$ ; NO CALL PCAN ; YES, EXECUTE THEM BR 209$ ; CHECK FOR ERRORS 200$: TST SUBMW ; ANY SUBMIT COMMANDS? BEQ 201$ ; NO CALL PSUB ; YES, EXECUTE THEM BR 209$ ; CHECK FOR ERRORS 201$: TST RELSW ; ANY RELEASE COMMANDS? BEQ 202$ ; NO CALL PREL ; YES, EXECUTE THEM BR 209$ ; CHECK FOR ERRORS 202$: TST LISTW ; ANY LIST COMMANDS? BEQ 203$ ; NO CALL PLIS ; YES, EXECUTE THEM BR 209$ ; CHECK FOR ERRORS 203$: TST TURNW ; ANY TURNROUND COMMANDS BEQ 204$ ; NO CALL PTUR ; YES, EXECUTE THEM BR 209$ ; 204$: TST PRIVF ; ANY PRIVILEGED FUNCTIONS? BEQ 25$ ; NO IS ERROR CALL XPRIVF ; EXECUTE PRIVILEGED FUNCTIONS 209$: TSTB ERRFLG ; ANY ERRORS? BNE 210$ ; YES, TERMINATE SCAN BITB #CS.MOR,CSIBLK+C.STAT ; ANY MORE FILES? BNE 20$ ; YES 210$: JMP GETCM ; BACK TO BEGINNING .PAGE .SBTTL AMBIGUOUS COMMAND MESSAGE ROUTINE ;+ ; ; *** AMBIG ; ; THIS ROUTINE IS CALLED WHEN AN AMBIGUOUS COMMAND IS ; DETECTED. AN ERROR MESSAGE IS PRINTED, AND THE FATAL ERROR ; FLAG IS SET. IF THE COMMAND WAS OBTAINED FROM A COMMAND ; FILE, THE OFFENDING LINE IS TYPED OUT. ; ;- AMBIG: PRINT #ERR11,#ERR11S,FATAL ; PRINT ERROR MESSAGE BITB #FD.TTY,GCML+F.RCTL ; DID COMMAND COME FROM TI: BNE AMBIGR ; YES MOV #DOLLAR,QIOW+Q.IOPL+4 ; SET PROMPT MODE PRINT #BATD,#BATDSZ ; TYPE OUT "BAT -- " MOV #PLUS,QIOW+Q.IOPL+4 ; SET OVERPRINT PRINT GCML+G.CMLD+2,GCML+G.CMLD ; TYPE OUT COMMAND LINE MOV #SPA,QIOW+Q.IOPL+4 ; RESET MODE AMBIGR: RETURN ; RETURN .PAGE .SBTTL PRELIMINARY TURNROUND PROCESSING ;+ ; ; *** PTUR ; ; THIS ROUTINE IS CALLED TO PERFORM PRELIMINARY PROCESSING ; WHEN A REQUEST HAS BEEN ISSUED TO FIND THE PREDICTED ; TURNROUND TIME OF A JOB IN THE QUEUE. THE JOB MUST NOT BE ; RUNNING OR IN HOLD. ; ;- PTUR: TST TURNW ; ANY WORK TO DO? BEQ PTURR ; NO TST PRIVF ; ANY PRIVILEGED FUNCTIONS? BEQ 1$ ; ONLY NO IS GOOD CALLR AMBIG ; AMBIGUOUS COMMAND 1$: TST TUJOB ; JOB NUMBER LEGAL? BGT 2$ ; YES PRINT #ERR6,#ERR6SZ,FATAL ; INVALID JOB NUMBER BR PTURR ; SO RETURN WITH ERROR FLAG SET 2$: MOV TUJOB,R0 ; GET JOB NUMBER CALL GETJB ; LOCATE ITS JOB PACKET BCC 5$ ; OK JMSG$ TUJOB,,#ERR22A ; JOB NOT IN QUEUE 5$: BIT #MRKEXE,Q.MASK(R1) ; IS THE JOB RUNNING? BEQ 10$ ; NO JMSG$ TUJOB,,#ERR21A ; JOB IS RUNNING, CANNOT /TU 10$: BIT #HFMASK!HUMASK,Q.MASK(R1) ; IS THE JOB ON HOLD? BEQ 15$ ; NO JMSG$ TUJOB,,#ERR25A ; CANNOT /TU FOR A JOB IN HOLD 15$: CALL $QLOCK ; LOCK BATCH QUEUES CALL GETQU ; COPY QUEUES TO INTERNAL BUFFER CALL $QUNLK ; UNLOCK QUEUES CALL TURJB ; CALCULATE THE TURNROUND PTURR: RETURN ; RETURN TO CALLER .PAGE .SBTTL PRELIMINARY QUEUE LISTING PROCESSING ;+ ; ; *** PLIS ; ; THIS ROUTINE IS CALLED TO PERFORM PRELIMINARY PROCESSING ; FOR THE LISTING SWITCHES. THE BATCH QUEUE IS COPIED ; TO THE INTERNAL BUFFER AND A ROUTINE IS CALLED TO FORMAT ; EACH ENTRY. ; ;- PLIS: TST LISTW ; ANY LIST COMMANDS? BEQ PLISR ; NO MOV TURNW,R1 ; FORM MASK FOR REMAINING COMMAND... ADD PRIVF,R1 ; ... CLASSES BEQ 1$ ; ONLY EQ IS GOOD CALLR AMBIG ; AMBIGUOUS COMMAND 1$: MOV $NUMQ,R1 ; GET NUMBER OF JOBS IN QUEUE BNE 2$ ; NE MEANS IT IS NON-ZERO PRINT #MSG4,#MSG4SZ ; PRINT QUEUE EMPTY MESSAGE BR PLISR ; AND RETURN 2$: MOV #MSG5A,R0 ; GET BUFFER ADDRESS FOR FORMATTED NUMBER CALL $DECML ; CONVERT TO DECIMAL SUB #MSG5,R0 ; GET MESSAGE LENGTH DIR$ #ATT ; ATTACH THE TERMINAL PRINT #MSG5,R0 ; TYPE IT OUT BIT #QQ.RDN,$QSTAT ; IS THE QUEUE IN RUNDOWN MODE? BEQ 4$ ; NO PRINT #MSG7,#MSG7SZ ; YES, TELL THE USER 4$: BIT #QQ.CLS,$QSTAT ; IS QUEUE IN CLOSEDOWN MODE BEQ 5$ ; NO PRINT #MSG8,#MSG8SZ ; YES, TELL THE USER 5$: CMP $NUMQ,#MAXJOB ; CAN WE FIT IN ALL THE JOBS? BLE 6$ ; YES PRINT #MSG11,#MSG11S ; NO, SAY BUFFER IS TOO SMALL 6$: CALL $QLOCK ; LOCK BATCH QUEUE LISTS CALL GETQU ; COPY QUEUE TO INTERNAL BUFFER CALL $QUNLK ; UNLOCK QUEUE LISTS CALL QLIST ; LIST THE QUEUE CONTENTS DIR$ #DET ; DETACH THE TERMINAL PLISR: RETURN ; AND RETURN .PAGE .SBTTL TURNROUND CALCULATION ROUTINE ;+ ; ; *** TURJB ; ; THIS ROUTINE CALCULATES THE PREDICTED TURNROUND FOR A JOB THAT ; ISKNOWN TO BE ELIGIBLE FOR EXECUTUTION. THE RESULT IS ; TO BE CONSIDERED APPROXIMATE ONLY, AS IT DEPENDS ON MANY ; FACTORS THAT THE BATCH SYSTEM CANNOT KNOW ABOUT. ; ;- TURJB: .IF DF T$$URN MOV #TIMBUF+2,R5 ; GET ADDRESS+2 OF TIME COUNTER CLR (R5) ; CLEAR IT CLR -(R5) ; MOV LSIZE,R3 ; GET SIZE OF INTERNAL BUFFER (# ENTRIES) MOV #LIBUF,R4 ; AND ADDRESS OF INTERNAL BUFFER 20$: CMP TUJOB,2(R4) ; THIS JOB? BEQ 35$ ; YES, TYPE OUT RESULTS BIT #MRKEXE,10(R4) ; NO, IS THIS JOB RUNNING? BEQ 25$ ; NO ADD 32(R4),2(R5) ; YES, ADD IN ORIGINAL JOB TIME (TICKS) ADC (R5) ; ADD 30(R4),(R5)+ ; SUB 36(R4),(R5) ; AND SUBTRACT WHAT THE JOB HAS ALREADY USED SBC -(R5) ; SUB 34(R4),(R5) ; BR 30$ ; GO TO NEXT ENTRY 25$: MOV R3,-(SP) ; SAVE R3 MOV #<60.*TKPS>,R0 ; GET NUMBER OF TICKS PER MINUTE MOV 32(R4),R1 ; AND TIME LIMIT IN MINUTES CALL $MUL ; CONVERT IT TO TICKS ADD R1,2(R5) ; ADD RESULT TO TOTAL ADC (R5) ; ADD R0,(R5) ; MOV (SP)+,R3 ; RESTORE R3 30$: ADD #,R4 ; POINT TO NEXT ENTRY DEC R3 ; ARE THERE ANY MORE? BNE 20$ ; YES, LOOP MOV #MSG9A,R0 ; CAN'T FIND JOB, GET DIAGNOSTIC ; MESSAGE ADDRESS MOV TUJOB,R1 ; GET JOB NUMBER CALL $OCTAL ; FORMAT IT SUB #MSG9,R0 ; CALCULATE MESSAGE LENGTH PRINT #MSG9,R0 ; TYPE OUT MESSAGE BR TURJR ; AND RETURN TO CALLER 35$: MOV #MSG10A,R0 ; GET ADDRESS FOR TURNROUND RESULT MOV TUJOB,R1 ; GET JOB NUMBER CALL $OCTAL ; FORMAT AS OCTAL MOVB #SPA,(R0)+ ; INSERT " IS " MOVB #'I,(R0)+ ; MOVB #'S,(R0)+ ; MOVB #SPA,(R0)+ ; MOV R5,R1 ; POINT R1 TO TURNROUND TIME CALL TFORM ; FORMAT IT SUB #MSG10,R0 ; CALCULATE MESSAGE LENGTH PRINT #MSG10,R0 ; PRINT IT OUT .IFF PRINT #MSG9,#MSG9SZ,FATAL ; TURNROUND COMMAND NOT AVAILABLE .ENDC ; DF T$$URN TURJR: RETURN ; AND RETURN TO CALLER .PAGE .SBTTL QUEUE LISTING ROUTINE ;+ ; *** QLIST ; ; THIS ROUTINE IS CALLED TO LIST THE BATCH QUEUE ONCE ; ALL THE DATA HAS BEEN COPIED TO THE INTERNAL BUFFER. ; ;- QLIST: MOV #LIBUF,R5 ; POINT TO SAVED DATA CLRB ERRFLG ; ASSUME A 132. COLUMN LISTING GLUN$S #ERRLUN,#BUF ; GET LOGICAL UNITS INFORMATION CMP BUF+G.LUCW+6,#80. ; LISTING DEVICE LESS THAN OR = 80 COLUMNS? BGT 2$ ; NO INCB ERRFLG ; YES, SET FOR SHORT LISTING 2$: MOV $TKTCB,R0 ; GET OUR TCB ADDRESS MOV T.UCB(R0),R0 ; AND OUR TI: UCB ADDRESS MOV U.LUIC(R0),-(SP) ; PUT LOGON UIC ON STACK CLR -(SP) ; INITIALISE QUEUE MEMBER NUMBER CLR CRTFLG ; ASSUME WE ARE NOT A CRT BIT #U2.CRT,U.CW2(R0) ; ARE WE A CRT? BEQ 3$ ; NO INC CRTFLG ; YES, SHOW IT IN FLAG 3$: BIT #ALMASK,LISTW ; WAS /AL EXPLICIT? BNE 5$ ; YES, GO AHEAD AS NORMAL BIT #U2.PRV,U.CW2(R0) ; NO, ARE WE PRIVILEGED? BEQ 5$ ; NO, LEAVE /AL SETTING ALONE BIT #ALMASK,CSIBLK+C.MKW1 ; WAS /-AL PRESENT (EXPLICITLY)? BNE 5$ ; YES, LEAVE /AL SETTING ALONE BIS #ALMASK,LISTW ; NO, SET /AL AS DEFAULT FOR PRIVILEGED USERS 5$: TST (R5) ; ANY MORE ENTRIES? BEQ 10$ ; NO CALL JFORM ; YES, FORMAT THIS JOB ENTRY ADD #,R5 ; POINT TO NEXT ENTRY BR 5$ ; SEE IF THERE'S ANY MORE 10$: CMP (SP)+,(SP)+ ; CLEAN THE STACK RETURN ; .PAGE .SBTTL PRELIMINARY JOB RELEASE PROCESSING ;+ ; ; *** PREL ; ; THIS ROUTINE IS CALLED TO PERFORM PRELIMINARY JOB RELEASE ; PROCESSING. IT CHECKS THE JOB NUMBER FOR VALIDITY, AND ; PRINTS AN ERROR MESSAGE IF IT IS NOT VALID. THE JOB IS ; RELEASED IF NOT ALREADY RELEASED. ; ;- PREL: BIT #RLMASK,RELSW ; /RL SPECIFIED? BEQ PRELR ; NO MOV LISTW,R1 ; ANY FURTHER COMMANDS? ADD TURNW,R1 ; ADD PRIVF,R1 ; BEQ 5$ ; ONLY NO IS GOOD CALLR AMBIG ; YES IS AMBIGUOUS COMMAND 5$: TST RLJOB ; CHECK JOB NUMBER BGT 10$ ; OK PRINT #ERR6,#ERR6SZ,FATAL ; INVALID JOB NUMBER BR PRELR ; AND RETURN 10$: CALL RLSJ ; RELEASE THE JOB PRELR: RETURN ; AND RETURN .PAGE .SBTTL PRELIMINARY JOB CANCEL PROCESSING ;+ ; ; *** PCAN ; ; THIS ROUTINE IS CALLED TO PERFORM PRELIMINARY JOB CANCEL ; PROCESSING. THE JOB NUMBER AND FLAG COMBINATION ARE ; CHECKED FOR VALIDITY. THE JOB IS REMOVED FROM THE ; BATCH QUEUE IF ALL IS OK. ; ;- PCAN: MOV SUBMW,R1 ; ANY FURTHER COMMANDS? ADD RELSW,R1 ; ADD LISTW,R1 ; ADD TURNW,R1 ; ADD PRIVF,R1 ; BEQ 10$ ; ONLY NO IS GOOD CALLR AMBIG ; COMMAND IS AMBIGUOUS 10$: BIT #CAMASK,CANCW ; /CA SPECIFIED? BEQ 30$ ; NO TST CAJOB ; CHECK JOB NUMBER BGT 20$ ; OK PRINT #ERR6,#ERR6SZ,FATAL ; INVALID JOB NUMBER BR PCANR ; AND RETURN 20$: CALLR $CANJ ; CANCEL THE JOB 30$: BIT #ABMASK,CANCW ; NO /CA, BUT /AB? BEQ PCANR ; NO PRINT #ERR7,#ERR7SZ,FATAL ; YES IS ERROR PCANR: RETURN ; .PAGE .SBTTL PRELIMINARY JOB SUBMIT PROCESSING ;+ ; ; *** PSUB ; ; THIS ROUTINE IS CALLED TO PERFORM PRELIMINARY JOB SUBMIT ; PROCESSING. THE SWITCHES AND THEIR ASSOCIATES VALUES ARE CHECKED ; FOR VALIDITY, AND THE RELEVANT STORAGE AREAS ARE INITIALISED. ; IMMEDIATE MODE EXECUTION IS HANDLED BY THIS ROUTINE. ; ;- PSUB: MOV RELSW,R1 ; CHECK FOR OTHER COMMAND CLASSES ADD LISTW,R1 ; ADD TURNW,R1 ; ADD PRIVF,R1 ; BEQ 1$ ; NONE IS GOOD CALLR AMBIG ; AMBIGUOUS COMMAND 1$: BIT #EXMASK,SUBMW ; EXPRESS JOB DESIRED? BEQ 102$ ; NO MOV $TKTCB,R0 ; YES, GET OUR TCB ADDRESS MOV T.UCB(R0),R0 ; AND OUR TI: UCB ADDRESS BIT #U2.PRV,U.CW2(R0) ; ARE WE PRIVILEGED? BNE 102$ ; YES PRINT #ERR13,#ERR13S,FATAL ; NO, PRIVILEGED COMMAND BR 6$ ; 102$: BIT #TLMASK,SUBMW ; WAS A TIME LIMIT SPECIFIED? BEQ 15$ ; NO TST TIMLIM ; YES, CHECK IT BGT 10$ ; POSITIVE IS GOOD 5$: PRINT #ERR9,#ERR9SZ,FATAL ; INVALID TIME LIMIT 6$: JMP PSUBR ; AND RETURN 10$: CMP #$TIMEX,TIMLIM ; TIME LIMIT TOO BIG? BLT 5$ ; YES 15$: ; REF. LABEL .IF DF M$$60M CMP TIMLIM,#60. ; JOB LONGER THAN 1 HOUR? BGE 1501$ ; IF GE YES, DO NOTHING CALL BMODE ; BATCH SYSTEM? BCS 1501$ ; IF CS NO, DO NOTHING MOV $TKTCB,R0 ; GET OUR TCB ADDRESS MOV T.UCB(R0),R0 ; AND OUR TI: UCB ADDRESS BIT #U2.PRV,U.CW2(R0) ; ARE WE PRIVILEGED? BNE 1501$ ; IF NE YES, DO NOTHING MOV #60.,TIMLIM ; MAKE IT 1 HOUR 1501$: ; REF. LABEL .ENDC ; DF M$$60M .IF DF L$$CNT BIT #LNMASK,SUBMW ; /LN SPECIFIED? BEQ 16$ ; NO TST LINES ; YES, SEE IF COUNT IS LEGAL BGT 152$ ; YES SO FAR 151$: PRINT #ERR29,#ERR29S,FATAL ; ILLEGAL LINE COUNT BR 6$ ; RETURN 152$: CMP #$MXLIN,LINES ; LINE COUNT TOO BIG? BLT 151$ ; YES CMP LINES,#$LWLIN ; LINE COUNT TOO SMALL? BGE 153$ ; NO MOV #$LWLIN,LINES ; YES, RESET IT 153$: ; REF. LABEL ; THIS BIT IS TO AVOID ANYTHING NASTY HAPPENING ; TO THE JOB WHEN IT IS LOGGING ON .ENDC 16$: BIT #PAMASK,SUBMW ; PASSWORD SPECIFIED? BNE 20$ ; YES TSTB PASFLG ; NO, DO WE ALREADY HAVE IT? BNE 20$ ; YES MOV #DOLLAR,QIOW+Q.IOPL+4 ; NO, NEED TO PROMPT PRINT #GETP,#GETPSZ ; PROMPT FOR PASSWORD MOV #IO.RNE,QIOW+Q.IOFN ; SET FOR READ WITH NO ECHO PRINT #PSWD,#7 ; READ PASSWORD BCS 19$ ; JUST IN CASE MOV #SPA,QIOW+Q.IOPL+4 ; RESET CARRIAGE CONTROL MOV #IO.WVB,QIOW+Q.IOFN ; RESET FUNCTION CODE TST IOSB+2 ; ANY CHARACTERS READ? BNE 20$ ; YES 19$: PRINT #ERR10,#ERR10S,FATAL ; ZERO IS BAD NEWS CALL CPSWD ; PASSWORD IS BAD, WE NEED IT AGAIN BR 6$ ; 20$: INCB PASFLG ; OK, WE'VE GOT A PASSWORD CMPB PSWD,#'* ; TRYING TO USE BATCH JOB'S PASSWORD? BNE 201$ ; NO, GO CHECK IT FOR LEGALITY CALL BMODE ; YES, ARE WE IN THE BATCH STREAM? BCC 21$ ; OK, GO AHEAD PRINT #ERR17,#ERR17S,FATAL ; CAN'T DEFAULT IF NOT BATCH CALL CPSWD ; SIGNAL PASSWORD AS BAD BR 35$ ;THAT'S IT 201$: CALL CHKPSW ; NOT BATCH OR NOT DEFAULT, CHECK PASSWORD BCS 19$ ; IF CS IT WAS ILLEGAL 21$: BIT #HUMASK,SUBMW ; /HU SPECIFIED? BEQ 25$ ; NO BIT #HFMASK,SUBMW ; YES, /HF ALSO? BEQ 30$ ; NO IS GOOD CALLR AMBIG ; /HU AND /HF IS NOT ALLOWED 30$: TST HUHR ; EXAMINE /HU HOUR BGE 32$ ; POSITIVE IS GOOD 31$: PRINT #ERR12,#ERR12S,FATAL ; INVALID HOLD SPECIFICATION 35$: JMP PSUBR ; 32$: TST HUHR ; HOLD HOUR POSITIVE OR ZERO? BLT 31$ ; NO IS ERROR CMP #24.,HUHR ; TOO BIG? BLE 31$ ; YES TST HUMIN ; EXAMINE /HU MINUTE BLT 31$ ; LT IS ERROR CMP #60.,HUMIN ; TOO BIG? BLE 31$ ; YES GTIM$S #TIMBUF ; GET CURRENT TIME MOV HUHR,R1 ; GET HOLD HOUR SUB TIMBUF+G.TIHR,R1 ; SUBTRACT CURRENT HOUR ASL R1 ; DOUBLE IT ASL R1 ; GET 4 X MOV R1,-(SP) ; SAVE 4X ON STACK ASL R1 ; GET 8 X ADD R1,(SP) ; 12 X ON STACK ASL R1 ; 16 X ADD R1,(SP) ; 28 X ON STACK ASL R1 ; 32 X ADD (SP)+,R1 ; R1 NOW HR DIFF. IN MINUTES ADD HUMIN,R1 ; CALC. HOLD TIME IN MINUTES SUB TIMBUF+G.TIMI,R1 ; HOLD TIME IN R1 BGT 33$ ; POSITIVE IS GOOD ADD #<24.*60.>,R1 ; POINT TO NEXT DAY 33$: MOV R1,HOLDTM ; STORE HOLD LIMIT BR 40$ ; 25$: BIT #HFMASK,SUBMW ; /HF SPECIFIED? .IF DF A$$HLD BNE 2511$ ; IF NE YES CALL BMODE ; ARE WE A BATCH JOB? BCS 40$ ; IF CS NO BIS #HFMASK,SUBMW ; YES, SET /HF SWITCH MOV #1,HFTIM ; FOR 1 MINUTE BR 37$ ; AND PROCESS IT 2511$: ; REF. LABEL .IFF BEQ 40$ ; NO .ENDC ; DF A$$HLD TST HFTIM ; HOLD IN DAYS OR MINUTES? BEQ 31$ ; ZERO IS INVALID BGT 37$ ; GT IS MINUTES NEG HFTIM ; MAKE IT POSITIVE MOV HFTIM,R0 ; AND PUT IT IN R0 CMP R0,#7 ; MORE THAN A WEEK? BGT 31$ ; YES IS ERROR MOV #<24.*60.>,R1 ; SET DAYS TO MINUTES CONVERSION FACTOR CALL $MUL ; CONVERT HOLD TIME TO MINUTES MOV R1,HFTIM ; AND REPLACE SPECIFIED VALUE 37$: MOV HFTIM,HOLDTM ; PUT IN PACKET 40$: BIT #IMMASK,SUBMW ; /IM SPECIFIED? BNE 42$ ; YES OPEN$R #$FDB,,#CSIBLK+C.DSDS ; NO, TRY TO OPEN JOB FILE BCC 50$ ; OK 41$: ERROR$ #ERR18,#ERR18A,FATAL ; ERROR AND FCS CODE JMP PSUBR ; RETURN 42$: CALL BMODE ; ARE WE IN A BATCH JOB? BCS 43$ ; ONLY NO IS ACCEPTABLE PRINT #ERR19,#ERR19S,FATAL ; SO SAY SO BR PSUBR ; 43$: OPEN$W #$FDB,,#CSIBLK+C.DSDS,,#BUF,#80. ; OPEN JOB FILE BCS 41$ ; IF ERROR PRINT #IMD,#IMDSZ ; SOLICIT COMMANDS 44$: DIR$ #IMMEDW ; PROMPT FOR A COMMAND DIR$ #IMMEDR ; READ COMMAND LINE BCS 55$ ; ERROR CMPB IOSB,#IE.EOF ; END OF FILE? BNE 45$ ; NO MOVB #IE.EOF,$FDB+F.ERR ; YES, SAY SO BR 55$ ; GO TELL USER 45$: MOV IOSB+2,R1 ; GET COUNT OF CHARACTERS READ BEQ 50$ ; ZERO MEANS END OF INPUT PUT$ #$FDB,,R1 ; WRITE TO FILE BCC 44$ ; OK, GO AGAIN 55$: ERROR$ #ERR20,#ERR20A ; I/O ERROR DELET$ #$FDB ; DELETE THE FILE BR PSUBR ; FORGET IT 50$: CLOSE$ #$FDB ; CLOSE FILE CMP $NUMQ,$MAXQ ; IS THE QUEUE FULL? BLT 54$ ; NO PRINT #ERR8,#ERR8SZ,FATAL ; YES, SAY SO BR PSUBR ; AND RETURN 54$: BIT #KEMASK,SUBMW ; WAS /KE SPECIFIED? BNE 60$ ; YES, /NO IS LEGAL BIT #NOMASK,SUBMW ; NO /KE, WAS THERE /NO? BEQ 60$ ; NO, OK TO SUBMIT JOB PRINT #ERR26,#ERR26S ; WARN USER THAT /NO IS IGNORED BIC #NOMASK,SUBMW ; CLEAR RELEVANT BIT IN SWITCH MASK 60$: CALL SUBJB ; SUBMIT THE JOB PSUBR: RETURN .PAGE .SBTTL PASSWORD CHECKING ROUTINE ;+ ; ; *** CHKPSW ; ; THIS ROUTINE CHECKS A PASSWORD FOR LEGALITY. ; VALID CHARACTERS ARE: ; (1) UPPER CASE A-Z ; (2) LOWER CASE A-Z (HELLO WILL CONVERT) ; (3) 0-9 ; ;- CHKPSW: MOV #PSWD,R0 ; GET ADDRESS OF PASSWORD BUFFER TSTB (R0) ; IS THE FIRST BYTE NULL? BEQ 30$ ; YES IS BAD NEWS MOV #6,R1 ; SET NUMBER OF BYTES TO CHECK 10$: TSTB (R0) ; NULL BYTE? BEQ 25$ ; YES IS END OF A GOOD PASSWORD CMPB (R0),#'0 ; NUMERIC? BLO 30$ ; LO IS BAD CMPB (R0),#'9 ; MAYBE BLOS 20$ ; YES, GOOD CMPB (R0),#'A ; UPPER CASE LETTER? BLO 30$ ; LO IS BAD CMPB (R0),#'Z ; MAYBE BLOS 20$ ; YES, GOOD CMPB (R0),#141 ; LOWER CASE LETTER? BLO 30$ ; LO IS BAD CMPB (R0),#172 ; MAYBE BHI 30$ ; ONLY LOS IS GOOD 20$: INC R0 ; POINT TO NEXT CHARACTER DEC R1 ; ANY MORE LEFT TO DO? BNE 10$ ; YES 25$: CLC ; PASSWORD CHECKS OUT OK BR CHKPR ; SO RETURN 30$: SEC ; PASSWORD IS BAD CHKPR: RETURN ; RETURN TO CALLER .PAGE .SBTTL ERROR CODE FORMATTING ROUTINE ;+ ; ; *** FCSERR ; ; THIS ROUTINE FORMATS THE FCS ERROR CODE ; ; INPUTS: ; R0 BUFFER POINTER ; R1 ERROR CODE ;- FCSERR: CLR R2 ; SET NO LEADING ZEROES CALL $CBDSG ; CONVERT TO DECIMAL (SIGNED) MOVB #DPT,(R0)+ ; INSERT DECIMAL POINT RETURN ; .PAGE .SBTTL BATCH JOB CHECK ROUTINE ;+ ; ; *** BMODE ; ; THIS ROUTINE IS CALLED TO CHECK IF WE ARE RUNNING FROM ; WITHIN A BATCH JOB, AS CERTAIN OPTIONS ARE ONLY LEGAL ; IN THIS STATE. ; ; R0 AND R1 ARE USED BY THIS ROUTINE ; OUTPUTS: ; CARRY CLEAR JOB IS RUNNING IN BATCH SYSTEM ; CARRY SET JOB IS NOT IN BATCH SYSTEM ; ;- BMODE: MOV $TKTCB,R0 ; GET OUR TCB ADDRESS MOV T.UCB(R0),R0 ; POINT TO OUR TI: UCB MOV U.DCB(R0),R1 ; THEN TO ITS DCB CMP D.NAM(R1),#"VT ; IS IT A VIRTUAL TERMINAL BNE 10$ ; NO CMP R0,#$VIRT0 ; YES, BUT IS IT VT0:? BNE 15$ ; ONLY NO IS GOOD 10$: SEC ; NO, SET CARRY BR BATCHR ; RETURN 15$: CLC ; OK BATCHR: RETURN ; .PAGE .SBTTL CLEAR PASSWORD FLAGS ROUTINE ;+ ; *** CPSWD ; ; THIS ROUTINE IS CALLED WHEN IT IS REQUIRED TO SIGNAL THAT ; A PASSWORD IS BAD. THE RELEVANT DATA AREAS ARE CLEARED. ; ;- CPSWD: CLRB PASFLG ; WE DON'T HAVE A PASSWORD ANY MORE MOV #PSWD,R0 ; GET ADDRESS OF PASSWORD BUFFER CLR (R0)+ ; ZERO OUT THE FOUR WORD FIELD CLR (R0)+ ; CLR (R0)+ ; CLR (R0)+ ; RETURN ; AND RETURN .PAGE .SBTTL JOB SUBMISSION ROUTINE ;+ ; *** SUBJB ; ; THIS ROUTINE PERFORMS THE ACTUAL JOB SUBMISSION. ; ALL PARAMETERS HAVE BEEN SET UP BY PSUB. ; ;- SUBJB: ; ENTRY POINT BIT #QQ.CLS,$QSTAT ; QUEUE IN CLOSEDOWN? BEQ 5$ ; PRINT #ERR28,#ERR28S,FATAL ; CAN'T ACCEPT JOB RIGHT NOW BR 17$ ; SO RETURN 5$: CLR PKTADR ; SET NO DSR PACKET FOUND MOV #Q.LGTH,R1 ; SET SIZE OF DSR PACKET NEEDED CALL $SWSTK,15$ ; SWITCH STACKS CALL $ALOCB ;; TRY TO GET A BLOCK BCS 10$ ;; ERROR MOV R0,PKTADR ;; OK, STORE PACKET ADDRESS 10$: RETURN ;; BACK TO TASK LEVEL 15$: MOV PKTADR,R5 ; GET PACKET ADDRESS BNE 20$ ; OK,WE GOT ONE PRINT #ERR14,#ERR14S,FATAL ; MEMORY ALLOCATION FAILURE 17$: JMP SUBJR ; SO RETURN 20$: INC $JOBN ; GET NEW JOB NUMBER CMP $JOBN,#77777 ; PASSED THE 5 DIGIT LIMIT? BLOS 21$ ; NO MOV #1,$JOBN ; YES, RESET JOB NUMBER 21$: MOV $JOBN,Q.JOBN(R5) ; AND STORE THE NEW JOBS NUMBER MOV $TKTCB,R4 ; GET OUR TCB ADDRESS MOV T.UCB(R4),R4 ; AND OUR TI: UCB ADDRESS MOV U.UIC(R4),Q.DUIC(R5) ; ASSUME DIRECTORY WAS DEFAULTED MOV U.LUIC(R4),Q.LUIC(R5) ; AND STORE LOGON UIC BITB #CS.DIF,CSIBLK+C.STAT ; EXPLICIT DIRECTORY? BEQ 30$ ; NO MOV #DIRD+2,R2 ; YES, POINT R2 TO ADDRESS OF DIRECTORY ; DESCRIPTOR+2. MOV #CSIBLK+C.DIRD+2,R3 ; MOV (R3),(R2) ; FILL IN DIRECTORY DESCRIPTOR MOV -(R3),-(R2) ; MOV R5,R3 ; POINT TO PLACE FOR BINARY DIRECTORY ADD #Q.DUIC,R3 ; CALL .ASCPP ; CONVERT DIRECTORY TO BINARY BCC 30$ ; ALL IS WELL MOV R5,R0 ; COPY PACKET ADDRESS MOV #Q.LGTH,R1 ; GET ITS LENGTH CALL $SWSTK,25$ ; SWITCH STACKS CALLR $DEACB ;; DEALLOCATE THE PACKET 25$: PRINT #ERR15,#ERR15S,FATAL ; BAD DIRECTORY STRING (SHOULD NOT HAPPEN) BR 17$ ; SO RETURN 30$: MOV #$FDB+F.FNB,R4 ; POINT TO FILENAME BLOCK MOV N.DVNM(R4),Q.DEVN(R5) ; FILL IN DEVICE NAME MOV N.UNIT(R4),Q.DEVU(R5) ; AND UNIT NUMBER MOV N.FNAM(R4),Q.FNAM(R5) ; FILL IN FILENAME MOV N.FNAM+2(R4),Q.FNAM+2(R5) ; MOV N.FNAM+4(R4),Q.FNAM+4(R5) ; MOV N.FTYP(R4),Q.FTYP(R5) ; FILL IN FILE TYPE MOV N.FVER(R4),R1 ; GET THE VERSION NUMBER BIT #NB.VER,N.STAT(R4) ; WAS THERE AN EXPLICIT VERSION? BNE 27$ ; YES BIT #EVMASK,SUBMW ; NO, BUT WAS /EV SPECIFIED? BNE 27$ ; YES CLR R1 ; CLEAR TO SIGNAL LATEST VERSION 27$: MOV R1,Q.FVER(R5) ; SET VERSION NUMBER MOV SUBMW,Q.MASK(R5) ; SET MASK WORD BIC #,Q.MASK(R5) ; CLEAR SUPERFLUOUS BITS (MAY BE USED ; BY SYSTEM FOR OTHER INFORMATION) CLR Q.TIME(R5) ; FILL IN TIME LIMIT MOV TIMLIM,Q.TIME+2(R5) ; MOV HOLDTM,Q.HOLD+2(R5) ; FILL IN HOLD LIMIT SXT Q.HOLD(R5) ; MAKE SURE HOLD CONDITION STICKS! BLT 28$ ; IF LT, NO NEED TO CONVERT TO TICKS MOV HOLDTM,R1 ; SET HOLD TIME MOV #<60.*TKPS>,R0 ; AND TICKS/MIN MULTIPLIER CALL $MUL ; MULTIPLY MOV R1,Q.HOLD+2(R5) ; SAVE LOW ORDER RESULT MOV R0,Q.HOLD(R5) ; AND HIGH ORDER RESULT 28$: MOV #PSWD,R1 ; POINT R1 TO PASSWORD STRING MOV R5,R3 ; AND POINT R3 TO PASSWORD LOCATION+4 ADD #Q.PSWD+4,R3 ; CLR (R3) ; ZERO IT OUT CLR -(R3) ; CLR -(R3) ; 281$: MOVB (R1)+,(R3)+ ; MOVE A BYTE OF THE PASSWORD BNE 281$ ; LOOP TO END OF PASSWORD CMPB PSWD,#'* ; DEFAULT PASSWORD? BNE 29$ ; NO MOV $TKTCB,R1 ; YES, WE NEED OUR TCB ADDRESS MOV T.UCB(R1),R1 ; TI: UCB ADDRESS MOV U.JPKT(R1),R1 ; GET OUR JOB PACKET ADDRESS MOV Q.PSWD(R1),Q.PSWD(R5) ; USE ITS PASSWORD MOV Q.PSWD+2(R1),Q.PSWD+2(R5) ; MOV Q.PSWD+4(R1),Q.PSWD+4(R5) ; 29$: ; REF. LABEL .IF DF P$$ARM CALL BPARM ; BUILD PARAMETER LIST BCC 291$ ; GOOD, WE MADE IT PRINT #ERR27,#ERR27S,FATAL ; ALLOCATION FAILURE, TELL THE USER CALL DPARM ; DELETE JOB PACKET AND ANY PARAMETER ; LIST THAT MAY HAVE BEEN CONSTRUCTED BR SUBJR ; AND RETURN .IFF CLR Q.PARM(R5) ; SET NO PARAMETERS .ENDC ; DF P$$ARM 291$: ; REF. LABEL .IF DF L$$CNT MOV LINES,Q.MXLN(R5) ; SET LINE COUNT FOR THIS JOB .IFF MOV #$DFLIN,Q.MXLN(R5) ; JUST IN CASE .IFTF CLR Q.LINE(R5) ; NO LINES OUTPUT YET .ENDC ; DF L$$CNT INC $NUMQ ; SHOW ONE MORE JOB IN QUEUE CALL $QLOCK ; LOCK BATCH SYSTEM LISTS CALL $LINK ; INSERT PACKET INTO JOB QUEUE CALL $QUNLK ; UNLOCK BATCH SYSTEM LISTS JMSG$ Q.JOBN(R5),,#MSG3A,NORET ; SEND JOB ACCEPTED MESSAGE SUBJR: RETURN ; .PAGE .SBTTL CLEAR PARAMETER FIELD ROUTINE ;+ ; *** CPARM ; ; THIS ROUTINE IS CALLED TO ZERO OUT THE FIELD IN WHICH A ; JOB PARAMETER IS TO BE DEPOSITED BY .CSI2 ; THE FIELD IS ONE BYTE LARGER THAN THE MAXIMUM PARAMETER SIZE ; TO ENSURE THAT A PARAMETER WILL ALWAYS END WITH A NULL BYTE. ; ; INPUTS: ; R0 ADDRESS OF PARAMETER FIELD ; ; OUTPUTS: ; R0,R1 USED ; ALL OTHER REGISTERS ARE PRESERVED ; ;- .IF DF P$$ARM CPARM: MOV #,R1 ; GET SIZE OF PARAMETER FIELD 10$: CLRB (R0)+ ; ZERO A BYTE DEC R1 ; ARE WE DONE YET? BNE 10$ ; IF NE NO RETURN ; DONE .ENDC ; DF P$$ARM .PAGE .SBTTL PARAMETER LIST ROUTINE ;+ ; *** LPARM ; ; THIS ROUTINE FORMATS A JOB'S PARAMETER LIST FOR THE QUEUE ; LISTING COMMANDS. ; WE HAVE TO MAKE A CHECK TO SEE IF THE PARAMETER LIST IS STILL ; THERE, IN CASE THE JOB'S STATUS HAS CHANGED RECENTLY. ; ; INPUTS: ; R0 BUFFER ADDRESS ; R5 POINTER TO JOB IN INTERNAL BUFFER FORM ; ; OUTPUTS: ; R0 UPDATED ; ALL OTHER REGISTERS PRESERVED ; ;- .IF DF P$$ARM LPARM: BIT #PMMASK,10(R5) ; DID JOB HAVE ANY PARAMETERS? BEQ LPARMR ; NO, JUST RETURN CALL $SKIPL ; SKIP TO NEXT LINE CALL $SWSTK,LPARMR ;; SWITCH STACKS MOV R0,R4 ;; SAVE BUFFER ADDRESS MOV 2(R5),R0 ;; GET JOB NUMBER CALL GETJB1 ;; LOCATE ITS PACKET BCS LPARMR ;; JUST IN CASE BIT #MRKEXE,Q.MASK(R1) ;; IS IT EXECUTING NOW (IT MIGHT BE!) BNE LPARMR ;; YES, NO CAN DO THEN MOV Q.PARM(R1),R2 ;; GET FIRST PARAMETER PACKET ADDRESS BEQ LPARMR ;; IF EQ THERE AREN'T ANY MOV R4,R0 ;; RESTORE BUFFER ADDRESS MOVB #HT,(R0)+ ;; INSERT "PM=" MOVB #'P,(R0)+ ;; MOVB #'M,(R0)+ ;; MOVB #'=,(R0)+ ;; MOVB #'(,(R0)+ ;; 10$: MOV R2,R3 ;; COPY PARAMETER PACKET ADDRESS TO R3 ADD #4,R3 ;; POINT TO ACTUAL PARAMETER 15$: MOVB (R3)+,(R0)+ ;; MOVE A BYTE OF THE PARAMETER BNE 15$ ;; IF NE THEN MORE TO MOVE DEC R0 ;; REMOVE NULL BYTE MOV (R2),R2 ;; POINT TO NEXT PARAMETER BEQ 20$ ;; IF EQ THERE ISN'T ONE MOVB #',,(R0)+ ;; INSERT A COMMA BR 10$ ;; THEN DO THE NEXT PARAMETER 20$: MOVB #'),(R0)+ ;; PUT IN TRAILING BRACKET MOV R0,2(SP) ;; SET UP USER R0 LPARMR: RETURN ;; RETURN TO USER LEVEL AND CALLER .ENDC ; DF P$$ARM .PAGE .SBTTL PARAMETER LIST BUILD ROUTINE ;+ ; *** BPARM ; ; THIS ROUTINE IS CALLED TO BUILD A PARAMETER LIST FOR A ; BATCH JOB. ; (1) THE JOB PACKET WORD AT OFFSET Q.PARM IS SET TO THE ADDRESS ; OF THE FIRST PARAMETER PACKET, OR ZERO IF THERE ARE ; NO PARAMETERS. ; (2) THE PARAMETER PACKETS FORM A FORWARD-LINKED LIST IN THE ; DYNAMIC STORAGE REGION. EACH PACKET IS IN THE SAME FORMAT ; AS THOSE CREATED BY THE STACK COMMAND. THIS MECHANISM ; ENSURES THAT POOL USE IS AS LOW AS POSSIBLE. ; ; INPUTS: ; R5 ADDRESS OF JOB DESCRIPTION PACKET ; ; OUTPUTS: ; R5 IS PRESERVED ; ALL OTHER REGISTERS ARE CHANGED ; CARRY CLEAR - PARAMETER LIST CONSTRUCTED OK. ; CARRY SET - POOL ALLOCATION FAILURE WHEN TRYING TO ; ALLOCATE A PACKET. ; ;- .IF DF P$$ARM BPARM: CLR Q.PARM(R5) ; ASSUME THAT THERE ARE NO PARAMETERS MOV R5,Q.PARM+2(R5) ; ADJUST SECOND WORD OF LISTHEAD... ADD #Q.PARM,Q.PARM+2(R5) ; ... TO POINT TO FIRST WORD BIT #PMMASK,SUBMW ; WERE ANY PARAMETERS SPECIFIED? BEQ BPARMC ; NO, JUST RETURN MOV R5,-(SP) ; SAVE R5 ON STACK ADD #Q.PARM,R5 ; POINT TO PARAMETER LIST LINK WORD MOV #PARM1,R4 ; GET ADDRESS OF FIRST PARAMETER FIELD CALL $GTPRM ; LINK INTO LIST BCS BPARMS ; IF CS ERROR MOV #PARM2,R4 ; REPEAT FOR OTHER PARAMETERS... CALL $GTPRM ; BCS BPARMS ; MOV #PARM3,R4 ; CALL $GTPRM ; BCS BPARMS ; MOV #PARM4,R4 ; CALL $GTPRM ; BCS BPARMS ; MOV (SP)+,R5 ; RESTORE R5 BPARMC: CLC ; CLEAR CARRY BIT BR BPARMR ; AND RETURN BPARMS: MOV (SP)+,R5 ; RESTORE R5 FIRST... SEC ; THEN SET CARRY BIT BPARMR: RETURN ; THEN RETURN .ENDC ; DF P$$ARM .PAGE .SBTTL PARAMETER LIST/JOB DELETION ROUTINE ;+ ; *** DPARM ; ; THIS ROUTINE IS CALLED WHEN AN ALLOCATION FAILURE ; OCCURS WHILE CONSTRUCTING A PARAMETER LIST. ANY ; PARAMETER PACKETS THAT MAY HAVE BEEN CONSTRUCTED ; ARE RETURNED TO THE POOL AND THE JOB DESCRIPTION ; PACKET IS DEALLOCATED. ; *NOTE* THIS ROUTINE IS ALSO CALLED BY $CANJ TO ; DELETE A JOB PACKET AND ITS ASSOCIATED PARAMETER ; PACKETS WHEN A JOB IS CANCELLED (ONLY IF PARAMETER ; LIST SUPPORT HAS BEEN INCLUDED) ; ; INPUTS: ; R5 JOB DESCRIPTION PACKET ADDRESS ; ;- .IF DF P$$ARM DPARM: CALL $SWSTK,DPARMR ; SWITCH STACKS 80$: MOV R5,R0 ;; SET R0 TO ADDRESS OF PARAMETER LISTHEAD ADD #Q.PARM,R0 ;; CALL $QRMVF ;; REMOVE A PARAMETER FROM THE LIST BCS 90$ ;; IF CS THEN THERE'S NO MORE MOV R1,R0 ;; COPY PACKET ADDRESS TO R0 MOV 2(R0),R1 ;; GET LENGTH OF THIS PACKET CALL $DEACB ;; RETURN IT TO THE POOL BR 80$ ;; SEE IF THERE'S ANY MORE 90$: MOV R5,R0 ;; COPY JOB PACKET ADDRESS TO R0 MOV #Q.LGTH,R1 ;; SET ITS LENGTH CALLR $DEACB ;; RETURN IT TO THE POOL AND THEN DPARMR: RETURN ; RETURN TO CALLER .ENDC ; DF P$$ARM .PAGE .SBTTL GET AND LINK PARAMETER ROUTINE ;+ ; *** $GTPRM ; ; THIS ROUTINE LINKS A PARAMETER INTO THE PARAMETER LIST. ; IF THE PARAMETER IS NULL, THE ENTRY IS SKIPPED, SO THAT ; THE FOLLOWING PARAMETER WILL TAKE ITS PLACE. ; ; INPUTS: ; R4 ADDRESS OF PARAMETER FIELD ; R5 ADDRESS OF PARAMETER PACKET LISTHEAD ; ; OUTPUTS: ; CARRY CLEAR: ; R0,R1,R4 USED ; R5 PRESERVED ; CARRY SET: ; MEMORY ALLOCATION FAILURE ; ;- .IF DF P$$ARM $GTPRM: MOV R4,R1 ; COPY PARAMETER FIELD ADDRESS TO R1 10$: TSTB (R1)+ ; LOOK FOR END OF FIELD BNE 10$ ; IF NE THEN NOT THERE YET SUB R4,R1 ; CALCULATE LENGTH OF FIELD (INCLUDING ; THE NULL BYTE) DEC R1 ; WAS THIS A NULL PARAMETER? BEQ GTPRMC ; YES, FORGET IT INC R1 ; NO, RESET BYTE COUNT ADD #4,R1 ; INCLUDE LINK WORD AND PACKET SIZE WORD MOV R1,-(SP) ; SAVE PACKET SIZE ON STACK CALL $SWSTK,30$ ; SWITCH STACKS CLR PKTADR ;; SET NO PACKET FOUND CALL $ALOCB ;; TRY TO GET A PACKET BCS 20$ ;; IF CS THEN ALLOCATION FAILURE MOV R0,PKTADR ;; STORE NEW PACKET ADDRESS 20$: RETURN ;; RETURN TO USER STATE 30$: MOV PKTADR,R0 ; DID WE GET A PACKET OK? BEQ GTPRMS ; NO, SET CARRY AND RETURN CLR (R0)+ ; ZERO LINK WORD MOV (SP)+,(R0)+ ; INSERT PACKET SIZE 40$: MOVB (R4)+,(R0)+ ; INSERT THE DATA BNE 40$ ; LOOP TO END CALL $SWSTK,GTPRMC ; SWITCH STACKS MOV R5,R0 ;; GET PARAMETER PACKET LISTHEAD ADDRESS MOV PKTADR,R1 ;; AND PARAMETER PACKET ADDRESS CALLR $QINSF ;; INSERT INTO PARAMETER LIST GTPRMC: CLC ; CLEAR CARRY BIT BR GTPRMR ; AND RETURN GTPRMS: SEC ; SET FAILURE GTPRMR: RETURN ; AND RETURN TO CALLER .ENDC ; DF P$$ARM .PAGE .SBTTL PRIVILEGED FUNCTIONS ROUTINE ;+ ; ; *** XPRIVF ; ; THIS ROUTINE EXECUTES THE PRIVILEGED FUNCTIONS /SAVE, /RESTORE, /QUESIZE, ; /RUNDOWN, /RUNJOBS, /STOP, /CLOSEDOWN AND /NEXTJOB ; THE IDENT FUNCTION /ID IS ALSO EXECUTED BY THIS ROUTINE. ; ;- XPRIVF: BIT #IDMASK,PRIVF ; /ID SWITCH PRESENT? BEQ PRIVF0 ; NO PRINT #IDENT,#IDSZ ; YES, SAY WHAT IT IS BIC #IDMASK,PRIVF ; CLEAR /ID SWITCH MASK TST PRIVF ; ANY PRIVILEGED FUNCTIONS LEFT? BNE PRIVF0 ; YES, DO THEM RETURN ; ELSE RETURN TO CALLER PRIVF0: MOV $TKTCB,R5 ; GET OUR TCB ADDRESS MOV T.UCB(R5),R5 ; AND OUR TI: UCB ADDRESS BIT #U2.PRV,U.CW2(R5) ; ARE WE PEIVILEGED? BNE 5$ ; YES PRINT #ERR13,#ERR13S ; PRIVILEGED COMMAND RETURN ; JUST RETURN 5$: BIT #SQMASK,PRIVF ; /SAVE (SAVE QUEUE)? BEQ 10$ ; NO DIR$ #QSAVE ; YES, SAVE THE QUEUE ;DJS STSE$S #SAVEFN ; WAIT FOR Q SAVE TO FINISH ;DJS 10$: BIT #RQMASK,PRIVF ; /RESTORE (RESTORE QUEUE)? BEQ 15$ ; NO PRINT #QRMSG, #QRMSLN ; YES--PRINT MESSAGE (RUN BATREST) ;DJS 15$: BIT #RJMASK,PRIVF ; /RUNJOBS (CLEAR RUNDOWN)? BEQ 20$ ; NO BIC #QQ.RDN!QQ.CLS!QQ.EXT,$QSTAT ; YES, CLEAR RUNDOWN CONDITION 20$: BIT #RDMASK,PRIVF ; /RUNDOWN (SET QUEUE IN RUNDOWN MODE)? BEQ 25$ ; NO BIS #QQ.RDN,$QSTAT ; YES, SET RUNDOWN MODE 25$: BIT #CLMASK,PRIVF ; /CLOSEDOWN (DON'T ACCEPT JOBS) BEQ 26$ ; NO BIS #QQ.CLS,$QSTAT ; YES, SET CLOSEDOWN MODE 26$: BIT #XTMASK,PRIVF ; /STOP (MARK BATMAN FOR EXIT)? BEQ 27$ ; NO BIS #QQ.RDN!QQ.EXT,$QSTAT ; YES, SET STOP AND RUNDOWN 27$: BIT #QSMASK,PRIVF ; /QUESIZE (CHANGE OR DISPLAY MAX. QUEUE SIZE)? BEQ 70$ ; NO CALL $QLOCK ; YES, LOCK BATCH SYSTEM LISTS MOV QUESIZ,R1 ; GET SWITCH VALUE BLE 50$ ; LE MEANS JUST DISPLAY CMP R1,$NUMQ ; CHECK AGAINST CURRENT QUEUE SIZE BGE 30$ ; IF GE WE MUSN'T CHANGE IT TO LOWER THAN ; IT ALREADY IS (OR SYSTEM WILL CRASH) MOV $NUMQ,R1 ; REPLACE REQUESTED WITH EXISTING SIZE 30$: MOV R1,$MAXQ ; RESET MAX. QUEUE SIZE 50$: MOV #BUF,R0 ; GET BUFFER ADDRESS FOR QUEUE SIZE DISPLAY MOV #QSTR,R1 ; GET ADDRESS OF LEADING TEXT STRING 55$: MOVB (R1)+,(R0)+ ; MOVE A BYTE BNE 55$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE MOV $MAXQ,R1 ; GET MAXIMUM QUEUE SIZE CALL $DECML ; FORMAT AS DECIMAL MOVB #COLON,(R0)+ ; INSERT A COLON MOV $NUMQ,R1 ; GET CURRENT QUEUE SIZE CALL $DECML ; FORMAT AS DECIMAL CALL $QUNLK ; UNLOCK BATCH SYSTEM LISTS SUB #BUF,R0 ; CALCULATE MESSAGE SIZE PRINT #BUF,R0 ; PRINT OUT THE DISPLAY 70$: BIT #NXMASK,PRIVF ; /NEXTJOB? BEQ PRIVFR ; NO CALL $QLOCK ; LOCK BATCH SYSTEM LISTS MOV NXJOB,R1 ; GET NUMBER OF NEXT JOB BLE 75$ ; IF LE THEN JUST DISPLAY IT MOV R1,$JOBN ; SET NEW VALUE 75$: MOV #BUF,R0 ; GET BUFFER ADDRESS MOV #NXJB,R1 ; AND ADDRESS OF LEADING TEXT STRING 76$: MOVB (R1)+,(R0)+ ; MOVE A BYTE BNE 76$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE MOV $JOBN,R1 ; GET NUMBER OF NEXT JOB CALL $OCTAL ; FORMAT AS OCTAL CALL $QUNLK ; UNLOCK BATCH SYSTEM LISTS SUB #BUF,R0 ; CALCULATE MESSAGE LENGTH PRINT #BUF,R0 ; AND TYPE IT OUT PRIVFR: RETURN ; AND RETURN TO CALLER .PAGE .SBTTL QUEUE LINK ROUTINE ;+ ; *** $LINK ; ; THIS ROUTINE LINKS THE NEWLY CREATED JOB PACKET INTO ; THE RELEVANT JOB QUEUE. EVERYTHING IS DONE AT SYSTEM LEVEL. ; ; INPUT: ; R5 JOB PACKET ADDRESS ; ;- $LINK: CALL $SWSTK,LINKR ; SWITCH STACKS MOV #$HOLDQ,R0 ;; ASSUME JOB IS ON HOLD MOV R5,R1 ;; COPY PACKET ADDRESS TO R1 BIT #HFMASK!HUMASK,Q.MASK(R5) ;; IS JOB TO BE ON HOLD? BNE 2$ ;; YES MOV #$EXPRQ,R0 ;; NO, ASSUME THAT IT'S EXPRESS BIT #EXMASK,Q.MASK(R5) ;; IS IT AN EXPRESS JOB? BEQ 5$ ;; NO, IT MUST BE A NORMAL JOB 2$: CALLR $QINSF ;; LINK INTO EXPRESS OR HOLD QUEUE 5$: MOV #$QUEHD,R1 ;; GET LISTHEAD ADDRESS (NORMAL JOBS) 10$: MOV R1,R0 ;; SAVE CURRENT ENTRY ADDRESS MOV (R0),R1 ;; GET ADDRESS OF NEXT ENTRY BEQ 20$ ;; IF EQ, END OF LIST CMP Q.TIME+2(R5),Q.TIME+2(R1) ;; DOES THE NEW ENTRY HAVE... ;; .. A HIGHER OR SAME TIME LIMIT? BGE 10$ ;; YES, IT DOESN'T GO HERE MOV R1,(R5) ;; LINK CURRENT TO NEW JOB ENTRY BR 30$ ;; 20$: MOV R5,$QUEHD+2 ;; SET ADDRESS OF NEW LAST ENTRY CLR (R5) ;; CLEAR LINK TO NEXT ENTRY 30$: MOV R5,(R0) ;; LINK NEW TO PREVIOUS ENTRY LINKR: RETURN ;; BACK TO USER LEVEL AND CALLER .PAGE .SBTTL GET JOB NUMBER ROUTINE ;+ ; *** GETJB ; ; THIS ROUTINE LOCATES THE JOB PACKET THAT MATCHES THE ; SPECIFIED JOB NUMBER. ; GETJB1 IS THE SAME, BUT DOES NOT SCAN THE EXECUTING JOBS QUEUE ; ; INPUT: ; R0 JOB NUMBER TO LOOK FOR ; OUTPUT: ; CARRY SET JOB NOT IN QUEUE ; CARRY CLEAR JOB FOUND ; R1 JOB PACKET ADDRESS ; R2 PACKET ADDRESS OF PREVIOUS JOB ; ;- GETJB: MOV #$CURJ,R1 ; JOB MIGHT BE EXECUTING, GET ; LISTHEAD ADDRESS CALL $QSRCH ; SEARCH FOR THE JOB BCC GETJR ; OK, WE GOT IT GETJB1: MOV #$QUEHD,R1 ; TRY NORMAL JOB QUEUE CALL $QSRCH ; SEARCH THE QUEUE BCC GETJR ; OK, WE GOT IT MOV #$HOLDQ,R1 ; IT MIGHT BE ON HOLD.. CALL $QSRCH ; IS IT? BCC GETJR ; YES MOV #$EXPRQ,R1 ; NO, TRY THE EXPRESS QUEUE CALL $QSRCH ; HOPE THE USER ISN'T WAITING FOR THIS GETJR: RETURN ; .PAGE .SBTTL QUEUE SEARCH ROUTINE ;+ ; *** $QSRCH ; ; THIS ROUTINE SEARCHES A SPECIFIED JOB QUEUE FOR A PACKET ; THAT MATCHES THE SPECIFIED JOB NUMBER. ; ; INPUT: ; R0 JOB NUMBER TO SEARCH FOR ; R1 LISTHEAD ADDRESS OF JOB QUEUE ; ; OUTPUT: ; CARRY SET JOB NOT IN QUEUE ; CARRY CLEAR JOB FOUND OK ; R1 ENTRY ADDRESS ; R2 PREVIOUS ENTRY ADDRESS ; R5 LISTHEAD ADDRESS ; ;- $QSRCH: MOV R1,R2 ; COPY LISTHEAD ADDRESS MOV R1,R5 ; ALSO TO R5 (NEEDED BY $CANJ) 5$: MOV (R2),R1 ; GET ADDRESS OF NEXT ENTRY BEQ 20$ ; IF EQ, END OF LIST CMP R0,Q.JOBN(R1) ; IS THIS THE RIGHT JOB? BEQ 10$ ; YES MOV R1,R2 ; NO, POINT TO NEXT ENTRY BR 5$ ; AND TRY IT 10$: CLC ; SET SUCCESSS BR QSRCHR ; AND RETURN 20$: SEC ; SET FAILURE QSRCHR: RETURN ; AND RETURN .PAGE .SBTTL ALL QUEUES COPY ROUTINE ;+ ; *** GETQU ; ; THIS ROUTINE COPIES THE CONTENTS OF ALL THE BATCH QUEUES INTO ; THE BUFFER LIBUF, UP TO BUFFER CAPACITY. ; ;- GETQU: MOV LSIZE,R5 ; SET THE LARGEST NUMBER OF JOBS WE.. ; CAN TAKE IN LIBUF MOV #LIBUF,R4 ; AND SET UP THE ADDRESS OF THE BUFFER MOV #$CURJ,R0 ; SET TO COPY EXECUTING JOBS CALL $QCOPY ; COPY THE QUEUE BCS 5$ ; BUFFER IS FULL MOV #$EXPRQ,R0 ; SET TO COPY EXPRESS QUEUE CALL $QCOPY ; AND DO IT BCS 5$ ; BUFFER IS FULL MOV #$QUEHD,R0 ; SET TO COPY NORMAL JOB QUEUE CALL $QCOPY ; AND DO IT BCS 5$ ; BUFFER IS FULL MOV #$HOLDQ,R0 ; SET TO COPY HOLD QUEUE CALL $QCOPY ; AND DO IT 5$: CLR (R4)+ ; SET END OF BUFFER FLAG RETURN ; THAT'S IT .PAGE .SBTTL SINGLE QUEUE COPY ROUTINE ;+ ; *** $QCOPY ; ; THIS ROUTINE COPIES THE CONTENTS OF A SINGLE JOB ; QUEUE TO THE INTERNAL BUFFER. IT IS CALLED INTERNALLY BY ; OTHER ROUTINES ONLY. ; ;- $QCOPY: MOV (R0),R0 ; GET NEXT QUEUE ENTRY ADDRESS BEQ 5$ ; IF EQ, END OF LIST CALL $ECOPY ; COPY THIS ENTRY DEC R5 ; CALCULATE REMAINING ENTRY SPACE BNE $QCOPY ; IF NE WE CAN DO MORE SEC ; BUFFER IS FULL BR QCOPYR ; SO RETURN 5$: CLC ; WE CAN TAKE MORE QCOPYR: RETURN ; RETURN .PAGE .SBTTL SINGLE QUEUE ENTRY COPY ROUTINE ;+ ; *** $ECOPY ; ; THIS ROUTINE COPIES A SINGLE QUEUE ENTRY INTO THE ; INTERNAL BUFFER. THE LINK WORD AND PASSWORD FIELDS ; ARE NOT COPIED. ; ; INPUT: ; R0 JOB PACKET ADDRESS ; R4 LIST BUFFER ADDRESS ; OUTPUT: ; R4 UPDATED ; ALL OTHER REGISTERS PRESERVED ;- $ECOPY: MOV R0,-(SP) ; SAVE PACKET POINTER TST (R0)+ ; SKIP LINK WORD MOV (R0)+,(R4)+ ; COPY VT: UCB ADDRESS MOV (R0)+,(R4)+ ; COPY JOB NUMBER MOV (R0)+,(R4)+ ; AND LOGON UIC MOV (R0)+,(R4)+ ; AND DIRECTORY UIC MOV (R0)+,(R4)+ ; AND MASK WORD MOV (R0)+,(R4)+ ; AND DEVICE NAME MOV (R0)+,(R4)+ ; AND UNIT NUMBER MOV (R0)+,(R4)+ ; COPY... MOV (R0)+,(R4)+ ; ... FILE.... MOV (R0)+,(R4)+ ; ... NAME MOV (R0)+,(R4)+ ; AND FILE TYPE MOV (R0)+,(R4)+ ; AND VERSION NUMBER ADD #6,R0 ; SKIP THE PASSWORD MOV (R0)+,(R4)+ ; COPY JOB TIME MOV (R0)+,(R4)+ ; MOV (R0)+,(R4)+ ; AND HOLD TIME MOV (R0)+,(R4)+ ; MOV (R0)+,(R4)+ ; COPY PARAMETER LIST POINTER MOV (R0)+,(R4)+ ; MOV (R0)+,(R4)+ ; LINES OUTPUT SO FAR MOV (R0)+,(R4)+ ; AND LINE LIMIT MOV (SP)+,R0 ; RESTORE PACKET POINTER RETURN ; AND RETURN .PAGE .SBTTL QUEUE MEMBER FORMATTING ROUTINE ;+ ; *** JFORM ; ; THIS ROUTINE IS CALLED TO FORMAT A JOB ENTRY FOR THE ; QUEUE LISTING COMMANDS. THE ENTRY IS SKIPPED IF IT DOES NOT ; BELONG TO THE CURRENT USER AND /AL WAS NOT SPECIFIED IN ; THE COMMAND LINE. ; ; INPUTS: ; R5 POINTER TO JOB DESCRIPTION PACKET ; (INTERNAL FORMAT, NOT POOL FORMAT) ; 2(SP) PREVIOUS QUEUE MEMBER NUMBER ; 4(SP) LOGON UIC OF CURRENT USER ; ; OUTPUTS: ; R5 PRESERVED ; 2(SP) UPDATED TO NEXT NUMBER ; ;- JFORM: BIT #MRKEXE,10(R5) ; IS THIS JOB RUNNING? BNE 5$ ; YES, DON'T UPDATE QUEUE MEMBER NUMBER INC 2(SP) ; NO, SHOW THAT IT'S WAITING FOR ; EXECUTION (AAAAAAAAAAGH) 5$: MOV #BUF,R0 ; SET BUFFER ADDRESS BIT #ALMASK,LISTW ; DO WE WANT ALL THE JOBS? BNE 10$ ; YES WE DO CMP 4(SP),4(R5) ; NO, DOES THIS JOB BELONG TO US? BEQ 10$ ; YES RETURN ; NO, JUST RETURN 10$: MOV 2(SP),R1 ; GET QUEUE MEMBER NUMBER CALL $DECML ; CONVERT TO DECIMAL TAB 5. ; SPACE TO COLUMN FIVE MOV 2(R5),R1 ; GET THE JOB NUMBER CALL $OCTAL ; CONVERT TO OCTAL TAB 12. ; NEXT FIELD STARTS IN COLUM 12. MOV 4(R5),R3 ; GET LOGON UIC CALL $FUIC ; FORMAT UIC AS [G,M] TAB 22. ; MOVE OVER TO COLUMN 22. MOVB 12(R5),(R0)+ ; MOVE IN DEVICE NAME (USE TWO MOVB 13(R5),(R0)+ ; MOVB'S BECAUSE THE BUFFER MAY ; NOT BE WORD ALIGNED) MOV 14(R5),R1 ; GET THE DEVICE NUMBER CALL $OCTAL ; CONVERT TO OCTAL MOVB #COLON,(R0)+ ; DEVICE/UIC SEPARATOR MOV 6(R5),R3 ; GET DIRECTORY UIC CALL $FUIC ; FORMAT AS [G,M] ADD #16,R5 ; POINT R5 TO FILENAME CALL $RAD50 ; FILENAME, CHARS. 1-3 CALL $RAD50 ; FILENAME, CHARS. 4-6 CALL $RAD50 ; FILENAME, CHARS. 7-9 MOVB #DPT,(R0)+ ; INSERT NAME/TYPE SEPARATOR CALL $RAD50 ; FILETYPE MOV (R5)+,R1 ; GET VERSION NUMBER BEQ 101$ ; IF EQ LATEST VERSION, DON'T PRINT ;0 MOVB #SEMI,(R0)+ ; TYPE/VERSION SEPARATOR CALL $OCTAL ; FORMAT AS OCTAL 101$: SUB #30,R5 ; POINT BACK TO START OF PACKET BIT #FUMASK,LISTW ; DO WE WANT FULL LISTING? BEQ TYPE ; NO, THAT'S IT THEN TAB 52. ; NEXT FIELD STARTS IN COL. 52. MOVB #'T,(R0)+ ; "T=" FOR TIME MOVB #'=,(R0)+ ; MOV R5,R1 ; POINT R1 TO JOB TIME ADD #30,R1 ; BIT #MRKEXE,10(R5) ; IS THE JOB RUNNING? BEQ 15$ ; NO ;FORMAT EXECUTING JOB CALL $JBTIM ; FORMAT JOB TIME (LIMIT) MOV R1,-(SP) ; SAVE R1 TAB 60. ; MOVE TO COLUMN 60. MOV (SP)+,R1 ; RESTORE R1 MOV #USED,R3 ; GET ADDRESS OF TEXT STRING 13$: MOVB (R3)+,(R0)+ ; MOVE A BYTE OF IT BNE 13$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE CMP (R1)+,(R1)+ ; NOW POINT TO JOB TIME USED CALL $JBTIM ; AND FORMAT IT MOVB #'),(R0)+ ; INSERT CLOSING BRACKET CALL $SKIPL ; MAKE NEW LINE IF TI: NOT WIDE ENOUGH .IF DF L$$CNT CALL $PUTLN ; PUT IN "LINES=" STRING MOVB #'(,(R0)+ ; AND OPENING BRACKET MOV 46(R5),R1 ; GET MAXIMUM LINE COUNT CALL $DECML ; FORMAT AS DECIMAL MOVB #'/,(R0)+ ; INSERT A SLASH MOV 44(R5),R1 ; GET CURRENT LINE COUNT CALL $DECML ; FORMAT AS DECIMAL MOVB #'),(R0)+ ; INSERT A TRAILING BRACKET .ENDC ; DF L$$CNT MOVB #HT,(R0)+ ; PUT IN A TAB MOV (R5),R3 ; GET VT: UCB ADDRESS CALL $FMTDV ; FORMAT DEVICE NAME ;PRINT OUT RESTARTABLE IF JOB IS.. BIT #RSMASK,10(R5) ; RESTARTABLE? BEQ TYPE ; NO, PRINT IT OUT MOVB #HT,(R0)+ ; PUT IN A TAB MOV #RSSTR,R1 ; YES, GET "RESTARTABLE" STRING ADDR 14$: MOVB (R1)+,(R0)+ ; MOVE A BYTE BNE 14$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE BR TYPE ; PRINT IT OUT ;FORMAT FOR JOB NOT EXECUTING 15$: MOV 32(R5),R1 ; GET TIME LIMIT CALL $DECML ; FORMAT AS DECIMAL MOVB #'M,(R0)+ ; AND "M" FOR MINUTES BIT #HFMASK!HUMASK,10(R5) ; JOB ON HOLD? BEQ 20$ ; NO TAB 60. ; YES, MOVE TO COLUMN 60. MOVB #'H,(R0)+ ; PUT "H=" FOR HOLD MOVB #'=,(R0)+ ; MOV R5,R1 ; POINT R1 TO HOLD TIME ADD #34,R1 ; CALL TFORM ; FORMAT HOLD TIME 20$: ; REF. LABEL .IF DF L$$CNT ! P$$ARM CALL $SKIPL ; IF TI: IS NOT WIDE ENOUGH .IFF BIT #EXMASK,10(R5) ; EXPRESS JOB BEQ 21$ ; NO CALL $SKIPL ; YES, MOVE TO NEXT LINE 21$: ; REF. LABEL .ENDC ; DF L$$CNT ! P$$ARM .IF DF L$$CNT CALL $PUTLN ; INSERT "LINES=" MOV 46(R5),R1 ; GET MAXIMUM LINE COUNT CALL $DECML ; FORMAT AS DECIMAL .ENDC ; DF L$$CNT BIT #EXMASK,10(R5) ; EXPRESS JOB? BEQ 26$ ; NO MOV #XPRS,R1 ; YES, GET "EXPRESS" STRING ADDRESS 25$: MOVB (R1)+,(R0)+ ; MOVE A BYTE BNE 25$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE 26$: .IF DF P$$ARM CALL LPARM ; FORMAT PARAMETER LIST .ENDC ; DF P$$ARM ;OUTPUT THE ENTIRE FORMATTED MESSAGE TYPE: CALL $CRT ; TERMINATE LINE FOR A CRT SUB #BUF,R0 ; CALCULATE LENGTH OF MESSAGE PRINT #BUF,R0 ; TYPE IT OUT JFORMR: RETURN ; AND RETURN .PAGE .SBTTL ROUTINE TO SKIP LINE IN LIST ;+ ; *** $SKIPL ; ; THIS ROUTINE TYPES OUT THE CURRENT LINE AND SKIPS TO A NEW ; LINE IN THE LISTING COMMANDS IF TI: IS NOT WIDE ENOUGH ; ;- $SKIPL: TSTB ERRFLG ; 132. COLUMN LISTING? BEQ SKIPLR ; YES CALL $CRT ; TERMINATE LINE FOR A VT52 SUB #BUF,R0 ; NO, GET LENGTH SO FAR PRINT #BUF,R0 ; TYPE IT OUT MOV #BUF,R0 ; RESET BUFFER POINTER MOVB #SPA,(R0)+ ; BLANK OUT COLS 1-3 MOVB #SPA,(R0)+ ; MOVB #SPA,(R0)+ ; ADD #8.,R0 ; LET DISPLAY INCLUDE JOB NUMBER SKIPLR: RETURN ; .PAGE .SBTTL CRT LINE TERMINATION ROUTINE ;+ ; *** $CRT ; ; THIS ROUTINE TERMINATES THE BUFFER WITH AN ESCAPE SEQUENCE FOR THE ; VT52 TO CLEAR TO END OF LINE. THIS IS USEFUL IF THIS TASK IS USED ; IN A COMMAND FILE TO PROVIDE A QUEUE DISPLAY FEATURE. ; ; INPUT: ; R0 BUFFER POINTER ; ; OUTPUT: ; R0 UPDATED ; ALL OTHER REGISTERS PRESERVED ; ;- $CRT: TST CRTFLG ; ARE WE A CRT? BEQ CRTR ; NO MOVB #33,(R0)+ ; YES, INSERT K MOVB #113,(R0)+ ; CRTR: RETURN ; RETURN TO CALLER .PAGE .SBTTL COLUMN SPACING ROUTINE ;+ ; *** TTAB ; ; THIS ROUTINE PUTS SPACES IN THE BUFFER UNTIL A DESIRED ; COLUMN IS OBTAINED. ; ; INPUTS: ; R0 CURRENT BUFFER POSITION ; R1 DESIRED POSITION ; ;- TTAB: CMP R0,R1 ; ALREADY THERE? BHIS TABR ; YES, JUST RETURN MOVB #SPA,(R0)+ ; NO, PUT IN A SPACE BR TTAB ; KEEP GOING TABR: RETURN ; RETURN TO CALLER .PAGE .SBTTL LINES= STRING MOVING ROUTINE ;+ ; *** $PUTLN ; ; THIS ROUTINE MOVES THE LINES= STRING FOR THE JFORM ROUTINE ; ; INPUT: ; R0 BUFFER ADDRESS ; ; OUTPUT: ; R0 UPDATED ; R1 USED ; ;- .IF DF L$$CNT $PUTLN: MOV #LCNT,R1 ; GET STRING ADDRESS 10$: MOVB (R1)+,(R0)+ ; MOVE A BYTE BNE 10$ ; LOOP TO END DEC R0 ; REMOVE NULL BYTE RETURN ; AND RETURN TO CALLER .ENDC ; DF L$$CNT .PAGE .SBTTL CPU AND I/O TIME FORMATTING ROUTINE ;+ ; *** $JBTIM ; ; THIS ROUTINE IS CALLED TO FORMAT A DOUBLE PRECISION ; TIME IN TICKS TO MINUTES IN THE FORM N.NM WHEN IT IS ; KNOWN THAT THE MINUTES RESULT WILL FIT INTO A ; 16-BIT WORD. ; ; INPUTS: ; R0 BUFFER POINTER ; R1 POINTER TO DOUBLE PRECISION TIME IN TICKS ; OUTPUTS: ; R0 UPDATED ; R1 PRESERVED ; ;- $JBTIM: MOV R1,-(SP) ; SAVE R1 MOV R0,-(SP) ; SAVE R0 MOV 2(R1),R2 ; GET LOW ORDER TICKS MOV (R1),R1 ; GET HIGH ORDER TICKS MOV #<6*TKPS>,R0 ; GET NUMBER OF TICKS PER TENTH MINUTE CALL $DDIV ; CONVERT MOV (SP)+,R0 ; RESTORE BUFFER POINTER MOV R2,R1 ; PUT RESULT IN R1 CLR R2 ; SET NO LEADING ZEROES CALL $CBDMG ; CONVERT TO DECIMAL MOVB -(R0),1(R0) ; MOVE OVER TENTHS DIGIT MOVB #DPT,(R0)+ ; INSERT A DECIMAL POINT INC R0 ; STEP PAST TENTHS DIGIT MOVB #'M,(R0)+ ; AND PUT IN AN "M" FOR MINUTES MOV (SP)+,R1 ; RESTORE R1 RETURN ; AND RETURN .PAGE .SBTTL TIME FORMAT ROUTINE ;+ ; *** TFORM ; ; THIS ROUTINE FORMATS A DOUBLE PRECISION TIME IN ; CLOCK TICKS TO HOURS IN THE FORMAT H.HH. ; ; INPUT: ; R0 - BUFFER POINTER ; R1 - POINTER TO DOUBLE PRECISION TIME IN TICKS ; ; OUTPUT: ; R0 - UPDATED BUFFER POINTER ; R1 PRESERVED ; ;- TFORM: MOV R1,-(SP) ; SAVE R1 MOV R0,-(SP) ; SAVE R0 MOV 2(R1),R2 ; GET LOW ORDER TICKS MOV (R1),R1 ; GET HIGH ORDER TICKS MOV #<36.*TKPS>,R0 ; SET DIVISOR FOR CONVERT CALL $DDIV ; CONVERT MOV (SP)+,R0 ; RESTORE R0 MOV R2,-(SP) ; SAVE LOW RESULT MOV R1,-(SP) ; SAVE HIGH RESULT BEQ 10$ ; BRANCH IF ZERO 5$: MOV SP,R1 ; POINT R1 TO NUMBER ON STACK CLR R2 ; NO LEADING ZEROES CALL $CDDMG ; FORMAT THE TIME MOVB -(R0),1(R0) ; MOVE OVER A CHARACTER MOVB -(R0),1(R0) ; AND ANOTHER MOVB #DPT,(R0)+ ; INSERT A DECIMAL POINT ADD #2,R0 ; POINT PAST NUMBER BR TFORMR ; CLEAN UP AND RETURN 10$: CMP R2,#10. ; TIME TOO SMALL? BGE 5$ ; NO MOVB #DPT,(R0)+ ; YES, PUT IN A POINT MOVB #'0,(R0)+ ; AND A ZERO ADD #'0,R2 ; BIAS RESULT TO CHARACTER MOVB R2,(R0)+ ; AND PUT IT IN TFORMR: CMP (SP)+,(SP)+ ; CLEAN THE STACK MOVB #'H,(R0)+ ; ADD "H" FOR HOURS MOV (SP)+,R1 ; AND RESTORE R1 RETURN ; THAT'S IT .PAGE .SBTTL PRIVILEGE CHECK ROUTINE ;+ ; *** $PRIV ; ; THIS ROUTINE CHECKS THAT THE USER HAS THE DESIRED ACCESS ; TO THE SPECIFIED JOB. IF NOT, AN ERROR MESSAGE IS ; PRINTED. A PRIVILEGED USER CAN ALTER THE STATE OF ANY ; JOB. A NON-PRIVILEGED USER CAN ALTER THE STATE OF ; JOBS SUBMITTED BY HIM ONLY. ; ; INPUT: ; R1 POINTS TO JOB PACKET TO CHECK ACCESS FOR ; ; OUTPUT: ; R4 IS USED, OTHER REGISTERS PRESERVED ; ;- $PRIV: MOV $TKTCB,R4 ; GET OUR TCB ADDRESS MOV T.UCB(R4),R4 ; GET OUR TI: UCB ADDRESS CMP Q.LUIC(R1),U.LUIC(R4) ; LOGON UIC'S MATCH? BEQ PRIV1 ; YES, OK BIT #U2.PRV,U.CW2(R4) ; NO, BUT ARE WE PRIVILEGED? BNE PRIV1 ; YES, IT'S OK THEN PRINT #ERR24,#ERR24SZ ; PRINT THE ERROR MESSAGE SEC ; SET FAILURE BR PRIVR ; AND RETURN PRIV1: CLC ; SET SUCCESS PRIVR: RETURN ; AND RETURN .PAGE .SBTTL RELEASE JOB ROUTINE ;+ ; *** RLSJ ; ; THIS ROUTINE IS CALLED TO REMOVE A JOB FROM HOLD ; STATUS. ALL NECESSARY PARAMETERS ARE ASSUMED TO ; HAVE BEEN SET UP BEFORE ENTRY TO THIS ROUTINE. ; ;- RLSJ: MOV RLJOB,R0 ; GET THE JOB NUMBER CALL GETJB ; LOCATE ITS JOB PACKET BCC 5$ ; OK JMSG$ RLJOB,,#ERR22A ; JOB NOT IN QUEUE 5$: CALL $PRIV ; DO WE HAVE ACCESS TO THIS JOB? BCS RLSJR ; NO BIT #MRKEXE,Q.MASK(R1) ; IS THE JOB RUNNING? BEQ 10$ ; NO JMSG$ RLJOB,,#ERR21A ; ERROR, JOB IS RUNNING 10$: BIT #HFMASK!HUMASK,Q.MASK(R1) ; IS THE JOB ON HOLD? BNE 15$ ; YES JMSG$ RLJOB,,#ERR23A ; JOB NOT IN HOLD 15$: MOV #-1,Q.HOLD(R1) ; FORGET ANY REMAINING HOLD TIME BIC #HFMASK!HUMASK,Q.MASK(R1) ; AND CLEAR HOLD BITS MOV (R1),(R2) ; CLOSE UP LIST AND REMOVE JOB BNE 20$ ; IF NE THEN NOT AT END OF LIST MOV R2,$HOLDQ+2 ; END OF LIST SO CORRECT LISTHEAD 20$: MOV R1,R5 ; COPY PACKET ADDRESS TO R5 CALL $LINK ; AND LINK INTO RIGHT JOB QUEUE JMSG$ RLJOB,,#MSG1A,NORET ; TELL THE USER THAT WE REMOVED IT RLSJR: RETURN ; THAT'S IT .PAGE .SBTTL JOB CANCEL ROUTINE ;+ ; *** $CANJ ; ; THIS ROUTINE IS CALLED TO REMOVE A JOB FROM THE QUEUE ; PERMANENTLY. IF THE SPECIFIED JOB IS RUNNING, IT IS MARKED FOR ; ABORT ONLY IF THE /AB SUBSWITCH WAS USED. ALL NECESSARY INPUT ; DATA IS ASSUMED TO HAVE BEEN SET UP PRIOR TO CALLING THIS ; ROUTINE. THE JOB PACKET IS DEALLOCATED AND RETURNED TO THE ; SYSTEM POOL. ; ;- $CANJ: MOV CAJOB,R0 ; GET JOB NUMBER CALL GETJB ; LOCATE JOB PACKET BCC 5$ ; OK JMSG$ CAJOB,,#ERR22A ; JOB NOT IN QUEUE 5$: CALL $PRIV ; ARE WE ALLOWED ACCESS TO THIS JOB? BCS CANJR ; NO BIT #MRKEXE,Q.MASK(R1) ; IS THE JOB RUNNING? BEQ 15$ ; NO BIT #ABMASK,CANCW ; YES, DID WE SPECIFY /AB? BNE 10$ ; YES JMSG$ CAJOB,,#ERR21A ; NO, SAY THAT JOB IS RUNNING 10$: BIS #MRKABO,Q.MASK(R1) ; MARK JOB FOR ABORT. ; BATMAN CHECKS THIS MARKER AND ABORTS ; THE JOB IF NECESSARY JMSG$ CAJOB,,#MSG2A ; JOB MARKED FOR ABORT 15$: DEC $NUMQ ; YES, MAKE IT ONE JOB LESS IN QUEUE MOV (R1),(R2) ; YES, CLOSE UP LIST AND REMOVE JOB BNE 20$ ; IF NE THEN NOT AT END OF LIST MOV R2,2(R5) ; CORRECT LISTHEAD IF AT END OF QUEUE 20$: ; REF. LABEL .IF DF P$$ARM MOV R1,R5 ; COPY JOB PACKET ADDRSS TO R5 CALL DPARM ; DELETE JOB PACKET AND ALL OF ITS ; PARAMETERS .IFF MOV R1,R0 ; COPY PACKET ADDRESS TO R0 MOV #Q.LGTH,R1 ; SET LENGTH TO DEALLOCATE CALL $SWSTK,25$ ; SWITCH STACKS CALLR $DEACB ;; DEALLOCATE PACKET AND RETURN TO USER LEVEL .ENDC ; DF P$$ARM 25$: JMSG$ CAJOB,,#MSG6A,NORET ; JOB CANCELLED OK CANJR: RETURN ; THAT'S IT. .PAGE .SBTTL JOB NUMBER MESSAGE ROUTINE ;+ ; *** JBMSG ; ; THIS ROUTINE CONSTRUCTS A MESSAGE THAT REQUIRES THE ; INSERTION OF AN OCTAL JOB NUMBER. THE MESSAGE IS PRINTED ; OUT WHEN COMPLETE. ; THE MESSAGE FORMAT IS: ; ; ; ; ; INPUTS: ; R1 BINARY JOB NUMBER TO BE INCLUDED ; R2 ADDRESS OF LEADING MESSAGE ; R3 ADDRESS OF TRAILING MESSAGE ; LEADING AND TRAILING MESSAGES SHOULD BE ; TERMINATED WITH A ZERO BYTE ; ; OUTPUTS: ; R0,R2,R3 USED ; ;- JBMSG: MOV #BUF,R0 ; GET RIGHT PLACE TO PUT FULL MESSAGE 5$: MOVB (R2)+,(R0)+ ; MOVE A BYTE OF LEADING MESSAGE BNE 5$ ; LOOP UNTIL ALL DONE DEC R0 ; REMOVE NULL BYTE CALL $OCTAL ; FORMAT THE BINARY NUMBER AS OCTAL 10$: MOVB (R3)+,(R0)+ ; MOVE A BYTE OF TRAILING MESSAGE BNE 10$ ; LOOP UNTIL ALL DONE DEC R0 ; REMOVE NULL BYTE SUB #BUF,R0 ; CALCULATE MESSAGE LENGTH PRINT #BUF,R0 ; PRINT IT OUT RETURN ; AND RETURN TO CALLER .END $BATEP