;AKA.ASM by Michael Conley & Larry Davis ; ;Version 1.3 CREATED 6/2/86 ; ;This program utilizes the Multiple Command buffer of ZCMD or ZCPRx to ;execute a series of commands without creating a submit file. The user ;simply calls the .COM file created from an edited version of this program ;and the rest is automatic. The user is asked to input a command line, and ;then make a new .COM file using the CP/M 'SAVE' command. Thereafter, the ;new file will execute the commands automatically when called. ; ;Note that any new file created by this program may ALSO create files by ;invoking it with a 'C' on the command line. This will make the program ;act just like a "virgin" copy of AKA. If a secure version, which may not ;be changed, is desired, simply set the SECURE equate to TRUE. In that way, ;only the real AKA will be able to create new files. ; ;REQUIREMENTS: ; ;Your CP/M 2.2 system must be running ZCMD or ZCPRx with Multiple Command ;option enabled. No program executed from this command line may end with a ;warmboot or following programs will not be executed. Both internal command ;line buffer and external command line buffer are supported - see installation ;notes. Also, any commands in the buffer which follow this program will be ;restored to the buffer, and the total length checked to be sure it's legal. ; ;INSTALLATION: ; ;In a system with a standard size CCP and an internal command buffer, ;the CCP entry and buffer addresses will be automatically calculated. ;The distributed .COM file will run in your system without assembling ;the source code. ; ;If you are running an EXTERNAL command line buffer, or if your CCP is of ;a non-standard size, you must edit the source code to set a few conditionals ;and equates for your system. Once the .COM file is created from the edited ;source, AKA will create its aliases already configured for your system. ; ;Secure option: Any copy of this program can 'clone' a new one by adding ;a 'C' on the command line. However this feature can be disabled by setting ;the SECURE equate TRUE. Also, of course, if your CP/M SAVE command is ;disabled, the user will not be able to SAVE a revised version. ; ;OPERATION: ; ;After installation (if required - see above) run AKA.COM. The program ;will ask for your command line input. Type in the commands of ;your choice (separated by semi-colons). Then SAVE 4 NEWNAME.COM ;and you will have an 'alias' file to run your command line. ; ;Alteration of a program if AKA is not handy: If all you have handy is ;NEWNAME.COM, type NEWNAME C and the program will act like AKA. This may ;be disabled by setting the SECURE equate TRUE at assembly time. ; ;Comments or suggestions should be left on the Charlatan's Cabin BBS ;(213) 656-4192 300/1200/2400 24 hrs, in a message to the SYSOP, Michael ;Conley, or to system member Larry Davis. ; ;---------------------------------------------------------------------------- ;special thanks: ; ;to Russ Pencin of the Dallas Connection RCP/M for his suggestions/help on ;the external command buffer option and the command change option. ; ; -Michael Conley ; ;---------------------------------------------------------------------------- ;What every good boy needs to know: ; FALSE EQU 0 TRUE EQU NOT FALSE ; ;---------------------------------------------------------------------------- ; ;CONDITIONAL ASSEMBLY OPTIONS: ; SECURE EQU FALSE ;set TRUE if you want to DISABLE the program ;feature which allows editing from ANY copy ;by specifying a 'C' on the command line. EXCBUF EQU FALSE ;if you are running ZCPR or ZCMD with an ;external command line buffer, set this ;TRUE and enter the buffer starting address ;next. IF EXCBUF CCPBUF EQU 00000H ;enter your external buffer address here ;if EXCBUF is true. ENDIF ;EXCBUF ; ;If you have a NON-STANDARD SIZE CCP, and are NOT running an EXTERNAL ;command line buffer, enter the CCP starting address here. ;Otherwise the program will calculate it automatically. Remember that ;your assembler probably requires a leading zero and a trailing 'h' for hex ;addresses. If your CCP is standard, set the equate set to zero. ; IF NOT EXCBUF CCPBUF EQU 00000H ;if using INTERNAL command line buffer, ;and you have a NON-STANDARD CCP length ;(i.e. not 2k long) enter the base address ;of your CCP here, and verify the offset ;equates ENDIF ;NOT EXCBUF ; ;---------------------------------------------------------------------------- ;these equates will be selected by the EXCBUF conditional and should not ;require any editing. ; IF EXCBUF MAXBUF EQU 2 ; offset to maximum buffer length byte CMDLEN EQU 3 ; offset to command length storage byte CMDBUF EQU 4 ; offset to address of actual command buffer NXTCHR EQU 0 ; offset to nxtchr for external buffer ENDIF ;EXCBUF ; IF NOT EXCBUF MAXBUF EQU 6 ;offset to maximum buffer length byte CMDLEN EQU 7 ;offset to command length storage byte CMDBUF EQU 8 ;offset to address of CCP command buffer NXTCHR EQU 9 ;character pointer is word variable at ;this offset from the base of the CCP, ;PLUS length of CCP buffer ENDIF ;NOT EXCBUF ;---------------------------------------------------------------------------- ;these equates should not need to be edited: ; DRUSER EQU 4 ;location of current drive/user in CP/M BDOS EQU 5 ;bdos entry point BDOSPG EQU 7 ;bdos memory address page is written here FCB EQU 05CH ;file control block TPA EQU 100H ;TPA starting address ; PROGBUF EQU 128 ;length of program internal buffer ; ;cpm function and ascii stuff ; PRSTR EQU 9 ;cpm print string function INSTR EQU 10 ;get a string from the console ; BELL EQU 7 ;bell CR EQU 13 ;carriage return LF EQU 10 ;linefeed ; ; ;**************************************** ; * ; BEGIN CODE * ; * ;**************************************** ; ORG TPA JMP START ; MAXLEN: DS 1 ;program will acquire maximum length from CCP ;and store here LENBYT: DS 1 ;actual command line length stored here COMMAND: DS PROGBUF ;program buffer length as distributed may be ;longer than actual command buffer. Program ;will generate a warning message if too much ;actual buffer length is exceeded when you ;load a command into the .COM file. ; ; START: ; execution actually happens here. LXI H,0 ; make a 0 in HL DAD SP ; add in stack pointer SHLD OLDSP ; save address LXI SP,STACK ; point SP at internal stack CALL CCPLOC ; locate the CCP, save in CCPADD LXI D,MAXBUF ; offset to maximum buffer amount byte DAD D MOV A,M ; maximum buffer length STA CCPLEN ; save it STA MAXLEN ; and put in buffer for CP/M input function CHKCMD: ; IF NOT SECURE LDA FCB+1 ; see if option switch set CPI 'C' ; did user type a C JZ GETCMD ; yes, pretend you're a virgin ENDIF ;NOT SECURE ; LDA LENBYT ; get length byte CPI 0 ; is the command line empty? JNZ SETUP ; no, run program, else get command line GETCMD: CALL CLRBUF ; first clear the buffer, just in case LXI D,CMDMSG ; print 'enter command' message CALL PRINT LXI D,MAXLEN ; point to command line buffer MVI C,INSTR ; CALL BDOS ; get command line from keyboard LDA LENBYT ; see if anything was entered CPI 0 JZ HELPME LDA LENBYT ; get our length MOV B,A ; stash in b LDA CCPLEN ; check against the CCP maximum SUB B ; be sure it's not longer than buffer JC EREXIT ; if so, bail out LXI D,SAVMSG ; print 'now save it' message BAIL: CALL PRINT JMP EXIT ; exit to CP/M HELPME: LXI D,HELP ; no input to raw program, run help message JMP BAIL ; then exit ; SETUP: CALL GETBUF ; create temporary buffer LHLD TBUF XCHG ; stash in DE LHLD CCPADD LXI B,NXTCHR ; first check the character pointer DAD B ; IF NOT EXCBUF LXI B,0 ; using internal buffer, offset to end LDA CCPLEN ; of buffer MOV C,A DAD B ENDIF ;NOT EXCBUF ; MOV A,M INX H MOV H,M ; get info from nxtchr pointer MOV L,A ; into hl SETUP1: MOV A,M ; copy from CCP into TBUF STAX D INX H INX D ORA A ; until we hit a null JNZ SETUP1 SETUP2: LHLD CCPADD ; get ccp base address LXI D,CMDBUF ; offset to command buffer DAD D LXI D,COMMAND ; point DE at program command buffer LDA CCPLEN ; get maximum length MOV B,A ; put it in B CALL MOVE ; copy command into CCP JZ EREXIT ; if zero flag set, we're out of room DCX H ; chop off trailing null XCHG ; LHLD TBUF XCHG CALL MOVE JZ EREXIT ; if zero flag set, we're out of room LHLD CCPADD LXI D,CMDLEN ; point HL at command length byte DAD D MOV M,B ; write actual command length to buffer LHLD CCPADD LXI D,NXTCHR ; now determine address of nxtchr pointer DAD D ; add offset to command buffer ; IF NOT EXCBUF LXI B,0 ; zero bc LDA CCPLEN ; external command buffer length MOV C,A ; save in C DAD B ; offset buffer end only if NOT external ENDIF ;NOT EXCBUF ; XCHG ; now DE contains address of NXTCHR word LHLD CCPADD LXI B,CMDBUF DAD B ; now HL points at CCP buffer XCHG ; DE points at buffer, HL points at NXTCHR MOV M,E ; store address at CCP's NXTCHR pointer INX H ; in case mult. command processing is MOV M,D ; allowed EXIT: LHLD OLDSP ; now get back stored stack pointer value SPHL ; put it back LXI H,DRUSER ; current drive/user MOV C,M ; into reg. C RET ; and return to CP/M ; EREXIT: ; command is too long, print message LXI D,ERMSG ; point at message CALL PRINT JMP EXIT ; then end without loading ccp ; ; ;subroutines ; CCPLOC: ;stores CCP address at CCPADD and in HL LXI H,CCPBUF ;first check if program equate is set MOV A,H ; CPI 0 ;if zero, not set JNZ CCPL0 ;otherwise don't calculate LXI H,BDOSPG ;get bdos page address MOV A,M SUI 8 ;ccp is -800h bytes from bdos (2k size) LXI H,0 ;zero hl MOV H,A ;put ccp page address in h SHLD CCPADD ;store address CCPL0: RET ; GETBUF: ;create a temporary buffer LXI H,CODEND ;point at end of code INR H ;go to next memory page MVI L,0 ;start on even page SHLD TBUF ;save address of temp buffer RET ; MOVE: ;read from DE, write to HL till null ;enter with B = max chars avail ;will error out if exceeded LDAX D MOV M,A INX H INX D DCR B JZ TOOBIG ORA A JNZ MOVE MVI A,0FFH ORA A RET ; TOOBIG: XRA A ;set the z flag ORA A RET ;and return ; CLRBUF: ;empties the command buffer LXI H,COMMAND ;point at command bufer MVI B,PROGBUF ;get length equats XRA A ;make a zero CLR0: MOV M,A ;stash zeroes INX H DCR B ;until end of buffer JNZ CLR0 RET ; PRINT: ;prints string at DE address, and ; looks for '$' terminator PUSH B PUSH H MVI C,PRSTR CALL BDOS POP H POP B RET ; ;message storage ; CMDMSG: DB CR,LF,' Enter your command line, end with a RETURN.' DB CR,LF,'>$' SAVMSG: DB CR,LF,' Now, type SAVE 4 newfile.COM to create new file.' DB CR,LF,'$' ; HELP: DB CR,LF,' To use AKA, simply enter a string of commands,' DB CR,LF,' separated by semicolons. End with a .' DB CR,LF,' Then create the new file by using the CP/M ''SAVE'' command.' DB CR,LF,'$' ERMSG: DB CR,LF,BELL,' ++ ERROR -- Program command longer than CCP buffer ++',CR,LF,'$' ; ; ;data storage ; CCPADD: DW CCPBUF ;address of CCP stored here by program CCPLEN: DS 1 ;program will store CCP buffer length here ; ; ;stack storage ; OLDSP: DW 0 ;save external stack pointer here DS 20 ;internal stack space STACK: TBUF: ;temporary buffer at end of program DW 0 CODEND: DW 0 ;indicate end of program for temp. buffer END