.ENABL LC .TITLE MC3 - Aux command dispatcher .IDENT /04.01/ .NLIST BEX ;+ ; Title: MC3 - Auxillary MCR command dispatcher ; Version: 04.01 (for RSX11M V3.2) ; Author: Greg Thompson (DEC SWS) ; Date: 7/21/80 ; ; MC3 is a slightly modified version of MC2 (from NASA/Ames BAYLUG ; DECUS submission) that does not do transparent command line submission ; and therefore doesn't need any IND or executive enhancements to run. ; ; MC3 takes command lines for which MCR can not find an installed task ; for and further processes these commands for which would have otherwise ; received an "MCR -- TASK NOT IN SYSTEM" error message. It operates as ; the catch-all task "...CA.". MC3 requires that the spawn directive be ; sysgened into the system for it to work. ; MC3 first examines its internal command translation table for the ; entered command name. If the command is found in the table it is ; processed by an internal routine and in most cases spawned to MCR as ; some other command. If the command is not found then a search is made ; for a file "command.*;*" where command is the entered command name. ; The search is made in a number of directories as specified by the table ; SRCH below. Changes in the search strategy can be made by changing this ; table. If an .TSK extension is found the task is installed with it ; marked to be removed on exit and it is invoked via spawn using the ; command line that invoked MC3. If an .CMD extension is found an @ ; is issued on the command file. If no suitable file is found an "MC3 -- ; Command not found." error message is returned. ; Because of the spawn directive became available with RSX version 3.2 ; this program was re-written to be non-privileged. In addition more ; flexability is provided in selecting the desired search strategy as to ; where it looks for tasks to invoke. ; ; Assemble: ; MAC [12,24]MC3,[12,34]MC3/-SP=[1,1]EXEMC/ML,[12,10]MC3 ; ; Build: ; TKB ; TKB>[1,54]MC3/-FP/CP=[12,24]MC3 ; TKB>/ ; TKB>UNITS=3 ; TKB>ASG=SY:1 ; TKB>ASG=TI:2 ; TKB>STACK=64 ; TKB>TASK=...CA. ; TKB>PRI=160 ; TKB>// ; ; Revisions: ; ; 03.02 13-JAN-80 Greg Thompson ; Added check to prevent infinite recurions. ; Modified it to use STLO$ directive when waiting on SPWN$ ; Don't let MC3 invoke itself. ; ; 04.01 21-JUL-80 Greg Thompson ; Version that doesn't use "INS task/RUN=REX" enhancements ; so that it will run on a non modified system. But ; the dynamic command line passing features wont be there. ;- .PAGE ; ; Macros ; .MCALL QIOW$,DIR$,GMCR$,EXIT$S,EXST$S .MCALL SPWN$,GTSK$,GLUN$,WTSE$S,STLO$S,ALUN$ .MCALL UCBDF$,LBLDF$ .MCALL FSRSZ$,FINIT$,FDBDF$,FDOP$A .MCALL READ$,OFID$R,GET$,CLOSE$,WAIT$ ; UCBDF$ ; Define UCB offsets LBLDF$ ; Define label block offsets ; ; Local macros ; .MACRO CALLR SUBR JMP SUBR .ENDM ; ; Equates ; MAXDTH = 113000 ; Max (e.x. CA.X10) MC3 taskname ; Value is RAD50 1st char code ; To catch infinite recursions... LUNFL = 1 ; LUN for file operations LUNTI = 2 ; LUN for TI: output LUNXX = 3 ; LUN for checking for valid device EFFIL = 1 ; Event flag for file operations EFTI = 2 ; Event flag for TI operations SPWEF = 3 ; Event flag to wait for spawn on SPWMK = 4 ; Mask for SPWEF MINLEN = 3 ; Minimum length for internal command MAXL = 9. ; Max # of chars for a command name SPWNL = 79. ; Maximum spawn command buffer length CR = 015 ; ASCII carriage return LF = 012 ; ASCII line feed ESC = 033 ; ASCII escape character SPA = 040 ; ASCII space MC3A = 020040 ; Two ASCII spaces ; .PAGE ; ; Table controlling search for .CMD, .PRV or .TSK files ; ; Format: .WORD DEVXX ; Pointer to device string ; .WORD DIRXXX ; Pointer to directory string ; .WORD options ; Options word where: ; VFYTSK = 1 ; Verify that .TSK file found is executable. MUSTPR = 2 ; If user not privileged don't look here. TSKPRV = 4 ; If verified task priv, user must also be. EQUUIC = 10 ; Skip if default UIC = protection UIC. CHKDEV = 20 ; Check to see if device exists first. ALWPRV = 40 ; Look for .PRV tasks in this directory ; ; A entry of zero ends the search table in which case an error ; message is printed saying command not found. ; SRCH:: .WORD DEVSY ; First look in SY:[default uic] .WORD DIRDEF ; .WORD VFYTSK!TSKPRV ; .WORD DEVSY ; Second look in SY:[protection uic] .WORD DIRPRO ; (if different from default UIC) .WORD VFYTSK!TSKPRV!EQUUIC ; .WORD DEVCM ; Third look in CM:[1,55] .WORD DIR155 ; .WORD CHKDEV!ALWPRV ; .WORD DEVLB ; Fourth look in system directory .WORD DIR154 ; LB:[1,54] .WORD VFYTSK!TSKPRV!ALWPRV ; .WORD DEVCM ; Fifth look in CM:[1,56] .WORD DIR156 ; .WORD MUSTPR!CHKDEV ; .WORD DEVC1 ; Sixth look in CM1:[1,55] .WORD DIR155 ; .WORD CHKDEV!ALWPRV ; .WORD DEVC1 ; Seventh look in CM1:[1,56] .WORD DIR156 ; .WORD MUSTPR!CHKDEV ; .WORD 0 ; *** End of search table *** ; ; Device and directory strings for above. ; DEVSY: .ASCII /SY0:/ ; Device SY0: DEVLB: .ASCII /LB0:/ ; Device LB0: DEVCM: .ASCII /CM0:/ ; Device CM0: DEVC1: .ASCII /CM1:/ ; Device CM1: DIRDEF: .ASCII /[000,000]/ ; User default directory DIRPRO: .ASCII /[000,000]/ ; User protection directory DIR154: .ASCII /[001,054]/ ; Directory of system files DIR155: .ASCII /[001,055]/ ; Directory of system wide files DIR156: .ASCII /[001,056]/ ; Directory of system files (priv user only) .EVEN .PAGE ; ; Table of supported file extensions ; ; Format: .RAD50 /ext/ ; RAD50 extension name ; .WORD Pext ; Address of routine to process it ; EXTABL: .RAD50 /CMD/ ; Indirect command files .WORD PCMD ; .RAD50 /PRV/ ; Privilege task permission .WORD PPRV ; .RAD50 /TSK/ ; Task image files .WORD PTSK ; .RAD50 / / ; End of extension table .WORD 0 ; ; ; File system stuff ; FSRSZ$ 0 ; NO FILE is opened IN MC3 *** FDB: FDBDF$ ; Define a FDB for .FIND FDOP$A LUNFL,MC3T,,FO.RD ; Init file open section ; MC3T: .WORD 4 ; Dataset descriptor DEVPTR: .WORD 0 ; Pointer to device name .WORD 9. ; DIRPTR: .WORD 0 ; Pointer to directory name COML: .WORD 0 ; Length of command string .WORD COMAND ; (Dataset name) ; ; Get command line DPB and buffer ; GMCR: GMCR$ ; Get command line BUF = GMCR+2 ; Buffer address BPTR: .WORD 0 ; Pointer into command line ; ; Output SPAWN command line buffer ; CMDLEN: .WORD 0 ; Spawn command length CMDLIN: .BLKB SPWNL ; Spawn command buffer .EVEN ; ; Other variables and DPBs ; OPTION: .WORD 0 ; Holds options word from SRCH table GTSK: GTSK$ TSKBUF ; Get task parameters for UIC info TSKBUF: .BLKW 16. ; Task info buffer GLUN: GLUN$ LUNTI,LUNBUF ; Get LUN information for PRIV info LUNBUF: .BLKW 6. ; TI: LUN information ALUN: ALUN$ LUNXX,XX,0 ; For checking out device name ESB: .BLKW 8. ; Exit status block for Spawn SPWN: SPWN$ MCR...,,,,,SPWEF,,ESB,CMDLIN,0,0 ; Spawn DPB RDSB: .BLKW 2 ; READ$ I/O status block VBNADR: .WORD 0 ; Virtual block number to label block 0 .WORD 1 ; is relative block 1 of task file LBLBF: .BLKB 512. ; Buffer to hold task label block 0 ; .PAGE ; ; MC3s error messages ; WERR: QIOW$ IO.CCO,LUNTI,EFTI,,,,<0,0,040> ERR1: .ASCIZ /MC3 -- Command line missing./ ERR2: .ASCII /MC3 -- Command "/ ERRCMD: .BLKB 24. ERR2R: .ASCIZ /" not found./ ERR3: .ASCIZ !MC3 -- System doesn't support parent/offspring tasking.! ERR4: .ASCIZ /MC3 -- No system pool space./ ERR5: .ASCIZ /MC3 -- Unable to SPWN$ an INStall./ ERR6: .ASCIZ /MC3 -- Install of task failed./ ERR7: .ASCIZ /MC3 -- GTSK$ or GLUN$ directive failed./ ERR8: .ASCII /MC3 -- Non-privileged user trying to / .ASCIZ /invoke privileged task./ ERR9: .ASCIZ /MC3 -- Found task image not executable./ ERR10: .ASCIZ /MC3 -- Unable to SPWN$ to the task./ ERR11: .ASCII /MC3 -- Maximum MC3 recursion depth exceeded./ .ASCIZ / Possible infinite recursion./ ERR12: .ASCIZ /MC3 -- Not allowed to invoke MC3 using MC3./ .EVEN .PAGE ; ; Internal command processing table (Alphabetical order) ; CTABL: .WORD ATS,CATS ; Active tasks list .WORD CHD,CUIC ; Change directory (UIC) .WORD DELETE,CDELET ; Delete (file) .WORD DIRECT,CDIREC ; Directory .WORD DLG,CDLG ; "DEV /LOG" .WORD ERASE,CERASE ; Erase (file) .WORD FREE,CFREE ; Free .WORD POOL,CPOOL ; Display Pool .WORD PURGE,CPURGE ; Purge (files) .WORD RENAME,CRENAM ; Rename (file) .WORD SPOOL,CSPOOL ; Spool file .WORD TRUNC,CTRUNC ; Truncate file .WORD TYPE,CTYPE ; Type (file to terminal) .WORD UIC,CUIC ; Uic (set/display uic) .WORD 0 ; End of table ; ; Internal command strings ; ATS: .ASCIZ /ATS/ ; Active tasks list CHD: .ASCIZ /CHD/ ; Change directory (UIC) DELETE: .ASCIZ /DELETE/ ; Delete (file) DIRECT: .ASCIZ /DIRECTORY/ ; Directory DLG: .ASCIZ /DLG/ ; "DEV /LG" ERASE: .ASCIZ /ERASE/ ; Erase FREE: .ASCIZ /FREE/ ; Free POOL: .ASCIZ /POOL/ ; Display pool PURGE: .ASCIZ /PURGE/ ; Purge (files) RENAME: .ASCIZ /RENAME/ ; Rename (file) SPOOL: .ASCIZ /SPOOL/ ; Spool file TRUNC: .ASCIZ /TRUNCATE/ ; Truncate file TYPE: .ASCIZ /TYPE/ ; Type (file to terminal) UIC: .ASCIZ /UIC/ ; Uic (set /uic) ; ; Misc strings ; COMAND: .ASCII /xxxxxxxxx.*;*/ ; Command string INSOPT: .ASCIZ !/RUN=REM! ; INS command task options INS: .ASCIZ /INS / ; CMD: .ASCIZ /.CMD / ; PIP: .ASCIZ /PIP / ; SDA: .ASCIZ /;*/ ; SDE: .ASCIZ !/DE! ; SLI: .ASCIZ !/LI! ; SFR: .ASCIZ !/FR! ; SPU: .ASCIZ !/PU! ; TRU: .ASCIZ !/TR! ; SRE: .ASCIZ !/RE! ; SSP: .ASCIZ !/SP! ; PIPTI: .ASCIZ /PIP TI:=/ ; SETUIC: .ASCIZ !SET /UIC! ; ACTALL: .ASCIZ !ACT /ALL! ; STPOOL: .ASCIZ !SET /POOL! ; DEVLOG: .ASCIZ !DEV /LOG! ; .EVEN .PAGE ; ; Auxillary MCR command dispatcher code ; ; Process command line ; MC3:: DIR$ #GMCR ; Get command line BCC 20$ ; Got a command line 10$: MOV #ERR1,R0 ; Command line missing error. JMP ERROR ; ; ; Got our command line, move command name, figure length ; 20$: MOV #BUF,BPTR ; Initialize buffer pointer CLR R2 ; Init command length counter MOV #COMAND,R0 ; R0 -> place to put command string MOV #MC3A,(R0) ; Init first six chars of command name MOV #MC3A,2(R0) ; To all spaces (since it gets $CAT5ed) MOV #MC3A,4(R0) ; 30$: CALL GETC ; Get next character BCS 50$ ; End of command string CMPB #'/,R1 ; Is it a slash "/" for options? BEQ 48$ ; Yes, end of command name MOVB R1,(R0)+ ; Put character in buffer INC R2 ; Bump character count CMP R2,#MAXL ; Maximum length of comand reached? BLT 30$ ; No, get another character 40$: CALL GETC ; Yes, flush rest of command to next space BCC 40$ ; BR 50$ ; ; 48$: DEC BPTR ; Backup over character 50$: MOV R2,COML ; Save command length BEQ 10$ ; If zero - command missing error CMP R2,#MINLEN ; Is string too short to be a local command BLT GETFIL ; Yes ; ; Now look for command in internal command table ; MOV #CTABL-2,R0 ; R0 -> command table 60$: MOV #COMAND,R1 ; R1 -> entered command MOV COML,R2 ; R2 = command length TST (R0)+ ; Skip over last dispatch address MOV (R0)+,R3 ; R3 -> current possible command BEQ GETFIL ; End of table if ptr zero 70$: CMPB (R1)+,(R3)+ ; Compare a byte of the strings BLO GETFIL ; If < current entry - not in table BHI 60$ ; If > current entry - try next command DEC R2 ; This char matches BGT 70$ ; More string to compare JMP @(R0)+ ; Match - dispatch to handling routine ; .PAGE ; ; Look for command.*;* to process command ; GETFIL: FINIT$ ; Init FSR MOV COML,R1 ; Get length of command MOVB #'.,COMAND(R1) ; Put ".*;*" on end of command string MOVB #'*,COMAND+1(R1) ; MOVB #';,COMAND+2(R1) ; MOVB #'*,COMAND+3(R1) ; ADD #4,COML ; Include ".*;*" in string length DIR$ #GLUN ; Get TI: information (to see if privileged) BCS 10$ ; Woops error where not expected. DIR$ #GTSK ; Get user's UICs BCS 10$ ; Woops error where not expected. CMP TSKBUF+G.TSTN+2,#MAXDTH ; See if we are too deep BLOS 20$ ; No, its ok MOV #ERR11,R0 ; Not ok, report error BR 15$ ; ; 10$: MOV #ERR7,R0 ; Error where not expected 15$: JMP ERROR ; Issue error message ; 20$: MOV TSKBUF+G.TSPC,R3 ; Convert user's default UIC MOV #DIRDEF,R2 ; Get ptr to place to put UIC MOV #1,R4 ; Don't zero suppress, do add seperators CALL .PPASC ; Convert UIC to ASCII MOV TSKBUF+G.TSDU,R3 ; Convert user's protection UIC MOV #DIRPRO,R2 ; Get ptr to place to put UIC MOV #1,R4 ; Don't zero suppress, do add seperators CALL .PPASC ; Convert UIC to ASCII MOV #SRCH,R5 ; Set up to search for file NEXT: MOV (R5)+,DEVPTR ; Set selected device BEQ NOTFND ; Did not find a file MOV (R5)+,DIRPTR ; Set selected directory MOV (R5)+,OPTION ; Save options word BIT #MUSTPR,OPTION ; Must the user be privileged? BEQ 10$ ; No BIT #U2.PRV,LUNBUF+G.LUCW+2 ; Yes, is he privileged? BEQ NEXT ; No, skip this entry 10$: BIT #EQUUIC,OPTION ; Skip if DEFUIC = PROUIC? BEQ 20$ ; No CMP TSKBUF+G.TSPC,TSKBUF+G.TSDU ; Do uics equal? BEQ NEXT ; Yes, don't check same directory twice 20$: BIT #CHKDEV,OPTION ; First validate device? BEQ FIND ; No MOV DEVPTR,R0 ; Yes, get pointer to device name MOV (R0)+,ALUN+A.LUNA ; Put device name in MOVB (R0)+,R0 ; Get unit number SUB #'0,R0 ; Convert to binary MOV R0,ALUN+A.LUNU ; Put unit number in DIR$ #ALUN ; Try to assign device BCS NEXT ; Skip entry if invalid device ; ; Try to find a command.*;* file to process command ; Return carry set if no file found else ; carry clear with (R3) = address of routine to process it ; FIND: MOV #FDB,R0 ; Get address of FDB MOV #,R1 ; Address of file name block MOV #MC3T,R2 ; Dataset descriptor address CLR R3 ; No default filename block MOV R5,-(SP) ; Save R5 through call CALL .PARSE ; Parse file name MOV (SP)+,R5 ; Restore R5 BCS NFIND ; Error occured BITB #FD.DIR,F.RCTL(R0) ; Directory device? BEQ NFIND ; No, don't search if no directory ... NEXTF: MOV #FDB,R0 ; Restore FDB address MOV #,R1 ; Restore FNB address MOV R5,-(SP) ; Save R5 through call CALL .FIND ; Look for a file MOV (SP)+,R5 ; Restore R5 BCS NFIND ; Nothing found ; ; Found something, check for valid extension ; MOV ,R2 ; Get file name extension MOV #EXTABL,R3 ; Get ptr to table of supported extensions 40$: CMP R2,(R3)+ ; Match? BNE 50$ ; No TST (R3) ; Make sure its not end of table BEQ NEXTF ; End of table, skip this file JMP @(R3)+ ; Match, dispatch to routine ; 50$: TST (R3)+ ; End of table? BNE 40$ ; No, check next entry BR NEXTF ; Yes, skip this file ; ; Nothing in this directory, try another ; NFIND: JMP NEXT ; Try next directory ; ; No file anywhere found to process command ; NOTFND: MOV #COMAND,R0 ; Stick command name in error message MOV #ERRCMD,R1 ; Where to put it MOV COML,R2 ; Length of command name SUB #4,R2 ; Don't include ".*;*" 10$: MOVB (R0)+,(R1)+ ; Move command in DEC R2 ; All moved? BNE 10$ ; No, move another character MOV #ERR2R,R0 ; Now stick rest of message on. 20$: MOVB (R0)+,(R1)+ ; Append end of message BNE 20$ ; It is terminated with a null MOV #ERR2,R0 ; Command not found error BR ERROR ; Issue error message ; .PAGE ; ; Get next character from MCR command line ; ; Character returned in R1 ; Carry set if end of current string ; GETC: MOVB @BPTR,R1 ; Get next byte INC BPTR ; Point at next character CMPB #SPA,R1 ; Space? BEQ 20$ ; Yes, set carry but advance pointer CMPB #ESC,R1 ; Escape character at end? BEQ 10$ ; Yes CMPB #CR,R1 ; CR at end? BNE 30$ ; No, return good character 10$: DEC BPTR ; Don't move past end of command line 20$: SEC ; Indicate end of current string RETURN ; Return to caller (char in R1) ; 30$: CLC ; Indicate good character received RETURN ; Return to caller (char in R1) ; ; Issue an error message to TI: and exit ; ; R0 = address of error message (zero terminated) ; ERROR: MOV R0,R1 ; Copy buffer address 10$: TSTB (R1)+ ; End of message? BNE 10$ ; No SUB R0,R1 ; Yes, figure length DEC R1 ; Don't count the zero in MOV R0,WERR+Q.IOPL ; Yes, set message address MOV R1,WERR+Q.IOPL+2 ; Set message length DIR$ #WERR ; Issue error message MOV #EX$SEV,ESB ; Set exit status to severe error EXIT: EXST$S ESB ; Try to exit with status EXIT$S ; else just exit ; .PAGE ; ; Co-routine to set up and spawn an MCR command buffer ; ; Calls back caller with R0 -> buffer of where to put command. ; Caller fills command buffer with command and then returns. ; Address of where to jump to after SPWN$ follows call. ; GMCRBF: MOV (SP)+,R5 ; Get return address MOV (R5)+,-(SP) ; Addr to return too after SPAWNing MOV #CMDLIN,R0 ; Set ptr to where to put command CLR CMDLEN ; Initialize command length MOV #^RMCR,SPWN+S.PWTN ; Initialize task name MOV #^R...,SPWN+S.PWTN+2 ; CALL (R5) ; Call caller back MOV CMDLEN,SPWN+S.PWCL ; put command length in DPB BEQ 20$ ; Nothing to spawn DIR$ #SPWN ; Spawn command to MCR BCC 10$ ; Directive accepted MOV #ERR4,R0 ; Assume pool error CMPB #IE.UPN,$DSW ; Not suficient pool space? BEQ ERROR ; Yes, report the error MOV #ERR3,R0 ; Assume illegal directive CMPB #IE.SDP,$DSW ; Invalid directive error? BEQ ERROR ; Yes, report the error 5$: MOV #ERR5,R0 ; No, some other spawn error BR ERROR ; ; 10$: STLO$S 0,#SPWMK ; Wait for spawn to complete BCC 20$ ; Wait completed CMPB #IE.SDP,$DSW ; Illegal directive? BNE 5$ ; No, some other spawn error? WTSE$S #SPWEF ; Yes, try WTSE$S instead BCS 5$ ; Branch if error 20$: MOV ESB,R0 ; Get return status in R0 MOV (SP)+,R5 ; Get addr to return too after SPAWNing BEQ EXIT ; Just exit if zero JMP (R5) ; else return to that address next ; .PAGE ; ; Routines to support given file extensions ; ; Indirect command file found ; PCMD: CALL GMCRBF ; Get a buffer for a MCR command .WORD 0 ; Just exit when done MOVB #'@,(R0)+ ; Issue @ command for file INC CMDLEN ; CALL DEVDIR ; Output device name and directory CALL MVCMD ; Output command name MOV #CMD,R1 ; Output ".CMD " extension CALL MVSTR ; CALL MVRST ; Output rest of command string RETURN ; Return and queue command to MCR ; ; Allow non-priv user to invoke privileged task permission ; ; The finding of a "command.PRV" file in a directory makes ; MC3 to act as if that user is privileged for further searches ; through the directory chains and allows him to invoke ; "command.TSK" even if it is privileged. ; PPRV: BIT #ALWPRV,OPTION ; Is a .PRV file allowed in this directory? BEQ 10$ ; No, just skip over it BIS #U2.PRV,LUNBUF+G.LUCW+2 ; Yes, make user privileged for MC3 10$: JMP NEXTF ; Continue searching in this directory ; ; Task image found ; PTSK: CALL GMCRBF ; Get a buffer for a INS command .WORD DOCMD ; Where to return after queueing INS command CMP #^RMC3, ; Trying to invoke MC3? BNE 10$ ; No MOV #ERR12,R0 ; Yes, don't let him do it JMP ERROR ; Issue error ; ; Create the INS command to temporarily INStall the task ; 10$: MOV #INS,R1 ; Output "INS " CALL MVSTR ; CALL DEVDIR ; Output device and directory CALL MVCMD ; Output command name MOV #INSOPT,R1 ; Output "/RUN=REM" CALL MVSTR ; ; ; Verify task image if required ; Assumes FDB is set up for OPEN$R ; VFY: BIT #VFYTSK,OPTION ; Yes, should I make sure task is executable? BEQ VFY5 ; No, just hope for the best ; OFID$R #FDB,,,#FD.RWM,,,VFY3 ; Open task image file ; READ$ #FDB,#LBLBF,#512.,#VBNADR,#EFFIL,#RDSB,,VFY2 ; Read label blk ; WAIT$ #FDB,#EFFIL,#RDSB,VFY2 ; TSTB RDSB ; Did read work? ; BMI VFY2 ; No ; CMPB LBLBF+L$BSYS,#4 ; Is it an RSX11M V3.x task? ; BHIS VFY2 ; No, can't execute task then ; TST LBLBF+L$BDAT+2 ; Do a couple validity checks ; BEQ VFY2 ; Month can't be zero ; CMP LBLBF+L$BDAT+2,#12. ; or can it be > 12. ; BHI VFY2 ; Branch if month is bad ; CMP LBLBF+L$BDAT+4,#31. ; Check day ; BHI VFY2 ; Branch if day is bad ; BIT #TS$NHD!TS$ACP,LBLBF+L$BFLG ; Is it an ACP or have no header? ; BEQ VFY4 ; No, looks good then ;VFY2: CLOSE$ #FDB ; Close the file ;VFY3: MOV #ERR9,R0 ; Task image found not executable error ; JMP ERROR ; Issue the error message ; ;VFY4: CLOSE$ #FDB ; Close the file ; BIT #TS$PRV,LBLBF+L$BFLG ; Is task privileged? ; BEQ VFY5 ; No, let it rip! ; BIT #U2.PRV,LUNBUF+G.LUCW+2 ; Yes, is it a privileged user? ; BNE VFY5 ; Yes, let him invoke it. ; BIT #TSKPRV,OPTION ; Allow non-priv user to run priv task? ; BEQ VFY5 ; Yes, let him do it. ; MOV #ERR8,R0 ; No, issue error message. ; JMP ERROR ; Non-priv user trying to invoke priv task ; VFY5: RETURN ; Return and queue command to MCR ; ; INS command issued, now spawn our newly installed task up ; DOCMD: CMP R0,#EX$SUC ; Was INS successful? BEQ 210$ ; Yes MOV #ERR6,R0 ; No, INS failed error JMP ERROR ; ; BR 260$ ; Report the error ; 210$: ; CALL GMCRBF ; Set up for another command ; .WORD 0 ; This won't be used ; CALL MVCMD ; Output command name ; MOVB #SPA,(R0)+ ; Add blank on end ; INC CMDLEN ; Include it in length ; CALL MVRST ; Output rest of command line ; MOV CMDLEN,SPWN+S.PWCL ; put command length in DPB ; CMPB #'.,COMAND+1 ; Make task name atleast 3 chars ; BNE 220$ ; so terminal number works on end ; MOVB #'.,COMAND+2 ; This magic works since ".*" on end ;220$: MOVB LUNBUF+G.LUNA,COMAND+3 ; Next comes Txx part of name ; MOVB LUNBUF+G.LUNU,R0 ; Handle unit number ; MOV R0,R1 ; Copy it ; BIC #177700,R0 ; Mask off high bits ; ASR R0 ; Move over 3 bits ; ASR R0 ; ; ASR R0 ; ; BIC #177770,R1 ; ; ADD #'0,R1 ; Make it an ASCII digit ; MOVB R1,COMAND+4 ; Assume high digit zero ; MOVB #SPA,COMAND+5 ; ; TST R0 ; Is high digit zero? ; BEQ 230$ ; Yes ; ADD #'0,R0 ; No, make high digit an ASCII digit ; MOVB R0,COMAND+4 ; ; MOVB R1,COMAND+5 ; ;230$: MOV #COMAND,R0 ; Convert 1st 3 chars of taskname ; MOV PC,R1 ; Accept periods ; CALL $CAT5 ; Convert name to RAD50 ; MOV R1,SPWN+S.PWTN ; Put task name in SPWN$ DPB ; CLR R1 ; No longer accept periods ; CALL $CAT5 ; Convert name to RAD50 ; MOV R1,SPWN+S.PWTN+2 ; Set second half of task name ;240$: DIR$ #SPWN ; Spawn command to MCR ; BCC 250$ ; Directive accepted ; MOV #ERR4,R0 ; Assume pool error ; CMPB #IE.UPN,$DSW ; Not suficient pool space? ; BEQ 260$ ; Yes, report the error ; MOV #ERR3,R0 ; Assume illegal directive ; CMPB #IE.SDP,$DSW ; Invalid directive error? ; BEQ 260$ ; Yes, report the error ; CMPB #IE.ACT,$DSW ; Task already active? ; BNE 255$ ; No, some other spawn error ; ADD #50*50,SPWN+S.PWTN+2 ; Yes, try next possible task name ; BR 240$ ; And try SPWN$ again ; ; Spawn accepted ; ;250$: STLO$S 0,#SPWMK ; Wait for spawn to complete ; BCC 270$ ; Wait completed ; CMPB #IE.SDP,$DSW ; Illegal directive? ; BNE 255$ ; No, some other spawn error? ; WTSE$S #SPWEF ; Yes, try WTSE$S instead ; BCC 270$ ; Branch if no error ;255$: MOV #ERR10,R0 ; No, some other spawn error ;260$: JMP ERROR ; ; ; Task completed ; 270$: JMP EXIT ; Return its exit status ; .PAGE ; ; Internal command routines ; ; ; ATS = "ACT /ALL" command ; CATS: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #ACTALL,R1 ; Output "ACT /ALL" CALLR MVSTR ; and queue command ; ; DELETE file command ; CDELET: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SDE,R1 ; Add "/DE" on end CALLR ENDSTR ; Then queue command to MCR ; ; DIRECTORY command ; CDIREC: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SLI,R1 ; Add "/LI" on end CALLR ENDSTR ; Then queue command to MCR ; ; DLG = "DEV /LOG" command ; CDLG: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #DEVLOG,R1 ; Output "DEV /LOG" command CALLR MVSTR ; Then queue command to MCR ; ; ERASE command ; CERASE: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL FNAMES ; Process file names MOV #SDE,R1 ; Add "/DE" on end CALLR ENDSTR ; Then queue command to MCR ; ; FREE space command ; CFREE: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SFR,R1 ; Add "/FR" on end CALLR ENDSTR ; Queue MCR command ; ; POOL = "SET /POOL" display pool command ; CPOOL: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #STPOOL,R1 ; Output "SET /POOL" CALLR MVSTR ; and queue the command ; ; PURGE files ; CPURGE: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SPU,R1 ; Add "/PU" on end CALLR ENDSTR ; Queue MCR command ; ; TRUNCATE files ; CTRUNC: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #TRU,R1 ; Add "/TR" on end CALLR ENDSTR ; Queue MCR command ; ; RENAME file command ; CRENAM: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SRE,R1 ; Add "/RE" on end CALLR ENDSTR ; Queue MCR command ; ; SPOOL file command ; CSPOOL: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIP,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line MOV #SSP,R1 ; Add "/SP" on end CALLR ENDSTR ; Queue MCR command ; ; TYPE file to terminal command ; CTYPE: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #PIPTI,R1 ; Output "PIP" CALL MVSTR ; CALL MVRST ; Output rest of line RETURN ; Queue MCR command ; ; CHD and UIC set/display command ; CUIC: CALL GMCRBF ; Get MCR command buffer .WORD 0 ; Exit when done MOV #SETUIC,R1 ; Output "SET /UIC" CALL MVSTR ; 10$: CALL GETCS ; Get a character BCS 50$ ; No UIC specified - display UIC then CALL TNUM ; Is it a number? BCC 10$ ; No MOVB #'=,(R0)+ ; Yes, output the "=[" MOVB #'[,(R0)+ ; MOVB R1,(R0)+ ; and the number ADD #3,CMDLEN ; CALL GETCS ; Get a character BCS 45$ ; End of line CALL TNUM ; Is it a number? BCC 20$ ; No, assume its the comma MOVB R1,(R0)+ ; Yes, output second digit INC CMDLEN ; CALL GETCS ; Get a character BCS 45$ ; End of line CALL TNUM ; Is it another number? BCC 20$ ; No, assume its the comma MOVB R1,(R0)+ ; Yes, output third digit INC CMDLEN ; 20$: MOVB #',,(R0)+ ; Add "," to output INC CMDLEN ; 30$: CALL GETCS ; Get a character BCS 45$ ; End of line CALL TNUM ; A number? BCC 30$ ; No, flush till we find one MOVB R1,(R0)+ ; Yes, output first digit 2nd half INC CMDLEN ; CALL GETCS ; Get a character BCS 45$ ; End of line CALL TNUM ; A number? BCC 40$ ; No MOVB R1,(R0)+ ; Yes, output second digit INC CMDLEN ; CALL GETCS ; Get a character BCS 45$ ; End of line CALL TNUM ; A number? BCC 40$ ; No MOVB R1,(R0)+ ; Yes output third digit INC CMDLEN ; 40$: CALL GETCS ; Now look for terminator BCC 40$ ; 45$: MOVB #'],(R0)+ ; Add trailing ']' INC CMDLEN ; 50$: RETURN ; Queue MCR command ; .PAGE ; ; Output subroutines ; ; ; Output device name and directory ; DEVDIR: MOV DEVPTR,R1 ; Device name is first MOVB (R1)+,(R0)+ ; d MOVB (R1)+,(R0)+ ; d MOVB (R1)+,(R0)+ ; n MOVB (R1)+,(R0)+ ; : MOV DIRPTR,R1 ; Directory is next MOVB (R1)+,(R0)+ ; [ MOVB (R1)+,(R0)+ ; g MOVB (R1)+,(R0)+ ; g MOVB (R1)+,(R0)+ ; g MOVB (R1)+,(R0)+ ; , MOVB (R1)+,(R0)+ ; m MOVB (R1)+,(R0)+ ; m MOVB (R1)+,(R0)+ ; m MOVB (R1)+,(R0)+ ; ] ADD #13.,CMDLEN ; 13. chars where output RETURN ; ; ; Output command name ; MVCMD: MOV COML,R2 ; Get command length SUB #4,R2 ; Don't include ".*;*" ADD R2,CMDLEN ; Include chars output in command length MOV #BUF,R1 ; In filename which is next 10$: MOVB (R1)+,(R0)+ ; Move a byte of command name DEC R2 ; Subtract one from length BGT 10$ ; Still characters left, continue RETURN ; ; ; Output rest of command string ; MVRST: CALL MVCHR ; Move a character BCC MVRST ; For the rest of the command line RETURN ; ; ; Output a string ; R1 -> string to output (zero terminated) ; MVSTR: CMP CMDLEN,#SPWNL ; Output full? BEQ 10$ ; Yes, don't output any more INC CMDLEN ; Remember how much we output MOVB (R1)+,(R0)+ ; Move a byte BNE MVSTR ; Not end if not zero DEC R0 ; Do not include zero byte DEC CMDLEN ; 10$: RETURN ; ; ; Move a character from input to output ; - Return carry set if end of string ; - Char moved retuned in R1 ; MVCHR: CLR R1 ; Init R1 CMP CMDLEN,#SPWNL ; Output full? BEQ CSET ; Yes, don't output any more CALL GETC ; Get a character BCC 10$ ; Not delimiter CMPB #SPA,R1 ; Was it just a space? BNE CSET ; No, real end of line 10$: MOVB R1,(R0)+ ; Output character INC CMDLEN ; Add this character to output CCLR: CLC ; No, indicate not end of line RETURN ; ; ; GETC with no carry set on space ; GETCS: CALL GETC ; Get a character BCS 10$ ; Carry set RETURN ; ; 10$: CMPB #SPA,R1 ; Space? BEQ CCLR ; Yes CSET: SEC ; No, set carry and return RETURN ; ; ; Insert a string before last output character ; INSERT: CMPB #CR,@BPTR ; Is the character a CR? BEQ 10$ ; Yes, don't need to backup CMPB #ESC,@BPTR ; How about a ESC? BEQ 10$ ; Yes, don't backup DEC BPTR ; Backup one character on input DEC R0 ; Backup one character on output DEC CMDLEN ; 10$: CALL MVSTR ; Output our string CALLR MVCHR ; Put back the character ; ; Process file names adding ;* where necessary ; FNAMES: CLR R2 ; R2 flag = 1 - ; seen, 2 - in directory 10$: CALL MVCHR ; Move a character BCS 30$ ; End of line reached CMPB #';,R1 ; Is it the semi-colon BNE 20$ ; No BIS #1,R2 ; Yes, remember it BR 10$ ; Continue ; 20$: BIT #2,R2 ; Are we in a directory name? BNE 22$ ; Yes, then comma doesn't end a filename CMPB #',,R1 ; Have we reached the end of a file name BNE 22$ ; No CALL 40$ ; Yes, add ";*" if necessary BR 10$ ; Continue ; 22$: CMPB #'[,R1 ; Are we entering a directory? BNE 24$ ; No BIS #2,R2 ; Yes, remember it BR 10$ ; Continue ; 24$: CMPB #'],R1 ; Leaving a directory? BNE 10$ ; No BIC #2,R2 ; Yes, remember it BR 10$ ; Continue ; 30$: CALLR 40$ ; Add ";*" if necessary and return to caller ; 40$: BIT #1,R2 ; Do we need to output a ";*" ? BEQ 60$ ; Yes BIC #1,R2 ; No, reset flag RETURN ; Return from 40$ call ; 60$: MOV #SDA,R1 ; Yes, insert ";*" before character CALLR INSERT ; And return from call ; ; Add a 3 character string to the end of a line ; ENDSTR: CMP CMDLEN,#SPWNL-3 ; Is there room for string? BLE 10$ ; Yes, just insert it MOV #SPWNL,CMDLEN ; No, force it to end of string MOV #CMDLIN+SPWNL-3,R2 ; MOVB (R1)+,(R2)+ ; Move the three chars to end of string MOVB (R1)+,(R2)+ ; MOVB (R1)+,(R2)+ ; RETURN ; ; 10$: CALLR MVSTR ; Insert string at end ; ; Test to see if a character is a octal number ; ; Carry set if it is ; TNUM: CMPB R1,#'0 ; Check lower bound BLO CCLR ; Not a number CMPB R1,#'7 ; Check upper bound BHI CCLR ; Not a number BR CSET ; Number - set carry ; .END MC3 ; End of dispatcher code