.ENABL LC .TITLE MC2 - Aux command dispatcher .IDENT /04.05/ .NLIST BEX ;+ ; Title: MC2 - Auxillary MCR command dispatcher ; Version: 03.02 (for RSX11M V3.2) ; Author: Greg Thompson (DEC SWS) ; Modified: Daniel Steinberg (SRI International) ; Date: 12/30/79 ; ; MC2 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.". MC2 requires that the spawn directive be ; sysgened into the system for it to work. (RPOI$ is also used if present.) ; ; Other modifications to the system with which MC2 interacts: ; INSHD.SLP, INSLB.SLP, INSPS.SLP ; enhancements to the INStall processor ; DREIF ; modification to EXEC module. ; ; MC2 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 MC2. If an .CDF extension is found an @ ; is issued on the command file. If no suitable file is found an "MC2 -- ; 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]MC2,[12,34]MC2/-SP=[1,1]EXEMC/ML,[12,10]MC2 ; ; Build: ; TKB ; TKB>[1,54]MC2/-FP/CP=[12,24]MC2 ; 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 STSE$ directive when waiting on SPWN$ ; Don't let MC2 invoke itself. ; 04.00 01-OCT-80 Daniel Steinberg ; Modified search path. ; Changed .CMD extension to .CLI for more explicit commands. ; Added /-LI switch to @file commands. ; Added .CSY and .TSY synonym extensions for simplified file ; synonym maintenance. ; Added code to support enhanced SPWN$ directive so that MC2 ; can exit and keep offspring status and T3.MCR straight. ; Added recursion protection for task spawning. ; Added NOMULT and NUMULP options to prevent multiple copies ; of user tasks getting spawned by accident. ; 04.01 23-APR-81 SNLL ; Modified search path again ; Changed .CLI to .CDF -- supported .CMD also ; 04.04 02-JUL-82 SNLL ; Modified to work under V4. (REMOVED -1 event flag) ; (Use RPOI$ instead.) ; Also changed /-LI to /QU (/QUIET). ; 04.05 19-JUL-82 SNLL ; Added code to prevent searching current or protection uic's ; when they are uic's where systems may be ([xx,54] xx < 11). ; Also allows search path to be easily modified to skip an entry ; with ZAP. ;- .SBTTL MACROS ; ; Macros ; .MCALL QIOW$,DIR$,GMCR$,EXIT$S,EXST$S .MCALL RQST$,SPWN$,GTSK$,GLUN$,WTSE$S,STSE$S,ALUN$ .MCALL RPOI$ ; 04.04 .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 = ^RX ; Max (e.x. CA.X10) MC2 taskname ; Value is RAD50 1st char code SPWDTH = ^RZ ; Max (e.g. PIPZ10) user taskname ; (matches modification to INStall) ; To catch infinite recursions... PRINT = 1 ; RPOI error print flag 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 MC2A = 020040 ; Two ASCII spaces ; ;+ ; Macro: CBTAR2 NCHAR,RADIX,SIGN,FILL ; Set R2 equal to mask required for system library routine $CBTA (Convert ; Binary (value in R1) To Ascii (string address in R0)) ; Where: ; NCHAR - number of characters to result from conversion ; RADIX - radix of conversion....one of: ; O -- octal ; D -- decimal ; H -- hexadecimal ; B -- binary ; n -- numeric base n ; SIGN - flag for signed or unsigned value conversion....one of: ; U -- unsigned ; S -- signed ; FILL - flag for zero-fill characteristic....one of: ; ZERO -- fill with zeroes ; SPACE -- fill with spaces ; NONE -- left-justify string with no fill characters ; ; Example: ; CBTAR2 4,D,S,NONE ;convert 4 signed decimal digits ; ;if R1 < 1000., print < 4 digits ; ; CBTAR2 3,8.,U,ZERO ;convert 3 unsigned octal digits ; ;right-justified with leading zeroes ;- .MACRO CBTAR2 NCHAR,RADIX,SIGN,FILL .NLIST $$$NCH = NCHAR * 4000 $$$RDX = -1 $$$SGN = -1 $$$FIL = -1 .IIF IDN,RADIX,O $$$RDX=8. .IIF IDN,RADIX,D $$$RDX=10. .IIF IDN,RADIX,H $$$RDX=16. .IIF IDN,RADIX,B $$$RDX=2 .IIF LT,$$$RDX $$$RDX=RADIX .IIF IDN,SIGN,U $$$SGN=0 .IIF IDN,SIGN,S $$$SGN=400 .IIF LT,$$$SGN .ERROR ;BAD SIGN ARG IN CBTAR2 .IIF IDN,FILL,ZERO $$$FIL=1000 .IIF IDN,FILL,SPACE $$$FIL=3000 .IIF IDN,FILL,NONE $$$FIL=0 .IIF LT,$$$FIL .ERROR ;BAD FILL ARG IN CBTAR2 $$$$R2=$$$NCH!$$$RDX!$$$SGN!$$$FIL .LIST MOV #$$$$R2,R2 ;SET CBTA CONVERSION CHARACTERISTICS .ENDM .SBTTL Search Table ; ; Table controlling search for .CDF, .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 NOMULT = 100 ; Multiple copies of .TSK or .TSY not allowed NOMULP = 200 ; Multiple copies allowed if user is privileged SKPDIR = 100000 ; Skip this directory. (** Must be sign bit **) ; ; 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 ; CUROPT: .WORD VFYTSK!TSKPRV!NOMULP ; .WORD DEVSY ; Second look in SY:[protection uic] .WORD DIRPRO ; (if different from default UIC) PROOPT: .WORD VFYTSK!TSKPRV!NOMULP!EQUUIC ; .WORD DEVLB ; Third look in system directory .WORD DIR155 ; LB:[1,55] .WORD VFYTSK!TSKPRV ; .WORD DEVLB ; Fourth look in system directory .WORD DIR156 ; LB:[1,56] .WORD VFYTSK!MUSTPR ; .WORD DEVLB ; Then look in system directory .WORD DIR105 ; LB:[1,5] .WORD VFYTSK!TSKPRV ; .WORD DEVCM0 ; Then look in system directory .WORD DIR155 ; CM0:[1,55] .WORD CHKDEV!VFYTSK!TSKPRV ; .WORD DEVCM0 ; Then look in system directory .WORD DIR156 ; CM0:[1,56] .WORD VFYTSK!MUSTPR!CHKDEV!SKPDIR ; Skip this for now. .WORD DEVCM0 ; Then look in system directory .WORD DIR105 ; CM0:[1,5] .WORD CHKDEV!VFYTSK!TSKPRV ; XXENT:: .WORD DEVXX ; .WORD DIRXX ; .WORD CHKDEV!VFYTSK!TSKPRV ; YYENT:: .WORD DEVYY ; .WORD DIRYY ; .WORD CHKDEV!VFYTSK!TSKPRV!SKPDIR ; SYSENT:: .WORD DEVDB ; Then look in system UIC .WORD DIRSYS ; DB:[1,54] .WORD VFYTSK!TSKPRV!ALWPRV ; .WORD 0 ; *** End of search table *** ; ; Device and directory strings for above. ; DEVTB:: DEVSY: .ASCII /SY0:/ ; Device SY0: DEVLB: .ASCII /LB0:/ ; Device LB0: DEVCM0: .ASCII /CM0:/ ; Device CM0: DEVDB: .ASCII /DB0:/ ; Device DB0: DEVXX:: .ASCII /DB0:/ ; SPARE DEVICE DEVYY:: .ASCII /YY0:/ ; SPARE DEVICE ;*** DEVC1: .ASCII /CM1:/ ; Device CM1: DIRTB:: DIRDEF: .ASCII /[000,000]/ ; User default directory DIRPRO: .ASCII /[000,000]/ ; User protection directory ;*** DIR154: .ASCII /[001,054]/ DIR155: .ASCII /[001,055]/ ; Directory of system wide files DIR156: .ASCII /[001,056]/ ; Directory of system files (priv user only) DIR105: .ASCII /[001,005]/ ; Directory of system wide files DIRSYS::.ASCII /[001,054]/ ; System directory DIRXX:: .ASCII /[000,000]/ ; SPARE UIC DIRYY:: .ASCII /[000,000]/ ; SPARE UIC .EVEN .SBTTL Table of supported file extensions ; ; Table of supported file extensions ; ; Format: .RAD50 /ext/ ; RAD50 extension name ; .WORD Pext ; Address of routine to process it ; EXTABL: .RAD50 /TSK/ ; Task image files .WORD PTSK ; .RAD50 /CMD/ ; Indirect command files .WORD PCMD ; .RAD50 /CDF/ ; Indirect command files .WORD PCDF ; .RAD50 /PRV/ ; Privilege task permission .WORD PPRV ; .RAD50 /TSY/ ; Task image synonym .WORD PTSY .RAD50 /CSY/ ; Command file synonym .WORD PCSY .RAD50 / / ; End of extension table .WORD 0 ; ; ; File system stuff ; FSRSZ$ 1 ; Only one file at a time is opened FDB: FDBDF$ ; Define a FDB for .FIND FDOP$A LUNFL,MC2T,,FO.RD ; Init file open section ; MC2T: .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 ERRLIN: .BLKB SPWNL+42 ; RPOI error buffer. .EVEN ; ; Other variables and DPBs ; FLAGS:: .WORD 0 ; Flag Word, bit 0 set = print SYNFLG: .WORD 0 ; Storage for synonym file strings OPTION: .WORD 0 ; Holds options word from SRCH table GTSK: GTSK$ TSKBUF ; Get task parameters for UIC info CHKTN: .BLKW 2 ; Temp storage for task name 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 RPOI: RPOI$ MCR...,,,,,,CMDLIN,0,RP.OEX!RP.OAL ; 04.04 ; 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 ; .SBTTL Error Messages ; ; MC2s error messages ; WERR: QIOW$ IO.CCO,LUNTI,EFTI,,,,<0,0,040> ERR1: .ASCIZ /MC2 -- Command line missing./ ERR2: .ASCII /MC2 -- Command "/ ERRCMD: .BLKB 24. ERR2R: .ASCIZ /" not found./ ERR3: .ASCIZ !MC2 -- System doesn't support parent/offspring tasking.! ERR4: .ASCIZ /MC2 -- No system pool space./ ERR5: .ASCIZ /MC2 -- Unable to SPWN$ an INStall./ ERR6: .ASCII /MC2 -- INStall of task "/ ER6T: .ASCIZ /......" failed./ ERR7: .ASCIZ /MC2 -- GTSK$ or GLUN$ directive failed./ ERR8: .ASCII /MC2 -- Non-privileged user trying to / .ASCIZ /invoke privileged task./ ERR9: .ASCIZ /MC2 -- Task image not executable./ ERR10: .ASCII /MC2 -- Unable to SPWN$....Directive error: / ER10N: .ASCIZ /-##./ ERR11: .ASCII /MC2 -- Maximum MC2 recursion depth exceeded./ .ASCIZ / Possible infinite recursion./ ERR12: .ASCIZ /MC2 -- Not allowed to invoke MC2 using MC2./ ERR13: .ASCII /MC2 -- Task "/ ER13T: .ASCIZ /......" already active./ ERR20: .ASCII /MC2 -- *** Task "/ ER20T: .ASCIZ /......" may still be INStalled ***/ ; ; RPOI error reporting ; ERRPOI: .ASCIZ /*** MC2 -- RPOI error / ERSZ1=.-ERRPOI ERRPOT: .ASCIZ /*** Task: / ERSZ2=.-ERRPOT ERRPOC: .ASCIZ /*** Command: / ERSZ3=.-ERRPOC .EVEN .SBTTL Internal Command Processing Table ; ; 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 ; .EVEN COMAND: .ASCII "xxxxxxxxx.*;*" ; Command string INSOPT: .ASCIZ "/EST=NO/RUN=REX/PAR=GEN" ; INS command task options INSNOM: .ASCII "/TASK=" INSTKN: .ASCIZ "......" INS: .ASCIZ "INS " ; CMD: .ASCIZ ".CMD " ; CDF: .ASCIZ ".CDF/QU " ; 04.04 TSY: .ASCIZ ".TSY" CSY: .ASCIZ ".CSY/QU " ; 04.04 PIP: .ASCIZ "PIP " ; SDA: .ASCIZ ";*" ; SDE: .ASCIZ "/SD" ; 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 .SBTTL Auxillary Command Dispatcher Code ; ; Auxillary MCR command dispatcher code ; ; Process command line ; MC2:: 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 #MC2A,(R0) ; Init first six chars of command name MOV #MC2A,2(R0) ; To all spaces (since it gets $CAT5ed) MOV #MC2A,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 ; .SBTTL File Search Code ; ; 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 separators 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 separators CALL .PPASC ; Convert UIC to ASCII CALL DIRCHK ; Check current uic (prevent a possible crash). 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 BLT NEXT ; Skip directory if sign bit is set. 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 #MC2T,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 ; .SBTTL Get Next Character Routine ; ; 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: CALL ERMSG ; Print error msg MOV #EX$SEV,ESB ; Set exit status to severe error EXIT: EXST$S ESB ; Try to exit with status EXIT$S ; else just exit ; ERMSG: 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 RETURN .SBTTL Co-Routine to SPAWN an MCR Command ; ; 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. ; .ENABL LSB 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 ; MOV #^RMCR,RPOI+R.POTK ; Set MCR... task name ; 04.04 MOV #^R...,RPOI+R.POTK+2 ; 04.04 BICB #RP.OAL,RPOI+R.POSC ; Clear "PASS-ALL" bit for MCR BISB #RP.ONX,RPOI+R.POSC ; Set "PASS first connection" bit. 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 SPWERR: 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 ; ; SPWAIT: 10$: STSE$S #SPWEF ; 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 to after SPAWNing BEQ EXIT ; Just exit if zero JMP (R5) ; else return to that address next .DSABL LSB ; ; ; Co-routine to set up and spawn a task, then exit if no error ; (This is not especially useful under standard V3.2 SPWN$.... ; MC2 now uses RPOI$ where the parent's OCBs and MCR prompt are ; requeued to the offspring.) ; ; Call with: CALL GCPWNx (where x is M or T) ; .WORD errret (where errret is executed only if error) ; GSPWNM: MOV #^RMCR,SPWN+S.PWTN ;Set MCR... task name MOV #^R...,SPWN+S.PWTN+2 MOV #^RMCR,RPOI+R.POTK ; Set MCR... task name ; 04.04 MOV #^R...,RPOI+R.POTK+2 ; 04.04 BICB #RP.OAL,RPOI+R.POSC ; Clear "PASS-ALL" bit for MCR BISB #RP.ONX,RPOI+R.POSC ; Set "PASS first connection" bit. GSPWNT: MOV (SP),R5 ;Get return addr MOV (R5)+,(SP) ;Set error return address MOV #CMDLIN,R0 ;Set address of command line CLR CMDLEN ; and clear former length CALL (R5) ;Call caller back MOV CMDLEN,SPWN+S.PWCL ;Set length of command MOV CMDLEN,RPOI+R.POBL ; 04.04 BEQ EXIT ; just exit GSPWN: DIR$ #RPOI ; 04.04 ; ; Advise of RPOI error for now ; CALL RPOIER ; ; Then try SPAWNing the command ; DIR$ #SPWN ; and try again BCC 90$ ; OK 15$: TST (SP) ;Got an error return? BEQ SPWERR ; nope...print a msg JMP @(SP)+ ; yup....go to it ; 90$: CLR (SP) ;set no return address BR SPWAIT ;and wait for exit status .SBTTL File Extension Support Routines ; ; Routines to support given file extensions ; ; Indirect command file found ; PCDF: MOV #CDF,SYNFLG ; Point to ".CDF/QU" BR PCMDCM ; and join common code PCMD: MOV #CMD,SYNFLG ; Point to ".CMD" BR PCMDCM ; and join common code ; ; CDF command file synonym found ; PCSY: MOV #CSY,SYNFLG ; point to ".CSY/-LI " string PCMDCM: CALL GSPWNM ; 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 SYNFLG,R1 ; Output 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 ; MC2 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 MC2 10$: JMP NEXTF ; Continue searching in this directory ; ; Task image found ; PTSK: CLR SYNFLG ; Clear synonym flag BR PTSKCM ; and join common code ; ; Task image synonym found (xxx.TSY) ; PTSY: MOV #TSY,SYNFLG ; Set address of extra string PTSKCM: CALL GMCRBF ; Get a buffer for a INS command .WORD DOCMD ; Where to return after queueing INS command CMP #^RMC2, ; Trying to invoke MC2? 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 SYNFLG,R1 ; If synonym, this is address of ".TSY" BEQ 12$ ; ...not a synonym CALL MVSTR ; move infile extension 12$: MOV #INSOPT,R1 ; Output "/EST=NO/RUN=REX/PAR=GEN" CALL MVSTR ; MOV R0,SYNFLG ; save command string address for later ; ; 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: 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,CHKTN ; Put task name in SPWN$ DPB CLR R1 ; No longer accept periods CALL $CAT5 ; Convert name to RAD50 MOV R1,CHKTN+2 ; Set second half of task name BIT #NOMULT!NOMULP,OPTION ; Multiple copies allowed? BEQ VFY6 ; Yes...ok BIT #NOMULP,OPTION ; Can priv user do it? BEQ 10$ ; nope...do the check BIT #U2.PRV,LUNBUF+G.LUCW+2 ;Is user priv? BNE VFY6 ; yes...we're ok 10$: MOV #INSTKN,R0 ; point to taskname in command line MOV CHKTN,R1 ; Get target task prefix CALL $C5TA ; convert to ascii MOV CHKTN+2,R1 ;get suffix CALL $C5TA ; and convert (for tt#: check) MOV #INSNOM,R1 ; point to "/TASK=xxxT##" MOV SYNFLG,R0 ; Retrieve command string address CALL MVSTR ; and put it in cmd VFY6: RETURN ; Return and queue command to MCR ; ; CNVTN: MOV SPWN+S.PWTN,R1 ; Get task name CALL $C5TA ; Convert to ASCII MOV SPWN+S.PWTN+2,R1 CALL $C5TA RETURN ; ; INS command issued, now spawn our newly installed task up ; .ENABL LSB DOCMD: MOV CHKTN,SPWN+S.PWTN ; Put task name in SPWN$ DPB MOV CHKTN+2,SPWN+S.PWTN+2 ; Set second half of task name BICB #RP.ONX,RPOI+R.POSC ; Clear "PASS first connection" bit. BISB #RP.OAL,RPOI+R.POSC ; Set "PASS-ALL" bit. MOV CHKTN,RPOI+R.POTK ; Set task name ; 04.04 MOV CHKTN+2,RPOI+R.POTK+2 ; 04.04 CMP R0,#EX$SUC ; Was INS successful? BEQ 210$ ; Yes ; INS failed...either error or task active CMPB INSTKN,#'. ; is task name unchanged? BEQ 205$ ; yes...write normal error msg MOV #ER13T,R0 ; no....write Task already active msg CALL CNVTN ; put in task name MOV #ERR13,R0 BR 270$ 205$: MOV #ER6T,R0 ; some other unknown INS error CALL CNVTN MOV #ERR6,R0 BR 270$ ; Report the error ; 210$: CALL GSPWNT ; Set up for another command .WORD DOCMDA ; Error routine 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 MOV CMDLEN,RPOI+R.POBL ; 04.04 240$: RETURN ; Try and spawn it ; ; ; Error in detaching with a spawn: ; DOCMDA: 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.INS,$DSW ; Task not installed? BEQ 100$ ;...if so, the older version already quit CMPB #IE.ACT,$DSW ; Task already active? BNE 255$ ; No, some other spawn error 100$: CMP SPWN+S.PWTN+2,#SPWDTH ;tried max increment? BHIS 255$ ; yes...error ADD #50*50,SPWN+S.PWTN+2 ; Yes, try next possible task name MOV SPWN+S.PWTN+2,RPOI+R.POTK+2 ; 04.04 MOV #DOCMDA,-(SP) ; push return addr on again JMP GSPWN ; and try again ; ; 255$: MOV #ER10N,R0 ; No, some other spawn error MOVB $DSW,R1 ; Get error code CBTAR2 2,D,S,SPACE ; 2 signed decimal digits CALL $CBTA ; Convert to ASCII MOV #ERR10,R0 260$: CALL ERMSG ; Print msg MOV #ER20T,R0 ; Task left installed...print its name CALL CNVTN MOVB #'?,ER20T+3 ; don't really know the real taskname MOV #ERR20,R0 ; "Task still installed" msg 270$: JMP ERROR ; .DSABL LSB .SBTTL Internal Command Routines ; ; Internal command routines ; ; ; ATS = "ACT /ALL" command ; CATS: CALL GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 GSPWNM ; 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 ; .SBTTL RPOI error printing routine ; ; RPOI error check routine ; RPOIER:: BIT #PRINT,FLAGS ; Is print flag set? BEQ 50$ ; If not, then skip this stuff. MOV #ERRLIN,R0 ; Get address of error message buffer. MOV #ERRPOI,R1 ; Get address of error message. 10$: MOVB (R1)+,(R0)+ ; Copy the next character BNE 10$ ; until all are copied. DEC R0 ; Back up over the NULL. MOVB $DSW,R1 ; Get the RPOI error code. MOV #014010,R2 ; Convert 3 unsigned OCTAL digits. CALL $CBTA SUB #ERRLIN,R0 ; Calculate the line length MOV #ERRLIN,WERR+Q.IOPL ; Set message address . MOV R0,WERR+Q.IOPL+2 ; Set message length . DIR$ #WERR ; Issue error message ; MOV #ERRLIN,R0 ; Get address of error message buffer. MOV #ERRPOT,R1 ; Get address of error message. 20$: MOVB (R1)+,(R0)+ ; Copy the next character BNE 20$ ; until all are copied. DEC R0 ; Back up over the NULL. MOV RPOI+R.POTK,R1 ; Get 1st 3 char. of task name. CALL $C5TA ; Convert them to ASCII. MOV RPOI+R.POTK+2,R1 ; Get next 3 char. CALL $C5TA ; and convert them too. SUB #ERRLIN,R0 ; Calculate the line length. MOV #ERRLIN,WERR+Q.IOPL ; Set message address. MOV R0,WERR+Q.IOPL+2 ; Set message length. DIR$ #WERR ; Issue error message. ; MOV #ERRLIN,R0 ; Get address of error message buffer. MOV #ERRPOC,R1 ; Get address of error message. 30$: MOVB (R1)+,(R0)+ ; Copy the next character BNE 30$ ; until all are copied. DEC R0 ; Back up over the NULL. MOV #CMDLIN,R1 ; Get command line address. MOV CMDLEN,R2 ; Get command line length. BLE 50$ ; Leave if no command line. 40$: MOVB (R1)+,(R0)+ ; Copy the command SOB R2,40$ ; until it's all copied. MOVB #CR,(R0)+ ; Add a MOVB #LF,(R0)+ SUB #ERRLIN,R0 ; Calculate the line length. MOV #ERRLIN,WERR+Q.IOPL ; Set message address . MOV R0,WERR+Q.IOPL+2 ; Set message length . DIR$ #WERR ; Issue error message 50$: RETURN .SBTTL UIC Check Routine ; ; UIC check routine ; DIRCHK: BIC #SKPDIR,CUROPT ; Clear Skip bit for current uic. BIC #SKPDIR,PROOPT ; Clear Skip bit for protection uic. ; Check current directory CMPB #54,TSKBUF+G.TSPC ; Possible system uic ? ([xx,54]) BNE 10$ ; If NE, no. CMPB #11,TSKBUF+G.TSGC ; xx < 11 ? BLE 10$ ; If LE, no. BIS #SKPDIR,CUROPT ; Set skip bit 10$: ; Check protection directory CMPB #54,TSKBUF+G.TSDU ; Possible system uic ? ([xx,54]) BNE 20$ ; If NE, no. CMPB #11,TSKBUF+G.TSDU+1 ; xx < 11 ? BLE 20$ ; If LE, no. BIS #SKPDIR,PROOPT ; Set skip bit 20$: RETURN .SBTTL Output Subroutines ; ; 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 MC2 ; End of dispatcher code