home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Phoenix CD 2.0
/
Phoenix_CD.cdr
/
01e
/
msk230s1.zip
/
MSSSER.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-02-12
|
78KB
|
1,637 lines
NAME mssser
; File MSSSER.ASM
; Edit history:
; Last edit: 1 Jan 1988
; 1 Jan 1988 version 2.30
; 26 Dec 1987 Telescope Bye, Fin, Logout commands, clean up. [jrd]
; 12 Dec 1987 Add TEK denyflg to defeat automatic invokation of Tek graphics
; by ESC Control-L when in Connect mode. [jrd]
; 24 Oct 1987 Ignore received Naks in Server idle loop
; 21 Sept 1987 Add error exit in GET for filenames too long for packet. [jrd]
; 26 Aug 1987 Add Remote Send to remote help response. [jrd]
; 19 Aug 1987 Correct local override name for files sent to/from server. [jrd]
; 31 July 1987 Redo Logo, Bye, Fin to not shift block check when repeating.
; 25 July 1987 Add global word denyflg to control server restrictions,
; and revise server functions accordingly. [jrd]
; 6 July 1987 Correct Server mode ACKs to use 1 char checksum throughout.[jrd]
; 25 June 1987 Add exit to DOS for LOGO and exit to Kermit prompt for
; FIN command reception, for use with CTTY operation of server. [jrd]
; 7 June 1987 Add DOS errlev of 4 when REMOTE commands to Server fail. [jrd]
; 16 April 1987 Clear local filename in Server idle loop, from Jack Bryans.
; 5 April 1987 Set flags.xflg around Generic I-pkt sends to suppress on-screen
; display of retry counts. Put cursor on line 25 at end of Server cmds. [jrd]
; 25 March 1987 Add Disable/Enable Delete/Host commands. [jrd]
; 9 March 1987 Add calls to statistics functions. [jrd]
; 6 March 1987 Respond to FIN, LOGO, BYE while in server mode
; with 1 byte checksums. Thanks to Jack Bryans.
; Triple waiting time in Server idle loop (fewer NAKs/minute). [jrd]
; 22 Feb 1987 Add Server SEND and WHO commands (both directions). [jrd]
; 1 Oct 1986 Version 2.29a
; 10 Sept 1986 Add display of ACK pkt in LOGO and FIN. Remove forced output
; to screen for REMOTE cmds; thanks to Bill Porteous.
; Add ACK message for received Bye, Logo, Fin commands. [jrd]
; 6 Sept 1986 Output cr/lf for REMote commands before rcving 1st pkt. [jrd]
; 14 August 1986 Allow changing EOL chars. [jrd]
; Modify Srvsnd to handle Set Dest Screen properly. [jrd]
; Correct negotiation on 8 bit quoting, fix checksum resetting. [jrd]
; 26 July 1986 Change ref to ext symbol rpack5 to be rpack. [jrd]
; 16 June 1986 Clear packet counters at start of Get command.
; Also correct use of wrong block check type in Server mode. [jrd]
; 26 May 1986 Revise code to permit serial display. [jrd]
; 14 May 86 - Modify action routine for reception of 'E' packets in server
; mode to be rskp rather than serv1. From Tad Marshall.
; Insert tests for Remote Kermit commands in proc genric to avoid counted
; strings. [jrd]
; [2.29] code frozen on 6 May 1986 [jrd]
public logout, bye, finish, remote, get, server, srvdsa, srvena
public denyflg
include mssdef.h
datas segment public 'datas'
extrn data:byte, flags:byte, trans:byte, pack:byte, curchk:byte
extrn curdsk:byte, diskio:byte, locfil:byte, comand:byte, rptq:byte
extrn filtst:byte, maxtry:byte, imxtry:byte, dtrans:byte,fmtdsp:byte
extrn inichk:byte, errlev:byte, portval:word
scrser equ 0023H ; place for server state display line
scrsrm equ 1000H ; place for messages and dos echoes
cwdflg equ 1 ; deny remote cwd
delflg equ 2 ; deny remote del
dirflg equ 4 ; deny remote dir
hostflg equ 8 ; deny remote host
spcflg equ 10H ; deny remote space
finflg equ 20H ; deny fin, bye, logo to server
getsflg equ 40H ; deny paths in get cmds to server
sndflg equ 80H ; deny paths in send cmds to server
typflg equ 100H ; deny paths in type
tekxflg equ 200h ; deny automatic Tektronix invokation
remcmd db 0 ; Remote command to be executed.
rempac db 0 ; Packet type: C (host) or G (generic).
cmer05 db cr,lf,'?Filename must be specified$'
ermes6 db '?Filename too long for packet$'
erms18 db cr,lf,'?Unable to get response from host$'
erms21 db cr,lf,'?Unable to tell host to execute command$'
infms1 db 'Server mode',cr,lf,'$'
remms1 db 'Kermit-MS Server: Unknown server command$'
remms2 db 'Kermit-MS Server: Illegal file name$'
remms3 db 'Kermit-MS Server: Could not create help file$'
remms4 db 'Kermit-MS Server: Unable to change directories$'
remms5 db 'Kermit-MS Server: No such file(s)$'
remms6 db 'Kermit-MS Server: Could not create directory listing$'
remms7 db 'Kermit-MS Server: Could not create space listing$'
remms8 db 'Kermit-MS Server: Protected or no such file(s)$'
remms9 db 'Kermit-MS Server: Command is Disabled$'
remms10 db 'Kermit-MS Server: Could not create work file$'
byemsg db 'Kermit-MS Server: Goodbye!',0
whomsg db 'Kermit-MS Server: Just this Server',0
sdshlp db cr,lf,'Server restricts access of selected commands:',cr,lf
db ' CWD, DEL, DIR, FIN (incl BYE & LOGO), GET, SEND, SPACE,'
db ' TYPE, and ALL.'
db cr,lf,'Also TEK (automatic invokation of Tek4010 graphics);'
db ' not a member of ALL.$'
senhlp db cr,lf,'Server permits full access of selected commands:',cr,lf
db ' CWD, DEL, DIR, FIN (incl BYE & LOGO), GET, SEND, SPACE,'
db ' TYPE, and ALL.'
db cr,lf,'Also TEK (automatic invokation of Tek4010 graphics);'
db ' not a member of ALL.$'
pass db lf,cr,' Password: $' ; When change directory
srvtmp db ' >$kermit$.tmp ',0 ; asciiz, kermit's temp output file
delstr db 'del ',0
dirstr db 'dir ',0
spcstr db 'chkdsk.com ',0
crlf db cr,lf,'$'
curstim db ? ; normal waiting time for packets
denyflg dw 0 ; bit field of denied commands
temp dw 0
inpbuf dw 0 ; Pointer to input buffer.
cnt dw 0
srvchr db 'SRGIEC' ; server cmd characters
srvfln equ $-srvchr ; length of tbl
srvfun dw srvsnd,srvrcv,srvgen,srvini,rskp,srvhos ; order as in srvchr
remhlp db cr,lf,'CWD change working directory' ; Answer to
db cr,lf,'Delete a file' ; local
db cr,lf,'Directory filespec' ; REM HELP
db cr,lf,'Help'
db cr,lf,'Host command'
db cr,lf,'Kermit command'
db cr,lf,'Send short one line message'
db cr,lf,'Space in a directory'
db cr,lf,'Type a file'
db cr,lf,'Who user spec$'
; Answer from Server to REMOTE HELP
hlprem db cr,lf,'Kermit-MS Server commands:',lf
db cr,lf,'GET filespec REMOTE DELETE filespec '
db 'REMOTE SEND message'
db cr,lf,'SEND filespec REMOTE DIRECTORY filespec '
db 'REMOTE SPACE'
db cr,lf,'FIN, LOGO, and BYE REMOTE HELP '
db 'REMOTE TYPE filespec'
db cr,lf,'REMOTE CWD directory REMOTE HOST command '
db 'REMOTE WHO',0 ; null terminated
remtab db 10 ; 10 entries
mkeyw 'CWD',remcwd
mkeyw 'Delete',remdel
mkeyw 'Directory',remdir
mkeyw 'Help',remhel
mkeyw 'Host',remhos
mkeyw 'Kermit',remker
mkeyw 'Send',remsen
mkeyw 'Space',remdis
mkeyw 'Type',remtyp
mkeyw 'Who',remwho
srvtab db 11 ; Server Enable/Disable list
mkeyw 'All',01ffh
mkeyw 'Cwd',cwdflg
mkeyw 'Delete',delflg
mkeyw 'Dir',dirflg
mkeyw 'Fin',finflg
mkeyw 'Get',getsflg
mkeyw 'Host',hostflg
mkeyw 'Send',sndflg
mkeyw 'Space',spcflg
mkeyw 'Tek4010',tekxflg ; for automatic Tektronix invokation
mkeyw 'Type',typflg
remfnm db ' Remote Source File: $'
lclfnm db ' Local Destination File: $'
filhlp db ' File name to use locally$'
filmsg db ' Remote filename or confirm with carriage return $'
frem db ' Name of file on remote system $'
genmsg db ' Enter text to be sent to remote server $'
srvbuf db 80H dup (0)
rdbuf db 20 dup (0)
datas ends
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
extrn erpos:near, rprpos:near, clrmod:near, crun:near
extrn prompt:near, updrtr:near, cmgetc: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
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.
call serini ; Initialize port.
call ihosts ; initialize the host
mov ah,trans.chklen ; Don't forget the checksum length.
mov curchk,ah
mov trans.chklen,1 ; Use one char for server functions.
call begtim ; start statistics
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
int dos
log2x: call serrst ; Reset port
mov ax,1 ; tell statistics this was a send operation
call endtim ; finish statistics
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.argblk,0 ; Packet number zero.
mov pack.argbk1,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.argbk1,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.argbk1 ; 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: call serrst ; Reset port
mov ax,1 ; tell statistics this was a send operation
call endtim ; finish statistics
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.
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 get3 ; yes, now check for override name.
; if empty line, ask for file names
get1: mov dx,offset remfnm ; ask for remote name first
call prompt
mov bx,offset srvbuf ; place for remote filename
mov dx,offset frem ; the help message
mov ah,cmtxt ; use this for embedded spaces
call comnd ; get a filename
jmp r
cmp flags.cxzflg,0 ; ^X, ^Z, or ^C typed?
je get2 ; e = no, continue
jmp rskp ; yes, quit
get2: mov al,ah
mov ah,0
mov cnt,ax ; remember number of chars read.
mov bx,offset srvbuf ; look at string again.
push es
push di
push si
mov ax,ds ; use segment 'datas' for es:
mov es,ax
mov si,bx ; look at start of string, remove whitespace
get2c: cmp byte ptr [si],0 ; at terminator?
je get2d ; e = yes
cmp byte ptr [si],' ' ; text (greater than space)?
ja get2d ; a = yes.
inc si ; look at next char
jmp get2c ; look some more
get2d: cmp bx,si ; did we find leading whitespace?
je get2e ; e = no
mov di,bx ; place to copy chars
call strcpy ; from ds:si to ds:di
get2e: mov dx,bx ; address of string
call strlen ; get its new length (returned in cx)
mov cnt,cx ; store it
pop si
pop di
pop es
cmp cnt,0 ; count of entered chars
jne get2f ; ne = got some
jmp rskp ; empty so abort this command
get2f: mov dx,offset lclfnm ; prompt for local filename
call prompt
get3: mov flags.nmoflg,0 ; assume no local override name
mov bx,offset filhlp
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 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
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
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 ipack ; Send Initialize, 'I', packet.
jmp get8 ; Sorry can't do it.
nop
mov cx,cnt ; Get back remote filename size.
mov pack.argbk1,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
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.argbk1 ; 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.
int dos
or errlev,2 ; set DOS error level to cannot rcv.
get9: test flags.remflg,dquiet+dserial ; quiet or serial display?
jnz get9a ; nz = yes
call clrmod
call rprpos
get9a: call serrst ; Reset port.
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.argblk,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 pack.argbk2,ax ; where rinit wants pkt type if GET
mov flags.getflg,1 ; note this is a GET
mov pack.state,'R' ; Set the state to receive initiate
jmp read12 ; go join read code
get11: mov ah,prstr ; Complain if no filename.
mov dx,offset cmer05
int dos
jmp rskp
get12: mov dx,offset ermes6 ; Complain if filename is too long for pkt
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
jmp rskp
GET ENDP
; server command
SERVER PROC NEAR
mov ah,cmcfm
call comnd
jmp r
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
mov fmtdsp,1 ; say using formatted display
call cmblnk ; clear screen
mov dx,scrser ; move cursor to top of screen
call poscur
serv1a: mov ah,prstr
mov dx,offset infms1 ; say now in server mode
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 fmtdsp,1 ; say using formatted display
mov dx,scrsrm ; move cursor to server message area
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
call poscur
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
call serini ; init serial line (send & receive reset it)
mov ax,1 ; assume previous operation was a send
call endtim ; do end of statistics, for loop back
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 rpack ; get a packet
jmp short serv2 ; no good, nak and continue
nop
call begtim ; start statistics
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; protocol error if omitted
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?
je serv5 ; yes, stop this.
call nak ; nak the packet
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
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 ax,1 ; tell statistics this was a send operation
call endtim ; stop statistics
mov fmtdsp,0 ; end of formatted display
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.argbk1 ; 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.argbk1,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:test denyflg,sndflg ; is command enabled?
jz srvsnd2 ; z = yes
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)
srvsnd2: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
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
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
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.argbk1,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
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
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srcwd4: cmp pack.argbk1,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.
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.argbk1,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.argbk1,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)"
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.argbk1,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)"
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"
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
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srvdel4:cmp pack.argbk1,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)"
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.argbk1,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
mov trans.chklen,1 ; reply with 1 char checksum
call errpack ; back to local kermit
ret
srspc1: mov di,offset srvbuf ; work area
mov si,offset spcstr ; prepend "chkdsk.com "
call strcpy
mov si,offset srvtmp ; add redirection tag of " >$kermit$.tmp"
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 srspc2 ; nc = yes
mov trans.chklen,1 ; reply with 1 char checksum
mov bx,offset remms7 ; "Could not create space listing"
call errpack ; send the error message
ret ; and exit
srspc2: 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
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
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.argbk1,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
cmp pack.argbk1,1 ; Any data in the packet?
jbe srvsen1 ; e = no, just ack the message.
call dodec ; Decode data.
mov di,offset data+2 ; Where the reply is. (skip M and byte cnt)
cmp byte ptr [di-2],'M' ; Message packet?
jne srvsen1 ; ne = no, ack and forget
mov cl,byte ptr [di-1] ; How much data we have.
sub cl,' ' ; remove ascii bias
cbw ; make a whole word
jle srvsen1 ; le = nothing
call prtscr ; Print it on the screen.
srvsen1:mov ah,'Y' ; reply with an ack
mov pack.argbk1,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
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 si,offset remms10 ; say could not create work file
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.argbk1,cx ; length
mov trans.chklen,1 ; reply with 1 char checksum
call pktsize ; report packet size
call spack
nop
nop
nop
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
call strlen ; put string length in cx
mov ah,write2 ; write to file
mov bx,diskio.handle
int dos ; write the info, ignore errors
mov ah,close2 ; close the file so we can reread it below
mov bx,diskio.handle
int dos
; 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 si,offset remms3 ; say could not create help file
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.argbk1,cx ; length
call pktsize ; report packet size
call spack
nop
nop
nop
jmp rskp ; and exit
srvhlp endp
srvdsa proc near ; DISABLE Server commands
mov dx,offset srvtab
mov bx,offset sdshlp
mov ah,cmkey ; parse key word
call comnd
jmp r ; bad parse
mov temp,bx ; save key value
mov ah,cmcfm ; get a confirm
call comnd
jmp r ; no confirm
mov bx,temp ; get selected item
or denyflg,bx ; turn on bit (deny) for that item
jmp rskp ; return successfully
srvdsa endp
srvena proc near ; ENABLE Server commands
mov dx,offset srvtab ; keyword table
mov bx,offset senhlp ; help on keywords
mov ah,cmkey ; parse key word
call comnd
jmp r ; bad parse
mov temp,bx ; save key value
mov ah,cmcfm ; get a confirm
call comnd
jmp r ; no confirm
mov bx,temp ; item to be enabled
not bx ; invert bits
and denyflg,bx ; turn off (enable) selected item
jmp rskp
srvena endp
; srvini - init parms based on init packet
srvini proc near
mov bx,offset data
mov ax,pack.argbk1 ; 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.argbk1,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
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.
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.
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.
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.
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.
jmp genric
REMKER ENDP
; REMDIR - Do a directory.
REMDIR PROC NEAR
mov remcmd,'D'
mov rempac,'G' ; Packet type = generic.
jmp genric
REMDIR ENDP
; REMDEL - Delete a remote file.
REMDEL PROC NEAR
mov remcmd,'E'
mov rempac,'G' ; Packet type = generic.
jmp genric
REMDEL ENDP
; REMCWD - Change remote working directory.
REMCWD PROC NEAR
mov remcmd,'C'
mov rempac,'G' ; Packet type = generic.
jmp genric
REMCWD ENDP
; REMSEN - Send one line short message to remote screen. [jrd]
REMSEN proc near
mov remcmd,'M'
mov rempac,'G'
jmp genric
REMSEN endp
; REMWHO - ask for list of remote logged on users [jrd]
REMWHO proc near
mov remcmd,'W'
mov rempac,'G'
jmp genric
REMWHO endp
; GENRIC - Send a generic command to a remote Kermit server.
GENRIC PROC NEAR
call begtim ; start statistics
mov bx,offset srvbuf ; Where to put the text.
cmp rempac,'C' ; Remote host command?
je genra ; Yes, leave as is.
cmp rempac,'K' ; Remote Kermit command?
je genra ; e = yes. Don't use counted string.
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 text.
call comnd
jmp r
mov al,ah ; Don't forget the size.
mov ah,0
mov cnt,ax ; Save it here.
mov flags.xflg,1 ; output coming to screen
cmp rempac,'K' ; Remote Kermit command?
je genra1 ; e = yes
cmp rempac,'C' ; Remote host command?
jne genrb ; No, skip this part.
genra1: call ipack ; Remote Host or Kermit
jmp genr2
mov curchk,ah ; Save desired checksum length.
mov trans.chklen,1 ; Use 1 char for server functions.
mov pack.numrtr,0 ; No retries yet.
mov pack.numtry,0
jmp genr1 ; Send the packet.
genrb: mov ax,cnt
cmp ax,0 ; Any data?
je genr0 ; Nope.
mov ah,al ; Don't overwrite the real count value
add ah,32 ; Do the char function.
mov temp,bx ; Remember where we are.
mov bx,offset srvbuf+1 ; Size of remote command.
mov [bx],ah
mov ah,0
inc al ; For the size field.
cmp remcmd,'C' ; Change working directory?
jne genr0 ; No, so don't ask for password.
mov cnt,ax ; Save here for a bit.
mov ah,prstr
mov dx,offset pass ; Send along an optional password.
int dos
mov bx,temp ; Where to put the password.
push bx ; Is safe since subroutine never fails
inc bx ; Leave room for count field.
call input ; Read in the password.
mov temp,bx ; Remember end of data pointer.
pop bx ; Where to put the size.
cmp ah,0 ; No password given?
jne genrc
mov ax,cnt
jmp genr0 ; Then that's it.
genrc: mov al,ah
add ah,32 ; Make it printable.
mov [bx],ah ; Tell remote host the size.
mov ah,0
push ax ; Remember the count.
call clearl ; Clear to end-of-line.
pop ax
inc al ; For second count value.
add ax,cnt ; Total for both fields of input.
genr0: inc al ; For char representing the command.
mov pack.argbk1,ax ; Set the size.
mov cnt,ax ; And remember it.
mov pack.argbk1,ax ; Set the size.
mov cnt,ax ; And remember it.
mov pack.numtry,0 ; Initialize count
mov bx,offset srvbuf ; Start of data buffer.
mov ah,remcmd ; Command subtype.
mov [bx],ah
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 erms21 ; Print error msg and fail.
int dos
genr2x: call serrst ; Reset the port.
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
call endtim
jmp rskp
genr3: mov ah,prstr
mov dx,offset crlf ; First go to a new line.
int dos
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.argbk1,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.argblk,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.argbk1,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.argbk1 ; How much data we have.
call prtscr ; Print it on the screen.
mov flags.xflg,0 ; reset screen output flag before leaving
genr31: xor ax,ax ; tell statistics this was a read
call endtim ; tell statistics
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.
mov pack.numtry,0
mov pack.numrtr,0
mov pack.numpkt,0
mov pack.pktnum,0
call bx ; Handle it almost like filename.
call read2 ; Receive the rest.
jmp r ; Oops, we failed.
nop
xor ax,ax ; tell statistics this was a read
call endtim
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
xor ax,ax ; tell statistics this was a read
call endtim
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
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 bx,portval
mov trans.ebquot,dqbin ; default 8 bit quote, needed with parity
cmp [bx].parflg,parnon ; using parity = none locally?
jne ipk1a ; ne = using local parity, need 8 bit quoting
mov trans.ebquot,'Y' ; say can do 8 bit quoting, if they insist
ipk1a: 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.argbk1,ax ; Save the number of arguments.
mov pack.argblk,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.argblk ; Is it the right packet number?
je ipk2
jmp ipk0 ; If not try again.
ipk2: mov ax,pack.argbk1 ; 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 in AH the count of characters read in.
; in BX the updated pointer to the input buffer.
INPUT PROC NEAR
mov cl,0 ; Keep a count.
mov inpbuf,bx ; Where to put data.
mov comand.cmquiet,1 ; turn on quiet mode
input0: call cmgetc ; get a character nicely
cmp al,CR ; Done with input?
jne input1
push cx ; save count
mov ah,prstr
mov dx,offset crlf
int dos ; echo a carriage return
pop cx
mov ah,cl ; Return count in AH.
mov comand.cmquiet,0 ; turn off quiet mode
jmp r
input1: cmp al,BS ; Backspace?
je inpt11
cmp al,DEL ; Or delete?
jne input3
inpt11: dec cl ; Don't include in char count.
cmp cl,0 ; Backspaced too much?
jns input2 ; No, is OK.
mov ah,conout
mov dl,bell
int dos
mov cl,0
jmp input0
input2: dec bx ; 'Remove' from buffer.
jmp input0 ; Go get more.
input3: cmp al,'U'-64 ; Control-U?
jne input4
mov cl,0 ; Reset count to zero.
mov bx,inpbuf ; Start at head of buffer.
jmp input0
input4: mov [bx],al ; Add char to buffer.
inc cl ; Include in count.
inc bx
jmp input0
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
; Jumping here is the same as a ret.
R PROC NEAR
ret
R ENDP
code ends
end