.TITLE CA. -- Catch-all Task .ENABLE LC ;*** ; Author: John P. McGrath ; ANPA Research Institute ; 1350 Sullivan Trail ; Easton, PA 18042 ; ; Copyright 1982 ANPA ; ; Permision is granted to use, copy and modify this program, ; but not for profit. ; ; This program is executed whenever MCR does not know what ; to do with a command. It examines the command, translates ; it to another command, and passes is to "MCR...". .IDENT /1.01/ ;*** When making modifications, update version info in both ; ".IDENT" and in the string "VERS". .GLOBL SYSTSK,SYSCMD,SYSTEC,SYSEDT .GLOBL SYSDEV,SYSUNT .GLOBL PRVVER,NPRVER .NLIST BEX .PAGE .SBTTL Macro definitions ; System macro definitions .MCALL DIR$,GMCR$,QIOW$,EXST$S,RPOI$,NMBLK$,FDBDF$ .MCALL DCBDF$,LCBDF$,UCBDF$,TCBDF$,FDOP$A,FSRSZ$,FINIT$ ;********************************************************************* ; ; CHKFIL: Check if a file exists. If it does, jump ; to 'ACTION', otherwise drop through. The ; file to search for is: DEV:[UFD]NAM.TYP;0 ; ; Input: R0 = FDB address ; R2 = Dataset descriptor address ; R3 = Default filename block address ; ; Dataset descriptor contains 'NAM' ; ; Output: R1,R4 - Destroyed ; ; If file is found: ; ; R0 = Start of command output buffer (OUTBUF) ; UIC = UIC on which file was found ; DEVICE = Device on which file was found ; UNIT = Unit number on which file was found .MACRO CHKFIL,DEV,UNT,UFD,TYP,ACTION,?LBL MOV DEV,N.DVNM(R3) ; Set device name in default filename block MOV UNT,N.UNIT(R3) ; Set device unit number MOV TYP,N.FTYP(R3) ; Set file type MOV UFD,R4 CALL CHKFL ; Search directory BCS LBL ; If file not found JMP ACTION ; File found LBL: .ENDM ;********************************************************************* ; ; MSG: Send a message to the terminal. ; ; MSG NAME ; ; Where "NAME" is defined by the "MSGTXT" macro .MACRO MSG,NAME MOV NAME,QIOW+Q.IOPL+2 ; Length of message MOV #NAME+2,QIOW+Q.IOPL ; Address of message DIR$ #QIOW .ENDM ;********************************************************************* ; ; MSGTXT: Create text for the "MSG" macro. ; Stores length followed by text of message. ; ; NAME: MSGTXT .MACRO MSGTXT,TXT,?LBL .WORD LBL-.-2 .ASCII /TXT/ LBL: .EVEN .ENDM ;********************************************************************* ; ; PUT: Copy a fixed variable ASCII string into the ; command output buffer. Output buffer pointer ; is advanced to the position after the last ; character inserted. ; ; Input: R0 = Output buffer pointer ; SOURCE = Address of string ; LEN = Length of string (possibly zero) ; ; Output: R0 = New output buffer pointer ; R1,R2 - Destroyed .MACRO PUT,SOURCE,LEN,?LBL1,?LBL2 MOV SOURCE,R1 ; Input string MOV LEN,R2 ; Input string length LBL1: TSTB R2 ; How many characters left? BEQ LBL2 ; If no more characters MOVB (R1)+,(R0)+ DEC R2 ; R2 = number of chars left BR LBL1 ; Copy next character LBL2: .ENDM ;********************************************************************* ; ; PUTC: Copy one character into the command output ; buffer and advance the output buffer pointer. ; ; Input: R0 = Command output buffer pointer ; CHAR = Character to insert ; Output: R0 = Points to next character .MACRO PUTC,CHAR MOVB CHAR,(R0)+ .ENDM ;********************************************************************* ; ; PUTN: Convert a one byte unsigned octal number into an ASCII ; string and store it in the command output buffer. The ; number is copied without leading blanks or zeroes. ; ; Input: R0 = Command output buffer pointer ; NUM = Number to convert ; OUTPUT: R0 = Advanced past last output char ; R1,R2 = Destroyed .MACRO PUTN,NUM CLR R1 BISB NUM,R1 ; Get number (no sign extension) MOV #14010,R2 ; $CBTA control word (base=8, fw=3, etc.) CALL $CBTA ; Convert binary to ASCII .ENDM ;********************************************************************* ; ; PUTS: Copy a fixed length ASCII string into the output buffer. ; The output buffer pointer is advanced to the position ; after the last character inserted. ; ; Input: R0 = Output buffer pointer ; SOURCE = Address of string ; Output: R0 = New output buffer pointer ; R1,R2 - Destroyed .MACRO PUTS,SOURCE,LEN,?LBL .IF LE LEN-7 ; If STRING <= 7 chars long MOV SOURCE,R1 .REPT LEN MOVB (R1)+,(R0)+ ; Just use "LEN" MOV instructions .ENDR .IFF ; If > 7 chars PUT SOURCE,#LEN ; PUT uses a loop .ENDC .ENDM ;********************************************************************* ; ; PUTZ: Copy an ASCII string (up to, but not including ; a zero byte) into the command output buffer. ; The output buffer pointer is advanced to the ; position after the last character inserted. ; ; Input: R0 = Output buffer pointer ; SOURCE = Address of string ; Output: R0 = New output buffer pointer ; R1,R2 - Destroyed .MACRO PUTZ,SOURCE,?LBL MOV SOURCE,R1 ; Input string LBL: MOVB (R1)+,(R0)+ TSTB (R1) ; Zero byte? BNE LBL ; If not done .ENDM .PAGE .SBTTL Constant / Data definitions SLUN = 1 ; LUN for file searches MLUN = 5 ; LUN for messages TAB = 11 ; Horizontal tab LF = 12 ; Line feed CR = 15 ; Carriage return BLANK = 40 ; Space character COMMA = 54 ; "," ; Flag bits FL.EXE = 1 ; If set, command is executed FL.DSP = 2 ; If set, command is displayed FL.PRV = 4 ; If set, terminal is privileged ; Offset definitions DCBDF$ ; Device control block LCBDF$ ; Logical assignment control block UCBDF$ ; Unit control block TCBDF$ ; Task control block ; Devices / UIC's SYSTSK: .BYTE 54,1 ; System task UIC = [1,54] SYSCMD: .BYTE 3,1 ; System command UIC = [1,3] SYSTEC: .BYTE 3,1 ; System teco macro UIC = [1,3] SYSEDT: .BYTE 3,1 ; System EDT initializer file UIC = [1,3] SYSDEV: .ASCII /LB/ ; System device SYSUNT: .WORD 0 ; System unit LOGUIC: .BLKW 1 ; Login UIC LOGDEV: .BLKW 1 ; Login device LOGUNT: .BLKW 1 ; Login unit TRMDEV: .BLKW 1 ; Terminal device (TT or VT) TRMUNT: .BLKW 1 ; Terminal unit DEFUIC: .BLKW 1 ; Default UIC (SET /UIC) DEFDEV: .BLKW 1 ; Default device DEFUNT: .BLKW 1 ; Default unit UIC: .BLKW 1 ; UIC of current file DEVICE: .BLKW 1 ; Device of current file UNIT: .BLKW 1 ; Unit of current file ; Files extensions (types) TSK: .RAD50 /TSK/ CMD: .RAD50 /CMD/ TEC: .RAD50 /TEC/ EDT: .RAD50 /EDT/ ; Version (generation) numbers PRVVER: .WORD 1777 ; Maximum version number for privileged terminals NPRVER: .WORD 777 ; Maximum version number for non-privileged terminals MAXVER: .BLKW 1 ; Maximum version number (set to PRVVER or NPRVER) ; Strings for generating commands. STR1: .ASCIZ 'RUN ' STR2: .ASCIZ 'EDT' STR3: .ASCIZ 'RUN $TEC' STR4: .ASCIZ 'RUN $PIP' STR5: .ASCIZ '/TASK=' STR6: .ASCIZ '/CMD="' STR7: .ASCIZ '/CMD="MUN ' STR8: .ASCIZ '/CMD="PIP ' STR9: .ASCIZ '/CMD="PIP TI:=' STR10: .ASCIZ '/LI' STR11: .ASCIZ '/DE' STR12: .ASCIZ 'SET /UIC=[' STR13: .ASCIZ 'Login UFD:' STR14: .ASCIZ 'Default UFD:' STR15: .ASCIZ 'CAT @' STR16: .ASCIZ '/PU' .EVEN ; EDT initializer file EDTINI: .ASCII 'EDTINI' EDTLEN = .-EDTINI ; Messages VERS: MSGTXT ERR1: MSGTXT ERR2: MSGTXT ERR3: MSGTXT ERR4: MSGTXT ERR5: MSGTXT ; Directive parameter blocks and related data QIOW: QIOW$ IO.WVB,MLUN,31,,,,<0,0,40> ; For output messages GMCR: GMCR$ ; Get MCR command line MCRBUF =GMCR+G.MCRB ; Start of command buffer RPOI: RPOI$ MCR...,,,,,,OUTBUF,0,RP.OEX!RP.ONX ; Request & pass offspring DD: ; Dataset descriptor DDDEV: .WORD 0,0 ; Device pointer DDUFD: .WORD 0,0 ; UFD pointer DDNAM: .WORD 0,0 ; File name pointer DFNB: NMBLK$ ; Default file name block FDB: FDBDF$ ; File descriptor block FDOP$A SLUN,DD,DFNB,FO.RD FSRSZ$ 0 ; Command line stuff OUTBUF: .BLKW 150. ; Command and message build area CMDLIN: .BLKW 1. ; Pointer to start of input command line CMDLEN: .BLKW 1. ; Length of input command line ENDCMD: .BLKW 1. ; Pointer input command line terminator CNMLEN: .BLKW 1. ; Length of full command name PARAMS: .BLKW 1. ; Address of parameter list PRMLEN: .BLKW 1. ; Length of parameter list CMD3CH: .BLKW 1. ; 3 character command name (RADIX-50) FLAGS: .WORD 0 ; Flag word DSEXCH: .BYTE '> ; Display and execute character DSPLCH: .BYTE '? ; Display only character .PAGE .SBTTL Subroutines ;********************************************************************* ; ; CHKFL: Perform a directory lookup on a file. If the file has ; a version number greater than or equal to MAXVER, it is ; treated as non-existant. If the file is found, then set ; up for creating command lines ; ; Input: R0 = FDB address ; R2 = Dataset descriptor address ; R3 = Default file name block address ; R4 = Default UIC (Group = high byte, ; Member = low byte) ; ; Output: R1 - Destroyed ; C-Bit = Clear if file found, set otherwise CHKFL: MOV R4,R1 ; Set UIC for .WDFUI CALL .WDFUI ; Set default uic in $$FSR2 MOV R0,R1 ADD #F.FNB,R1 ; Add CALL .PARSE ; Parse file name BCS 10$ ; If error in file name (or no UFD) CALL .FIND ; Search for file BCS 10$ ; If no file found CMP MAXVER,F.FVER(R0) ; Is version number too high BLO 10$ ; Yes ; Set up for generating command line MOV #OUTBUF,R0 ; Set pointer to beginning of output buffer MOV R4,UIC ; Save UIC MOV DFNB+N.DVNM,DEVICE ; Save device name MOV DFNB+N.UNIT,UNIT ; Save unit number 10$: RETURN ;********************************************************************* ; ; DVINFO: Get device information ; ; *** This subroutine must be called from ; *** the system state ; ; Input: R1 = Pointer to device UCB ; ; Output: R1 - Points to re-directed device ; R2 = DCB for device ; R3 = Unit number ; R4,R5 - Destroyed DVINFO: 10$: MOV U.RED(R1),R1 ;; Point to redirected device CMP U.RED(R1),R1 ;; Does redirect point to itself BNE 10$ ;; No - continue following chain MOV U.DCB(R1),R2 ;; R2 := DCB MOV D.UCBL(R2),R4 ;; R4 := length of UCB CLR R3 BISB D.UNIT(R2),R3 ;; R3 := low unit number for DCB MOV D.UCB(R2),R5 ;; R5 := pointer to first UCB for this DCB 20$: CMP R5,R1 ;; Does R5 point to this UCB BEQ 30$ ;; Yes - we are done INC R3 ;; Increment unit number ADD R4,R5 ;; Point to next UCB BR 20$ ;; Try again 30$: RETURN ;********************************************************************* ; ; PUTDEV: Generate the device string ; ; Input: R0 = Output buffer pointer ; DEVICE = Device name ; UNIT = Unit number ; ; Output: R0 = Advanced to character after string ; PUTDEV: PUTS #DEVICE,2 ; Device name TST UNIT ; Is unit number zero? BEQ 10$ ; Yes - Skip unit number PUTN UNIT ; Unit number 10$: PUTC #': ; : RETURN ;********************************************************************* ; ; PUTTSK: Generate the /TASK=xxxTnn (or Vnn) Parameter for the ; run command, from the terminal number. E.G. "T4", ; "T15" or "V5". R0 contains the pointer to the output ; string. It is advanced to the position passed the last ; character generated. If the command name is less than ; 3 characters long, fill out to three characters with dots. PUTTSK: PUTZ #STR5 ; /TASK= MOV CMD3CH,R1 ; RADIX-50, 3 character command name CALL $C5TA ; xxx MOV #3,R1 ; 3 character minimum SUB CNMLEN,R1 ; R1 := number of chars to fill (if R1 > 0) MOV R0,R2 ; Output buffer pointer 10$: DEC R1 ; Character count BMI 20$ ; If no more characters MOVB #'.,-(R2) ; Back up, filling in with dots BR 10$ ; Next character 20$: PUTC TRMDEV ; T or V PUTN TRMUNT ; nn RETURN ;********************************************************************* ; ; PUTUIC: Generate the UIC string ; ; Input: R0 = Output command buffer pointer ; UIC = High byte = group, Low byte = member ; ; Output: R0 = Advanced to character after string ; PUTUIC: PUTC #'[ ; [ PUTN UIC+1 ; Group PUTC <#',> ; , PUTN UIC ; Member PUTC #'] ; ] RETURN .PAGE .SBTTL Entry point CA.: DIR$ #GMCR ; Get command line BCC 10$ ; If command found MSG ERR4 ; No command - display error message JMP ERROR ; And exit 10$: MOV $DSW,R0 ; R0 := length of command ADD #MCRBUF,R0 ; R0 := pointer to terminator MOV R0,ENDCMD FINIT$ ; Initialize FSR CALL $SWSTK,50$ ;; Switch to system state MOV $TKTCB,R0 ;; R0 := TCB address MOV T.UCB(R0),R1 ;; R1 := UCB address for TI: CALL DVINFO ;; Get device info for TI: MOV D.NAM(R2),TRMDEV;; Store device name MOV R3,TRMUNT ;; Store unit number MOV U.LUIC(R1),LOGUIC ;; Store login UIC MOV U.UIC(R1),DEFUIC ;; Store default UIC ; Determine if terminal is privileged and set PRIV flag. ; Set value of MAXVER to PRVVER or NPRVER, depending on ; privilege. BIC #FL.PRV,FLAGS ;; Assume non priveleged MOV NPRVER,MAXVER ;; Set max version number BIT U2.PRV,U.CW2(R1);; Is terminal privileged? BEQ 12$ ;; No BIS #FL.PRV,FLAGS ;; Set priv flag MOV PRVVER,MAXVER ;; Set max version number 12$: ; Scan the logical assignment control blocks (LCB's) for a ; login assignment for this terminal for SY0: MOV $LOGHD,R3 ;; Head of LCB list CLR R0 ;; Indicate no SY0: LCB's found 20$: TST R3 ;; Are there any more LCB's BEQ 30$ ;; No SY0: login assignment found CMP L.UCB(R3),R1 ;; Is LCB for this terminal? BNE 24$ ;; No - skip it CMP L.NAM(R3),#"SY ;; Is logical device "SY"? BNE 24$ ;; No - skip it TSTB L.UNIT(R3) ;; Is it unit 0? BNE 24$ ;; No - skip it TST R0 ;; Is this the first SY0: LCB? BNE 22$ ;; Yes - it's not the default SY0: MOV L.ASG(R3),R0 ;; No - Save UCB of default SY0: 22$: TSTB L.TYPE(R3) ;; Is this a login LCB BGE 24$ ;; No - skip it MOV L.ASG(R3),R1 ;; R1 := UCB of login SY0: BR 40$ 24$: MOV L.LNK(R3),R3 ;; Get next LCB BR 20$ ;; And check it ; No assignment found - we must use the device SY0: ; Find device control block (DCB) for SY: 30$: MOV $DEVHD,R3 ;; Pointer to first DCB entry 32$: CMP D.NAM(R3),#"SY ;; Is this DCB for SY: BEQ 34$ ;; Yes - find UCB for SY0: MOV D.LNK(R3),R3 ;; Point to next DCB BR 32$ ;; Try again 34$: MOV D.UCB(R3),R1 ;; Pointer to SY0: UCB ; R1 points to UCB of login SY0:, and R0 points to UCB of ; default SY0:. Store device names and unit numbers for ; both login SY0: and default SY0:. 40$: CALL DVINFO ;; Get device info MOV D.NAM(R2),LOGDEV ;; Store device name MOV R3,LOGUNT ;; Store unit number TST R0 ;; Did we find any SY0: LCB's BEQ 42$ ;; No - use SY0: device MOV R0,R1 ;; R1 := UCB of default device CALL DVINFO ;; Get device info 42$: MOV D.NAM(R2),DEFDEV ;; Save default device name MOV R3,DEFUNT ;; Save default unit number RETURN ;; Return to user state 50$: .PAGE .SBTTL Parse command line ; Parse the MCR command line into: ; ; 1) execute / Display flags ; 2) 3 character command name ; 3) Full command name ; 4) Parameters PARSE: BIS #FL.EXE,FLAGS ; Default is execute command, no display MOV #MCRBUF,R0 ; Start of MCR command buffer CMPB (R0),DSPLCH ; Display command character BNE 5$ ; If not display command char BIS #FL.DSP,FLAGS ; Display BIC #FL.EXE,FLAGS ; No execute INC R0 ; Advance input command pointer 5$: CMPB (R0),DSEXCH ; Display and execute character BNE 10$ ; If not display and execute BIS #FL.DSP,FLAGS ; Set display flag INC R0 ; Advance input command pointer 10$: MOV R0,R1 ; Beginning of input command line 15$: CMPB (R1),#'Z BHI 25$ ; Not a valid command character CMPB (R1),#'A-1 BHI 20$ ; Letter - valid command character CMPB (R1),#'9 BHI 25$ ; Not a valid command character CMPB (R1),#'0 BLO 25$ ; Not a valid command character 20$: INC R1 ; Increment input command pointer BR 15$ 25$: MOV R1,R2 ; R2 := pointer to char after command 30$: CMPB (R2),#BLANK ; Skip blanks BNE 35$ ; No blank - begin parameters INC R2 ; Blank - skip it BR 30$ 35$: MOV R0,CMDLIN ; Pointer to command line MOV ENDCMD,R3 ; Pointer to command line terminator MOV R3,R4 ; Save end of command pointer SUB R0,R3 MOV R3,CMDLEN ; Length of command line SUB R0,R1 ; Pointer to end of command name MOV R1,CNMLEN ; Length of command name MOV R2,PARAMS ; Pointer to parameters SUB R2,R4 ; End of command - beginning of params MOV R4,PRMLEN ; Length of parameters ; Set up command name as file name in dataset descriptor. MOV R1,DDNAM ; Set command (file) name length MOV R0,DDNAM+2 ; Set pointer to command (file) name ; Store first three characters of command name in RADIX-50 format ; for table lookup and generating task name. MOV #1,R1 ; $CAT5 flag - don't stop on period CALL $CAT5 ; R1 := 3 char command name (RADIX-50) MOV R1,CMD3CH .PAGE .SBTTL Search command table SEARCH: MOV #CMDTBL,R1 ; R1 := pointer to start of table MOV CMD3CH,R0 ; RADIX-50 command name MOV R0,SENTNL ; Insert sentinal in table 10$: CMP R0,(R1) ; Does command match? BEQ 20$ ; Yes - jump to address in table ADD #4,R1 ; Next entry (entry size = 2 words) BR 10$ ; Try again 20$: MOV #OUTBUF,R0 ; Output command buffer pointer JMP @2(R1) ; Process command. Second word in command. ; Table entry is address of routine. ;*** CA. command table. ; ; table contains a two word entry for each command. ; ; word 1: 3 character command name in radix-50 format. ; Word 2: Address of routine that handles command. CMDTBL: .RAD50 /CA./ ; Display version info .WORD CA.VER .RAD50 /SHD/ ; Show directory: SET /UIC .WORD SHD .RAD50 /CHD/ ; Change directory: SET /UIC=[] .WORD CHD .RAD50 /DIR/ ; Directory list: PIP /LI .WORD DIR .RAD50 /DEL/ ; Delete: PIP /DE .WORD DEL .RAD50 /PUR/ ; Purge: PIP /PU .WORD PUR .RAD50 /TYP/ ; Type: PIP TI:= .WORD TYP .RAD50 /ED/ ; Edt - with initializer file .WORD ED SENTNL: .BLKW 1 ; Sentinal for command table search .WORD FNDFIL ; Routine to process commands not in table .PAGE .SBTTL Internal commands ;*** CA. -- Display CA. version info CA.VER: MSG VERS ; Output CA. version string to terminal JMP EXITOK ; Exit ;*** SHD --> SET /UIC SHD: PUTZ #STR13 ; Login Directory: MOV LOGDEV,DEVICE ; Set device name MOV LOGUNT,UNIT ; Set unit number CALL PUTDEV MOV LOGUIC,UIC ; Set UIC CALL PUTUIC PUTC #CR PUTC #LF PUTZ #STR14 ; Default Directory: MOV DEFDEV,DEVICE ; Set device name MOV DEFUNT,UNIT ; Set unit number CALL PUTDEV MOV DEFUIC,UIC ; Set UIC CALL PUTUIC PUTC #CR ; Terminator SUB #OUTBUF,R0 ; R0 := Length of message MOV R0,QIOW+Q.IOPL+2 ; Set message length MOV #OUTBUF,QIOW+Q.IOPL ; Set message address DIR$ #QIOW ; Put message JMP EXITOK ; And exit ;*** CHD g,m --> SET /UIC=[g,m] ; CHD m --> SET /UIC=[g,m] (where "g" = current group) CHD: PUTZ #STR12 ; SET /UIC=[ MOV PARAMS,R1 ; Start of parameters MOV PRMLEN,R2 ; Length of parameters 10$: BEQ 20$ ; If end of parameters (no comma seen) CMPB (R1)+,#COMMA ; Is it a comma? BEQ 30$ ; Yes - don't insert group DEC R2 ; One less character to look at BR 10$ ; Next character 20$: PUTN DEFUIC+1 ; Insert group number PUTC #COMMA ; and a "," 30$: PUT PARAMS,PRMLEN ; g,m PUTC #'] JMP DOCMD ;*** DIR zzzzz --> RUN $PIP/TASK=DIRTn/CMD="PIP zzzzz/LI" DIR: PUTZ #STR4 ; RUN $PIP CALL PUTTSK ; /TASK=DIRTnn PUTZ #STR8 ; /CMD="PIP PUT PARAMS,PRMLEN ; zzzzz PUTZ #STR10 ; /LI PUTC #'" ; " JMP DOCMD ;*** DEL zzzzz --> RUN $PIP/TASK=DELTn/CMD="PIP zzzzz/DE" DEL: PUTZ #STR4 ; RUN $PIP CALL PUTTSK ; /TASK=DELTnn PUTZ #STR8 ; /CMD="PIP PUT PARAMS,PRMLEN ; zzzzz PUTZ #STR11 ; /DE PUTC #'" ; " JMP DOCMD ;*** PUR zzzzz --> RUN $PIP/TASK=PURTn/CMD="PIP zzzzz/DE" PUR: PUTZ #STR4 ; RUN $PIP CALL PUTTSK ; /TASK=PURTnn PUTZ #STR8 ; /CMD="PIP PUT PARAMS,PRMLEN ; zzzzz PUTZ #STR16 ; /PU PUTC #'" ; " JMP DOCMD ;*** TYP zzzzz --> RUN $PIP/TASK=TYPTn/CMD="PIP TI:=zzzzz" TYP: PUTZ #STR4 ; RUN $PIP CALL PUTTSK ; /TASK=TYPTnn PUTZ #STR9 ; /CMD="PIP TI:= PUT PARAMS,PRMLEN ; zzzzz PUTC #'" JMP DOCMD ;*** ED zzzzz --> EDT zzzzz,dd:[g,m]EDTINI.EDT ED: MOV #EDTLEN,DDNAM ; Set length in dataset descriptor MOV #EDTINI,DDNAM+2 ; Set file name in dataset descriptor MOV #FDB,R0 ; File descriptor block address MOV #DD,R2 ; Dataset descriptor MOV #DFNB,R3 ; Default file name block CHKFIL LOGDEV,LOGUNT,LOGUIC,EDT,10$ CHKFIL SYSDEV,SYSUNT,SYSEDT,EDT,10$ MSG ERR5 ; No initializer file JMP ERROR 10$: PUTZ #STR2 ; EDT MOV PARAMS,R3 ; Pointer to parameters MOVB -1(R3),R4 ; Character before parameters CMPB R4,#BLANK BNE 20$ ; If it was not a blank PUTC #BLANK ; It was, so put in a blank 20$: PUT PARAMS,PRMLEN ; zzzzz PUTC #COMMA ; , CALL PUTDEV ; ddn: CALL PUTUIC ; [g,m] .list me PUTS #EDTINI,EDTLEN ; Initializer file name .nlist me JMP DOCMD .PAGE .SBTTL Find a file to execute ; Try to find a file to execute. First search in the login UIC. ; First look for a ".TSK" file. If that fails, try ".CMD", and ; finally ".TEC". If all three fail, then look in the system-wide ; UICs. First the UIC "SYSTSK" is searched for a ".TSK" file, then ; "SYSCMD" is searched for a ".CMD" file, and finally "SYSTEC" is ; searched for a ".TEC" file. If a file is found, then a command ; line is generated and sent to the appropriate processor. ; ; .TSK RUN dev:[UIC]file/TASK=filTnn/CMD="cmd" ; .CMD CAT @dev:[UIC]cmd ; .TEC RUN $TEC/TASK=filTnn/CMD="MUN dev:[UIC]cmd" ; ; WHERE: dev = "SY" for home UIC, "LB" for system UIC ; UIC = home UIC, SYSTSK, SYSCMD, OR SYSTEC ; file = File name from command string ; fil = First three characters of "file" ; cmd = Command typed by user FNDFIL: MOV #FDB,R0 ; File descriptor block address MOV #DD,R2 ; Dataset descriptor MOV #DFNB,R3 ; Default file name block CHKFIL LOGDEV,LOGUNT,LOGUIC,TSK,RUN CHKFIL LOGDEV,LOGUNT,LOGUIC,CMD,ICP CHKFIL LOGDEV,LOGUNT,LOGUIC,TEC,MUN CHKFIL SYSDEV,SYSUNT,SYSTSK,TSK,RUN CHKFIL SYSDEV,SYSUNT,SYSCMD,CMD,ICP CHKFIL SYSDEV,SYSUNT,SYSTEC,TEC,MUN MSG ERR1 ; No command found - err msg JMP ERROR ; And exit .PAGE .SBTTL File execution ; xxxyy zzzz --> RUN dd:[g,m]xxxyy/TASK=xxxTnn/CMD="xxxyy zzzz" RUN: PUTZ #STR1 ; RUN CALL PUTDEV ; ddn: CALL PUTUIC ; [g,m] PUT CMDLIN,CNMLEN ; xxxyy CALL PUTTSK ; /TASK=xxxTnn PUTZ #STR6 ; /CMD= PUT CMDLIN,CMDLEN ; xxxyy zzzz PUTC #'" JMP DOCMD ; xxxyy zzzz --> CAT @dd:[g,m]xxxyy zzzz ICP: PUTZ #STR15 ; CAT @ CALL PUTDEV ; ddn: CALL PUTUIC ; [g,m] PUT CMDLIN,CMDLEN ; xxxyy zzzz JMP DOCMD ; xxxyy zzzz --> RUN $TEC/TASK=xxxTnn/CMD=MUN dd:[g,m]xxxyy zzzz" MUN: PUTZ #STR3 ; RUN $MUN CALL PUTTSK ; /TASK=xxxTnn PUTZ #STR7 ; /CMD="MUN CALL PUTDEV ; ddn: CALL PUTUIC ; [g,m] PUT CMDLIN,CMDLEN ; xxxyy zzzz PUTC #'" JMP DOCMD .PAGE .SBTTL Execute a command string ;*** ; DOCMD: execute command string ; ; Input: Command line starts at #OUTBUF ; R0 = Pointer to end of command ;*** DOCMD: MOV R0,R3 ; Save pointer to terminator PUTC #CR ; Append a carriage return to command line SUB #OUTBUF,R0 ; R0 := length of output command line CMP R0,#80. ; Is command line too long? BGT 10$ ; Yes - Force display on BIT #FL.DSP,FLAGS BEQ 20$ ; If display flag not set 10$: MOV #OUTBUF,QIOW+Q.IOPL ; Display command buffer MOV R0,QIOW+Q.IOPL+2 ; Length of buffer DIR$ #QIOW 20$: CMP R0,#80. ; Length of command line BLE 30$ ; If command line too long MSG ERR2 ; Display error message JMP ERROR ; And exit 30$: BIT #FL.EXE,FLAGS BEQ EXITOK ; If execute flag not set MOVB @ENDCMD,(R3) ; Use terminator from input command line MOV R0,RPOI+R.POBL ; Set length of command string DIR$ #RPOI ; execute the command ; If successfull, RPOI will not return. so if we have gotten ; to this point, we have an error. MSG ERR3 ; Display error message JMP ERROR ; And exit .PAGE .SBTTL Exit EXITOK: EXST$S #EX$SUC ; Exit status: Success ERROR: EXST$S #EX$ERR ; Exit status: Error .END CA.