;***************************************************** ;* ;* Command Line Interpreter, Program Chain ;* ;***************************************************** ;=========== chain_entry: ;=========== sub dx,dx ;============ clicmd_entry: ;============ ; 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. If this succeeds, The default console ; is assigned to a process by the same name. ; The commandtail is then written to the queue and ; the we exit (even if assign fails). ; If there is a failure, We make the type name in the ; FCB to be 'CMD' and 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 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 push dx ! call mxread ! pop dx mov bx,rlr ! mov ax,p_flag[bx] mov cli_pflag,ax and ax,not pf_keep ! or ax,pf_tempkeep mov p_flag[bx],ax ; we have MXcli queue. ; 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 mpmif ! 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_copy 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_copy: 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_goodparse mov clierr,cx jmp cli_exit cli_goodparse: call shifttail ;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 mpmif ! jcxz cli_goodq retcli1: cmp cx,0 ! ret ;we successfully opened the queue ;check for process by assign console 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 mpmif ! 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],0 call conasn ! sub 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 sub ax,ax ! rep stosw pop es ; Initialize the PD for Load mov al,cli_fcb mov cli_lddsk,al 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 mov al,cli_user ! mov p_user[bx],al mov al,cli_cns ! mov p_cns[bx],al mov al,p_lst[si] ! sub al,ncondev mov p_lst[bx],al ; 3. Open the file mov si,(offset cli_fcb)+fcb_dskmap 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 fileopen 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_bopen ;extended error mov cl,srchdisk cmp cl,cli_dsk ! je cli_bopen cmp cli_fcb,0 ! jne cli_bopen ; try system disk mov bx,rlr mov p_dsk[bx],cl call fileopen cmp bl,0ffh ! je cli_bopen ;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 fileclose mov bx,rlr cmp p_user[bx],0 ! je cli_bopene mov p_user[bx],0 call fileopen cmp bl,0ffh ! je cli_bopen mov bx,offset cli_fcb test byte ptr fcb_type+1[bx],080h jnz cli_gopen call fileclose jmps cli_bopene ;could not find CMD file cli_bopen: cmp bh,0 ! jne cli_rmpd2 cli_bopene: 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 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 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 mov cx,f_cload cli_ld: call mpmif cli_cl: push bx ! push cx mov u_error_mode,0 call fileclose 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 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 ; init default fcb push es ! mov es,cli_bpage mov al,cli_lddsk mov es:bpg_lddsk,al mov di,offset bpg_fcb0 sub ax,ax ! stosb ;default disk mov al,' ' mov cx,11 ! rep stosb ;name,type sub 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 ; init load disk ; if cmdtail, parse cmp cli_cmdtail,0 ! je cmdtaildone call pfn cmp bx,0ffffh ! je cmdtaildone ; 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] 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 cmdtaildone push cli_pcb ! inc bx mov cli_pcb,bx call pfn pop cli_pcb cmp bx,0ffffh ! je cmdtaildone ; 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] mov es:bpg_pw2ptr,ax mov al,fcb_plen[si] mov es:bpg_pw2len,al mov cx,8 rep movsw pop es cmdtaildone: ; 10. Create the process cmp cli_chain,true ! jne noprior mov cx,f_setprior mov dx,1 ! call mpmif noprior: mov dx,cli_pd ! mov cx,f_createproc call mpmif ; 11. Assign Console to new process cmp cli_dfil,true ! jne nocrlf call crlf nocrlf: 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 pushf ! cli mov bx,pul ! mov si,cli_pd mov p_link[si],bx ! mov pul,si popf ; Normal EXIT cli_exit: ; close file and release MXCli queue 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 cmp cli_term,true ! jne clirls mov bx,rlr and p_flag[bx],not (pf_keep+pf_sys+pf_tempkeep+pf_ctlc) mov cx,f_terminate jmp mpmif clirls: push cli_pflag call mxwrite pop ax ! and ax,pf_tempkeep+pf_keep mov bx,rlr ! mov cx,p_flag[bx] and cx,not pf_tempkeep+pf_keep or cx,ax ! mov p_flag[bx],cx test p_flag[bx],pf_ctlc ! jz cli_nctl mov cx,f_terminate ! sub dx,dx call mpmif mov cli_err,e_abort ; setup error return if needed cli_nctl: mov cx,clierr ! sub bx,bx jcxz cli_gexit mov bx,0ffffh cli_gexit: ret shifttail: ;--------- ; setup command tail to be parsed ; input: AX = output of previous parsefilename cmp ax,0 ! je cli_notail ;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 cli_notail: mov cli_cmdtail,0 ret crlf: mov dl,13 ! call prchar mov dl,10 ;jmps prchar prchar: mov cx,f_conout ! jmp mpmif 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: sub bx,bx ! push ds mov ax,cs ! mov ds,ax call cprnt ! pop ds ! ret prtyp: mov bh,3 ! jmps prn1 prnam: mov bh,8 prn1: mov bl,' ' cprnt: mov cx,f_conprint ! jmps jmpm fileclose: mov cx,f_fclose ! mov dx,offset cli_fcb jmps fo1 fileopen: 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 mpmif ! pop es ! ret mxwrite:mov cx,f_qwrite jmps mxw1 mxread: mov cx,f_qread mxw1: mov dx,offset mxcliqpb jmpm: jmp mpmif pfn: mov dx,offset cli_pcb ! mov cx,f_parsefilename jmps jmpm conasn: mov cx,f_conassign ! mov dx,offset cli_acb jmps jmpm questr db ' Msg Qued',0 userstr db '(User 0)',0 ;========= user_retf: ;========= ; If a user does a RETF expecting to go to CCP, ; The process ends here mov bx,rlr and p_flag[bx],not pf_keep+pf_tempkeep+pf_ctlc+pf_sys mov cx,f_terminate ! sub dx,dx ! int mpmint