public clscpt, defkey, cptfcb, inicpt, clscpi, telnet public dopar, shokey, prkey include msdefs.h datas segment public 'datas' extrn flags:byte, trans:byte, buff:byte, portval:word targ termarg <0,1,80,24,cptchr,2dch,0,scntab,deftab,0,,parnon> ssp dw 0 ; Save SP in Telnet. crlf db cr,lf,'$' tmp db ?,'$' temp dw 0 temp1 dw ? ; Temporary storage. temp2 dw ? ; Temporary storage. tmsg1 db cr,lf,'[Connecting to host, type $' tmsg3 db ' C to return to PC]',cr,lf,cr,lf,cr,lf,'$' tmsg2 db cr,lf,'[Back at micro]',cr,lf,'$' erms22 db cr,lf,'?No capture file open$' ;[jd] esctl db 'Control-$' ; [6] inthlp db cr,lf,' ? This message' db cr,lf,' C Close the connection' db cr,lf,' S Status of the connection' db cr,lf,' B Send a break' db cr,lf,' M Toggle mode line' db cr,lf,' Q Quit logging' db cr,lf,' R Resume logging' db cr,lf,' 0 Send a null' db cr,lf,' Typing the escape character will send it to the host' db 0 intprm db 'Command>$' CPTFCB DB 25H DUP (?) CAPBUF DB 200 DUP (?) CAPBP DW ? CAPLFT DB ? SCNTLEN EQU 200 ; MAX # OF DEFINITIONS ONE can have defbsiz equ 400 ; combined length of all definitions... scntab dw scntlen dup (?) ; scan codes redefined deftab dw scntlen dup (?) ; pointer to definition strings defbuf db defbsiz dup (?) defptr dw defbuf ; pointer starts at beginning deflen dw defbsiz ; amt of space left in buffer sttmsg db 'Type space to continue$' shkmsg db cr,lf,'Press key: $' datas ends code segment public extrn comnd:near, outchr:near, stat0:near extrn escprt:near, clrbuf:near, term:near extrn cmblnk:near, locate:near, prtchr:near extrn beep:near, puthlp:near extrn serini:near,serrst:near, sendbr:near, showkey:near assume cs:code, ds:datas ; the show key command. shokey proc near mov ah,cmcfm ; confirm with carriage return call comnd jmp r ; uh oh... mov dx,offset shkmsg mov ah,prstr int dos ; print a prompt for it mov ax,offset targ ; give it terminal arg block. call showkey ; show them the key definition push ax push cx ; save results mov dx,offset crlf mov ah,prstr int dos pop cx pop ax call prkey ; print the buffer mov dx,offset crlf mov ah,prstr int dos jmp rskp ; and return shokey endp ; pass a string pointer in ax, length in cx. ; Prints the string, quoting any unprintables, except crlf. prkey proc near mov si,ax ; copy string ptr jcxz prke6 ; no string, stop here prke1: push cx ; save counter lodsb ; get a byte and al,7fH ; only consider low-order 7 bits. cmp al,' ' ; printable? jb prke2 ; no, print the hard way cmp al,7fH ; maybe a delete? jne prke4 ; no, can just put into string prke2: jcxz prke3 ; last char, can't be crlf cmp al,cr ; carriage return? jne prke3 ; no, go on cmp byte ptr [si],lf ; followed by linefeed? jne prke3 mov ah,prstr mov dx,offset crlf int dos ; else just print crlf inc si ; skip over lf pop cx ; careful... dec cx push cx jmp short prke5 prke3: push ax ; preserve the char mov ah,conout mov dl,'\' int dos ; print the quote character pop ax call proct ; print the octal byte jmp short prke5 prke4: mov dl,al ; normal char, just print it mov ah,conout int dos prke5: pop cx ; restore count loop prke1 prke6: ret ; and return prkey endp ; print the byte in al as an octal number proct proc near mov dl,al ; get the byte and dl,7h ; keep low-order byte mov cl,3 shr al,cl ; shift to get next digit jz proc1 ; 0, no more to print push dx ; else save current digit call proct ; print rest pop dx proc1: mov ah,conout add dl,'0' ; make printable int dos ret proct endp ; This is the CONNECT command. TELNET PROC NEAR mov ah,cmcfm call comnd ; Get a confirm. jmp r ; Didn't get a confirm. mov ah,prstr ; Output mov dx,offset crlf ; a crlf. int dos call domsg ; Reassure user. [19b] mov al,targ.flgs ; get present flags and al,modoff ; this is only one we can keep around or al,havtt ; defaults (!) cmp flags.debug,0 ; debug mode? jz tel0 ; no, keep going or al,trnctl ; yes, show control chars tel0: cmp flags.vtflg,0 ; vt52 emulation? jz tel1 or al,emheath tel1: mov bx,portval cmp [bx].ecoflg,0 ; echoing? jz tel2 or al,lclecho tel2: mov targ.flgs,al ; store flags mov ah,flags.comflg mov targ.prt,ah ; Port 1 or 2 mov ah,trans.escchr mov targ.escc,ah mov ah,[bx].parflg mov targ.parity,ah mov ax,[bx].baud mov targ.baudb,al mov ah,flags.capflg and ah,capt or targ.flgs,ah call serini ; init serial port tem: mov ax,offset targ ; Point to terminal arguments call term or targ.flgs,scrsam ; assume screen is the same. intchr: mov ah,dconio ; Direct console I/O. mov dl,0FFH ; Input. int dos ; Get a char. jz intchr ; no char, keep looking mov ah,al jz intchr ; If so, go until we get a char. cmp ah,' ' ; space - ignore it je tem mov bh,ah ; Save the actual char. and ah,not ('a'-'A') ; Convert to upper case. or ah,40H ; convert ctl-char to actual char. cmp ah,'C' ; Is it close? jne intch1 call serrst ; reset serial port jmp rskp ; and return intch1: cmp ah,'S' ; Is it status? jnz intch2 call stat0 ; If so, call stat0. call puthlp ; put help on screen mov dx,offset sttmsg mov ah,prstr int dos intch1a:mov ah,8 ; console input, no echo int dos cmp al,' ' ; space? jne intch1a and targ.flgs,not scrsam ; remember screen changed. jmp tem intch2: cmp ah,'B' ; Send a break? [20g] jne intch3 ; No. [20g] call sendbr ; Yes, so send a break. [20g] jmp tem ; And return. [20g] intch3: cmp ah,'M' ; mode line? jne intch4 xor targ.flgs,modoff ; toggle mode line jmp tem ; and reconnect intch4: cmp bh,'?' ; Is it help? jne intch5 ; If not, go to the next check. mov ax,offset inthlp ; If so, get the address of the help message. call puthlp ; write help msg mov dx,offset intprm mov ah,prstr ; Print it. int dos and targ.flgs,not scrsam ; remember screen changed jmp intchr ; Get another char. intch5: cmp bh,trans.escchr ; Is it the escape char? jne intch7 ; If not, go send a beep to the user. intch6: mov ah,al call outchr nop nop nop jmp tem ; Return, we are done here. intch7: cmp ah,'Q' ; maybe want to stop logging? jne intch8 test targ.flgs,capt ; not capturing, can't do this jz intc10 and targ.flgs,not capt ; stop capturing jmp tem ; and resume intch8: cmp ah,'R' ; maybe resume? jne intch9 ; no, keep going cmp flags.capflg,0 ; can we capture? jz intc10 ; no, forget it test targ.flgs,capt ; already capturing? jnz intc10 ; yes, can't toggle back on then or targ.flgs,capt ; else turn flag on jmp tem ; and resume intch9: cmp bh,'0' ; perhaps want a null (note original chr in bh) jne intc10 mov ah,0 call outchr nop nop nop jmp tem intc10: call beep jmp tem TELNET ENDP ; Reassure user about connection to the host. Tell him what escape ; sequence to use to return and the communications port and baud ; rate being used. [19b] DOMSG PROC NEAR mov ah,prstr mov dx,offset tmsg1 int dos call escprt mov ah,prstr mov dx,offset tmsg3 int dos ret DOMSG ENDP ; Set parity for character in Register AL. dopar: push bx mov bx,portval cmp [bx].parflg,parnon ; No parity? [10 start] je parret ; Just return cmp [bx].parflg,parevn ; Even parity? jne dopar0 and al,07FH ; Strip parity. jpe parret ; Already even, leave it. or al,080H ; Make it even parity. jmp parret dopar0: cmp [bx].parflg,parmrk ; Mark parity? jne dopar1 or al,080H ; Turn on the parity bit. jmp parret dopar1: cmp [bx].parflg,parodd ; Odd parity? jne dopar2 and al,07FH ; Strip parity. jpo parret ; Already odd, leave it. or al,080H ; Make it odd parity. jmp parret dopar2: and al,07FH ; Space parity - turn off parity bit. parret: pop bx ret ; [10 end] inicpt proc near mov capbp,offset capbuf mov caplft,128 ; init buffer ptr & chrs left ret ; and return inicpt endp cptchr proc near ; capture routine, char in al push di mov di,capbp mov byte ptr [di],al inc di mov capbp,di ; restore pointer pop di dec caplft ; decrement chars remaining jnz cptch1 ; more room, forget this part call cptdmp ; dump the info call inicpt ; re-init ptrs. cptch1: ret ; and return cptchr endp cptdmp proc near ; empty the capture buffer push ax push dx mov ah,setdma mov dx,offset capbuf ; the capture routine buffer int dos mov ah,writef mov dx,offset cptfcb int dos ; write out the block ;*** must be fixed... check error returns, disable capturing, ;*** figure out how to put dma address back mov dx,offset buff mov ah,setdma int dos ; put dma back pop dx pop ax ret cptdmp endp clscpt proc near test flags.capflg,0FFH ; doing capture jnz clscp1 ; yes, go ahead mov dx,offset erms22 mov ah,prstr int dos jmp rskp clscp1: mov ah,cmcfm call comnd jmp r clscpi: mov al,'Z'-64 ; control-z for eof... call cptchr ; output to file mov al,caplft cmp al,128 ; is buffer empty? je clscp2 ; yes, forget this stuff call cptdmp ; dump buffer (preserves registers) clscp2: mov ah,0 sub word ptr cptfcb+16,ax ; subtract remaining from low filsize sbb word ptr cptfcb+18,0 ; and from high size (with borrow) mov ah,closf mov dx,offset cptfcb int dos ; close up file mov flags.capflg,0 ; no longer capturing... jmp rskp ; and return clscpt endp ; enter with ax/scan code to define, si/ pointer to definition, cx/ length ; of definition. Defines it in definition table. ;*** somewhere should check for overflow etc of defbuf, and of scntab defkey proc near push ax ; save scan code mov ax,ds mov es,ax ; address data segment mov di,defptr ; this is where the def gets built inc di ; leave a byte for length defk1: lodsb ; get a byte from the source cmp al,'\' ; escape? jne defk2 ; no, just deposit him dec cx ; count available is one less call trnesc ; translate the escape sequence inc cx ; account for '\' (loop will decrement again). defk2: stosb ; drop off character loop defk1 ; and keep going while we have more mov ax,di ; get ptr to end dec ax ; back up pointer to end mov si,defptr ; pick up old ptr value sub ax,si ; this is actual length used mov byte ptr [si],al ; fill in length of entry mov defptr,di ; this is next free byte ; definition address is in si pop ax ; recover scan code mov cx,targ.klen ; length of scan table jcxz defk4 ; not there, just go add it mov di,offset scntab ; the scan code table repne scasw ; look for this one jne defk4 ; not defined already sub di,offset scntab + 2 ; compute index into table mov deftab[di],si ; fill in address ret ; and return defk4: mov di,targ.klen ; get length again inc di cmp di,scntlen ja defk5 ;** ignore def if over size mov targ.klen,di ; update length shl di,1 ; double for word index mov scntab[di-2],ax ; put scan code into table mov deftab[di-2],si ; and fill in definition defk5: ret ; that's it defkey endp ; enter with si/ source pointer, cx/ count ; converts an escape sequence, updates all pointers trnesc proc near push bx push dx ; preserve these mov al,0 ; this is current accumulation jcxz trnes2 ; empty string, forget it mov bl,3 ; this is max # of digits to use mov bh,8 ; this is radix trnes1: mov dl,[si] cmp dl,'0' jb trnes2 ; out of range, stop here cmp dl,'7' ja trnes2 inc si ; accept character sub dl,'0' ; convert to binary mul bh ; shift accumulation add al,dl ; add to accumulation dec bl ; decrement digit counter loopnz trnes1 ; and keep trying trnes2: pop dx pop bx ret ; and return trnesc endp ; Jumping to this location is like retskp. It assumes the instruction ; after the call is a jmp addr. RSKP PROC NEAR pop bp add bp,3 push bp ret RSKP ENDP ; Jumping here is the same as a ret. R PROC NEAR ret R ENDP code ends end