Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 2.0 SOURCE/kern/command.sup
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

718 lines
15 KiB
Plaintext

;*****************************************************
;*
;* Command Line Interpreter, Program Chain
;*
;*****************************************************
;=========
chain_ent:
;=========
xor dx,dx
;=======
cli_ent:
;=======
; Create a process based on an Ascii Command Line.
; The command Line is first parsed and an FCB is
; initialized as a result.
; An attempt is made to open a queue with the filename
; of the FCB, and with the RSP flag on.
; The command tail is written to the queue if it is found.
; If the queue cannot be opened or is not and RSP type then
; we try and load the command from disk.
; If the write queue fails we return e_q_full error code and
; do not look on the disk.
; After the queue write, an console assign call attempted to
; a process with the same name and the PF_DSKLD flag off.
; Irregardless of the success of the assign we then return.
;
; If the RSP queue cannot be opened, or is not an RSP type queue then
; we make the name type in the
; FCB to be 'CMD' and attempt to open the file. If this fails,
; so do we.
; We then obtain a Process Descriptor from the
; PD table. Again we fail if it does.
; On a successful open, we call the BDOS load function.
; If the load fails, so do we. The PD is
; initialized, the default console is assigned to the
; PD, the PF_DSKLD flag turned on,
; and a create process call is made.
;
; input: DX -> command buffer in u_wrkseg
; It is assumed that the calling process
; is attached to its default console
; and is willing to lose it since it
; will be handed to the newly created
; process.
; if DX = 0, assume chain w/command in DMA
;
; output: BX = 0 if successful
; = 0ffffh if failure has occured
; CX = error code
mov bx,rlr ! mov ax,p_flag[bx]
push ax ;save flags on stack
or ax,pf_tempkeep + pf_noctls
mov p_flag[bx],ax
push dx ;save parameter
call cli_sync ;rentrancy stops with sync call
pop dx ;we can save the flags
pop cli_pflag ;and other variables in the CLI
;data area
; we have CLI SYNC
; Check for Chain
mov cli_chain,false
cmp dx,0 ! jne cli_cli
mov cli_chain,true
mov cli_term,false
cli_cli:
; initialize defaults from parent PD
mov cli_dfil,false
cmp dayfile,0ffh ! jne nodf
push dx ! mov cx,f_cconattch
call osif ! pop dx
cmp cx,0 ! jne nodf
mov cli_dfil,true
push dx
call prtime
pop dx
nodf: mov bx,rlr
mov cli_ppd,bx
mov cl,p_dsk[bx]
mov cli_dsk,cl
mov cl,p_user[bx]
mov cli_user,cl
mov cl,p_cns[bx]
mov cli_cns,cl
mov cl,u_error_mode
mov cli_err_mode,cl
mov cx,u_dma_ofst
mov cli_dma_ofst,cx
mov cx,u_dma_seg
mov cli_dma_seg,cx
mov clierr,0
; copy command into local area
cmp cli_chain,true ! jne cli_cpy
push es ! push ds
mov es,sysdat
mov si,cli_dma_ofst
mov di,offset cli_cmdtail
mov ds,cli_dma_seg
mov cx,040H
rep movsw
pop ds ! pop es
jmp cli_parse
cli_cpy:
push es ! push ds
mov ds,u_wrkseg ! pop es
; DS=Wrkseg, ES=Sysdat, SP->UDA
; copy clicb_net
mov si,dx ! mov di,offset cli_net
movsb
; copy command
mov si,dx ! add si,clicb_cmd
mov di,offset cli_cmdtail
mov cx,clicblen-clicb_cmd
rep movsb
push es ! pop ds ! pop es
;parse the command
cli_parse:
call pfn ! jcxz cli_gprs
mov clierr,cx
jmp cli_exit
cli_gprs:
call shtal
;fcb has parsed filename
;if not explicit disk then
; if not RSP try CMD
;else try CMD
cmp cli_fcb,0 ! jne cli_ffload
mov bx,(offset cli_fcb)
cmp fcb_plen[bx],0 ! jne cli_ffload
call cli_checkque ! jnz cli_ffload
;successful RSP access
cli_qful:
cmp cli_chain,true ! jne cli_exit2
mov cli_term,true
cli_exit2: jmp cli_exit
cli_ffload:
cmp cx,e_q_full ! jne cli_fload
mov clierr,cx ! jmps cli_qful
cli_checkque:
;------------
; output: z flag on if successful
;copy fcb.name to qpb.name
mov si,(offset cli_fcb)+fcb_name
mov di,(offset cli_cuspqpb)+qpb_name
mov cx,qnamsiz/2 ! push es ! push ds ! pop es
push si ! rep movsw
;copy fcb.name to acb.name
pop si ! mov cx,qnamsiz/2
mov di,(offset cli_acb)+acb_name
rep movsw ! pop es
;open queue
mov cx,f_qopen ! mov dx,(offset cli_cuspqpb)
call osif ! jcxz cli_goodq
retcli1: cmp cx,0 ! ret ;CX = 0ffffh on error
;we successfully opened the queue
;now check RSP flag
cli_goodq:
mov bx,offset cli_cuspqpb
mov bx,qpb_qaddr[bx]
test q_flags[bx],qf_rsp ! jnz cli_gq
mov cx,e_no_queue ! jmps retcli1
;write command tail to queue
cli_gq: mov cx,f_cqwrite ! mov dx,offset cli_cuspqpb
call osif ! jcxz cli_qw
mov cx,e_q_full ! jmps retcli1
;successful queue write, assign console
cli_qw: cmp cli_dfil,true ! jne noqm
call prcusp
noqm: mov bx,offset cli_acb
mov al,cli_cns ! mov acb_cns[bx],al
mov acb_match[bx],false
mov acb_pd[bx],1 ;match on PD with DSKLD flag off
call conasn ! xor cx,cx ! ret
cli_fload:
;---------
; Try to Load a file for execution
; The Command Line Parsed correctly and we have an FCB
; set up. We already know there isn't a queue and a
; process by the same name as the command.
; Obtain a Process Descriptor
pushf ! cli ! mov bx,pul
cmp bx,0 ! jne cli_gpd
popf ! mov clierr,e_no_pd
jmp cli_exit
cli_gpd:
mov si,p_link[bx] ! mov pul,si
popf ! mov cli_pd,bx
; zero PD
push es ! push ds ! pop es
mov di,bx ! mov cx,pdlen/2
xor ax,ax ! rep stosw
pop es
; Initialize the PD for Load
mov bx,cli_pd
mov p_flag[bx],pf_table
mov di,bx ! add di,p_name
mov si,offset cli_fcb ! add si,fcb_name
push es ! mov ax,ds ! mov es,ax
mov cx,pnamsiz/2 ! rep movsw
pop es
mov si,rlr
mov al,cli_dsk ! mov p_dsk[bx],al ;inherit parents drive/user
mov al,cli_user ! mov p_user[bx],al ;even if we load off another
;drive or user
;this should be in
;process create ?
mov al,cli_cns ! mov p_cns[bx],al
mov al,p_lst[si]
if mpm
sub al,ncondev
endif
mov p_lst[bx],al
; 3. Open the file
mov si,(offset cli_fcb)+fcb_pwd
mov di,offset cli_dma
push es ! mov es,sysdat
mov cx,4 ! rep movsw
pop es
mov u_dma_ofst,offset cli_dma
mov u_dma_seg,ds
mov si,offset cli_fcb
mov byte ptr fcb_type[si],'C'
mov byte ptr fcb_type+1[si],'M'
mov byte ptr fcb_type+2[si],'D'
; Open the CMD file
mov u_error_mode,0feh
call flopn
cmp bl,0ffh ! jne cli_gopen
; on failure,
; if default is not system disk
; and not an explicit disk then
; try CMD file on System disk
cmp bh,0 ! jne cli_bo ;extended error
mov cl,srchdisk
cmp cl,cli_dsk ! je cli_bo ;already on system disk
cmp cli_fcb,0 ! jne cli_bo ;check for explicit
;select
; try system disk
; mov bx,rlr
; mov p_dsk[bx],cl
inc cl
mov cli_fcb,cl ;set drive byte to
call flopn ;system disk
cmp bl,0ffh ! je cli_bo
;make sure SYS attribute is on...
mov bx,offset cli_fcb
test byte ptr fcb_type+1[bx],080h ! jnz cli_gopen
;We opened a NON-SYS file. Do explicit open
;on user zero if not already
call flclse
mov bx,rlr
cmp p_user[bx],0 ! je cli_boe
mov p_user[bx],0
call flopn
cmp bl,0ffh ! je cli_bo
mov bx,offset cli_fcb
test byte ptr fcb_type+1[bx],080h
jnz cli_gopen
call flclse
jmps cli_boe
;could not find CMD file
cli_bo: cmp bh,0 ! jne cli_rmpd2
cli_boe: mov clierr,e_bad_open
cli_rmpd2: jmp cli_rmpd
cli_gopen:
; 8. Call the load function
mov bx,rlr
test p_flag[bx],pf_ctlc ! jz cli_ld1
mov bx,0ffffh ! mov cx,e_abort
jmp cli_cl
cli_ld1:
cmp cmod,true ! jne not_cmod
mov bx,cli_pd
mov si,offset cli_fcb
;test F1 bit
mov p_cmod[bx],0
test byte ptr fcb_name[si],080h ! jz not_f1
or p_cmod[bx],080h
;test F2 bit
not_f1: test byte ptr fcb_name+1[si],080h ! jz not_f2
or p_cmod[bx],040h
;test F3 bit
not_f2:
;if mpm dave brown test
test byte ptr fcb_name+2[si],080h
jz not_f3
;endif
or p_cmod[bx],020h
;test F4 bit
not_f3: test byte ptr fcb_name+3[si],80h ! jz not_cmod
or p_cmod[bx],070h
not_cmod:
cmp cli_chain,true ! jne cli_kuda
mov bx,cli_pd
mov p_uda[bx],es
mov ax,offset inituda
mov cl,4 ! shr ax,cl
add ax,sysdat
mov bx,es ! mov es,ax ! mov di,0
mov ds,bx ! mov si,di
mov cx,ulen/2
rep movsw
pushf ! cli ! pop dx
mov ax,es
mov ds,sysdat
mov ss,ax
mov bx,rlr
mov p_uda[bx],ax
push dx ! popf
cli_kuda:
cmp cli_dfil,true ! jne noprfil
call prfilnam
call crlf
noprfil:mov bx,cli_pd
mov dx,offset cli_fcb
mov cx,f_load
cmp cli_chain,true ! jne cli_ld
mov cli_term,true
cli_ld: call osif
cli_cl: push bx ! push cx
mov u_error_mode,0
call flclse
pop cx ! pop bx
jcxz cli_gload
cmp cx,e_abort ! jne cli_lnab
jmp cli_rmpd
cli_lnab: mov clierr,cx
jmp cli_rmpd
cli_gload:
mov cli_bpage,bx
; 9a. Parse Command Tail
; copy cmdtail to user DMA buffer
push es ! mov es,cli_bpage
mov di,offset bpg_dma+1
mov si,offset cli_cmdtail
mov cx,127
rep movsb ! pop es
; count cmd length and convert
; to upper case
push ds ! mov ds,cli_bpage
mov cl,0 ! mov di,offset bpg_dma+1
ncmdchar:
cmp byte ptr [di],0 ! je endtail
; convert CMD tail to UPPER CASE
cmp byte ptr [di],'a' ! jb nlow
cmp byte ptr [di],'z' ! ja nlow
and byte ptr [di],05fh
nlow:
inc di ! inc cl ! jmps ncmdchar
endtail:
mov bpg_dma,cl ! pop ds
; load disk init, location 50H
; of base page is done in LOAD
push es ! mov es,cli_bpage
; init default fcb
mov di,offset bpg_fcb0
xor ax,ax ! stosb ;default disk
mov al,' '
mov cx,11 ! rep stosb ;name,type
xor ax,ax
mov cx,2 ! rep stosw ;other
push ds ! push es ! pop ds
mov si,offset bpg_fcb0
mov cx,8 ! rep movsw
pop ds ! pop es
; if cmdtail, parse
cmp cli_cmdtail,0 ! je ctdone
call pfn
cmp bx,0ffffh ! je ctdone
; copy fcb to user fcb front
push es ! mov es,cli_bpage
mov di,offset bpg_fcb0
mov si,offset cli_fcb
mov ax,fcb_pptr[si]
; AX->password in CLI_CMDTAIL
sub ax,offset cli_cmdtail
add ax,offset bpg_dma + 1
; AX->password in Base Page
mov es:bpg_pw1ptr,ax
mov al,fcb_plen[si]
mov es:bpg_pw1len,al
mov cx,8 ! rep movsw ! pop es
; if more cmdtail, parse
cmp bx,0 ! je ctdone
push cli_pcb ! inc bx
mov cli_pcb,bx
call pfn
pop cli_pcb
cmp bx,0ffffh ! je ctdone
; copy 2nd fcb front
push es ! mov es,cli_bpage
mov di,offset bpg_fcb1
mov si,offset cli_fcb
mov ax,fcb_pptr[si]
; AX->password in CLI_CMDTAIL
sub ax,offset cli_cmdtail
add ax,offset bpg_dma + 1
; AX->password in Base Page
mov es:bpg_pw2ptr,ax
mov al,fcb_plen[si]
mov es:bpg_pw2len,al
mov cx,8
rep movsw
pop es
ctdone:
; 10. Create the process
cmp cli_chain,true ! jne nprior
mov cx,f_setprior
mov dx,1 ! call osif
nprior:
mov si,cli_pd ! or p_flag[si],pf_dskld ;from disk, to differ
mov dx,si ! mov cx,f_createproc ;from RSP with same name
call osif
; 11. Assign Console to new process
mov bx,rlr
and p_flag[bx],not pf_ctlc
; Check to see if user hit CTRL D
test p_flag[bx],pf_ctld ! jz asgn
and p_flag[bx],not pf_ctld
mov bx,cli_pd
or p_flag[bx],pf_ctld
jmp cli_exit
asgn: mov bx,offset cli_acb
mov al,cli_cns ! mov acb_cns[bx],al
mov ax,cli_pd ! mov acb_pd[bx],ax
mov acb_match[bx],true
call conasn
mov clierr,cx
jmps cli_exit
; 12. All Done
cli_rmpd: ; release PD
mov si,cli_pd
; Release any memory that might still be
; associated with the PD. This could
; happen from a CTRL C.
cmp p_mem[si],0 ! je rmpd1
push ds ! push es
push si
mov si,p_mem[si]
push ms_start[si]
mov cx,f_memfree
mov dx,sp
mov ax,ss ! mov ds,ax
call osif
pop ax ! pop si
pop es ! pop ds
jmps cli_rmpd
; Place empty PD on PUL.
rmpd1: pushf ! cli
mov bx,pul
mov p_link[si],bx ! mov pul,si
popf
; Normal EXIT
cli_exit: ; close file and release CLI SYNC
mov bx,rlr
mov cl,cli_dsk ! mov p_dsk[bx],cl
mov cl,cli_user ! mov p_user[bx],cl
mov cl,cli_err_mode ! mov u_error_mode,cl
mov cx,cli_dma_ofst ! mov u_dma_ofst,cx
mov cx,cli_dma_seg ! mov u_dma_seg,cx
cmp cli_chain,true ! jne clirls
mov bx,rlr ! mov si,cli_pd ;inherit calling PD's
mov ax,p_parent[bx] ;parent if chaining
mov p_parent[si],ax
cmp cli_term,true ! jne clirls
and p_flag[bx],not (pf_keep+pf_sys+pf_tempkeep+pf_ctlc)
mov cx,f_terminate ;TERM_ACT in dispatcher
jmp osif ;releases CLI_SYNC
clirls:
push cli_pflag
push cli_err
call cli_unsync
pop dx
pop ax ! and ax,pf_tempkeep+pf_noctls
mov bx,rlr ! mov cx,p_flag[bx]
and cx,not pf_tempkeep+pf_noctls
or cx,ax ! mov p_flag[bx],cx
test p_flag[bx],pf_ctlc ! jz cli_nctl
mov cx,f_terminate ! xor dx,dx
call osif
and p_flag[bx],not pf_ctlc
mov dx,e_abort
; setup error return if needed
cli_nctl:
mov cx,dx
xor bx,bx
jcxz cli_gexit
mov bx,0ffffh
cli_gexit:
ret
shtal:
;---------
; setup command tail to be parsed
; input: AX = output of previous parsefilename
cmp ax,0 ! je ntail
;shift command tail to beginning
;of command buffer
push ax ! sub ax,offset cli_cmdtail
mov cx,128 ! sub cx,ax ! shr cx,1
pop si ! mov di,offset cli_cmdtail
push es ! push ds ! pop es
rep movsw ! pop es
ret
ntail:
mov cli_cmdtail,0
ret
;============================
; Various string subroutines
crlf: mov dl,13 ! call prchar
mov dl,10
;jmps prchar
prchar:
mov si,u_conccb
mov di,rlr
cmp [si],di ! jne prr
mov cx,f_conout ! jmp osif
prr: ret
prtime: mov dl,tod_hr ! call prnum
mov dl,':' ! call prchar
mov dl,tod_min ! call prnum
mov dl,':' ! call prchar
mov dl,tod_sec ! call prnum
mov dl,' ' ! jmps prchar
prnum: push dx ! mov cl,4
shr dl,cl ! add dl,'0'
call prchar
pop dx ! and dl,0fh
add dl,'0' ! jmps prchar
prfilnam:
call prdisk
mov dx,(offset cli_fcb)+fcb_name
call prnam
mov dl,'.' ! call prchar
mov dx,(offset cli_fcb) + fcb_type
call prtyp
mov dl,' ' ! call prchar
mov bx,offset cli_fcb
test byte ptr fcb_name+7[bx],080h ! jnz pruser
cmp cli_user,0 ! je pret
mov bx,rlr
cmp p_user[bx],0 ! je pruser
pret: ret
pruser: mov dx,offset userstr
jmps prcsm
prdisk: mov dl,cli_fcb
cmp dl,0 ! je prpddsk
dec dl ! jmps prdsk1
prpddsk:
mov bx,rlr
mov dl,p_dsk[bx]
prdsk1: add dl,'A' ! call prchar
mov dl,':' ! jmp prchar
prcusp: mov dx,(offset cli_cuspqpb) + qpb_name
call prnam ! mov dx,offset questr
call prcsm ! jmp crlf
prcsm: mov si,u_conccb
mov di,rlr
cmp [si],di ! jne prr1
xor bx,bx ! push ds
mov ax,cs ! mov ds,ax
call cprnt1 ! pop ds
prr1: ret
prtyp: mov bh,3 ! jmps prn1
prnam: mov bh,8
prn1: mov bl,' '
mov si,u_conccb
mov di,rlr
cmp [si],di ! jne prr1
cprnt1: mov cx,f_conprint ! jmps jos
flclse:
mov cx,f_fclose ! mov dx,offset cli_fcb
jmps fo1
flopn:
mov cx,f_fopen
mov si,offset cli_fcb
or byte ptr fcb_name+5[si],080h ;f6`=open read-only
mov dx,si
fo1: push es ! call osif ! pop es ! ret
cli_sync:mov cx,f_sync
jmps mx1
cli_unsync: mov cx,f_unsync
mx1: mov bx,offset cli_spb
jos: jmp osif
pfn: mov dx,offset cli_pcb ! mov cx,f_parsefilename
jmps jos
conasn: mov cx,f_conassign ! mov dx,offset cli_acb
jmps jos
questr db ' Msg Qued',0
userstr db '(User 0)',0