.PSECT MID .TITLE MID .IDENT /V1.2/ .ENABL LC .NLIST BEX .SBTTL MIDNIGHT.MAC -- Documentation ;======================================================================== ; MIDNIGHT.MAC ; ; Phil Hoffman ; Department of Chemistry ; Michigan State University ; East Lansing, MI 48824 ; 8-April-1983 ; ; V1.1 No time out set for privileged request. ; ; V1.2 Calls to $LOCKL and $UNLKL removed and replaced w/ direct switch ; to system state. ;======================================================================== ; MIDNIGHT.MAC is a small utility program, allowing both privileged and ; non-privileged users, a modified form of batch stream access to the ; system. It was originally designed to run CPU-intensive programs ; during the middle of the night (hence, its moniker), thereby eliminating ; all sorts of screaming and hollering from those who were trying to ; run interactive tasks at the same time. Furthermore, it provides a ; very simple means for running system diagnostics, disk squishers, etc. ; at regular intervals without having to hassle the clock queue. ; The actual time at which MIDNIGHT is run and its rescheduling interval ; is entirely at the operator's discression. ; ; Any user may gain access to MIDNIGHT by creating an indirect command ; file called MIDNIGHT.CMD in his/her directory. When MIDNIGHT is ; activated, it scans all directories on a selected list of system ; devices (supplied at assembly time) for MIDNIGHT.CMD files and ; executes them. File protection and privilege are modified for ; each MIDNIGHT.CMD executed, in accordance with the directory in ; which it was contained. ; ; The tasks spawned by MIDNIGHT are submitted from a system terminal ; of the operator's choosing (again, this is decided at assembly time). ; In many instances, it may be best to ascribe this function to a terminal ; which is not actually connected or otherwise inaccessable, since it ; is logged on, and at times privileged, while MIDNIGHT is active. The ; console may also be redirected to this terminal, if desired, while ; MIDNIGHT is active. ; ; To prevent MIDNIGHT from slopping-over into morning or perhaps afternoon, ; assembly time options provide for time-outs on all spawned tasks. ; Similarly, there is an assembly time option for renaming MIDNIGHT.CMD ; files to MIDNIGHT.DON files after they have been executed, thereby ; preventing the same file from executing every night without ; direct user intervention. Both of these options may be "split" for ; command files in privileged vs. non-privileged directories. ; ; MIDNIGHT also produces a log file indicating all command files run, ; internal errors encountered, time-out errors, and tasks which were ; aborted in accordance with those time-outs. ; ; The above options may be specified in the USER SELECTED OPTIONS ; section of this code. ;------------------------------------------------------------------------ .PAGE .SBTTL Macro Calls and Definitions ;------------------------------------------------------------------------ ; Macro calls and definitions ;------------------------------------------------------------------------ .MCALL FSRSZ$,FDBDF$,FDOP$A,FDBF$A,FDAT$A,FDRC$A,FINIT$ .MCALL OPEN$W,PUT$,CLOSE$ .MCALL IOERR$,UCBDF$,TCBDF$ .MCALL SPWN$,MRKT$,WTSE$,CMKT$S,SETF$,ABRT$,WSIG$S .MCALL DIR$,ASTX$S,EXIT$S,GTIM$S ; UCBDF$ ; Define the UCB offsets IOERR$ ; Define IO error codes TCBDF$ ; Define Task Control Block codes ; .PSECT MID ;------------------------------------------------------------------------ ; The Macros PUSH and POP facilitate moving arguments to and from ; the stack ;------------------------------------------------------------------------ .MACRO PUSH,ARGS .IRP X, MOV X,-(SP) .ENDM .ENDM PUSH ; .MACRO POP,ARGS .IRP X, MOV (SP)+,X .ENDM .ENDM POP ;------------------------------------------------------------------------ ; The Macro STRING is used to generate an ascii string and produce ; a symbolic value equal to its length in bytes ;------------------------------------------------------------------------ .MACRO STRING,STR,LEN .ASCII \STR\ ; Generate the string .IF NB LEN ; Was a length arg. desired? .NCHR LEN, ; Yes - get the string length .ENDC ; Else, just exit .ENDM STRING ;------------------------------------------------------------------------ ; The Macro DEVS generates a list of the devices to be searched for ; MIDNIGHT.CMD files, and a pointer table into that list. NDEVS ; is the number of devices to be searched, and the pointer table is ; of the form LENGTH(DEV1), ADDR(DEV1), ... , LENGTH(DEV n), ADDR(DEV n) ;------------------------------------------------------------------------ .MACRO DEVS,DEVICS NDEVS = 0 ; Initialize # devices counter DEVLST: ; Construct the list of dev. names .IRP X, .ASCII /X/ ; Create the entry NDEVS = NDEVS + 1 ; Increment the dev. counter .ENDM .EVEN DEVPTR: ; Construct the pointer table O.DEV = 0 ; Initialize offsert into DEVLST .IRP X, .NCHR DEVLEN, ; Determine the dev. name length .WORD DEVLEN ; Put in the length word .WORD DEVLST + O.DEV ; and starting address O.DEV = O.DEV + DEVLEN ; Update the address pointer .ENDM .ENDM DEVS ;------------------------------------------------------------------------ ; The macro RUNAT sets the terminal from which the MIDNIGHT.CMD files ; are run (or, appear to be run). It also defines that terminal's ; UCB if console redirection is selected, the spawning DPB and status block. ;------------------------------------------------------------------------ .MACRO RUNAT,NUM NEWUCB: .WORD .TT'NUM ; Define the UCB for the terminal SPAWN: SPWN$ MCR...,,,,,EFNS,,ESB,,,NUM,TT ; Define the SPAWN DBP ESB: .BLKW 8. ; and its status block .ENDM RUNAT ;------------------------------------------------------------------------ ; The macro TMO sets the appropriate time-out values for privileged ; and non-privileged command files ;------------------------------------------------------------------------ .MACRO TMO,TYPE,MAG,UNITS .IF B TYPE!MAG!UNITS .ERROR ; Missing argument .MEXIT .ENDC ; ; Check the units and the magnitude for legal values ; .IF IDN UNITS,T ; Ticks .IFT .IF LT MAG ; Must be a positive number .ERROR ; Illegal magnitude .MEXIT .ENDC TYPE'TMOU = 1 .IFF .IF IDN UNITS,S ; Seconds .IFT .IF LT MAG .ERROR ; Illegal magnitude ; Must be a positive number .MEXIT .ENDC TYPE'TMOU = 2 .IFF .IF IDN UNITS,M ; Minutes .IFT .IF GT MAG-1440. ; Must be 1440. or less .ERROR ; Illegal magnitude .MEXIT .ENDC TYPE'TMOU = 3 .IFF .IF IDN UNITS,H ; Hours .IFT .IF GT MAG-24. ; Must be 24. or less .ERROR ; Illegal magnitude .MEXIT .ENDC TYPE'TMOU = 4 .IFF .ERROR ; Unknown interval unit .ENDC .ENDC .ENDC .ENDC ; TYPE'TMOM = MAG ; Define the magnitude ; .ENDM TMO ;------------------------------------------------------------------------ ; The macro LOGFIL generates the data set descriptor for MIDNIGHT's ; log file ;------------------------------------------------------------------------ .MACRO LOGFIL,DEV,UIC LOGDEV: STRING DEV,LOGDVL ; Set device string and its length LOGUIC: STRING ,LOGUIL ; Set directory string and its length LOGNAM: STRING ,LOGNML ; Set file name string and its length .EVEN LOGDSD: .WORD LOGDVL,LOGDEV,LOGUIL,LOGUIC,LOGNML,LOGNAM ; DSD .ENDM LOGFIL ; .SBTTL FDB's, filespecs, and event flags ;------------------------------------------------------------------------ ; Define the event flags used ;------------------------------------------------------------------------ EFND = 1 ; Directory search FDB event flag EFNC = 2 ; Command file search FDB event flag EFNL = 3 ; Log file FDB event flag EFNR = 4 ; Rename ind. cmd. file flag EFNS = 5 ; Spawn synch. event flag EFNT = 6 ; Command file time-out event flag EFNA = 7 ; Used for 10. sec delay during ABOALL ;------------------------------------------------------------------------ ; Define the directory file and indirect command file search FDB's, ; as well as the log file FDB, and that used to rename the command ; file after it has been executed ;------------------------------------------------------------------------ FSRSZ$ 2,,MID ; DIRFDB: FDBDF$ FDOP$A 1,DIRDSD,,FO.RD FDBF$A EFND ; CMDFDB: FDBDF$ FDOP$A 1,CMDDSD,,FO.RD FDBF$A EFNC ; LOGFDB: FDBDF$ FDAT$A R.VAR,FD.CR FDRC$A ,LOGBUF,82. FDOP$A 2,LOGDSD,,FO.WRT,FA.DLK FDBF$A EFNL ; RENFDB: FDBDF$ FDOP$A 3,RENDSD FDBF$A EFNR ;------------------------------------------------------------------------ ; Define the directory file ( [0,0]*.DIR) data set descriptor ;------------------------------------------------------------------------ DDIRNM: .ASCII /[0,0]/ DFILNM: .ASCII /*.DIR;*/ .EVEN DIRDSD: .WORD 0,0,5,DDIRNM,7,DFILNM ; Leave device name blank ;------------------------------------------------------------------------ ; Define the MIDNIGHT.CMD file data set descriptor ;------------------------------------------------------------------------ CDIRNM: .ASCII /[000,000]/ ; Put aside enough space for uic CGRP = CDIRNM + 1 ; pointer to group code CMEM = CDIRNM + 5 ; pointer to member code CFILNM: .ASCII /MIDNIGHT.CMD;0/ ; Force most recent version .EVEN CMDDSD: .WORD 0,0,9.,CDIRNM,14.,CFILNM ; Again dev. name is blank ;------------------------------------------------------------------------ ; Define the MIDNIGHT.DON data set descriptor (used for renaming the ; MIDNIGHT.CMD file after it has executed ;------------------------------------------------------------------------ RFILNM: .ASCII /MIDNIGHT.DON/ .EVEN RENDSD: .WORD 0,0,9.,CDIRNM,12.,RFILNM ; Use dflt. dev. and current UIC ; .SBTTL Command strings used for spawning ;------------------------------------------------------------------------ ; Define some ascii strings used to spawn command lines ;------------------------------------------------------------------------ ASNSTR: STRING ,ASNLEN ; Assign new system device ASN = ASNSTR + 4 ; Point to "fill-in" region INDSTR: STRING <@MIDNIGHT.CMD>,INDLEN ; Execute the indirect command file .EVEN ; .SBTTL Working storage and DPB's ;------------------------------------------------------------------------ ; Define some working storage and DPB'S ;------------------------------------------------------------------------ OLDUCB: .BLKW 1 ; Storage - old value of U.RED in CO0: UICBUF: .BLKW 1 ; Scratch - for gen of binary UIC MARK: MRKT$ EFNT,,,TIMOUT ; Command file time-out MARK2: MRKT$ EFNA,10.,2. ; 10. sec delay during ABOALL SET: SETF$ EFNS ; Cancel cmd file wait for completion WAIT: WTSE$ EFNS ; Wait for command file completion WAIT2: WTSE$ EFNA ; Wait corresponding to MARK2 ABORT: ABRT$ ; Abort cmd file and its tasks ALSTSZ = 10. ; # of task names to fit in abo list ABOLST: .BLKW 2*ALSTSZ+1 ; Allocate the abort task list DELAY: .BLKW 1 ; Used to count # tsks mrkd for abo RSRV1: .RAD50 /.../ ; Set aside reserved words for ... RSRV2: .RAD50 /MCR/ ; and MCR SPACES: .BYTE 40,40 ; Define some ascii spaces LOGBUF: .BLKB 82. ; Record buffer for log file TIMBUF: .BLKW 8. ; Buffer for time and date ; .SBTTL MIDNIGHT.LOG Messages ;------------------------------------------------------------------------ ; MIDNIGHT.LOG messages ;------------------------------------------------------------------------ LOG1: STRING ,LOG1L LOG2: STRING ,LOG2L LOG3: STRING ,LOG3L ; LOGE0: STRING ,LOGE0L LOGE1: STRING <.PARSE ERROR during >,LOGE1L LOGE2: STRING <.FIND ERROR during >,LOGE2L LOGE3: STRING ,LOGE3L LOGE4: STRING ,LOGE4L LOGE5: STRING ,LOGE5L LOGE6: STRING ,LOGE6L LOGE7: STRING ,LOGE7L ; .PAGE .SBTTL User Selected Options ;======================================================================== ; BEGINNING OF USER SELECTED OPTIONS SECTION ;======================================================================== ; ;------------------------------------------------------------------------ ; Use the macro DEVS to specify the devices to be searched for ; MIDNIGHT.CMD files. The form of the macro is ; DEVS ; where "arglst" constains, PHYSICAL device specifications. For example ; DEVS ; or DEVS DK5: ;------------------------------------------------------------------------ DEVS ;------------------------------------------------------------------------ ; Specify the number of the terminal from which the indirect command ; files are to be run, using the macro ; RUNAT n ; where "n" is the number of the terminal ;------------------------------------------------------------------------ RUNAT 14 ;------------------------------------------------------------------------ ; While MIDNIGHT is running, the console is redirected to the 'run at' ; terminal. If this feature is NOT desireable, comment-out the ; following line, so that REDIR is NOT defined. ;------------------------------------------------------------------------ REDIR = 1 ; Redirect the console ;------------------------------------------------------------------------ ; A given MIDNIGHT.CMD file (and all of the tasks it may be running) may ; be aborted after a selectable time has passed since its initiation. ; Two separate time-out's may be defined, for privileged and non-privileged ; indirect command files, via the macro TMO. The call to TMO must ; be of the form ; TMO TYPE,MAG,UNITS ; where TYPE has legal values of P for priileged and N for non-privileged, ; MAG is the time-out interval magnitude (a positive integer), and ; UNITS has legal values of T for clock ticks, S for seconds, M for ; minutes, and H for hours. In no case may the total time out interval ; exceed 24. hours. For example: ; TMO N,5,M ; generates a time-out for non-privileged command files after 5 minutes. ; If no time-out is supplied for a given class of command files, they ; are allowed to execute indefinately. ;------------------------------------------------------------------------ ; TMO P,6.,H ; No privileged time out ;V1.1 TMO N,6.,H ; 6 hours non-priv tmo ;------------------------------------------------------------------------ ; Using the macro LOGFIL, specify the device and UIC for writing ; the MIDNIGHT.LOG log file. The form of the macro is ; LOGFIL DDnn:,<[ugc,umc]> ;------------------------------------------------------------------------ LOGFIL DK6:,<[50,54]> ;------------------------------------------------------------------------ ; Once a MIDNIGHT.CMD file has completed its execution (either through ; natural causes or time-out), it may be renamed to MIDNIGHT.DON to ; prevent its subsequent execution without direct owner intervention. ; Again, this option is separated according to the privilege of the ; command file's owning UIC. The following lines should be "commented-out" ; to inhibit this renaming feature. ;------------------------------------------------------------------------ ; PRENAM = 1 ; DONT Rename privileged files NRENAM = 1 ; Rename non-privileged files ;======================================================================== ; END OF USER SELECTED OPTIONS SECTION ;======================================================================== .PAGE .SBTTL Entry Point ;======================================================================== ; ENTRY POINT ;======================================================================== MID:: .SBTTL Initialization FINIT$ ; Initialize the FSR OPEN$W #LOGFDB ; Open the log file CALL NOW ; Get time into log file record buffer MOV #LOG1,R2 ; Point to startup message MOV #LOG1L,R3 ; Get its length 2$: MOVB (R2)+,(R1)+ ; Write it into the record buffer SOB R3,2$ ; loop until all of msg. transferred CALL PUTREC ; Write the initialization message ; MOV NEWUCB,R4 ; Get the addr of the 'run at' term. BIC #,U.CW2(R4) ; Log it on, non-privileged BIS #U2.SLV,U.CW2(R4) ; Slave it ; .IF DF REDIR ; Redirect the console if desired MOV #.CO0,R3 ; Point to the console UCB MOV U.RED(R3),OLDUCB ; Save its redirection pointer MOV NEWUCB,U.RED(R3) ; and redirect the console as desired .ENDC ; .SBTTL Device search ;------------------------------------------------------------------------ ; Begin searching through the device list ;------------------------------------------------------------------------ MOV #NDEVS,R0 ; Set count for # of devs. to search MOV #DEVPTR,R1 ; Point to the device table 4$: MOV (R1),DIRDSD ; Move device length into DSD MOV (R1),CMDDSD ; for directory, .CMD file MOV (R1)+,RENDSD ; and .DON file MOV (R1),DIRDSD+2 ; Move device name string address MOV (R1),CMDDSD+2 ; into the DSD's MOV (R1)+,RENDSD+2 PUSH ; Save the counter and pointer ; .SBTTL Directory search ;------------------------------------------------------------------------ ; .PARSE the directory filespec into the FDB ;------------------------------------------------------------------------ MOV #DIRFDB,R0 ; Point to the FDB MOV #,R1 ; and it's file name region MOV #DIRDSD,R2 ; and the data set descriptor CLR R3 ; flag no default file name CALL .PARSE ; Load up the FDB BCC 6$ ; No errors, keep on truckin' JMP PRSERR ; Handle the .PARSE error ;------------------------------------------------------------------------ ; Search for directories on the selected device ;------------------------------------------------------------------------ 6$: CALL .FIND ; Search for the directory BCC 10$ ; No errors CMPB F.ERR(R0),#IE.NSF ; No more directories on this device? BNE 8$ ; No - other error JMP 48$ ; Yes - move on to next device 8$: JMP FNDERR ; Else, handle the .FIND error ;------------------------------------------------------------------------ ; A directory has been found. Extract the UIC from the directory file ; name and convert it back to ascii so that it can be used as part ; of the file name string for the MIDNIGHT.CMD search. ;------------------------------------------------------------------------ 10$: MOV #CGRP,R0 ; Point to the group code area MOV ,R1 ; Get the group code in RAD50 CALL $C5TA ; Convert RAD50 to ascii. MOV #CMEM,R0 ; Point to the member code area MOV ,R1 ; Get the member code in RAD50 CALL $C5TA ; and convert again ; .SBTTL Command file search ;------------------------------------------------------------------------ ; Search for the MIDNIGHT.CMD file in this UIC on the selected device ;------------------------------------------------------------------------ MOV #CMDFDB,R0 ; Point to the FDB MOV #,R1 ; and its file name block MOV #CMDDSD,R2 ; and data set descriptor CALL .PARSE ; Fill the FDB BCC 12$ ; No errors JMP PRSER2 ; Handle .PARSE error 12$: CALL .FIND ; Search for the .CMD file BCC 16$ ; No errors CMPB F.ERR(R0),#IE.NSF ; Was it a file not found error? BNE 14$ ; No - handle fatal error JMP 44$ ; Yes - try next directory 14$: JMP FNDER2 ; Else handle other .FIND error ; .SBTTL Command file execution ;------------------------------------------------------------------------ ; A MIDNIGHT.CMD file has been found ;------------------------------------------------------------------------ 16$: MOV #,R2 ; Point to the current UIC string MOV #UICBUF,R3 ; Point to the binary UIC buffer CALL .ASCPP ; Convert ASCII UIC to binary UIC MOV (R3),U.LUIC(R4) ; Set log-in UIC MOV (R3),U.UIC(R4) ; and current UIC CMPB 1(R3),#7 ; Is the user privileged? BGT 18$ ; No, member code > 7 BIS #U2.PRV,U.CW2(R4) ; Yes , set privilege bit ; 18$: MOV SPACES,ASN ; Clear device field to reassign MOV SPACES,ASN+2 ; default system device MOV SPACES,ASN+4 MOV DIRDSD,R1 ; Get length of current device spec MOV ,R2 ; and point to it's starting address MOV #ASN,R3 ; and dest. in the ASN spawn string 20$: MOVB (R2)+,(R3)+ ; Copy the device name string SOB R1,20$ ; and loop until done ;------------------------------------------------------------------------ ; Spawn the appropriate command lines to correctly assign the default ; system device, write the log file entry, and execute the indirect command ; file ;------------------------------------------------------------------------ 22$: MOV #SPAWN,R2 ; Point to the spawn DPB MOV UICBUF,S.PWUM(R2) ; Set UIC for task MOV #ASNSTR,S.PWCA(R2) ; Point to the ASN command line MOV #ASNLEN,S.PWCL(R2) ; Set its length DIR$ R2 ; and spawn it BCC 24$ ; If no error, wait JMP SPNERR ; Handle fatal error 24$: DIR$ #WAIT ; Wait for spawned task to finish ; PUSH ; Save R0 and R2 for now CALL NULREC ; Write out a null record to the log CALL NOW ; Get the current time MOVB #'@,(R1)+ ; Put the "@" in the record buffer MOV DIRDSD,R3 ; Get length of current device str MOV ,R2 ; and its address 26$: MOVB (R2)+,(R1)+ ; Move in the string SOB R3,26$ ; Loop until done MOV #CDIRNM,R2 ; Point to the MIDNIGHT.CMD dsd MOV #21.,R3 ; Counter for uic + filename str 28$: MOVB (R2)+,(R1)+ ; Move in the command file name SOB R3,28$ ; Loop until done CALL PUTREC ; Write the current command file msg POP ; Restore the registers ; MOV #INDSTR,S.PWCA(R2) ; Point to the @MIDNIGHT.CMD str MOV #INDLEN,S.PWCL(R2) PUSH R2 ; Save R2 again DIR$ R2 ; Spawn the command file BCC 30$ ; No errors - issue mark-time and wait JMP SPNERR ; Handle fatal error 30$: CALL TIMER ; Set necessary time-outs DIR$ #WAIT CMKT$S #EFNT ; Cancel time-out if still pending ; 32$: POP R2 ; Restore pointer to SPWN$ DPB .IF DF PRENAM!NRENAM ; Asemble only if renaming enabled BIT #U2.PRV,U.CW2(R4) ; Is cmd file privileged? BEQ 34$ ; No - handle it ; .IF DF PRENAM ; Yes - should it be renamed? .IFT ; Yes BR 36$ ; Handle the renaming .IFF ; No BR 42$ ; Branch around the renaming .ENDC ; 34$: .IF NDF NRENAM ; Non-priv -- leave it alone? BR 42$ ; Yes .ENDC ; 36$: MOV #RENFDB,R0 ; Point to the rename FDB MOV #,R1 ; and its file name region MOV #RENDSD,R2 ; and its data set descriptor CLR R3 ; flag no default file name CALL .PARSE ; parse in new name in current UIC BCC 38$ ; no errors - keep going CALL PRSER3 ; handle .PARSE error JMP 44$ ; and keep on truckin ; 38$: MOV R0,R1 ; set up to rename - point to RENFDB MOV #CMDFDB,R0 ; and original FDB CALL .RENAM ; rename the file BCC 39$ ; No Renaming errors, keep going CALL RNMERR ; Handle the renaming error JMP 44$ ; and keep on truckin ; 39$: CALL NOW ; Get the time MOV #LOG3,R2 ; Point to the string renames message MOV #LOG3L,R3 ; Get its length 40$: MOVB (R2)+,(R1)+ ; Move it into the log file buffer SOB R3,40$ ; Loop until done CALL PUTREC ; Write the record to the log file .ENDC ; 42$: BIC #U2.PRV,U.CW2(R4) ; Disable privilege bit ;------------------------------------------------------------------------ ; Set up to continue searching other directories for MIDNIGHT.CMD ; files, and do so ;------------------------------------------------------------------------ 44$: MOV #DIRFDB,R0 ; Point to the directory FDB MOV #,R1 ; and its file name block MOV #DIRDSD,R2 ; and data set descriptor JMP 6$ ; and search for the next directory ;------------------------------------------------------------------------ ; Repeat the procedure on the specified devices ;------------------------------------------------------------------------ 46$: JMP 4$ 48$: POP ; Restore the dev. pointer and counter SOB R0,46$ ; Loop until done BR OUT ; Quit ; .SBTTL Systematic Error handler ;------------------------------------------------------------------------ ; Systematic Error Handler ;------------------------------------------------------------------------ SPNERR: ; Spawning error CALL NOW ; Get the time MOV #LOGE0,R2 ; Point to the error message MOV #LOGE0L,R3 ; get its length 10$: MOVB (R2)+,(R1)+ ; move it over SOB R3,10$ ; loop until done BR FINISH ; Write error message and leave ; PRSERR: ; .PARSE Error during directory search CALL PESTR ; Get the .PARSE error string CALL DESTR ; get the directory search i.d. str BR FINISH ; write error message and leave ; FNDERR: ; .FIND Error during directory search CALL FESTR ; Get the .FIND error string CALL DESTR ; for directory search BR FINISH ; write error message and leave ; PRSER2: ; .PARSE Error during cmd file search CALL PESTR CALL CESTR BR FINISH ; write error message and leave ; FNDER2: CALL FESTR CALL CESTR BR FINISH ; write error message and leave ; PRSER3: ; .PARSE Error during renaming CALL PESTR MOV #LOGE5,R2 ; get the error string MOV #LOGE5L,R3 ; and its length 10$: MOVB (R2)+,(R1)+ ; write the msg. into the record buf. SOB R3,10$ ; loop until done CALL PUTREC ; write the record RETURN ; RNMERR: ; .RENAME Error CALL NOW MOV #LOGE7,R2 ; get the error string MOV #LOGE7L,R3 ; and its length 10$: MOVB (R2)+,(R1)+ ; write it out SOB R3,10$ ; loop until done CALL PUTREC ; write the record RETURN ; FINISH: CALL PUTREC ; write fatal error message ; and fall through to exit ; .SBTTL Clean-up and exit ;------------------------------------------------------------------------ ; Clean-up and exit ;------------------------------------------------------------------------ OUT: BIS #U2.LOG,U.CW2(R4) ; Log off the 'run at' terminal BIC #U2.SLV,U.CW2(R4) ; and un-slave it ; .IF DF REDIR ; UN-redirect CO: if necessary MOV #.CO0,R3 ; Point to the console UCB MOV OLDUCB,U.RED(R3) ; Restore its redirect pointer .ENDC ; CALL NULREC ; Write a null record CALL NOW ; Get the time MOV #LOG2,R2 ; Point to the termination message MOV #LOG2L,R3 ; Get its length 10$: MOVB (R2)+,(R1)+ ; Move the message into the buffer SOB R3,10$ ; Loop until done CALL PUTREC ; Write the termination message CLOSE$ ; Close the log file EXIT$S ; and quit ; .PAGE .SBTTL Subroutine TIMER ;------------------------------------------------------------------------ ; TIMER is called immediately after an indrect command file begins ; executing. TIMER determines the privilge status of the current ; command file and initiates the count-down for command file ; time-out ;------------------------------------------------------------------------ TIMER: .IF DF PTMOM!NTMOM ; Either time-out requested? MOV #MARK,R1 ; Yes - point to MRKT$ DPB BIT #U2.PRV,U.CW2(R4) ; Is cmd file currently privileged? BEQ 10$ ; No - handle it ; .IF DF PTMOM ; Yes, but has priv TMO been requested .IFT ; Yes MOV #PTMOM,M.KTMG(R1) ; Set correct magnitude MOV #PTMOU,M.KTUN(R1) ; and unit DIR$ R1 ; Start the countdown .IFTF RETURN ; and return .ENDC ; 10$: .IF DF NTMOM ; Has non-priv TMO been requested? .IFT ; Yes MOV #NTMOM,M.KTMG(R1) ; Set correct magnitude MOV #NTMOU,M.KTUN(R1) ; and unit DIR$ R1 ; Start the countdown .IFTF RETURN ; and return .ENDC .ENDC ; .IF NDF PTMOM&NTMOM ; if neither tmo defined RETURN ; just return .ENDC ; ; ; ; .SBTTL Command File Time-Out service routine TIMOUT ;------------------------------------------------------------------------ ; TIMOUT is called asynchronously when the current command file has ; exceeded its time-out restrictions. ;------------------------------------------------------------------------ TIMOUT: .IF DF PTMOM!NTMOM ; Do we need this section? .IFT ; Yes - assemble it CALL NOW ; Get the current time MOV #LOGE6,R2 ; Point to the time out message MOV #LOGE6L,R3 ; and get its length 10$: MOVB (R2)+,(R1)+ ; Put the message in the record buf SOB R3,10$ ; Loop until done CALL PUTREC ; write the time out message ; PUSH R4 ; Save R4 since its clobbered by ; $SWSTK in ABOALL CALL ABOALL ; Abort all tasks run by this cmd file DIR$ #SET ; Cancel wait for ind. cmd. file POP R4 ; Restore R4 TST (SP)+ ; Pop EFN from stack .IFTF ; Make sure the return makes it in ASTX$S ; and go home .ENDC ; ; ; ; .SBTTL Command file Abort subroutine ABOALL ;------------------------------------------------------------------------ ; ABOALL is called by the time-out service routine to abort the current ; command file and any tasks it has activated. ;------------------------------------------------------------------------ ABOALL: CLR DELAY ; Clear the delay flag .IF DF PTMOM!NTMOM ; Do we need this section? .IFT ; Yes - assemble it CALL $SWSTK,14$ ;; Switch stacks MOV $TSKHD,R1 ;; Get the addr of first task header MOV #ABOLST,R2 ;; Point to the abort list MOV #ALSTSZ,R3 ;; Set counter for list size ;------------------------------------------------------------------------ ; Fill the abort list with the names of all tasks attributed to the ; 'run at' terminal to a maximum of ALSTSZ. ;------------------------------------------------------------------------ CLR (R2)+ ;; clear the abo. list counter 2$: TST T.STAT(R1) ;; Is the task pointed to active? BMI 10$ ;; No -- get the next one CMP NEWUCB,T.UCB(R1) ;; Active - is it from 'run at' term? BNE 10$ ;; No -- keep searching ;------------------------------------------------------------------------ ; Check this task name against MCR... and ...MCR. If it matches either ; one, do not put it into the abort list ;------------------------------------------------------------------------ CMP T.NAM(R1),RSRV1 ;; First word ...? (for ...MCR) BNE 4$ ;; No - check for MCR... CMP <2+T.NAM>(R1),RSRV2 ;; Yes - second word MCR? (for ...MCR) BEQ 10$ ;; Yes - skip it BR 6$ ;; No - fair game for abort ; 4$: CMP T.NAM(R1),RSRV2 ;; First word MCR? (for MCR...) BNE 6$ ;; No - fair game to abort CMP <2+T.NAM>(R1),RSRV1 ;; Yes - 2nd word ...? (for MCR...) BEQ 10$ ;; Yes - skip it, else abort ; 6$: BIT #,T.STAT(R1) ;; Run down or abo msg output? BNE 8$ ;; Yes - set the delay BIT #,T.ST2(R1) ;; Halted or mrked for abo? BNE 8$ ;; Yes - set the delay ; MOV T.NAM(R1),(R2)+ ;; Put 1st word of name into abo list MOV <2+T.NAM>(R1),(R2)+ ;; and the second word INC ABOLST ;; and increment the lst counter BR 12$ ;; See if we've filled the list ; 8$: INC DELAY ;; Increment the delay word ; 10$: MOV T.TCBL(R1),R1 ;; point to next task header TST T.TCBL(R1) ;; Is this the null task? BEQ 14$ ;; Yes - quit BR 2$ ;; No - continue checking ; 12$: SOB R3,10$ ;; If list isn't full keep going ;------------------------------------------------------------------------ ; Either the list is full, or the null task has been found ;------------------------------------------------------------------------ 14$: RETURN ;; Return from system state 15$: MOV ABOLST,R3 ; Get the list counter BEQ 22$ ; No point if the list is empty TST DELAY ; Are there tasks on their way out? BEQ 16$ ; No - clobber according to the list ;------------------------------------------------------------------------ ; There are some tasks marked for abort, but not clobbered yet. Wait ; for 10 seconds (use the general timeout and wait dpb's for this) ; then check the system lists again ;------------------------------------------------------------------------ DIR$ #MARK2 ; Issue 10. second count-down DIR$ #WAIT2 ; Wait for it BR ABOALL ; And start all over again ;------------------------------------------------------------------------ ; Begin clobbering from the abort list ;------------------------------------------------------------------------ 16$: MOV #,R1 ; Point to the start of the abo list MOV #ABORT,R2 ; and point to the ABRT$ DPB 18$: MOV (R1)+,A.BTTN(R2) ; Move the task name ( 2 words) MOV (R1)+,<2+A.BTTN>(R2) ; into the ABRT$ DPB DIR$ R2 ; and abort the task WSIG$S ; Wait for completion of the kill SOB R3,18$ ; loop until done ;------------------------------------------------------------------------ ; Log the tasks aborted ;------------------------------------------------------------------------ MOV #LOGBUF,R0 ; Point to the record buffer MOV ABOLST,R3 ; Get the abort list size MOV #,R4 ; And the addr of the first entry 20$: MOV (R4)+,R1 ; Get the first word of task name CALL $C5TA ; and convert it to ascii MOV (R4)+,R1 ; Do the same for CALL $C5TA ; the second word MOVB SPACES,(R0)+ ; Put in a trailing space SOB R3,20$ ; Loop through the abort list MOV R0,R1 ; Get the address in the right place CALL PUTREC ; Write the list of tasks aborted ;------------------------------------------------------------------------ ; Continue searching system lists and aborting tasks until no more ; are found, in case there were more tasks that would fit in the list ; on one pass, or in case something started up asynchronously and ; wasn't found in the task list before. ;------------------------------------------------------------------------ BR ABOALL ; and around we go again ;------------------------------------------------------------------------ ; There are no more tasks to abort. ;------------------------------------------------------------------------ .IFTF ; make sure that the RETURN is there 22$: RETURN .ENDC ; ; ; ; .SBTTL Subroutine NOW ;------------------------------------------------------------------------ ; Subroutine NOW determines the current time and data, converts that ; information to ascii, and stores it at the front of the record buffer ; to be written to the log file. Register 1 is modified, i.e., returned ; with the address of the next available location in the record buffer ;------------------------------------------------------------------------ NOW: PUSH ; Save some registers GTIM$S #TIMBUF ; Get current time and date MOV #LOGBUF,R0 ; Point to output buffer MOV #TIMBUF,R1 ; Point to input buffer CALL $DAT ; Convert binary date to ascii MOVB SPACES,(R0)+ ; Put in some spaces MOV #3,R2 ; Specify HH:MM:SS for time CALL $TIM ; Convert binary time to ascii MOVB SPACES,(R0)+ ; Put in some trailing spaces MOV R0,R1 ; Return next buffer address in R1 POP ; Restore the registers RETURN ; and return ; ; ; ; .SBTTL Subroutine NULREC/PUTREC ;------------------------------------------------------------------------ ; There are two entry points into this subroutine, NULREC and PUTREC ; which write a null record, or the contents of the record buffer, to ; the log file, respectively. It is assumed in the case of PUTREC that ; R1 contains the address of the next available location in the record ; buffer when PUTREC is called. Registers 0 and 1 are modified, and ; are returned with the address of the log file FDB and the current ; record size in bytes, respectively. ;------------------------------------------------------------------------ NULREC: CLR R1 ; Indicate record size of 0 BR WRITE ; and write the null record ; PUTREC: SUB #LOGBUF,R1 ; Get the current record size WRITE: PUT$ #LOGFDB,,R1 ; Write the record RETURN ; ; ; ; .SBTTL Subroutine PESTR ;------------------------------------------------------------------------ ; Subroutine PESTR writes the error string indicating an error during ; the .PARSE routine into the log file's record buffer. Register 1 is ; returned with the next available location in the buffer. ;------------------------------------------------------------------------ PESTR: CALL NOW ; Get the time MOV #LOGE1,R2 ; Point to the .PARSE error string MOV #LOGE1L,R3 ; Get its length 10$: MOVB (R2)+,(R1)+ ; Move the string over SOB R3,10$ ; Loop until done RETURN ; ; ; ; .SBTTL Subroutine FESTR ;------------------------------------------------------------------------ ; Identical to PESTR, above, but pertains to an error during .FIND ;------------------------------------------------------------------------ FESTR: CALL NOW ; Get the time MOV #LOGE2,R2 ; Get .FIND error message MOV #LOGE2L,R3 ; and its length 10$: MOVB (R2)+,(R1)+ ; Copy it over SOB R3,10$ ; Loop until done RETURN ; ; ; ; .SBTTL Subroutine DESTR ;------------------------------------------------------------------------ ; Subroutine DESTR indicates that the .FIND or the .PARSE error currently ; being handled occured during the directory search phase of MIDNIGHT. ; It is assumed that DESTR is called with R1 pointing to the next ; available location in the log file's record buffer. R1 is returned ; pointing to the (updated) next available location in that buffer. ;------------------------------------------------------------------------ DESTR: MOV #LOGE3,R2 ; Point to the directory phase error MOV #LOGE3L,R3 ; and get its length 10$: MOVB (R2)+,(R1)+ ; Copy it over SOB R3,10$ ; Loop until done RETURN ; ; ; ; .SBTTL Subroutine CESTR ;------------------------------------------------------------------------ ; Identical to DESTR, above, but error has occurred during the command ; file search phase of MIDNIGHT ;------------------------------------------------------------------------ CESTR: MOV #LOGE4,R2 ; Point to the cmd phase error MOV #LOGE4L,R3 ; and get its length 10$: MOVB (R2)+,(R1)+ ; Copy it over SOB R3,10$ ; Loop until done RETURN ; .END MID