home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
ccdos.zip
/
ccsser.asm
< prev
next >
Wrap
Assembly Source File
|
1991-09-08
|
70KB
|
1,542 lines
NAME ccsser
; File CCSSER.ASM
;CHINESE
ifdef MSDOS
include mssser.dat
else
include ccsser.dat
endif
code segment public 'code'
extrn comnd:near, serrst:near, spack:near, rpack:near, init:near
extrn read12:near, serini:near, read2:near, rpar:near, spar:near
extrn rin21:near, rfile3:near, error1:near, clrfln:near
extrn dodel:near, clearl:near, dodec: near, doenc:near
extrn packlen:near, send11:near, errpack:near, pktsize:near
extrn nak:near, rrinit:near, cmblnk:near, poscur:near, lnout:near
extrn erpos:near, rprpos:near, clrmod:near, crun:near, ctlu:near
extrn prompt:near, updrtr:near, prtfn:near, prtscr:near
extrn strcat:near, strlen:near, strcpy:near, fparse:near, isfile:near
extrn prtasz:near, ihosts:near, begtim:near, endtim:near
extrn inptim:near, chktmo:near, pcwait:near
assume cs:code, ds:datas, es:nothing
; BYE command - tell remote KERSRV to logout & exits to DOS.
BYE PROC NEAR
mov ah,cmcfm ; Parse a confirm
call comnd
jmp r
mov remcmd,'L' ; Logout command letter
call logo ; Tell the mainframe to logout
jmp rskp ; Failed - don't exit
mov flags.extflg,1 ; Set exit flag
jmp rskp
BYE ENDP
; FINISH - tell remote KERSRV to exit
FINISH PROC NEAR
mov ah,cmcfm ; Parse a confirm
call comnd
jmp r
mov remcmd,'F' ; Finish command letter
call logo
jmp rskp
jmp rskp
FINISH ENDP
; LOGOUT - tell remote KERSRV to logout
LOGOUT PROC NEAR
mov ah,cmcfm
call comnd ; Get a confirm
jmp r
mov remcmd,'L' ; Logout command letter
call logo
jmp rskp ; Go get another command whether we
jmp rskp ; succeed or fail
LOGOUT ENDP
; Common routine for FIN, LOGOUT, BYE
LOGO PROC NEAR
mov pack.numtry,0 ; Initialize count
mov pack.numrtr,0 ; No retries yet
mov ah,trans.chklen ; Don't forget the checksum length
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions
call serini ; Initialize port
jc logo2 ; c = failure
call ihosts ; initialize the host
mov diskio.string,0 ; clear local filename for stats
call begtim ; start statistics counter
logo1: cmp pack.state,'A' ; Did user type a ^C?
je log2x ; e = yes, leave in failure state for Bye
mov ah,pack.numtry
cmp ah,maxtry ; Too many times?
jl logo3 ; No, try it
logo2: mov ah,prstr
; mov dx,offset erms18
mcmsg erms18, cerms18
int dos
log2x:;;;call serrst ; Reset port
mov ax,1 ; a send operation
call endtim ; stop statistics counter
mov ah,curchk
mov trans.chklen,ah ; Restore value
ret ; and exit in failure state for Bye
logo3: inc pack.numtry ; Increment number of tries
mov pack.seqnum,0 ; Packet number zero
mov pack.datlen,1 ; One piece of data
mov ah,remcmd ; get command letter ('L' or 'F')
mov data,ah ; Logout the remote host
mov cx,1 ; One piece of data
call doenc ; Do encoding
mov ah,'G' ; Generic command packet
call spack
jmp logo2 ; Tell user and die
nop
call rpack ; Get ACK (w/o screen msgs.)
jmp logo1 ; Go try again
nop
push ax
call dodec ; Decode packet
pop ax
cmp ah,'Y' ; ACK?
jne logo4
cmp pack.datlen,0 ; Any data in the ACK?
je logo6 ; Nope - just return.
mov ah,prstr ; output a cr/lf
mov dx,offset crlf
int dos
mov di,offset data ; Where the reply is
mov cx,pack.datlen ; How much data we have.
call prtscr ; Print it on the screen
jmp logo6 ; and exit
logo4: cmp ah,'E' ; Error packet?
je logo5 ; e = yes
jmp logo1 ; try sending again
logo5: call error1
logo6: mov ax,1 ; a send operation
call endtim ; stop statistics counter
mov ah,curchk
mov trans.chklen,ah ; Restore value
jmp rskp ; use rskp so Bye succeeds
LOGO ENDP
; GET command. Ask remote server to send the specified file(s)
; Queries for remote filename and optional local override path/filename
GET PROC NEAR
mov flags.nmoflg,0 ; Reset flags from fn parsing
mov byte ptr locfil,0 ; clear, for safety
mov byte ptr srvbuf,0 ; ditto
mov flags.cxzflg,0 ; no Control-C typed yet
mov cnt,0 ; count of filename chars
mov bx,offset srvbuf ; Where to put text
mov byte ptr [bx],0 ; clear for safety
; mov dx,offset filmsg ; In case user needs help
mcmsg filmsg, cfilmsg
mov ah,cmtxt ; filenames with embedded whitespace
call comnd ; Get text or confirm
jmp r ; Fail
mov al,ah
mov ah,0
mov cnt,ax ; Remember number of chars we read
cmp al,0 ; Read in any chars?
je get1 ; e = no
jmp get3b ; yes, analyze
; if empty line, ask for file names
get1:
; mov dx,offset remfnm ; ask for remote name first
mcmsg remfnm, cremfnm
call prompt
mov bx,offset srvbuf ; place for remote filename
; mov dx,offset frem ; the help message
mcmsg frem, cfrem
mov ah,cmtxt ; use this for embedded spaces
call comnd ; get a filename
jmp r
mov al,ah
mov ah,0
mov cnt,ax ; remember number of chars read
cmp al,0 ; count of entered chars
je get1 ; e = none, try again
get2:
; mov dx,offset lclfnm ; prompt for local filename
mcmsg lclfnm, clclfnm
call prompt
get3: mov flags.nmoflg,0 ; assume no local override name
; mov bx,offset filhlp
mcmsgb filhlp, cfilhlp
mov dx,offset locfil ; complete local filename
mov byte ptr locfil,0 ; clear, for safety
mov ah,cmfile ; allow paths
call comnd
jmp r
mov temp,ax
mov ah,cmcfm
call comnd
jmp r
mov ax,temp
cmp ah,0 ; any text?
je get2 ; e = none, ask again
mov bx,offset locfil
cmp byte ptr [bx],'#' ; Is first char a replacement for '?'
jne get3a ; ne = no
mov byte ptr [bx],'?' ; yes. Replace '#' by '?'
get3a: mov al,ah ; number of chars in locfil according to cmd
mov flags.nmoflg,al ; 0 = no override
mov ah,0
add bx,ax
mov byte ptr [bx],0 ; force a termination null
get3b: mov bx,offset srvbuf ; get remote filename address again
cmp byte ptr [bx],'#' ; Is first char a replacement for '?' ?
jne get4 ; ne = no
mov byte ptr [bx],'?' ; yes. Replace '#' by '?'
get4: cmp flags.cxzflg,0 ; ^X, ^Z, or ^C typed?
je get5 ; e = no, keep going
mov flags.cxzflg,0 ; clear the interrupt flag
or errlev,2 ; say cannot receive
or fsta.xstatus,2+80h ; set status failed + intervention
mov kstatus,2 ; local status
jmp rskp
get5: call begtim ; start statistics
cmp flags.destflg,2 ; receiving to screen?
je get5a ; e = yes, skip screen stuff
mov flags.xflg,0 ; no, reset x flag
call init ; init screen
get5a: call begtim ; start statistics
mov kstatus,0 ; global status, success
call ipack ; Send Initialize, 'I', packet
jmp get8 ; Sorry can't do it
nop
mov cx,cnt ; Get back remote filename size
mov pack.datlen,cx ; Need it here to send packet
mov si,offset srvbuf ; Move from here
mov di,offset data ; to here
call strcpy ; copy from srvbuf to data
mov di,offset fsta.xname ; to statistics remote name field
call strcpy
mov di,offset diskio.string ; and to here for prtfn
call strcpy
test flags.remflg,dquiet ; quiet display mode?
jnz get6 ; nz = yes, don't print anything
cmp flags.remflg,dserial ; serial mode display?
je get6 ; e = yes, skip extra display item
cmp flags.destflg,2 ; Receiving to screen?
je get6 ; Yes skip screen stuff
call prtfn ; print filename in data
get6:
call rrinit ; clear pack.xxx counters
mov pack.numrtr,-1 ; No retries yet (gets incremented below)
mov pack.state,'R' ; this is what state will be soon
mov cx,pack.datlen ; Data size
call doenc ; Encode data
jnc get6a ; nc = success
jmp get12 ; c = data could not all fit into packet
get6a: mov ah,trans.chklen ; Don't forget the checksum length
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions
get7: call updrtr
cmp pack.state,'A' ; Did user type a ^C?
je get9 ; Yes - just return to main loop
mov ah,pack.numtry
cmp ah,maxtry ; Too many times?
jbe get10 ; Nope, try it
get8: test flags.remflg,dquiet ; quiet display mode?
jnz get9 ; nz = yes, no printing
call erpos
mov ah,prstr
; mov dx,offset erms18 ; Can't get init packet.
mcmsg erms18, cerms18
int dos
or errlev,2 ; set DOS error level to cannot rcv
or fsta.xstatus,2 ; set status
mov kstatus,2 ; global status
get9: test flags.remflg,dquiet+dserial ; quiet or serial display?
jnz get9a ; nz = yes
call clrmod
call rprpos
get9a: mov ah,curchk
mov trans.chklen,ah ; Restore value
xor ax,ax ; say this was a receive operation
call endtim ; do statistics
jmp rskp
get10: inc pack.numtry ; Increment number of tries
mov pack.seqnum,0 ; Start at packet zero
call pktsize ; report packet size
mov ah,'R' ; Receive init packet
call spack ; Send the packet
jmp get8 ; Tell user we can't do it
nop
call rpack ; Get ACK
jmp get7 ; Got a NAK - try again
nop
push ax
mov ah,curchk
mov trans.chklen,ah ; Restore value
pop ax
mov flags.getflg,ah ; note this is a GET, use pkt type
mov pack.state,'R' ; Set the state to receive initiate
jmp read12 ; go join read code
get12:
; mov dx,offset ermes6 ; Complain if filename is too long for pkt
mcmsg ermes6, cermes6
test flags.remflg,dquiet ; quiet display mode?
jnz get13 ; nz = yes, no printing
call erpos ; position cursor on formatted screen
mov ah,prstr
int dos
get13: mov bx,dx ; point to message, for errpack
call errpack ; tell the host we are quiting
test flags.remflg,dserial ; serial display mode?
jnz get14 ; nz = yes
call clrmod ; clear mode line
call rprpos ; Put prompt here
get14: or errlev,2 ; set DOS error level to cannot rcv
or fsta.xstatus,2 ; set status
mov kstatus,2 ; global status
jmp rskp
GET ENDP
; server command
SERVER PROC NEAR
mov ah,cmfile ; get a word
mov dx,offset srvbuf ; place to put text
; mov bx,offset inthlp ; help message
mcmsgb inthlp, cinthlp
call comnd ; get the pattern text
jmp r ; nothing, complain
nop
mov temp,ax ; ah has byte count
mov ah,cmcfm
call comnd
jmp r
mov srvtime,0 ; assume not doing timed residence
cmp byte ptr temp+1,0 ; time of day given?
je serv0b ; e = no
mov si,offset srvbuf
cmp byte ptr [si],'0' ; numeric or colon?
jb serv0 ; b = not proper time value
cmp byte ptr [si],':' ; this covers the desired range
ja serv0 ; a = no proper time value
call inptim ; convert text to timeout tod
jnc serv0a ; nc = no syntax errors in time
serv0: ret ; else return now
serv0a: mov srvtime,1 ; say doing timed residence
serv0b: push es
mov ax,ds
mov es,ax ; address data segment
mov al,flags.remflg ; get display mode flag
push ax ; preserve for later
; Enable the line below if the server screen is to be quiet (clear),
; or make the line a comment if the server screen is to show file transfers
;===> mov flags.remflg,dquiet ; set quiet display flag if server
;
or flags.remflg,dserver ; signify we are a server now
mov ax,0 ; simulate empty parameter packet
call spar ; and thus set our params to defaults
mov ah,drpt ; force default repeat prefix char
mov rptq,ah ; char be our active one
test flags.remflg,dquiet ; quiet display?
jnz serv1c ; nz = yes
mov ah,prstr
mov dx,offset crlf
int dos
test flags.remflg,dserial ; serial display?
jnz serv1a ; nz = yes
call cmblnk ; clear screen
; mov dx,scrser ; move cursor to top of screen
mcscr scrser, cscrser
call poscur
serv1a: mov ah,prstr
; mov dx,offset infms1 ; say now in server mode
mcmsg infms1, cinfms1
int dos
serv1c: mov ah,inichk ; set default checksum length
mov curchk,ah ; save it here
serv1: test flags.remflg,dquiet+dserial ; quiet or serial display?
jnz serv1b ; nz = yes
; mov dx,scrsrm ; move cursor to server message area
mcscr scrsrm, cscrsrm
add dx,0100H ; look at line below (DOS does CR/LF first)
call poscur
call clearl ; and clear the line
; mov dx,scrsrm ; back to message line
mcscr scrsrm, cscrsrm
call poscur
cmp flags.debug,0 ; debug display active?
je serv1b ; e = no
mov fmtdsp,1 ; yes, do formatted display
serv1b: mov flags.nmoflg,0 ; clear, say no local override filenames
mov flags.cxzflg,0 ; clear ^X, ^Z, ^C seen flag
mov flags.xflg,0 ; reset X packet flag
mov locfil,0 ; say no local filename [JB]
mov ah,dtrans.seol ; restore default end-of-line char
mov trans.seol,ah
mov byte ptr srvbuf,0 ; plant terminator to clear
mov trans.chklen,1 ; checksum len = 1
mov pack.pktnum,0 ; pack number resets to 0
mov pack.numtry,0 ; no retries yet
mov al,trans.stime ; get current timeout interval
mov curstim,al ; save current timeout interval
add al,al ; triple it for server idle loop
add al,curstim ; times three
mov trans.stime,al ; use this longer interval in the idle loop
call serini ; init serial line (send & receive reset it)
jnc serv1e ; nc = success
jmp serv5 ; c = failure
serv1e: cmp srvtime,0 ; doing timed residence?
je serv1d ; e = no
call chktmo ; check for time to exit Server mode
jnc serv1d ; nc = ok
jmp serv5 ; c = timeout, exit server mode
serv1d: call rpack ; get a packet
jmp short serv2 ; no good, nak and continue
nop
push ax
mov al,curstim ; get original timeout interval
mov trans.stime,al ; restore timeout interval
pop ax
cmp ah,'I' ; never "decode" S, I, and A packets
je serv3 ; its an I packet
cmp ah,'S'
je serv3
cmp ah,'A'
je serv3
call dodec ; decode packet
jmp short serv3 ; try to figure this out
serv2: push ax
mov al,curstim ; get original timeout interval
mov trans.stime,al ; restore timeout interval
pop ax
cmp flags.cxzflg,'C' ; Control-C?
jne serv2a ; ne = no
mov flags.cxzflg,0 ; clear flag for later uses
jmp serv5 ; and exit server mode
serv2a: cmp ah,'T' ; packet type of time-out?
jne serv2b ; ne = no
mov al,srvtmo ; server timeout value
mov trans.stime,al
call nak ; nak the packet
mov al,curstim
mov trans.stime,al ; restore regular send timeout
serv2b: mov al,curchk ; restore checksum length
mov trans.chklen,al
jmp serv1 ; and keep readiserv2 packets
serv3: mov al,curchk ; restore checksum length
mov trans.chklen,al
push ds
pop es ; set es to datas segment
mov di,offset srvchr ; server characters
mov cx,srvfln ; length of striserv2
mov al,ah ; packet type
cld
repne scasb ; hunt for it
je serv4 ; we know this one, go handle it
cmp al,'N' ; received a Nak?
je serv3a ; e = yes, ignore it
; mov bx,offset remms1 ; else give a message
mcmsgb remms1, cremms1
call errpack ; back to local kermit
serv3a: jmp serv1 ; and keep lookiserv2 for a cmd
serv4: sub di,offset srvchr+1 ; find offset, +1 for pre-increment
shl di,1 ; convert to word index
call srvfun[di] ; call the appropriate handler
jmp serv5 ; someone wanted to exit..
jmp serv1 ; else keep goiserv2 for more cmds
serv5: mov al,curchk ; restore checksum length
mov trans.chklen,al
pop ax ; get this off stack
test flags.remflg,dserial+dquiet ; serial or quiet display?
jnz serv5a ; nz = yes
call rprpos ; Put prompt here
serv5a: mov flags.remflg,al ; restore old flag
;; call serrst ; reset serial handler
mov fmtdsp,0 ; end of formatted display
mov flags.cxzflg,0 ; clear this flag before exiting
pop es ; restore register
jmp rskp ; and return
SERVER ENDP
; server commands
; srvsnd - receives a file that a remote kermit is sending
srvsnd proc near
mov bx,offset data
mov ax,pack.datlen ; get number of data bytes
call spar ; parse the send-init packet
mov al,trans.chklen ; get negotiated checksum length
mov curchk,al ; and remember it here
call packlen ; figure max packet
mov bx,offset data
call rpar ; make answer for them
mov al,ah ; length of packet
mov ah,0
mov pack.datlen,ax ; store length for spack
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
mov ah,'Y' ; ack
call spack ; answer them
jmp rskp ; can't answer, forget this
mov al,curchk ; restore checksum length
mov trans.chklen,al
call rrinit ; init variables for init
cmp flags.destflg,2 ; file destination = screen?
jne srvsnd0 ; ne = no
mov flags.xflg,1 ; say receiving to screen
jmp srvsnd1
srvsnd0:call init ; setup display form
srvsnd1:mov si,offset srvbuf ; work buffer
mov byte ptr[si],5ch ; backslash
inc si
mov ah,gcd ; get current directory (path really)
xor dl,dl ; use current drive
int dos ; returns ds:si with asciiz path (no drive)
mov si,offset srvbuf
mov di,offset locfil ; destination is local override name
call strcpy ; copy the path to local filename
mov dx,di
call strlen ; get length of string into cx
mov di,cx ; length of local path
mov locfil[di],5ch ; add backslash
mov locfil[di+1],0 ; null terminator
mov flags.nmoflg,1 ; say have override name (zaps external path)
inc pack.pktnum ; count the send-init packet
mov pack.state,'F' ; expecting file name about now
call read12 ; join read code. changed from read2
nop
nop
nop ; ignore errors
mov flags.xflg,0
jmp rskp ; and return for more
srvsnd endp
; srvrcv - send a file to a distant kermit
srvrcv proc near
mov si,offset data ; received filename, asciiz from rpack
test denyflg,getsflg ; command enabled?
jz srrcv2 ; z = yes
mov di,offset srvbuf ; local path
mov si,offset rdbuf ; local filename
mov dx,offset data ; local string
call fparse ; split string
mov si,offset rdbuf ; copy local filename to
srrcv2: mov di,offset diskio.string ; destination
call strcpy ; copy data to diskio.string
mov pack.state,'R' ; remember state
call send11 ; this should send it
jmp rskp
jmp rskp ; return in any case
srvrcv endp
; srvgen - G generic server command dispatcher
;
srvgen proc near
mov al,data ; get 1st packet char
srvge2: cmp al,'T' ; Type a file?
jne srvge3 ; ne = no
call srvtyp ; do the typing
jmp rskp
srvge3: cmp al,'D' ; do a directory?
jne srvge4
call srvdir ; do the directory command
jmp rskp
srvge4: cmp al,'E' ; do a file erase (delete)?
jne srvge5
call srvdel ; do the delete command
jmp rskp
srvge5: cmp al,'C' ; change working dir?
jne srvge6 ; ne = no
call srvcwd ; do it
jmp rskp
srvge6: cmp al,'U' ; do a space command?
jne srvge7
call srvspc ; do the space command
jmp rskp
srvge7: cmp al,'F' ; FIN?
jne srvge8 ; ne = no
jmp srvfin
srvge8: cmp al,'L' ; LOGO or BYE?
jne srvge9 ; ne = no
call srvfin
jmp short srvge8a ; permitted to exit Kermit
nop
jmp rskp ; stay active (command denied)
srvge8a:mov flags.extflg,1 ; set exit flag
ret ; leave server mode and Kermit
srvge9: cmp al,'M' ; one line Message?
jne srvge10 ; ne = no
call srvsen
jmp rskp
srvge10:cmp al,'W' ; WHO?
jne srvge11 ; ne = no
call srvwho
jmp rskp
srvge11:cmp al,'H' ; Help?
jne srvgex ; ne = no
jmp srvhlp
srvgex:
; mov bx,offset remms1 ; reply Unknown server command
mcmsgb remms1, cremms1
mov trans.chklen,1 ; reply with 1 char checksum
call errpack
jmp rskp
srvgen endp
; srvfin - respond to remote host's Fin command. [jrd]
srvfin proc near
test denyflg,finflg ; command enabled?
jz srfin1 ; z = yes
; mov bx,offset remms9 ; else give a message
mcmsgb remms9, cremms9
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
jmp rskp ; stay in server mode
srfin1:
; mov si,offset byemsg ; add brief msg of goodbye
mcmsgsi byemsg, cbyemsg
mov di,offset data ; packet's data field
call strcpy ; copy msg to pkt
mov dx,si ; strlen works on dx
call strlen
mov ah,'Y' ; reply with an ack
mov pack.datlen,cx ; length
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
call spack ; send it, expect no response
nop ; ignore errors
nop
nop
mov ax,100 ; wait 0.1 sec for client to settle
call pcwait
ret ; ret exits server mode
srvfin endp
; srvcwd - handle other side's Remote CWD dirspec [jrd]
srvcwd proc near
test denyflg,cwdflg ; is command enabled?
jz srcwd4 ; z = yes
; mov bx,offset remms9 ; else give a message
mcmsgb remms9, cremms9
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srcwd4: cmp pack.datlen,1 ; any data?
je srcwd3 ; e = no
mov cl,data+1 ; get the filename byte count
sub cl,' ' ; ascii to numeric
mov ch,0 ; set up counter
cmp cl,0 ; anything there?
jle srcwd3 ; le = no, an error
mov si,offset data+2 ; received dir spec, from rpack
mov di,offset srvbuf ; destination
push es ; save es
push ds
pop es ; make es:di point to datas segment
cld
rep movsb ; copy data to srvbuf, cx chars worth
pop es
mov byte ptr [di],0 ; plant terminator
mov dx,offset srvbuf ; for DOS
mov ax,dx ; dir spec pointer for isfile
cmp byte ptr [di-1],':' ; did user just type A: or similar?
je srcwd1 ; e = yes, so skip directory part
mov ah,chdir ; want to do change dir
int dos
jnc srcwd1 ; nc = ok
srcwd3:
; mov bx,offset remms4 ; an error
mcmsgb remms4, cremms4
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; send the bad news
ret
srcwd1: mov dl,data+3 ; see if drive given (look for :)
cmp dl,':'
jne srcwd2 ; ne = no drive
mov dl,data+2
and dl,5fH ; convert to upper case
sub dl,'A' ; count A = 0 for seldsk call
mov ah,seldsk
int dos ; change disks
jc srcwd3 ; c = an error
inc dl ; now make A = 1 etc internally
mov curdsk,dl ;and update internal current disk code
srcwd2: mov ah,'Y' ; return an ack
mov pack.datlen,0 ; no data
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
call spack
nop
nop
nop
ret
srvcwd endp
; srvtyp - handle other side's Remote Type filename request [jrd]
; expects "data" to hold Tcfilename where c = # bytes in filename
srvtyp proc near
cmp pack.datlen,1 ; any data in packet
je srtyp2 ; e = no
mov cl,data+1 ; get the filename byte count
sub cl,' ' ; ascii to numeric
mov ch,0 ; set up counter
mov si,offset data+2 ; received filename, asciiz from rpack
mov di,si
add di,cx
mov byte ptr [di],0 ; make string asciiz
test denyflg,typflg ; paths permitted?
jz srtyp1 ; z = yes, else use just filename part
mov di,offset srvbuf ; local path
mov si,offset rdbuf ; local filename
mov dx,offset data+2 ; local string
call fparse ; split string
mov si,offset rdbuf ; copy local filename to
srtyp1: mov di,offset diskio.string ; destination
call strcpy ; do the copy
mov ax,offset diskio.string ; pointer to filename, for isfile
call isfile ; does it exist?
jnc srtyp3 ; nc = yes
srtyp2:
; mov bx,offset remms5 ; "No such file(s)"
mcmsgb remms5, cremms5
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; send error message
ret ; and exit
srtyp3: mov flags.xflg,1 ; say use X packet rather than F pkt
mov pack.state,'R' ; remember state
call send11 ; this should send it
nop
nop
nop
mov flags.xflg,0 ; clear flag
ret ; return in any case
srvtyp endp
; serdir - handle other side's Remote Dir filespec(optional) request [jrd]
srvdir proc near
mov cx,0 ; assume no data in packet
cmp pack.datlen,1 ; any data in the packet?
je srdir4 ; e = no
mov cl,data+1 ; get the filename byte count
sub cl,' ' ; ascii to numeric
mov ch,0 ; set up counter
srdir4: mov di,offset data+2 ; received filespec, asciiz from rpack
add di,cx
mov byte ptr [di],0 ; make string asciiz
test denyflg,dirflg ; paths permitted?
jz srdir1 ; z = yes, else use just filename part
mov di,offset srvbuf ; local path
mov si,offset rdbuf ; local filename
mov dx,offset data+2 ; local string
call fparse ; split string
mov si,offset rdbuf ; copy local filename to
mov di,offset data+2 ; final filename
call strcpy ; do the copy
mov ax,di
call isfile ; is/are there any such file?
jc srdir1 ; c = there is none
test byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
jz srdir1 ; z = not protected
; mov bx,offset remms8 ; "Protected or no such file(s)"
mcmsgb remms8, cremms8
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; send error message
ret ; and exit
srdir1: mov di,offset srvbuf ; work area
mov si,offset dirstr ; prepend "dir "
call strcpy
mov si,offset data+2 ; directory spec, asciiz
mov di,offset srvbuf
call strcat
mov si,offset srvtmp ; add redirection tag of " >$kermit$.tmp"
mov di,offset srvbuf
call strcat
mov si,offset srvbuf ; command pointer for crun
call crun
nop
nop
nop
mov si,offset srvtmp+2 ; get name of temp file
mov di,offset diskio.string ; destination
call strcpy ; copy it there
mov ax,di ; filename pointer for isfile
call isfile ; did we make the temp file?
jnc srdir3 ; nc = yes
; mov bx,offset remms6 ; "Could not create directory listing"
mcmsgb remms6, cremms6
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; send the error message
ret ; and exit
srdir3: mov flags.xflg,1 ; say use X rather than F packet
mov pack.state,'R' ; remember state
call send11 ; this should send it
nop
nop
nop
mov flags.xflg,0 ; clear flag
mov dx,offset diskio.string
mov ah,del2 ; delete the file
int dos
ret ; return in any case
srvdir endp
; serdel - handle other side's request of Remote Del filespec [jrd]
srvdel proc near
test denyflg,delflg ; command enabled?
jz srvdel4 ; z = yes
; mov bx,offset remms9 ; else give a message
mcmsgb remms9, cremms9
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srvdel4:cmp pack.datlen,1 ; any data?
je srdel1 ; e = no
mov di,offset srvbuf ; work area
mov si,offset delstr ; prepend "del "
call strcpy
mov dx,offset srvbuf
call strlen
add di,cx ; di points at terminator
mov ax,di ; save pointer to incoming filespec
mov cl,data+1 ; get the filename byte count
sub cl,' ' ; ascii to numeric
mov ch,0 ; set up counter
cmp cl,0 ; anything there?
jle srdel3 ; le = no
mov si,offset data+2 ; received filespec, asciiz from rpack
push es ; save es
push ds
pop es ; set es to datas segment
cld
rep movsb ; append data to srvbuf
pop es ; restore es
mov byte ptr [di],0 ; plant terminator
call isfile ; is/are there any to delete?
jc srdel1 ; c = there is none
test byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
jz srdel2 ; z = not protected
srdel1:
; mov bx,offset remms8 ; "Protected or no such file(s)"
mcmsgb remms8, cremms8
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; send error message
ret ; and exit
srdel2: mov si,offset srvbuf ; set pointer for crun
call crun
nop
nop
nop
srdel3: mov ah,'Y' ; return an ack
mov pack.datlen,0 ; no data
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
call spack
nop
nop
nop
ret
srvdel endp
; serspc - handle other side's request of Remote Space [jrd]
srvspc proc near
test denyflg,spcflg ; is command enabled?
jz srspc1 ; z = yes
; mov bx,offset remms9 ; else give a message
mcmsgb remms9, cremms9
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srspc1: mov dl,0 ; use current drive
mov ah,36h ; get disk free space
int dos ; ax = sectors/cluster
cmp ax,0ffffh ; invalid drive indicator?
jne srspc2 ; ne = no
mov di,offset data
; mov si,offset spcmsg2 ; give Drive not ready message
mcmsgsi spcmsg2, cspcmsg2
call strcpy
jmp short srspc3 ; send it
srspc2: mul bx ; sectors/cluster * clusters = sectors
mul cx ; bytes = sectors * bytes/sector
mov di,offset data ; destination
mov word ptr [di],0d0ah ; cr/lf
mov word ptr[di+2],' ' ; space space
add di,4 ; start number here
call lnout ; convert number to asciiz in [di]
; mov si,offset spcmsg ; trailer of message
mcmsgsi spcmsg2, cspcmsg2
call strcat ; tack onto end of number part
srspc3: mov trans.chklen,1 ; reply with 1 char checksum
mov dx,offset data
call strlen ; get data size into cx for doenc
call doenc ; encode
mov ah,'Y' ; reply with an ack
call pktsize ; report packet size
call spack ; send it, expect no response
nop ; ignore errors
nop
nop
ret
srvspc endp
; srvwho - respond to remote host's WHO command. [jrd]
srvwho proc near
; mov si,offset whomsg ; add brief msg of just us chickens
mcmsgsi whomsg, cwhomsg
mov di,offset data ; packet's data field
call strcpy ; copy msg to pkt
mov dx,si ; strlen works on dx
call strlen
mov trans.chklen,1 ; reply with 1 char checksum
mov ah,'Y' ; reply with an ack
mov pack.datlen,cx ; length
call pktsize ; report packet size
call spack ; send it, expect no response
nop ; ignore errors
nop
nop
ret
srvwho endp
; srvmsg - respond to remote host's Message (Send) command
; show message on our screen. [jrd]
srvsen proc near
test denyflg,sndflg ; is command enabled?
jnz srvsen1 ; nz = yes
cmp pack.datlen,1 ; Any data in the packet?
jbe srvsen1 ; e = no, just ack the message.
cmp data,'M' ; Message packet?
jne srvsen1 ; ne = no, ack and forget
mov data,' ' ; remove the 'M'
mov data+1,' ' ; and byte count field
call dodec ; Decode data
call ctlu ; clear the line
mov dx,offset data+2 ; Where the reply is. (skip M and byte cnt)
call prtasz ; Print it on the screen
srvsen1:mov ah,'Y' ; reply with an ack
mov pack.datlen,0 ; length
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
call spack ; send it, expect no response
nop ; ignore errors
nop
nop
ret
srvsen endp
; srvhos - handle other side's request of REM Host command-line. [jrd]
; We execute the command with STDOUT redirected to $kermit$.tmp and then
; read and transmit that file to the other end. No such file results in
; returning just an error msg ACK packet
srvhos proc near
test denyflg,hostflg ; command enabled?
jz srvhos2 ; z = yes
mov trans.chklen,1 ; reply with 1 char checksum
; mov bx,offset remms9 ; else give a message
mcmsgb remms9, cremms9
call errpack ; back to local kermit
jmp rskp
srvhos2:mov si,offset data ; received filename, asciiz from rpack
mov di,offset srvbuf ; destination
call strcpy ; copy data to srvbuf
mov si,offset srvtmp ; add redirection tag of " >$kermit$.tmp"
call strcat
mov si,offset srvbuf ; si = pointer for crun
call crun ; go do the command
nop
nop
nop
mov si,offset srvtmp+2 ; get name of temp file
mov di,offset diskio.string ; destination
call strcpy ; copy it to diskio.string
mov ax,di ; filename pointer for isfile
call isfile ; did we make the temp file?
jnc srhos1 ; nc = yes
mov trans.chklen,1 ; reply with 1 char checksum
; mov bx,offset remms10 ; else give a message
mcmsgb remms10, cremms10
call errpack ; back to local kermit
call pktsize ; report packet size
jmp rskp ; and exit
srhos1: mov flags.xflg,1 ; say use X rather than F packet
mov pack.state,'R' ; remember state
call send11 ; this should send it
nop
nop
nop
mov flags.xflg,0 ; clear flag
mov dx,offset diskio.string
mov ah,del2 ; delete the temp file
int dos
jmp rskp ; return in any case
srvhos endp
; Respond to other side's request of Remote Help. Write & read $kermit$.tmp
; Return rskp. [jrd]
srvhlp proc near
mov si,offset srvtmp+2 ; use filename of $kermit$.tmp
mov di,offset diskio.string ; put name here
call strcpy
mov ah,creat2 ; create the file
mov cx,0 ; attributes r/w
mov dx,offset diskio.string ; use $kermit$.tmp name
int dos
jc srvhlp4 ; c = could not open
mov diskio.handle,ax ; file handle
; mov dx,offset hlprem ; data to be sent, strlen uses dx
mcmsg hlprem, chlprem
call strlen ; put string length in cx
mov ah,write2 ; write to file
mov bx,diskio.handle
int dos ; write the info
pushf ; save carry bit
mov ah,close2 ; close the file so we can reread it below
mov bx,diskio.handle
int dos
popf ; recover carry bit
jc srvhlp4 ; c = write error, tell remote user
; Send temporary file to remote screen
mov flags.xflg,1 ; say use X rather than F packet
mov pack.state,'R' ; remember state
call send11 ; this should send it
nop
nop
nop
mov flags.xflg,0 ; clear flag
mov dx,offset diskio.string ; filename
mov ah,del2 ; delete the temp file
int dos
jmp rskp ; and return
srvhlp4:mov trans.chklen,1 ; reply with 1 char checksum
; mov bx,offset remms3 ; else give a message
mcmsgb remms3, cremms3
call errpack ; back to local kermit
call pktsize ; report packet size
jmp rskp
srvhlp endp
; srvini - init parms based on init packet
srvini proc near
mov bx,offset data
mov ax,pack.datlen ; get number of data bytes
call spar ; parse info
call packlen ; this should really be part of spar, but..
mov bx,offset data
call rpar ; setup info about our reception
push ax
mov al,trans.chklen ; checksum length negotiated
mov curchk,al ; use as new working length
pop ax
mov al,ah
mov ah,0
mov pack.datlen,ax ; set size of return info
mov trans.chklen,1 ; reply with 1 char checksum
mov ah,'Y'
call pktsize ; report packet size
call spack ; send the packet off
nop
nop
nop
mov al,curchk ; restore checksum length before proceeding
mov trans.chklen,al
jmp rskp ; and go succeed
srvini endp
; This is the REMOTE command
REMOTE PROC NEAR
mov dx,offset remtab ; Parse a keyword from the REMOTE table
; mov bx,offset remhlp
mcmsgb remhlp, cremhlp
mov ah,cmkey
call comnd
jmp r
call bx ; Call the appropriate routine
jmp r ; Command failed
jmp rskp
REMOTE ENDP
; REMDIS - Get disk usage on remote system
REMDIS PROC NEAR
mov remcmd,'U' ; Disk usage command
mov rempac,'G' ; Packet type = generic
mov remlen,0 ; no text required
jmp genric ; Execute generic Kermit command
REMDIS ENDP
; REMHEL - Get help about remote commands
REMHEL PROC NEAR
mov remcmd,'H' ; Help
mov rempac,'G' ; Packet type = generic
mov remlen,0 ; no text required
jmp genric ; Execute generic Kermit command
REMHEL ENDP
; REMTYP - Type a remote file
REMTYP PROC NEAR
mov remcmd,'T' ; Type the file
mov rempac,'G' ; Packet type = generic
mov remlen,1 ; text required
jmp genric
REMTYP ENDP
; REMHOS - Execute a remote host command
REMHOS PROC NEAR
mov remcmd,' ' ; Don't need one
mov rempac,'C' ; Packet type = remote command
mov remlen,1 ; text required
jmp genric
REMHOS ENDP
; REMKER - Execute a remote Kermit command
REMKER PROC NEAR
mov remcmd,' ' ; Don't need one
mov rempac,'K' ; Packet type = remote Kermit command
mov remlen,1 ; text required
jmp genric
REMKER ENDP
; REMDIR - Do a directory
REMDIR PROC NEAR
mov remcmd,'D'
mov rempac,'G' ; Packet type = generic
mov remlen,0 ; no text required
jmp genric
REMDIR ENDP
; REMDEL - Delete a remote file
REMDEL PROC NEAR
mov remcmd,'E'
mov rempac,'G' ; Packet type = generic
mov remlen,1 ; text required
jmp genric
REMDEL ENDP
; REMCWD - Change remote working directory
REMCWD PROC NEAR
mov remcmd,'C'
mov rempac,'G' ; Packet type = generic
mov remlen,0 ; no text required
jmp genric
REMCWD ENDP
; REMLOGIN - LOGIN [username [password [account]]]
REMLOGIN PROC NEAR
mov remcmd,'I'
mov rempac,'G' ; Packet type = generic
mov remlen,0 ; no text required
jmp genric
REMLOGIN ENDP
; REMMSG - Send one line short message to remote screen. [jrd]
REMMSG proc near
mov remcmd,'M'
mov rempac,'G'
mov remlen,1 ; text required
jmp genric
REMMSG endp
; REMWHO - ask for list of remote logged on users [jrd]
REMWHO proc near
mov remcmd,'W'
mov rempac,'G'
mov remlen,0 ; no text required
jmp genric
REMWHO endp
; GENRIC - Send a generic command to a remote Kermit server
GENRIC PROC NEAR
mov bx,offset srvbuf ; Where to put the text
mov temp,bx ; where field starts
cmp rempac,'C' ; Remote Host command?
je genra ; e = yes, no counted string(s)
cmp rempac,'K' ; Remote Kermit command?
je genra ; e = yes, no counted string(s)
mov ah,remcmd ; get command letter
mov [bx],ah ; store in buffer
inc temp ; inc to data field
add bx,2 ; Leave room for type and size
genra: mov ah,cmtxt ; Parse arbitrary text up to a CR
; mov dx,offset genmsg ; In case they want help
mcmsg genmsg, cgenmsg
call comnd
jmp r
nop
mov al,ah ; Don't forget the size
mov ah,0
mov cnt,ax ; Save it here
add temp,ax ; point to next field
cmp rempac,'C' ; Remote Host command?
je genra3 ; e = yes, no counted string(s)
cmp rempac,'K' ; Remote Kermit command?
je genra3 ; e = yes, no counted string(s)
cmp al,0 ; any text?
je genra3 ; e = no
add al,32 ; Do the tochar function
mov srvbuf+1,al ; Size of first field
inc temp ; include count byte
genra3: cmp al,remlen ; got necessary command text?
jae genra2 ; ae = yes
mov ah,prstr
; mov dx,offset ermes1 ; need more info
mcmsg ermes1, cermes1
int dos
or errlev,2 ; say cannot receive
or fsta.xstatus,2 ; set status failed
mov kstatus,2 ; global status
jmp rskp
genra2: mov flags.xflg,1 ; output coming to screen
cmp rempac,'K' ; Remote Kermit command?
jne genraa
jmp genr0 ; e = yes
genraa: cmp rempac,'C' ; Remote host command?
jne genrb
jmp genr0 ; No, skip this part
genrb:
cmp remcmd,'C' ; Change working directory?
je genrf ; e = yes, ask for password
cmp remcmd,'I' ; remote login command?
je genrd ; e = yes
jmp genr0 ; neither so no extra prompts here
genrd: cmp cnt,0 ; have user name already?
jne genrf ; ne = yes
; mov dx,offset user ; prompt for username
mcmsg user, cuser
call prompt
mov bx,offset srvbuf+1 ; skip command letter
mov temp,bx ; start of field
call input ; Read text
jcxz genr0 ; z = none
mov temp,bx ; point to next data field
genrf:
; mov dx,offset password ; Get optional password
mcmsg password, cpassword
call prompt
mov bx,temp ; Where to put the password
mov comand.cmquiet,1 ; turn on quiet mode
call input ; Read in the password
mov comand.cmquiet,0 ; turn off quiet mode
jcxz genr0 ; z = no text, do not add field
mov temp,bx ; point to next data field
;
cmp remcmd,'I' ; remote login command?
jne genr0 ; ne = no
; mov dx,offset account ; get optional account ident
mcmsg account, caccount
call prompt
mov bx,temp ; Where this field starts
call input ; Read in text
jcxz genr0 ; z = no text, do not add field
mov temp,bx ; point to next data field
; All fields completed
genr0: mov ax,temp ; pointer to next field
sub ax,offset srvbuf ; minus start of buffer = data length
mov cnt,ax ; remember size here
cmp flags.cxzflg,'C' ; Control-C entered?
jne genr0a ; ne = no
ret ; return failure
genr0a: mov kstatus,0 ; global status
mov pack.numtry,0 ; Initialize count
call ipack ; Send init parameters
jmp genr2
nop ; Make it 3 bytes long
mov ah,trans.chklen
mov curchk,ah ; Save desired checksum length
mov trans.chklen,1 ; Use 1 char for server functions
mov pack.numrtr,0 ; No retries yet
genr1: cmp pack.state,'A' ; Did the user type a ^C?
je genr2x
mov ah,pack.numtry
cmp ah,maxtry ; Too many tries?
jl genr3 ; Nope, keep trying
genr2: mov ah,prstr
; mov dx,offset erms18 ; Print error msg and fail
mcmsg erms18, cerms18
int dos
genr2x: mov ah,curchk
mov trans.chklen,ah ; Restore
mov flags.xflg,0 ; reset screen output flag before leaving
xor ax,ax ; tell statistics this was a read
or errlev,4 ; DOS error level, failure of REMote cmd
mov fsta.xstatus,4 ; set status
mov kstatus,4 ; global status
jmp rskp
genr3: push es ; Prepare to put string into packet
push ds
pop es
mov si,offset srvbuf ; Move from here
mov di,offset data ; to here
mov cx,cnt ; Move this many characters
cld
rep movsb ; Perform the string move
pop es
mov ax,cnt
mov pack.datlen,ax ; How much data to send
mov cx,ax ; Size of data
call doenc ; Encode it
inc pack.numtry ; Increment number of trials
mov trans.chklen,1 ; use block check 1 to server
mov pack.seqnum,0 ; Packet number 0
mov ah,rempac ; Packet type
call pktsize ; report packet size
call spack ; Send the packet
jmp genr2 ; Tell user we can't do it
nop
call rpack ; Get ACK (w/o screen stuff)
jmp genr3a ; Got a NAK - try again
nop
jmp genr3b ; Ok
genr3a: push ax
mov ah,curchk
mov trans.chklen,ah ; Restore after reception
pop ax
jmp genr1 ; NAK, try again
genr3b: push ax ; Ok
mov ah,curchk
mov trans.chklen,ah ; Restore after reception
pop ax
cmp ah,'Y' ; Is all OK?
jne genr4
cmp pack.datlen,0 ; Any data in the ACK?
je genr31 ; Nope - just return.
call dodec ; Decode data
mov di,offset data ; Where the reply is
mov cx,pack.datlen ; How much data we have
jcxz genr31 ; z = nothing
mov ah,prstr
mov dx,offset crlf ; start with cr/lf
int dos
call prtscr ; Print it on the screen
genr31: mov flags.xflg,0 ; reset screen output flag before leaving
jmp rskp ; And we're done.
genr4: cmp ah,'X' ; Text packet?
je genr5
cmp ah,'S' ; Handling this like a file?
jne genr6
mov pack.state,'R' ; Set the state
mov bx,offset rin21 ; Where to go to
jmp genr51 ; Continue
genr5: mov pack.state,'F'
call dodec ; Decode data
mov bx,offset rfile3 ; Jump to here
genr51: mov flags.xflg,1 ; Remember we saw an "X" packet
push ax
mov ah,prstr
mov dx,offset crlf ; for some systems
int dos
pop ax ; keep packet type in ah
mov pack.numtry,0
mov pack.numrtr,0
mov pack.numpkt,0
mov pack.pktnum,0
call begtim ; start next statistics group
call bx ; Handle it almost like filename
call read2 ; Receive the rest
jmp r ; Oops, we failed
nop
jmp rskp ; Done OK
genr6: cmp ah,'E' ; Error packet?
je genr6x ; e = yes
jmp genr1 ; Try again
genr6x: call dodec ; Decode data
call error1 ; Print the error messge
;;;; call serrst
mov flags.xflg,0 ; reset screen output flag before leaving
jmp rskp ; And return
GENRIC ENDP
; Send "I" packet with transmission parameters
IPACK PROC NEAR
call serini ; Initialize port
jc ipk0x ; c = failure
call ihosts ; initialize the host
mov pack.pktnum,0 ; Use packet number 0
mov pack.numtry,0 ; Number of retries
mov pack.numrtr,-1 ; no retries (incremented below)
ipk0: call updrtr
cmp pack.state,'A' ; Did user type a ^C?
je ipk0x ; e = yes
push dx
mov dl,imxtry
cmp pack.numtry,dl ; Reached our limit?
pop dx
jl ipk1 ; l = no
ipk0x: ret ; Yes, so we fail
ipk1: inc pack.numtry ; Save the updated number of tries
mov ah,dtrans.ebquot ; default 8 bit quote, needed with parity
mov trans.ebquot,ah ; save as active mode
mov bx,offset data ; Get a pointer to our data block
call rpar ; Set up the parameter information
xchg ah,al
mov ah,0
mov pack.datlen,ax ; Save the number of arguments
mov pack.seqnum,0 ; Use packet number 0
mov ah,dtrans.seol ; restore default end-of-line char
mov trans.seol,ah
mov ah,trans.chklen
mov curchk,ah ; Save real value
mov trans.chklen,1 ; One char for server function
call pktsize ; report packet size
mov ah,'I' ; "I" packet
call spack ; Send the packet
jmp ipk4
nop
call rpack ; Get a packet
jmp ipk4 ; Try again
nop
push ax
mov ah,curchk
mov trans.chklen,ah ; Reset
pop ax
cmp ah,'Y' ; ACK?
jne ipk3 ; If not try next
mov ax,pack.pktnum ; Get the packet number
cmp ax,pack.seqnum ; Is it the right packet number?
je ipk2
jmp ipk0 ; If not try again
ipk2: mov ax,pack.datlen ; Get the number of pieces of data
mov bx,offset data ; Pointer to the data
ipk2a: call spar ; Read in the data
mov ah,trans.chklen
mov curchk,ah ; This is what we decided on
call packlen ; Get max send packet size
mov pack.numtry,0 ; Reset the number of tries
jmp rskp
ipk3: cmp ah,'N' ; NAK?
jne ipk3y ; Yes, try again
jmp ipk0
ipk3y: cmp ah,'E' ; Is it an error packet
je ipk3x
jmp ipk0 ; Trashed data.
ipk3x: mov ax,0 ; Other side doesn't know about "I" packet
; force defaults (zero length response)
jmp ipk2a ; to use lowest common denominator
ipk4: mov ah,curchk
mov trans.chklen,ah ; Reset.
cmp flags.cxzflg,0 ; did user say quit?
jne ipk5 ; ne = yes, quit
jmp ipk0 ; Keep trying
ipk5: ret
IPACK ENDP
; Returns CX the count of characters read
; BX the updated pointer to the input buffer
; input buffer = <ascii data length count byte>textstring
INPUT PROC NEAR
mov inpbuf,bx ; Where to put byte count
inc bx ; skip over count byte
mov dx,0 ; help, none
mov ah,cmtxt ; get text with embedded whitespace
call comnd
jmp r
nop
mov al,ah ; length of text
mov ah,0
mov cnt,ax ; save here
input1: push bx
mov bx,inpbuf
mov [bx],al ; store count byte
add byte ptr [bx],32 ; convert to ascii
pop bx ; return pointer to next free byte
mov cx,cnt ; return byte count
ret
INPUT 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