;***************************************************** ;* ;* Submit CCP/M-86 ;* ;***************************************************** ;Revisions: ; 30 Mar 83 dh - attach after commands except chain ; 21 Mar 83 whf - cli on 'mov ss'; fix readchar eof ; 18 Feb 83 whf - $global/$local cmds ; 15 Feb 83 dh - closing windows cseg jmps submit db 'SUBMIT 1.3 ' db 'COPYRIGHT (C) 1983,' db ' DIGITAL RESEARCH ' db '3/21/83' db 13,10,0,'$' true equ 0ffh false equ 0 unknown equ 0 mpmint equ 224 ; int vec for mpm ent. mpm_conin equ 1 mpm_conout equ 2 mpm_conwrite equ 9 mpm_conread equ 10 mpm_constat equ 11 mpm_version equ 12 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_chain equ 47 mpm_terminate equ 143 mpm_setprior equ 145 mpm_conattach equ 146 mpm_condetach equ 147 mpm_setdefcon equ 148 mpm_clicmd equ 150 mpm_parse equ 152 mpm_getdefcon equ 153 mpm_getpdadr equ 156 mpm_setdeflst equ 160 mpm_getdeflst equ 164 ; fcb offsets mode2 equ 6 ; 2nd open mode byte modesys equ 10 ; SYS attribute byte ftype equ 9 ; file type sysdrive equ byte ptr .4bh ;system disk in SYSDAT 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 p_prior equ 05H ;process descriptor priority p_flag equ word ptr 06H ;flags p_name equ 08H ;name of process p_parent equ 1EH ;PD's parent p_drv equ byte ptr 012H p_user equ byte ptr 013H p_list equ byte ptr 024H pf_keep equ 02H ;keep flag pf_childabort equ 800H ;child aborted abnormally pf_ctlc equ 080H ;control c occured ;***************************************************** ;* ;* Submit Code ;* ;***************************************************** ;====== submit: ; PROGRAM MAIN - INITIALIZATION ;====== mov ax,ds pushf ! pop bx ! cli ;disable interrupts for stack switch mov ss,ax mov sp,offset stacktop push bx ! popf ;restore interrupts mov cl,mpm_version call mpm and bh,not 2 ;strip network bit cmp bh,11H ! jz okvers ;check MP/M-86 or cmp bh,14H ! jz okvers ;check Concurrent CP/M-86 mov dx,offset wrongvers call print_string jmp terminate okvers: ; ;set priority better than parent ; mov cl,mpm_getpdadr call mpm ;get our PD address mov pdadr,bx ;save PD address mov sysdatseg,es ;and the system data area segment mov bx,es:p_parent[bx] ;get our parent's PD address mov parent_offset,bx ;save parent's PD addr cmp bx,0 ! jne psetpar ;see if parent exists mov dx,197 ! jmps setp ; oops, set to better than TMP psetpar:mov dx,es:p_prior[bx] ;our parent's priority dec dx ;we run at one better, cmp dx,64 ! jae setp mov dx,64 ;don't compete w/system setp: mov cl,mpm_setprior call mpm ;set our priority mov cl,mpm_setdma ;using default buffer at 80H for mov dx,offset dma ;command tail and argument expansion call mpm call getuser mov command_user,al mov defuser,al mov si,offset fcb mov byte ptr ftype[si],'S' ;look for file with type = SUB mov byte ptr ftype+1[si],'U' mov byte ptr ftype+2[si],'B' or byte ptr mode2[si],80h ;open in R/O mode mov dx,si call openfile cmp al,0ffh jne exists mov dl,0 ;try user 0 mov command_user,dl call setuser mov es,sysdatseg ;on system drive mov al,es:sysdrive inc al mov fcb,al mov dx,offset fcb call openfile cmp al,0ffh je openfail mov si,offset fcb test byte ptr modesys[si],080H ;does it have SYS attribute? jnz exists openfail: mov dx,offset sopen_err call print_string jmp submitabort exists: mov dx,offset fcb call closefile mov al,fcb ;save disk number where command file is cmp al,0 ;default disk ? jnz save_disk_no call getdisk inc al save_disk_no: mov command_disk,al call getconsole ;save console number this mov command_con,al ;program was run from ; ;deblank command tail ; mov si,offset cmdtail + 1 mov di,offset deblankbuf firstwhites: cmp byte ptr [si],' ' jnz tab jmps morewhites tab: cmp byte ptr [si],9 jnz deblank morewhites: inc si jmps firstwhites deblank: mov al,byte ptr [si] inc si cmp al,' ' jz skipwhite cmp al,9 ;tab jz skipwhite jmps copychar copychar: cmp al,0 ;end of of command tail ? jz putlastblank mov [di],al inc di jmps deblank putlastblank: mov byte ptr [di],' ' inc di mov [di],al ;ends with space and zero jmps dedone skipmore: inc si skipwhite: ;input = si points at tab or blank mov al,[si] cmp al,' ' jz skipmore cmp al,9 ;tab jz skipmore mov byte ptr [di],' ' inc di jmps deblank ;si points to non white char ;di is next char to copy dedone: ; ;fill argument tail ; mov bp,offset deblankbuf mov bx,offset argtable xor si,si ;pointer into deblankbuf mov di,si ;index into argtable nxtfill: mov al,byte ptr [bp + si] ;0th argument is '.sub' cmp al,0 jz filldone mov [bx + di],si inc di call skiparg ;skip over argument and blank jmps nxtfill skiparg: inc si cmp byte ptr [bp + si],' ' jnz skiparg inc si ;char after blank ret filldone: mov numargs,di call crlf mov cmdbuf,maxcmdlen ;get first command mov dx,offset cmdbuf call readbuffer cmp bx,0 jne submitexit ;EOF on first command mov lcmdbuf,maxcmdlen ;try next command mov dx,offset lcmdbuf call readbuffer mov no_more_cmds,bl ;true if EOF jmps topofcmdloop ;and look ahead to see ;if there are more commands ;========== submitexit: ;========== mov cl,0 ! mov dx,0 ;jmp mpm ;=== mpm: ; INTERFACE ROUTINE FOR SYSTEM ENTRY POINTS ;=== int mpmint ! ret ;=========== topofcmdloop: ; LOOP FOREVER ;=========== ; ; print CR,LF if we just sent a command ; cmp cmdsent,false ! je noclearline mov cmdsent,false call crlf noclearline: ; ; set up and print user prompt ; ; get current default disk call getdisk mov defdisk,al ; get current default user # ; this call should be made on every ; loop in case the 'USER' program ; has changed the default user number call getuser mov defuser,al ;create user part of prompt string mov promptutens,13 mov promptuones,13 test al,al ;don't print user 0 jz prprompt mov promptuones,'0' cmp al,10 ! jb ones mov promptutens,'1' sub al,10 ones: add promptuones,al prprompt: ; create disk part of prompt string mov al,'A' ! add al,defdisk mov promptdisk,al ; write user prompt mov dx,offset prompt cmp promptutens,13 ! jne writeprompt mov dx,offset promptutens writeprompt: call print_ds_string ; ; copy command to cli buffer, make upper case and ; expand command arguments ; mov si,offset cmd ;where command is mov bp,offset clicmd ;copy w/ expanded args here xor di,di ;index into cli command nextchar: mov al,[si] ;char from command inc si cmp al,'$' ;argument ? jz argmaybe noarg: call copyit jcxz nextchar jmps echo_cmd ;can't expand any more params, ;buffer is full argmaybe: cmp byte ptr [si],'$' ;look for two '$' in a row jne numeric inc si ;skip 2nd $ sign jmps noarg ;copy one $ sign to command buffer numeric: cmp byte ptr [si],'0' ;is next char after '$' a digit ? jb noarg cmp byte ptr [si],'9' ja noarg realarg: xor ax,ax ;copy argument throw out - '$' in al mov al,[si] sub al,'0' ;1st digit inc si cmp byte ptr [si],'0' ;is there a second digit ? jb onedigit cmp byte ptr [si],'9' ja onedigit mov dl,10 ;1st digit is tens in column mul dl mov dl,[si] ;2nd argument is ones column inc si sub dl,'0' add al,dl onedigit: mov bx,ax copyarg: cmp bx,numargs jb oknum ;numargs in range 1 to n jmps nextchar ;no such argument oknum: mov bl,argtable[bx] ;argument address rel to deblankbuf copymore: mov al,deblankbuf[bx] cmp al,' ' jz nextchar ;end of argument call copyit inc bx jmps copymore copyit: ;copy character in AL to location BP + DI, increment DI. ;if AL = 0, or command buffer is full then return CX = 0ffffH ;else return CX = 0H mov [bp + di],al ;mov to cli command buffer inc di xor cx,cx cmp di,maxcmdlen ;cli buffer size jae donecopy testend: cmp al,0 jz donecopy ret donecopy: mov clicmdlen, di dec cx ret echo_cmd: mov si, offset clicmd ;print command line after mov cx, clicmdlen ;parameter substitution call printcmdline ; ; echo newline ; call crlf ; ; make sure not a null command ; lea bx,cmd cmp blen,0 ! je gonextcmd dblank: cmp byte ptr [bx],' ' ! je zapblank cmp byte ptr [bx],9 ! jne noblanks ;no tabs zapblank: inc bx ! dec blen ! jmps dblank noblanks: lea ax,cmd ! cmp ax,bx ! je chksemi ; remove leading blanks push ds ! pop es ! xor ch,ch ! mov cl,blen mov di,ax ! mov si,bx ! cld ! rep movsb mov bx,ax chksemi: ; see if line starts with semicolon cmp byte ptr [bx],';' ! je gonextcmd ; ; see if disk change - if 'X:' change def disk to X ; cmp blen,2 ! jne notdrive cmp byte ptr 1[bx],':' ! jne try_builtin ; change default disk mov dl,[bx] ;get disk name and dl,5fh ;make Upper Case sub dl,'A' ;make disk number ; check bounds cmp dl,0 ! jb subex cmp dl,15 ! jbe okdrive subex: mov dx,offset errstr ! call print_string mov dx,offset drverr ! call print_string !call crlf jmp submitabort okdrive: push dx ! call setdisk ! pop dx ; select default disk cmp fix_parent,false jz gonextcmd ;don't change parent's drive mov bx,parent_offset ! test bx,bx jz gonextcmd ;parent doesn't exist mov es,sysdatseg mov es:p_drv[bx],dl gonextcmd: jmp getnxtcmd notdrive: mov di,offset clicmd mov si, offset parseresult call parsefilename jcxz goodparse mov cl,126 mov di,offset clicmd mov al, ' ' push cs ! pop es repne scasb mov byte ptr[di], '$' jmp clierror goodparse: mov parseret,bx cmp parseresult,0 ! jz try_builtin jmp not_builtin try_builtin: mov di,offset usercmd mov si,offset parseresult ! inc si push ds ! pop es mov cx,4 ! repz cmpsw jnz notuser mov si,offset parseresult mov di,parseret ! cmp di,0 je pruser call parsefilename ; CX = 0 if ok cmp cx,0 ! jne pruser mov si,offset parseresult ! inc si mov dx,[si] call a_to_b cmp bl,15 ! ja usererr mov dl,bl ! push dx call setuser ! pop dx mov defuser,dl cmp fix_parent,false jz pruser ;don't fix parent mov bx,parent_offset ! test bx,bx jz pruser ;parent doesn't exist mov es,sysdatseg mov es:p_user[bx],dl jmps pruser usererr: mov dx,offset usererrmsg call print_string jmp submitabort ;any error fatal pruser: mov dx,offset usermsg call print_string call getuser mov dl,bl ! call prnum call crlf ! call crlf jmp getnxtcmd notuser: mov si,offset parseresult ! inc si mov di,offset printercmd push ds ! pop es mov cx,4 ! repz cmpsw jnz notprinter mov si,offset parseresult mov di,parseret ! test di,di jz prprinter call parsefilename ; CX = 0 if ok cmp cx,0 ! jne prprinter; no tail mov si,offset parseresult ! inc si mov dx,[si] call a_to_b cmp bl,0ffh ! je printererr mov dl,bl ! push dx call setlist ! pop dx jcxz setparent ;CX=0 if ok list # printererr: mov dx,offset printererrmsg call print_string ! jmp submitabort ;any err fatal setparent: cmp fix_parent,false jz prprinter ;don't fix parent mov bx,parent_offset ! test bx,bx jz prprinter ;check for parent mov es,sysdat_seg mov es:p_list[bx],dl ;0 relative ;in CCP/M prprinter: mov dx,offset printermsg call print_string call getlist mov dl,bl ! call prnum call crlf ! call crlf jmp getnxtcmd notprinter: ; check for '$include' option mov si,offset parseresult ! inc si mov di,offset includecmd push ds ! pop es mov cx,4 ! repz cmpsw jnz notinclude mov si,offset parseresult mov di,parseret ! test di,di jz notinclude call parsefilename ; CX = 0 if ok cmp cx,0 ! jne includerr; no tail mov si,pdadr add si,p_name mov di,offset clicmd mov cl,4 push ds ! pop es push ds ! mov ds,sysdatseg ; overwrite $include with rep movsw ; name of this program ; for recursive submits pop ds mov dx,offset includemsg call print_string jmps clicall ; send submit command includerr: mov dx,offset includerrmsg call print_string jmp submitabort notinclude: ; check for '$global' option mov si,offset parseresult ! inc si mov di,offset globalcmd push ds ! pop es mov cx,4 ! repz cmpsw jnz notglobcmd mov fix_parent,true ;for d:, USER & PRINTER cmds mov dx,offset globalmsg call print_string jmp getnxtcmd notglobcmd: ; check for '$local' option mov si,offset parseresult ! inc si mov di,offset localcmd push ds ! pop es mov cx,4 ! repz cmpsw jnz notlocal mov fix_parent,false ;for d:, USER & PRINTER cmds mov dx,offset localmsg call print_string jmp getnxtcmd notlocal: notbuiltin: ;======= cli_call: ; SEND CLI COMMAND ;======= ; initialize Cli Control Block mov clicb_net,0 ; make cli call mov cmdsent,true cmp no_more_cmds,true jne gocli mov dx,offset clicmd ;this is the last command mov cl,mpm_setdma call mpm mov cl,mpm_chain call mpm ;returned from chain ;********* ; mov cx,e_bad_open no longer with us nop ! nop ! nop ;so same as patch ;********* jmp clierror gocli: lea dx,clicb ! mov cl,mpm_clicmd call mpm cmp bx,0 ! jne clierror ;jmps get_nxtcmd getnxtcmd: cmp no_more_cmds,true jne getnxt2 jmp submitexit ;terminate if no more commands getnxt2: call attach ;get the console back ;before the TMP does mov si,offset lcmdbuf ;copy look ahead command mov di,offset cmdbuf ;buffer to cmdbuf mov cx,maxcmdlen+3 ;cmd buffer length mov ax,ds mov es,ax cld rep movsb mov dx,offset lcmdbuf ;get look ahead command call readbuffer mov no_more_cmds,bl ;true if EOF jmp topofcmdloop ;and look ahead to see ;if there are more commands ;======== clierror: ;======== ; Cli call unsuccesful, analyze and display err msg ; input: CX = ERROR CODE mov si,(offset clierrtab)-4 push ds ! push cs ! pop ds nexterr: add si,4 cmp cs:word ptr [si],0ffffh ! je unknownerr cmp cx,cs:[si] ! jne nexterr unknownerr: mov dx,cs:2[si] pop ds ; jmps showerr showerr: ; Print Error String ;------- ; input: DX = string in CSEG perr: push dx ! call crlf mov dx, offset errstr ! call print_string pop dx ! call print_string ! call crlf mov dx, offset cmdstr ! call print_string mov si, offset clicmd mov cx, clicmdlen call printcmdline ! call crlf ;jmp submitabort ;any error at this level is fatal ;=========== submitabort: ;=========== ; Tell user we are aborting mov dx,offset abortstr ! call print_string jmp submitexit ;========== readbuffer: ;========== ; Simulate Read Console buffer from a disk file. ; input: DX = buffer address ; output: BX = 0ffffh if EOF mov di,dx xor al,al mov 1[di],al ;no chars read cmp 0[di],al ;zero length buffer jnz buf_ok ;return no error - nop mov bx,0ffffh ;ready for error ret buf_ok: mov si,di ! inc si ! inc si ;si is next char read_another: mov al,1[di] cmp al,[di] jae done_ok ;full buffer push di call readchar ;fills [si] pop di cmp bx,0 ;non-zero or eof error jz not_error ret not_error: cmp byte ptr [si],0ah ! jne not_lf jmps done_ok not_lf: cmp byte ptr [si],0dh ! je done_ok inc byte ptr 1[di] ;not cr, inc buffer count inc si ;inc char position jmp read_another done_ok: cmp byte ptr 1[di],0 ;no characters read in buffer jz read_another ;skip leading cr's and lf's mov byte ptr [si],0 mov bx,0 ! ret ;======== readchar: ;======== ; Read a character from file. ; input = SI is address of where to put character ; output = BX = 0ffffh if error or EOF ; xor bh,bh mov bl,buf_ptr ;char ptr in dma buffer cmp bl,128 jb no_read push si mov dl,command_user ;user number of command file call setuser mov bx,offset fcb mov al,command_disk ;disk drive number of command file mov [bx],al ;re-open each time to allow deletion or byte ptr mode2[bx],80h ;of command file, open in R/O mode mov dx,bx call openfile cmp al,0ffh jz readerr mov dx,offset fcb call readfile ;read sequential cmp al,0 jnz readerr mov dx,offset fcb call closefile mov bx,0 pop si no_read: mov al,dma[bx] cmp al,1ah ;check for EOF jz ret_eof mov [si],al inc bl mov buf_ptr,bl ;point to next char in disk buffer xor bx,bx jmps read_ret readerr: pop si ret_eof: mov bx,0ffffh ;error or eof ;jmps read_ret read_ret: push bx ! mov dl,defuser ! call setuser ! pop bx ret ;***************************************************** ;* ;* SUBROUTINES ;* ;***************************************************** printcmdline: ;SI = string to print, CX = length test cx,cx ;print byte by byte jz blank ;to include $ signs moreecho: lodsb mov dl,al push cx ! push si call prchar pop si ! pop cx loop moreecho blank: ret 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 terminate: xor dx,dx ! mov cx,dx ! jmps mpm1 charin: mov cl,mpm_conin ! jmps mpm1 prchar: mov cl,mpm_conout ! jmps mpm1 getuser: mov dl,0ffh setuser: mov cl,mpm_usercode ! jmps mpm1 crlf: mov dx,offset crlfstr ;jmp printstring print_string: push ds ! mov ax,cs ! mov ds,ax call print_ds_string ! pop ds ! ret print_ds_string: push es ! push ds ! pop es mov si,dx mov di,dx mov cx,0FFFFH mask: lodsb and al,07FH ;mask parity stosb cmp al, '$' ! je print_it loop mask print_it: pop es mov cl,mpm_conwrite ! jmps mpm1 getconsole: mov cl,mpm_getdefcon ! 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 openfile: mov cl,mpm_openfile ! jmps mpm1 closefile: mov cl,mpm_closefile ! jmps mpm1 readfile: mov cl,mpm_readfile ;!; jmps mpm1 mpm1: jmp mpm ;***************************************************** ;* ;* CODE DATA AREA - can be shared ;* ;***************************************************** 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; ; MESSAGES wrongvers db 'Requires CCP/M-86 or MP/M-86' crlfstr db 10,13,'$' usererrmsg db 13,10,'Invalid User Number',13,10,'$' usermsg db 'User Number = $' printererrmsg db 13,10,'Invalid Printer Number',13,10,'$' printermsg db 'Printer Number = $' includerrmsg db 13,10,'Include Error$' includemsg db '(submit)',10,13,'$' globalmsg db 'Global mode ON',13,10,10,'$' localmsg db 'Global mode OFF',13,10,10,'$' abortstr db 'SUBMIT can not continue',13,10,'$' errstr db 'CP/M Error: $' memerr db 'Not Enough Memory$' pderr db 'PD Table Full$' fnameerr db 'Bad File Spec$' catcherr db 'Unknown CLI Error$' ;we should never print ;this error, it means ;we have added CLI ;error returns and ;have not updated SUBMIT loaderr db 'Load Error$' openerr db 'Can''t Find Command$' qfullerr db 'RSP Command Que Full$' aborterr db 'CLI Abort$' drverr db 'Invalid Drive$' cmdstr db 'Command = $' sopen_err db 'No ''SUB'' File Present',10,13, '$' ;***************************************************** ;* ;* Data Area - separate per invokation of SUBMIT ;* ;***************************************************** dseg org 05cH fcb rb 32 cr db 0 ;current record r0 rw 0 r2 rb 0 org 080h cmdtail rb 128 stack dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch dw 0cccch,0cccch,0cccch stacktop rw 0 maxcmdlen equ 128 ; the Read Console Buffer and the ; Cli Control Block share the same memory dma rb 128 numargs rw 1 argtable rb 64 ;address of arguments in cmdtail deblankbuf rb maxcmdlen + 1 no_more_cmds db false ;set to true when EOF is ;found lcmdbuf rb 1 lblen rb 1 ;read from disk to here, lcmd rb maxcmdlen + 1 ;copy this to CMD cmdbuf rb 1 ;current cmd goes here blen rb 1 cmd rb maxcmdlen + 1 ;copy w/ expanded args to CLICMD clicb rb 0 ;cmd w/ expanded args goes here clicb_net db 0 clicmd rb maxcmdlen+1 clicmdlen dw 0 command_user rb 1 command_disk rb 1 command_con rb 1 defdisk rb 1 defuser rb 1 buf_ptr db 128 ;force initial read ;in readchar routine prompt db 13 promptutens db '0' promptuones db '0' promptdisk db 'A' promptend db '>$' pcb dw offset clicmd dw offset parseresult parseret dw 0 parseresult rb 36 cmdsent db false pdadr rw 1 ;our pd address sysdatseg rw 1 ;the system data area's segment parent_offset rw 1 ;parents pd address fix_parent db false ;local/global mode usercmd db 'USER ' printercmd db 'PRINTER ' includecmd db '$INCLUDE' globalcmd db '$GLOBAL ' localcmd db '$LOCAL ' end