;***************************************************** ;* ;* Terminal Message Processor ;* ;* The TMP determines the user interface to MPM. ;* Much of the interface is available though ;* system calls. This TMP takes advantage of ;* as much as possible for simplicity. The TMP ;* could, for instance, be easily modified to ;* force logins and have non-standard defaults. ;* ;* With a little more work, The TMP could do all ;* command parsing and File Loading instead of ;* using the CLI COMMAND FUNCTION. This is also ;* the place to AUTOLOAD programs for specific ;* users. Suggestions are given in the MP/M-86 ;* SYSTEM'S GUIDE. ;* ;***************************************************** true equ 0ffh false equ 0 unknown equ 0 mpmint equ 224 ; int vec for mpm ; mpm86 equ false ; CCP/M if false mpm86 equ true ; MP/M if true cr equ 13 lf equ 10 mpm_conout equ 2 mpm_conwrite equ 9 mpm_conread equ 10 mpm_diskselect equ 14 mpm_openfile equ 15 mpm_closefile equ 16 mpm_readfile equ 20 mpm_getdefdisk equ 25 mpm_setdma equ 26 mpm_usercode equ 32 mpm_freedrive equ 39 mpm_conattach equ 146 mpm_condetach equ 147 mpm_setdefcon equ 148 mpm_clicmd equ 150 mpm_parse equ 152 mpm_setdeflst equ 160 mpm_getdeflst equ 164 ps_run equ 00 ; on ready list root pf_sys equ 001h ; system process pf_keep equ 002h ; do not terminate s_mpmseg equ word ptr 40H ;begin MPM segment s_sysdisk equ byte ptr 04bh ;system disk s_ncns equ byte ptr 47H ;sys. consoles s_version equ word ptr 78h ;ofst ver. str in SUP rsp_top equ 0 rsp_md equ 008h rsp_pd equ 010h rsp_uda equ 040h rsp_bottom equ 140h e_no_memory equ 3 ; cant find memory e_no_pd equ 12 ; no free pd's e_q_full equ 15 ; full queue e_illdisk equ 23 ; illegal disk # e_badfname equ 24 ; illegal filename e_badftype equ 25 ; illegal filetype e_bad_load equ 28 ; bad ret. from BDOS load e_bad_read equ 29 ; bad ret. from BDOS read e_bad_open equ 30 ; bad ret. from BDOS open e_nullcmd equ 31 ; null command sent e_ill_lst equ 37 ; illegal list device e_ill_passwd equ 38 ; illegal password e_abort equ 40 ; aborted in CLI ;***************************************************** ;* ;* TMP Shared Code and Constant Area ;* ;***************************************************** cseg org 0 ;=== mpm: ; INTERFACE ROUTINE FOR SYSTEM ENTRY POINTS ;=== int mpmint ! ret ;=== tmp: ; PROGRAM MAIN - INITIALIZATION ;=== ; set default console # = TMP# mov dl,defconsole ! call setconsole ; set default disk = system drive if MP/M, A: if CCP/M if mpm86 push ds ! mov ds,sysdatseg mov dl,.s_sysdisk ! pop ds endif if not mpm86 xor dl,dl endif call setdisk if mpm86 mov dl,defconsole ;set default user # = console endif if not mpm86 xor dl,dl ;all TMPs come up user 0 endif ;in CCP/M call setuser call attach ;print version push ds ! mov ds,sysdatseg mov dx,.s_version mov ds,.s_mpmseg call print_ds_string ! pop ds call detach mov al,defconsole ;look for startup file add tmpnum,al ;works for 1st 10 TMPS mov dx,offset fcb mov cl,mpm_openfile call mpm cmp al,0ffh je nostartup mov dx,offset clicb_cmd mov cl,mpm_setdma call mpm mov dx,offset fcb mov cl,mpm_readfile call mpm push ax mov dx,offset fcb mov cl,mpm_closefile call mpm pop ax test al,al jnz nostartup mov ax,ds mov es,ax mov al,cr mov cx, 128 mov di,offset clicb_cmd repne scasb inc di ;include cr lf in line mov byte ptr [di],'$' sub di,offset clicb_cmd mov ax,di sub ax, 2 mov read_blen, al mov dx,offset supmsg call printstring mov dx,offset clicb_cmd call print_ds_string jmps startup nostartup: ; THIS IS WHERE A LOGIN ROUTINE MIGHT ; BE IMPLEMENTED. THE DATA FILE THAT ; CONTAINS THE USER NAME AND PASSWORD ; MIGHT ALSO CONTAIN AN INITIAL DEFAULT ; DISK AND USER NUMBER FOR THAT USER. ;=========== nextcommand: ; LOOP FOREVER ;=========== ; free drive mov dx,0ffffh ! call freedrive ; attach console call attach ; print CR,LF if we just sent command cmp cmdsent,false ! je noclearline mov cmdsent,false call crlf noclearline: ; set up and print user prompt ; get current default user # and disk ; this call should be made on every ; loop in case the last command ; has changed the default. mov dl,cr ! call prchar call getuser mov dl,bl ! call prnum call getdisk mov dl,'A' ! add dl,bl call prchar mov dx,offset prompt call print_string ; Read Command from Console mov dx,offset read_buf ! call conread startup: ; echo newline mov dl,lf ! call prchar ; make sure not a null command lea bx,clicb_cmd cmp read_blen,0 ! je gonextcmd cmp byte ptr [bx],';' ! je gonextcmd ; see if disk change ; if 'X:' change def disk to X cmp read_blen,2 ! jne clicall cmp byte ptr 1[bx],':' jne clicall ; change default disk mov dl,[bx] ;get disk name and dl,5fh ;Upper Case sub dl,'A' ;disk number ; check bounds cmp dl,0 ! jb gonextcmd cmp dl,15 ! ja gonextcmd ; select default disk call setdisk gonextcmd: jmp nextcommand ;======= clicall: ; SEND CLI COMMAND ;======= ; put null at end of input mov bx,offset clicb_cmd mov al,read_blen ! mov ah,0 add bx,ax ! mov byte ptr [bx],0 ; copy command string for error ; reporting later and to check ; for built in commands... mov cx,64 mov si,offset clicb_cmd mov di,offset savebuf push ds ! pop es rep movsw ; parse front to see if ; built in command mov si,offset fcb mov di,offset savebuf call parsefilename jcxz goodparse sub bx,bx ! mov bl,read_blen add bx,offset savebuf mov byte ptr [bx],'$' jmp clierror goodparse: mov parseret,bx cmp bx,0 ! jne haveatail mov bl,read_blen add bx,offset savebuf haveatail: mov byte ptr [bx],'$' ! inc bx cmp fcb,0 ! je try_builtin jmp not_builtin ; is it USER command? try_builtin: mov si,offset fcb ! inc si mov di,offset usercmd push cs ! pop es mov cx,4 ! repz cmpsw jnz notuser mov si,offset fcb mov di,parseret cmp di,0 ! je pruser inc di call parsefilename cmp cx,0 ! jne pruser mov si,offset fcb inc si mov dx,[si] call a_to_b cmp bl,15 ! ja usererr mov dl,bl call setuser jmp pruser usererr: mov dx,offset usererrmsg call printstring pruser: mov dx,offset usermsg call printstring call getuser mov dl,bl ! call prnum call crlf jmp nextcommand notuser: mov si,offset fcb ! inc si mov di,offset printercmd push cs ! pop es mov cx,4 ! repz cmpsw jnz notprinter mov si,offset fcb mov di,parseret cmp di,0 ! je prprinter inc di call parsefilename cmp cx,0 ! jne prprinter mov si,offset fcb inc si mov dx,[si] call a_to_b cmp bl,0ffh je printererr mov dl,bl call setlist jcxz prprinter printererr: mov dx,offset printemsg call printstring prprinter: mov dx,offset printermsg call printstring call getlist mov dl,bl ! call prnum call crlf jmp nextcommand notprinter: not_builtin: ; initialize Cli Control Block mov clicb_net,0 ; make cli call mov cmdsent,true lea dx,clicb ! mov cl,mpm_clicmd call mpm cmp bx,0 ! jne clierror jmp nextcommand ;======== clierror: ;======== ; Cli call unsuccesful, analyze and display err msg ; input: CX = ERROR CODE mov si,(offset clierrtab)-4 nexterr: add si,4 cmp word ptr [si],0ffffh ! je unknownerr cmp cx,[si] ! jne nexterr unknownerr: mov dx,2[si] ; jmps showerr showerr: ; Print Error String ;------- ; input: DX = address of Error ; string in CSEG ; if DX=0 then NULL COMMAND cmp dx,0 ! jne perr mov cmdsent,false ! jmp nextcommand perr: push dx mov dx,offset savebuf ! call print_ds_string mov dl,':' ! call prchar mov dl,' ' ! call prchar pop dx call printstring ! call crlf jmp nextcommand parsefilename: ; SI = fcb DI = string mov cx,mpm_parse mov bx,offset pcb mov [bx],di ! mov 2[bx],si mov dx,bx ! jmp mpm a_to_b: ;dl = 1st char, dh = 2nd char cmp dh,' ' ! jne atob2char mov dh,dl ! mov dl,'0' atob2char: cmp dh,'0' ! jb atoberr cmp dh,'9' ! ja atoberr cmp dl,'0' ! jb atoberr cmp dl,'9' ! ja atoberr sub dh,'0' ! sub dl,'0' mov ax,0 ! mov al,dl push dx ! mov cl,10 mul cl ! pop dx mov dl,dh ! mov dh,0 add ax,dx mov bx,ax ! ret atoberr: mov bl,0ffh ! ret prnum: ; dl = num (0-15) cmp dl,10 ! jb prnum_one push dx mov dl,'1' ! call prchar pop dx ! sub dl,10 prnum_one: add dl,'0' ; jmp prchar prchar: mov cl,mpm_conout ! jmp mpm1 getuser: mov dl,0ffh setuser: mov cl,mpm_usercode ! jmp mpm1 crlf: mov dx,offset crlfstr ;jmp printstring printstring: push ds ! mov ax,cs ! mov ds,ax call print_ds_string ! pop ds ! ret print_ds_string:mov cl,mpm_conwrite ! jmps mpm1 setconsole: mov cl,mpm_setdefcon ! jmps mpm1 setdisk: mov cl,mpm_diskselect ! jmps mpm1 getdisk: mov cl,mpm_getdefdisk ! jmps mpm1 setlist: mov cl,mpm_setdeflst ! jmps mpm1 getlist: mov cl,mpm_getdeflst ! jmps mpm1 attach: mov cl,mpm_conattach ! jmps mpm1 detach: mov cl,mpm_condetach ! jmps mpm1 conread: mov cl,mpm_conread ! jmps mpm1 freedrive: mov cl,mpm_freedrive ! jmps mpm1 mpm1: jmp mpm ;***************************************************** ;* ;* CONSTANTS (IN SHARED CODE SEGMENT) ;* ;***************************************************** clierrtab dw e_nullcmd, 0 ;null command dw e_no_memory, memerr ;No memory dw e_no_pd, pderr ;No unused PD dw e_badfname, fnameerr;Ill. command dw e_illdisk, fnameerr;Ill. disk dw e_ill_passwd, fnameerr;Ill. password dw e_badftype, fnameerr;Ill. type dw e_bad_load, loaderr ; dw e_bad_read, loaderr ; dw e_bad_open, openerr ; dw e_q_full, qfullerr; dw e_abort, aborterr; ; a few extra entries for future errors dw 0ffffh, catcherr; dw 0ffffh, catcherr; dw 0ffffh, catcherr; dw 0ffffh, catcherr; prompt db '>$' crlfstr db 13,10,'$' memerr db '?Not Enough Memory$' pderr db '?PD Table Full$' fnameerr db '?Bad File Spec$' catcherr rb 0 ;Unknown Errs give loaderr db '?Load Error$' ; Load Error Msg openerr db '?Can''t Find Command$' qfullerr db '?RSP Command Que Full$' aborterr db '?CLI Abort$' usererrmsg db 13,10,'Invalid User Number,' db ' IGNORED',13,10,'$' usermsg db 13,10,'User Number = $' printemsg db 13,10,'Invalid Printer Number,' db ' IGNORED',13,10,'$' printermsg db 13,10,'Printer Number = $' usercmd db 'USER ' printercmd db 'PRINTER ' supmsg db 'Start up command: $' ;***************************************************** ;* ;* TMP Data Area - this area is copied once for ;* each system console. The 'defconsole' ;* field is unique for each copy ;* - Each Data Area is run by a common ;* shared code segment. ;* ;***************************************************** DSEG org rsp_top sysdatseg dw 0 sdatvar dw s_ncns defconsole db 0,0 dw 0,0,0,0,0 org rsp_pd pd dw 0,0 ; link fields db ps_run ; status db 198 ; priority dw pf_sys+pf_keep ; flags db 'Tmp ' ; Name dw offset uda/10h ; uda seg db 0,0 ; disk,user db 0,0 ; ldisk,luser dw 0ffffh ; mem dw 0,0 ; dvract,wait db 0,0 ; org,net dw 0 ; parent db 0,0 ; cns,abort db 0,0 ; cin,cout db 0,0 ; lst,sf3 db 0,0 ; sf4,sf5 dw 0,0 ; reserved dw 0,0 ; pret,scratch org rsp_uda uda dw 0,offset dma,0,0 ;0-7 dw 0,0,0,0 ;8-fh dw 0,0,0,0 ;10-17 dw 0,0,0,0 ;18-1f dw 0,0,0,0 ;20-27 dw 0,0,0,0 ;28-2f dw 0,0,offset stack_top,0 ;30-37 dw 0,0,0,0 ;38-3f dw 0,0,0,0 ;40-47 dw 0,0,0,0 ;48-4f dw 0,0,0,0 ;50-57 dw 0,0,0,0 ;58-5f dw 0,0,0,0 ;60-67 org rsp_bottom dma rb 128 stack dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch stack_top dw offset tmp ; code offset dw unknown ; code seg dw unknown ; init. flags maxcmdlen equ 128 ; the Read Console Buffer and the ; Cli Control Block share the same memory read_buf rb 0 read_maxcmd db 128 clicb rb 0 clicb_net rb 0 read_blen rb 1 clicb_cmd rb maxcmdlen + 1 cmdsent db false parseret dw 0 pcb dw offset savebuf dw offset fcb fcb db 0, '$' tmpnum db '0' db '$ SUP' rb 20 db 0 ;current record savebuf rb 128 db 0 ;make sure hex is formed end