.TITLE FLYINS Flying Command Catchall .IDENT /Y01.10/ ; Internal use only .ENABL LC .NLIST BEX ; Don't list binary extensions .NLIST CND ; Don't list unsatisfied conditionals ; FFFFFFFFFF LL YY YY IIIIIIII NN NN SSSSSSSSS ; FFFFFFFFFF LL YY YY IIIIIIII NN NN SSSSSSSSS ; FF LL YY YY II NNNN NN SS ; FF LL YY YY II NNNN NN SS ; FFFFFFFF LL YYYY II NN NN NN SSSSSSSS ; FFFFFFFF LL YYYY II NN NN NN SSSSSSSS ; FF LL YY II NN NNNN SS ; FF LL YY II NN NNNN SS ; FF LL YY II NN NNN SS ; FF LL YY II NN NNN SS ; FF LLLLLLLLLL YY IIIIIIII NN NN SSSSSSSS ; FF LLLLLLLLLL YY IIIIIIII NN NN SSSSSSSS .SBTTL Introduction ; FLYINS - Secondary Level Flying Command Catchall Task ; Authors: ; Bruce R. Mitchell ; Source Site ; Electrocardiology Computer Systems ; Plummer Building, Mayo Clinic, Rochester, Minnesota 55902 ; Source Hardware and Operating System: ; DEC PDP-11/70 under RSX-11M-Plus V2.1 Update E ; Target Site: ; Same ; Target Hardware and Operating System: ; Same ; Revision History: ; 20-Mar-86 First version coded ; 17-Apr-86 Add support for passoff to other secondary catchalls ; 09-May-86 Change protection UIC to default UIC for file searches ; 14-Aug-86 Add network UIC for file searches .PAGE .SBTTL Description and Philosophy 101 ; System manager: "We want - POOL." ; RSX-11 system: "You won't get it from me!" ; System programmer: "By hook or by crook, we will." ; ; This task is a smarter, yet in some ways more stupid, version of the ; DEC TDX catchall task. It uses the catchall task facilty of the CLI ; system to process commands which are not understood by the CLIs. ; Such commands are passed to this task (when installed with the name ; ...CA.) automatically by CLIs. ; ; About POOL. Every task which is installed steals some POOL. But if ; the task isn't installed, you can't get at it without doing a RUN ; command. This task is intended to get around that problem by finding ; a task for the user transparently and running it on his behalf. And ; if it can't be found, the command line is (hopefully) passed to the ; next catchall task in line, ...CA2. ; ; Operation proceeds as follows: ; ; (1) Assign a LUN to the TI: device. Exit on error. ; (2) Get the passed CLI command line. Exit on error. ; (3) Check to see the passed line is 3 chars or more. Exit if not. ; (4) Build 4 possible name buffers; x.CMD, x.TSK, xRES.TSK and xFSL.TSK ; (5) Search by device and UFD for a command file of the built name ; (6) If the search failed, pass the command line to step 11 ; (7) If the search succeeded, build an AT. command line. ; (8) RPOI$ the command line to MCR... ; (9) If the RPOI$ failed, Spawn the command line to MCR... ; (10) Exit to RSX with success status regardless of Spawn status. ; (11) Search by device and UFD for a task file of the built names. ; (12) If the search failed, pass the command line to ...CAx ; (13) If the search succeeded, build a RUN /TASK /CMD command line. ; (14) RPOI$ the command line to MCR... ; (15) If the RPOI$ failed, Spawn the command line to MCR... ; (16) Exit to RSX with success status regardless of Spawn status. .PAGE .SBTTL Caveats and Restrictions ; None known. .PAGE .SBTTL .SBTTL Macro Calls and Definitions ; ; Directive Macros from LB:[1,1]RSXMAC.SML ; .MCALL ALUN$ ; Assign Logical Unit Number .MCALL DIR$ ; Execute directive .MCALL EXST$S ; Exit with status .MCALL FDBDF$ ; Allocate space for an FDB .MCALL FINIT$ ; Initialize Files-11 services .MCALL FSRSZ$ ; Define FSR record area size .MCALL GLUN$ ; Get LUN information .MCALL GMCR$ ; Get MCR command line .MCALL GTSK$ ; Get task information .MCALL MRKT$ ; Mark time .MCALL NBOFF$ ; Define file name block offsets .MCALL QIOW$ ; Queue I/O and wait for completion .MCALL RPOI$ ; Request and pass offspring information .MCALL SPWN$ ; Spawn a command line FSRSZ$ 0 ; No record I/O files ; ; Local macro definitions ; ; Macro to send a timestamped message to the system console .MACRO PRINT STRING ; Begin PRINT macro MOV #STRING, TTYOUT+Q.IOPL MOV #STRING'L, TTYOUT+Q.IOPL+2 DIR$ #TTYOUT .ENDM ; End PRINT macro .PAGE .SBTTL .SBTTL Data .SBTTL .PSECT FLYDAT, RW, D .SBTTL Symbol Definitions ; ; Conditional assembly definitions ; ; D$$BUG = 1 ; Enable debugging support ; ; Logical unit numbers and event flags associated with them ; TILUN = 1 ; User terminal TI: I/O LUN TSKLUN = 2 ; Task file lookup LB: LUN TIEFN = 1 ; User terminal TI: I/O EFN TSKEFN = 2 ; Task file lookup LB: EFN MKTEFN = 3 ; Marktime activity EFN .PAGE .SBTTL Directive Parameter Blocks ; ; Directive Parameter Blocks ; ; Assign LUN to device DPBs ALUNTI: ALUN$ TILUN, TI, 0 ; Get LUN information DPBs GTINFO: GLUN$ TILUN, LUNBUF ; Get MCR command line DPBs GETMCR: GMCR$ ; Get task information DPBs GETTSK: GTSK$ TSKBUF ; QIO DPBs TTYOUT: QIOW$ IO.WVB, TILUN, TIEFN,,,, <0, 0, 40> ; Request and pass offspring information DPBs REQCA2: RPOI$ ...CA0,,,,,, GETMCR+G.MCRB,, RP.OEX!RP.OAL REQTSK: RPOI$ MCR...,,,,,, CMDLIN,, RP.OEX!RP.ONX ; Spawn task DPBs SPNCA2: SPWN$ ...CA0,,,,,,,, GETMCR+G.MCRB SPNTSK: SPWN$ MCR...,,,,,,,, CMDLIN .PAGE .SBTTL File Descriptor Blocks ; File descriptor block for wildcard .FINDs WLDFDB: FDBDF$ ; Allocate space for FDB ; Dataset descriptor WLDDDS: .WORD 0, 0 ; Device name descriptor (len, addr) .WORD 0, 0 ; UFD descriptor (len, addr) .WORD 0, 0 ; File name (len, addr) .PAGE .SBTTL Tables ; Task file search device and UFD table in prioritized order CMDTBL: .ASCII \SY:[000,000]\ .ASCII \US:[3,1]\ .BYTE 0 ; End of table ; Task file search device and UFD table in prioritized order TSKTBL: .ASCII \SY:[000,000]\ ; User's current UFD .ASCII \LB:[3,54]\ ; System nonpriv UFD .ASCII \LB:[3,55]\ ; Custom nonpriv UFD .ASCII \LB:[1,54]\ ; System nonpriv UFD .ASCII \LB:[1,55]\ ; Custom nonpriv UFD .ASCII \LB:[5,54]\ ; Network UFD .BYTE 0 ; End of table .PAGE .SBTTL Messages and Strings ; ; Messages ; MS00: .ASCII \CA. -- Couldn't get command, $DSW = \ MS00A: .BLKB 3 MS00L = . - MS00 MS01: .ASCII \CA. -- Unable to spawn offspring task\ MS01L = . - MS01 MS03: .ASCII \CA. -- Invalid character in command\ MS03L = . - MS03 MS04: .ASCII \CA. -- Generated command too long to spawn\ MS04L = . - MS04 MS05: .ASCII \CA. -- Invalid command\ MS05L = . - MS05 .IF DF D$$BUG ; If debugging enabled ; ; Debugging messages ; DB00: .ASCII \DEBUG -- Searching \ DB00A: .BLKB 32. DB00L = . - DB00 DB01: .ASCII \DEBUG -- RPOI$ failed, DSW = \ DB01A: .BLKB 3 DB01L = . - DB01 DB02: .ASCII \DEBUG -- Running taskname is "\ DB02A: .BLKB 6 .ASCII \"\ DB02L = . - DB02 DB03: .ASCII \DEBUG -- Attempting to pass command to "\ DB03A: .BLKB 6 .ASCII \"\ DB03L = . - DB03 .EVEN .ENDC ; DF D$$BUG ; ; Strings ; CANAME: .ASCII \...CA0\ CMDSFX: .ASCIZ \/CMD="\ RUNPFX: .ASCIZ \RUN \ INDEXT: .ASCII \.CMD\ INDEXL = . - INDEXT INDPFX: .ASCIZ \@\ TSKEXT: .ASCII \.TSK\ TSKEXL = . - TSKEXT TSKSFX: .ASCIZ \/TASK=\ .EVEN .PAGE .SBTTL Block Variables CMDLIN: .BLKB 100. ; Buffer for task command line INDNAM: .BLKB 16. ; Buffer for command filename LUNBUF: .BLKW 6 ; Buffer for terminal LUN info MYNAME: .BLKB 6 ; Buffer for task's ASCII name TSKBUF: .BLKW 16. ; Buffer for task information TSKFSL: .BLKB 16. ; Buffer for FCSFSL taskname TSKNAM: .BLKB 16. ; Buffer for vanilla taskname TSKRES: .BLKB 16. ; Buffer for FCSRES taskname .PAGE .SBTTL Single Variables CMDLEN: .WORD 0 ; Length of task command line GMCLEN: .WORD 0 ; Length of GMCR$ command line INDLEN: .WORD 0 ; Length of INDirect filename TSKLEN: .WORD 0 ; Length of taskname .PAGE .SBTTL .SBTTL Mainline Code .SBTTL .PSECT FLYCOD, RO, I .SBTTL FLYENT Entry Point ; We just woke up. Assign a LUN to our TI: for error messages. FLYENT: DIR$ #ALUNTI ; Assign a LUN to TI: ; Get task information and convert the running taskname for later use DIR$ #GETTSK ; Get task information on self MOV #MYNAME, R0 ; Load output field address in R0 MOV TSKBUF+G.TSTN, R1 ; Load first half of taskname in R1 CALL $C5TA ; Convert taskname to ASCII MOV TSKBUF+G.TSTN+2, R1 ; Load second half of taskname in R1 CALL $C5TA ; Convert taskname to ASCII .IF DF D$$BUG ; If debugging enabled ; Dump the task name on the invoking terminal for debugging purposes MOV #DB02A, R0 ; Load output field address in R0 MOV #MYNAME, R1 ; Load taskname buffer address in R1 MOV #6, R2 ; Copy 6 bytes 10$: MOVB (R1)+, (R0)+ ; Copy a byte from source to target SOB R2, 10$ ; Until all copied PRINT DB02 ; Print taskname debugging message .ENDC ; DF D$$BUG ; Get the CLI command line waiting for us. DIR$ #GETMCR ; Try to get the invoking command line BCC 20$ ; If we got it, proceed ; What's this? We have no command line today? Message TI: and error out. MOV #MS00A, R0 ; Load output field address in R0 MOV $DSW, R1 ; Load the DSW into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude PRINT MS00 ; "Couldn't get command, $DSW ..." EXST$S #EX$ERR ; Exit with error status ; Ensure the command line is non-void (length 3 or more) 20$: MOV $DSW, GMCLEN ; Save the command length CMP $DSW, #3 ; Is the command 3 or longer? BHIS 30$ ; If so, proceed with it ; Funny command line. We don't want to process it. Pass it to ...CA2 JMP PASCA2 ; Pass the command line to ...CA2 .PAGE .SBTTL * Build Filenames ; Load the "file name" (up to 9 alphanumeric characters) buffers 30$: MOV #GETMCR+G.MCRB, R0 ; R0 points to start of command buffer MOV #INDNAM, R1 ; Load command filename buffer address MOV #TSKNAM, R2 ; Load vanilla taskname buffer address MOV #TSKRES, R3 ; Load FCSRES taskname buffer address MOV #TSKFSL, R4 ; Load FCSFSL taskname buffer address MOV GMCLEN, R5 ; Load command length in bytes in R2 CLR INDLEN ; Clear the "filename" length 40$: CMPB (R0), #'0 ; Is this character valid? BLO 70$ ; If not, we're done copying CMPB (R0), #'9 ; Is this character numeric? BLOS 50$ ; If so, go store it BICB #40, (R0) ; Convert lower to upper case CMPB (R0), #'A ; Is this character valid? BLO 70$ ; If not, we're done copying CMPB (R0), #'Z ; Is this character valid? BHI 70$ ; If not, we're done copying ; See if filename buffer overflows. If so, pass the command to ...CAx+1 50$: CMP INDLEN, #9. ; Is the taskname length more than 9? BLOS 60$ ; If not, continue processing ; Taskname buffer overflow. We don't want it. Try the next catchall. JMP PASCA2 ; Pass to next catchall ; It's not full yet. Copy the character into the buffer and loop. 60$: MOVB (R0), (R1)+ ; Copy byte to command "filename" MOVB (R0), (R2)+ ; Copy byte to vanilla "taskfile" MOVB (R0), (R3)+ ; Copy byte to FCSRES "taskfile" MOVB (R0)+, (R4)+ ; Copy byte to FCSFSL "taskfile" INC INDLEN ; Bump the "filename" length by 1 SOB R5, 40$ ; And continue to copy until all done ; Append the type extensions to the FCSRES and FCSFSL taskname buffers 70$: MOV INDLEN, TSKLEN ; Save virgin buffer length for later MOVB #'R, (R3)+ ; Append RES to the FCSRES task buffer MOVB #'E, (R3)+ ; MOVB #'S, (R3)+ ; MOVB #'F, (R4)+ ; Append FSL to the FCSFSL task buffer MOVB #'S, (R4)+ ; MOVB #'L, (R4)+ ; ; Append the .CMD extension to the filename buffer MOV INDLEN, TSKLEN ; Copy virgin length to taskfile length MOV #INDEXT, R0 ; Point at the .CMD ASCII extension MOV #INDEXL, R5 ; Which is INDEXL bytes long 80$: MOVB (R0)+, (R1)+ ; Append to the buffer SOB R5, 80$ ; And loop until all built ADD #INDEXL, INDLEN ; Correct command filename length ; Append the .TSK extensions to the taskname buffers MOV #TSKEXT, R0 ; Point at the .TSK ASCII extension MOV #TSKEXL, R5 ; Which is TSKEXL bytes long 90$: MOVB (R0), (R2)+ ; Append to the vanilla buffer MOVB (R0), (R3)+ ; Append to the FCSRES buffer MOVB (R0)+, (R4)+ ; Append to the FCSFSL buffer SOB R5, 90$ ; And loop until all built ADD #TSKEXL, TSKLEN ; Correct vanilla taskname length ; Command line looks OK. Call flying install / indirect in order. CALL FLYINS ; Try to flying install CALL FLYIND ; Try to flying indirect JMP PASCA2 ; If all else fails, pass to next CAx .PAGE .SBTTL FLYIND Flying INDirect .SBTTL * Find Command File ; Load the user's running UIC into the UFD search table FLYIND: MOV #CMDTBL+4, R0 ; Point at UFD group output field MOVB TSKBUF+G.TSGC, R1 ; Load group code byte into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude INC R0 ; Point past separating comma MOVB TSKBUF+G.TSPC, R1 ; Load user code byte into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude ; Search all devices and UFDs in the table for the command file MOV #CMDTBL, R5 ; Load device/UFD table address in R5 MOV #INDNAM, WLDDDS+10. ; Load command filename address into DDS MOV INDLEN, WLDDDS+8. ; Load command filename length into DDS ; Load and parse the next device spec address into the dataset descriptor 10$: MOV R5, WLDDDS+2 ; Load device spec address into DDS 20$: CMPB (R5)+, #': ; Found separating colon yet? BNE 20$ ; If not, go look again, my boy MOV R5, WLDDDS+0 ; Load address one past colon into DDS SUB WLDDDS+2, WLDDDS+0 ; Subtract device address, giving length MOV #WLDFDB, R0 ; Load wildcard FDB address in R0 MOV #TSKLUN, F.LUN(R0) ; Stick working LUN into FDB MOV #WLDFDB+F.FNB, R1 ; Load filename block address in R1 MOV #WLDDDS, R2 ; Load dataset descriptor addr in R2 CLR R3 ; Don't use a default filename block CALL .PRSDV ; Parse the info into the wildcard FNB ; Load and parse the next UFD spec address into the dataset descriptor MOV R5, WLDDDS+6 ; Load UFD spec address into DDS 30$: CMPB (R5)+, #'] ; Found terminating bracket yet? BNE 30$ ; If not, go look again, my boy MOV R5, WLDDDS+4 ; Load address one past colon into DDS SUB WLDDDS+6, WLDDDS+4 ; Subtract UFD address, giving length MOV #WLDFDB, R0 ; Load wildcard FDB address in R0 MOV #WLDFDB+F.FNB, R1 ; Load filename block address in R1 MOV #WLDDDS, R2 ; Load dataset descriptor addr in R2 CLR R3 ; Don't use a default filename block CALL .PRSDI ; Parse the info into the wildcard FNB ; See if we can find the file CALL WLDFND ; See if we can find the task image BCC 40$ ; If we found it, go run it ; Didn't find it. Set the next UFD string up and go try again. TSTB (R5) ; Out of device/directory specs yet? BNE 10$ ; If not, go try the next 3 tasknames ; After all that work, no task found? Return to the caller RETURN ; Return to the caller .PAGE .SBTTL * Build Command Line ; Build the spawn command line with a preceding RUNb 40$: MOV #CMDLIN, R0 ; Load spawn command buffer addr in R0 MOV #INDPFX, R1 ; Load AT. prefix string addr in R1 CALL MOVSTR ; Move the prefix string ; Copy the task file's device name to the spawn buffer MOV WLDDDS+2, R1 ; Load DDS device name address in R1 MOV WLDDDS+0, R2 ; Load DDS device name length in R2 50$: MOVB (R1)+, (R0)+ ; Copy device name to spawn buffer SOB R2, 50$ ; Until the whole thing is copied ; Copy the task file's UFD name to the spawn buffer MOV WLDDDS+6, R1 ; Load DDS UFD name address in R1 MOV WLDDDS+4, R2 ; Load DDS UFD name length in R2 60$: MOVB (R1)+, (R0)+ ; Copy UFD name to spawn buffer SOB R2, 60$ ; Until the whole thing is copied ; Append the rest of the original command line MOV #GETMCR+G.MCRB, R1 ; Load incoming cmd buffer addr in R1 MOV GMCLEN, R2 ; Load command length in R2 70$: MOVB (R1)+, (R0)+ ; Copy a byte from source to target SOB R2, 70$ ; Until all is copied ; Calculate the length of the generated command line SUB #CMDLIN, R0 ; Subtract buffer base address from R0 MOV R0, CMDLEN ; And save the generated command length ; Convert the command line to upper case MOV #CMDLIN, R0 ; Load input buffer address in R0 MOV #CMDLIN, R1 ; Load output buffer address in R1 MOV CMDLEN, R2 ; Load command length in R2 CALL $CVTUC ; Convert line to upper case .IF DF D$$BUG ; If debugging support enabled ; Print the generated command line on the invoking terminal MOV #CMDLIN, TTYOUT+Q.IOPL ; Load command line address in QIO DPB MOV CMDLEN, TTYOUT+Q.IOPL+2 ; Load command line length in QIO DPB DIR$ #TTYOUT ; Print the command on the terminal .ENDC ; DF D$$BUG .PAGE .SBTTL * Spawn Command Line ; Check the generated command line to make sure it's not too long CMP CMDLEN, #80. ; Is command line more than 80 chars? BLOS 80$ ; If not, proceed with it PRINT MS04 ; "Generated command too long to spawn" EXST$S #EX$ERR ; Exit with error status ; Attempt an RPOI$ of the command line to the MCR CLI 80$: MOV CMDLEN, REQTSK+R.POBL ; Load command length into DPB DIR$ #REQTSK ; Attempt to pass the command line .IF DF D$$BUG ; If debugging enabled ; If the RPOI$ fails, dump a message on the invoking terminal MOV #DB01A, R0 ; Load output field address in R0 MOV $DSW, R1 ; Load failing DSW into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude PRINT DB01 ; Dump the debugging message .ENDC ; DF D$$BUG ; RPOI$ failed, since it should have forced us to exit. Try a Spawn. MOV CMDLEN, SPNTSK+S.PWCL ; Load command length into DPB DIR$ #SPNTSK ; Attempt to pass the command line TST $DSW ; Did the Spawn succeed? BPL 90$ ; If so, just exit PRINT MS01 ; "Unable to spawn offspring task" 90$: EXST$S #EX$SUC .PAGE .SBTTL FLYINS Flying Installs .SBTTL * Find Task File ; Load the user's running UIC into the UFD search table FLYINS: MOV #TSKTBL+4, R0 ; Point at UFD group output field MOVB TSKBUF+G.TSGC, R1 ; Load group code byte into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude INC R0 ; Point past separating comma MOVB TSKBUF+G.TSPC, R1 ; Load user code byte into R1 MOV SP, R2 ; Force no zero suppression CALL $CBTMG ; Convert binary byte to octal magnitude ; Search all devices and UFDs in the table for vanilla, FSL and RES tasks MOV #TSKTBL, R5 ; Load device/UFD table address in R5 ; Load and parse the next device spec address into the dataset descriptor 10$: MOV R5, WLDDDS+2 ; Load device spec address into DDS 20$: CMPB (R5)+, #': ; Found separating colon yet? BNE 20$ ; If not, go look again, my boy MOV R5, WLDDDS+0 ; Load address one past colon into DDS SUB WLDDDS+2, WLDDDS+0 ; Subtract device address, giving length MOV #WLDFDB, R0 ; Load wildcard FDB address in R0 MOV #TSKLUN, F.LUN(R0) ; Stick working LUN into FDB MOV #WLDFDB+F.FNB, R1 ; Load filename block address in R1 MOV #WLDDDS, R2 ; Load dataset descriptor addr in R2 CLR R3 ; Don't use a default filename block CALL .PRSDV ; Parse the info into the wildcard FNB ; Load and parse the next UFD spec address into the dataset descriptor MOV R5, WLDDDS+6 ; Load UFD spec address into DDS 30$: CMPB (R5)+, #'] ; Found terminating bracket yet? BNE 30$ ; If not, go look again, my boy MOV R5, WLDDDS+4 ; Load address one past colon into DDS SUB WLDDDS+6, WLDDDS+4 ; Subtract UFD address, giving length MOV #WLDFDB, R0 ; Load wildcard FDB address in R0 MOV #WLDFDB+F.FNB, R1 ; Load filename block address in R1 MOV #WLDDDS, R2 ; Load dataset descriptor addr in R2 CLR R3 ; Don't use a default filename block CALL .PRSDI ; Parse the info into the wildcard FNB ; Look for the FCSFSL version first MOV #TSKFSL, WLDDDS+10. ; Load FSL taskname address into DDS MOV TSKLEN, WLDDDS+8. ; Load vanilla taskname length into DDS ADD #3, WLDDDS+8. ; Because it's an FSL task (we hope) CALL WLDFND ; See if we can find the task image BCC 40$ ; If we found it, go run it ; Check for an FCSRES version next MOV #TSKRES, WLDDDS+10. ; Load RES taskname address into DDS MOV TSKLEN, WLDDDS+8. ; Load vanilla taskname length into DDS ADD #3, WLDDDS+8. ; Because it's an FSL task (we hope) CALL WLDFND ; See if we can find the task image BCC 40$ ; If we found it, go run it ; Finally try a non-FSL version MOV #TSKNAM, WLDDDS+10. ; Load vanilla taskname address into DDS MOV TSKLEN, WLDDDS+8. ; Load vanilla taskname length into DDS CALL WLDFND ; See if we can find the task image BCC 40$ ; If we found it, go run it ; Didn't find it. Set the next UFD string up and go try again. TSTB (R5) ; Out of device/directory specs yet? BNE 10$ ; If not, go try the next 3 tasknames ; After all that work, no task found? Return to the caller RETURN ; Return to the caller .PAGE .SBTTL * Build Command Line ; Build the spawn command line with a preceding RUNb 40$: MOV #CMDLIN, R0 ; Load spawn command buffer addr in R0 MOV #RUNPFX, R1 ; Load RUN prefix string addr in R1 CALL MOVSTR ; Move the prefix string ; Copy the task file's device name to the spawn buffer MOV WLDDDS+2, R1 ; Load DDS device name address in R1 MOV WLDDDS+0, R2 ; Load DDS device name length in R2 50$: MOVB (R1)+, (R0)+ ; Copy device name to spawn buffer SOB R2, 50$ ; Until the whole thing is copied ; Copy the task file's UFD name to the spawn buffer MOV WLDDDS+6, R1 ; Load DDS UFD name address in R1 MOV WLDDDS+4, R2 ; Load DDS UFD name length in R2 60$: MOVB (R1)+, (R0)+ ; Copy UFD name to spawn buffer SOB R2, 60$ ; Until the whole thing is copied ; Copy the task file's file name to the spawn buffer MOV WLDDDS+10., R1 ; Load DDS taskname address in R1 MOV R1, R3 ; Copy it into R3 for later use MOV WLDDDS+8., R2 ; Load DDS task name length in R2 SUB #4, R2 ; Don't copy the .TSK extension! 70$: MOVB (R1)+, (R0)+ ; Copy task name to spawn buffer SOB R2, 70$ ; Until the whole thing is copied ; Append a trailing /TASK=xxx MOV #TSKSFX, R1 ; Load task suffix string addr in R1 CALL MOVSTR ; Move the suffix string MOVB (R3)+, (R0)+ ; Append the first 3 chars of taskname MOVB (R3)+, (R0)+ ; MOVB (R3)+, (R0)+ ; ; Get LUN info for TI: so we can stick in the V, T, H and unit # DIR$ #GTINFO ; Get terminal information MOVB LUNBUF+G.LUNA, (R0)+ ; Stick in the terminal type MOVB LUNBUF+G.LUNU, R1 ; Load the terminal unit number in R1 MOV #11010, R2 ; Radix 8, width 2, no ldg 0 suppress CMP R1, #10 ; Terminal number more than 10 octal? BHIS 80$ ; If so, convert with field width 2 MOV #5010, R2 ; Convert with field width 1 80$: CALL $CBTA ; Convert binary to ASCII ; Append a trailing /CMD=", the command line, and final " MOV #CMDSFX, R1 ; Load command suffix string addr in R1 CALL MOVSTR ; Move the suffix string MOV #GETMCR+G.MCRB, R1 ; Load incoming cmd buffer addr in R1 MOV GMCLEN, R2 ; Load command length in R2 90$: MOVB (R1)+, (R0)+ ; Copy a byte from source to target SOB R2, 90$ ; Until all is copied MOVB #'", (R0)+ ; And append the trailing double quote ; Calculate the length of the generated command line SUB #CMDLIN, R0 ; Subtract buffer base address from R0 MOV R0, CMDLEN ; And save the generated command length ; Convert the command line to upper case MOV #CMDLIN, R0 ; Load input buffer address in R0 MOV #CMDLIN, R1 ; Load output buffer address in R1 MOV CMDLEN, R2 ; Load command length in R2 CALL $CVTUC ; Convert line to upper case .IF DF D$$BUG ; If debugging support enabled ; Print the generated command line on the invoking terminal MOV #CMDLIN, TTYOUT+Q.IOPL ; Load command line address in QIO DPB MOV CMDLEN, TTYOUT+Q.IOPL+2 ; Load command line length in QIO DPB DIR$ #TTYOUT ; Print the command on the terminal .ENDC ; DF D$$BUG .PAGE .SBTTL * Spawn Command Line ; Check the generated command line to make sure it's not too long CMP CMDLEN, #80. ; Is command line more than 80 chars? BLOS 100$ ; If not, proceed with it PRINT MS04 ; "Generated command too long to spawn" EXST$S #EX$ERR ; Exit with error status ; Attempt an RPOI$ of the command line to the MCR CLI 100$: MOV CMDLEN, REQTSK+R.POBL ; Load command length into DPB DIR$ #REQTSK ; Attempt to pass the command line ; RPOI$ failed, since it should have forced us to exit. Try a Spawn. MOV CMDLEN, SPNTSK+S.PWCL ; Load command length into DPB DIR$ #SPNTSK ; Attempt to pass the command line TST $DSW ; Did the Spawn succeed? BPL 110$ ; If so, just exit PRINT MS01 ; "Unable to spawn offspring task" 110$: EXST$S #EX$SUC .PAGE .SBTTL MOVSTR Move ASCIZ String ; MMM MMM OOOOOOOO VV VV SSSSSSSSS TTTTTTTTTT RRRRRRRRR ; MMM MMM OOOOOOOO VV VV SSSSSSSSS TTTTTTTTTT RRRRRRRRR ; MMMM MMMM OO OO VV VV SS TT RR RR ; MMMM MMMM OO OO VV VV SS TT RR RR ; MM MM MM OO OO VV VV SSSSSSSS TT RRRRRRRRR ; MM MM MM OO OO VV VV SSSSSSSS TT RRRRRRRRR ; MM MM OO OO VV VV SS TT RR RR ; MM MM OO OO VV VV SS TT RR RR ; MM MM OO OO VVVV SS TT RR RR ; MM MM OO OO VVVV SS TT RR RR ; MM MM OOOOOOOO VV SSSSSSSS TT RR RR ; MM MM OOOOOOOO VV SSSSSSSS TT RR RR ; MOVSTR - Move ASCIZ String ; ; This subroutine moves an ASCIZ string pointed to by R1 to the area ; pointed to by R0. ; ; Inputs: R1 - Address of input ASCIZ string ; R0 - Address of output buffer ; ; Outputs: R0 - Next free byte in output buffer ; ; Register dispositions: R1 modified ; ; Variable dispositions: None modified MOVSTR: MOV R1, -(SP) ; Save R1 on the stack 10$: TSTB (R1) ; At end of string yet? BEQ 20$ ; If so, go exit copy loop MOVB (R1)+, (R0)+ ; Copy a byte from source to target BR 10$ ; And loop until all are copied 20$: MOV (SP)+, R1 ; Restore R0 from the stack RETURN ; Return to the caller .PAGE .SBTTL PASCA2 Pass to Next Catchall ; PASCA2 - Pass Incoming Command Line to Secondary Catchall ; ; This subroutine passes the incoming command line to the next catchall ; task in line, ...CAn. The next catchall name is determined by adding ; 1 to the third ASCII character in the taskname. If this task isn't ; running as a CAxxxx task, then it tries to pass to ...CA0 instead. ; ; Inputs: GMCLEN - Incoming command line length ; ; Outputs: None ; ; Register dispositions: Who cares? This is a terminal routine. ; ; Variable dispositions: Same here. ; Decide whether to pass to ...CA0 or to the next catchall ...CAn PASCA2: CMP MYNAME, #"CA ; Am I running as a secondary catchall? BNE 1$ ; If not, pass to ...CA0 ; Build and convert the next catchall's name from our running name MOVB MYNAME+2, CANAME+5 ; Make next task name identical to ours INCB CANAME+5 ; Now bump the catchall number up by 1 MOV #CANAME, R0 ; Load next name buffer address in R0 MOV #1, R1 ; Accept periods in R50 conversion CALL $CAT5 ; Convert ASCII to Radix-50 MOV R1, REQCA2+R.POTK ; Load first half into RPOI$ DPB MOV R1, SPNCA2+S.PWTN ; Load first half into SPWN$ DPB MOV #1, R1 ; Accept periods in R50 conversion CALL $CAT5 ; Convert ASCII to Radix-50 MOV R1, REQCA2+R.POTK+2 ; Load second half into RPOI$ DPB MOV R1, SPNCA2+S.PWTN+2 ; Load second half into SPWN$ DPB ; Load command buffer length into DPBs 1$: MOV GMCLEN, REQCA2+R.POBL ; Load command length into RPOI$ DPB MOV GMCLEN, SPNCA2+S.PWCL ; Load command length into SPWN$ DPB INC REQCA2+R.POBL ; Pass RPOI$ with the terminator char .IF DF D$$BUG ; If debugging enabled ; Dump the taskname of the next catchall on the invoking terminal MOV #CANAME, R0 ; Load taskname field address in R0 MOV #DB03A, R1 ; Load output field address in R1 MOV #6, R2 ; Copy 6 bytes 2$: MOVB (R0)+, (R1)+ ; Copy a byte from source to target SOB R2, 2$ ; Until all are copied PRINT DB03 ; Dump the debugging message .ENDC ; DF D$$BUG ; Attempt to pass the command line to the next catchall DIR$ #REQCA2 ; Attempt to pass the command line ; RPOI$ failed, since it should have forced us to exit. Try a Spawn. DIR$ #SPNCA2 ; Attempt to pass the command line ; Next catchall not installed, so we'd better tell user the command is bad PRINT MS05 ; "Invalid command" EXST$S #EX$SUC .PAGE .SBTTL WLDFND Wildcard File Finder ; WW WW LL DDDDDDDD FFFFFFFFFF NN NN DDDDDDDD ; WW WW LL DDDDDDDD FFFFFFFFFF NN NN DDDDDDDD ; WW WW LL DD DD FF NNNN NN DD DD ; WW WW LL DD DD FF NNNN NN DD DD ; WW WW LL DD DD FFFFFFFF NN NN NN DD DD ; WW WW LL DD DD FFFFFFFF NN NN NN DD DD ; WW WW WW LL DD DD FF NN NNNN DD DD ; WW WW WW LL DD DD FF NN NNNN DD DD ; WWWW WWWW LL DD DD FF NN NNN DD DD ; WWWW WWWW LL DD DD FF NN NNN DD DD ; WWW WWW LLLLLLLLLL DDDDDDDD FF NN NN DDDDDDDD ; WWW WWW LLLLLLLLLL DDDDDDDD FF NN NN DDDDDDDD ; WLDFND - Wildcard DDS File Specification Finder ; ; This subroutine attempts to find a file of the filename specified in ; the wildcard dataset descriptor. ; ; Inputs: WLDFDB - Wildcard search FDB ; WLDDDS - Wildcard search DDS ; ; Outputs: Carry set on error, clear if file found ; ; Register dispositions: None modified ; ; Variable dispositions: WLDFDB modified WLDFND: CALL $SAVAL ; Save R0 - R5 ; Parse the filename into the filename block for .FIND's use MOV #WLDFDB, R0 ; Load wildcard FDB address in R0 MOV #WLDFDB+F.FNB, R1 ; Load filename block address in R1 CLR N.FNAM+2(R1) ; Zero the second and third words of CLR N.FNAM+4(R1) ; the filename block from old name BIC #^C, N.STAT(R1) ; Wipe old bits in status word MOV #WLDDDS, R2 ; Load dataset descriptor addr in R2 CLR R3 ; Don't use a default filename block CALL .PRSFN ; Parse the info into the wildcard FNB BCS 40$ ; If parse failed, go exit .IF DF D$$BUG ; If debugging enabled ; Print the name of the file we're currently searching MOV R0, -(SP) ; Save R0 on the stack MOV R1, -(SP) ; Save R1 on the stack MOV R2, -(SP) ; Save R2 on the stack MOV #DB00A, R0 ; Load search buffer address in R0 MOV WLDDDS+2, R1 ; Load DDS device name address in R1 MOV WLDDDS+0, R2 ; Load DDS device name length in R2 10$: MOVB (R1)+, (R0)+ ; Copy device name to buffer SOB R2, 10$ ; Until the whole thing is copied ; Copy the task file's UFD name to the spawn buffer MOV WLDDDS+6, R1 ; Load DDS UFD name address in R1 MOV WLDDDS+4, R2 ; Load DDS UFD name length in R2 20$: MOVB (R1)+, (R0)+ ; Copy UFD name to buffer SOB R2, 20$ ; Until the whole thing is copied ; Copy the task file's file name to the spawn buffer MOV WLDDDS+10., R1 ; Load DDS taskname address in R1 MOV R1, R3 ; Copy it into R3 for later use MOV WLDDDS+8., R2 ; Load DDS task name length in R2 30$: MOVB (R1)+, (R0)+ ; Copy task name to buffer SOB R2, 30$ ; Until the whole thing is copied MOV #DB00, TTYOUT+Q.IOPL ; Load string address into print DPB MOV R0, TTYOUT+Q.IOPL+2 ; Load termination address in print DPB SUB #DB00, TTYOUT+Q.IOPL+2 ; Now the DPB contains message length DIR$ #TTYOUT ; Print the debugging message MOV (SP)+, R2 ; Restore R2 from the stack MOV (SP)+, R1 ; Restore R1 from the stack MOV (SP)+, R0 ; Restore R0 from the stack .ENDC ; DF D$$BUG ; Parse succeeded; see if we can .FIND the task image file CALL .FIND ; Is there such a file? 40$: RETURN ; Return with carry showing yes/no .END FLYENT