public read12, read2, rin21, rfile3, read, updrtr, nak, rrinit include msdefs.h datas segment public 'datas' extrn fcb:byte, data:byte, bufpnt:word, chrcnt:word, curchk:byte extrn comand:byte, flags:byte, pack:byte, trans:byte ermes7 db '?Unable to receive initiate$' ermes8 db '?Unable to receive file name$' ermes9 db '?Unable to receive end of file$' erms10 db '?Unable to receive data$' infms1 db cr,' Receiving: In progress$' infms3 db 'Completed$' infms4 db 'Failed$' infms6 db 'Interrupted$' remmsg1 db 'Kermit-MS: Invalid filename' filhlp2 db ' Confirm with carriage return or specify name ' db ' to use for incoming file $' ender db bell,bell,'$' crlf db cr,lf,'$' temp dw 0 datas ends code segment public extrn gofil:near, outbuf:near, fixfcb:near, comnd:near extrn spack:near, rpack:near, serini:near, serrst:near extrn spar:near, rpar:near, init:near, init1:near, cxmsg:near extrn error:near, ptchr:near, erpos:near, rtpos:near extrn stpos:near, rprpos:near, nppos:near, nout:near extrn dodec:near, doenc:near, errpack:near extrn send11:near, clrmod:near assume cs:code, ds:datas ; Update retry count and fall through to send a NAK. nak0: call updrtr ; Update retry count. nak: mov ax,pack.pktnum ; Get the packet number we're waiting for. mov pack.argblk,ax mov pack.argbk1,0 mov cx,0 ; No data, but this may change. call doenc ; So call encode. mov ah,'N' ; NAK that packet. call spack jmp abort nop ; So 'jmp rskp' in SPACK comes here. [19a] ret ; Go around again. updrtr: cmp pack.state,'A' ; Supposed to abort? je upd0 ; Yes, don't bother with retry count. inc pack.numrtr ; Increment the number of retries. cmp flags.xflg,1 ; Writing to screen? je upd0 call rtpos ; Position cursor. mov ax,pack.numrtr call nout ; Write the number of retries. upd0: ret ; Abort ABORT PROC NEAR mov pack.state,'A' ; Otherwise abort. ret ABORT ENDP ; init variables for read... rrinit proc near mov pack.numpkt,0 ; Set the number of packets to zero. mov pack.numrtr,0 ; Set the number of retries to zero. mov pack.pktnum,0 ; Set the packet number to zero. mov pack.numtry,0 ; Set the number of tries to zero. ret rrinit endp ; RECEIVE command -- Some code moved to the GET routine. [21a] READ PROC NEAR mov comand.cmrflg,1 ; Say we're receiving a file. [21a start] mov comand.cmcr,1 ; Allow bare CR after RECEIVE. mov flags.droflg,0 ; Override default drive flag. mov flags.nmoflg,0 ; Override file name from other host? mov dx,offset fcb ; Put filename here. mov bx,offset filhlp2 ; Text of help message. mov ah,cmifi ; Read in the filename. call comnd jmp r mov comand.cmrflg,0 ; Reset flag. mov comand.cmcr,0 mov flags.wldflg,0 ; Just in case mov ah,cmcfm ; Get a confirm. call comnd jmp r read1: cmp flags.remflg,0 ; remote mode? jne read12 ; yes, no printing call init read12: mov flags.cxzflg,0 ; Reset ^X/^Z flag. [20c] call rrinit ; init variables for read call serini ; Initialize serial port. [14] cmp flags.remflg,0 ; in remote mode? jne read12a ; yes, no printing call init1 ; Clear the line and initialize the buffers. call stpos mov ah,prstr ; Be informative. mov dx,offset infms1 int dos call rtpos ; Position cursor. mov ax,pack.numrtr call nout ; Write the number of retries. read12a:mov pack.state,'R' ; Set the state to receive initiate. read2: cmp flags.xflg,1 ; Are we receiving to the screen. [21c] je read21 ; Skip the screen stuff. [21c] cmp flags.remflg,0 ; maybe remote mode? jne read21 ; yup, skip the screen stuff call nppos ; Position cursor for number of packets msg. mov ax,pack.numpkt call nout ; Write the number of packets. read21: mov ah,pack.state ; Get the state. [21c] cmp ah,'D' ; Are we in the data send state? jne read3 call rdata jmp read2 read3: cmp ah,'F' ; Are we in the file receive state? jne read4 call rfile ; Call receive file. jmp read2 read4: cmp ah,'R' ; Are we in the receive initiate state? jne read5 call rinit jmp read2 read5: cmp ah,'C' ; Are we in the receive complete state? jne read6 call serrst ; Reset serial port. [14] cmp flags.xflg,0 ; Did we write to the screen? [21c] je read51 ; No so print status. [21c] mov flags.xflg,0 ; Reset it. [21c] jmp rskp ; Yes, so just return. [21c] read51: cmp flags.remflg,0 ; remote mode? jne read51a ; yes, keep going call stpos ; Position cursor. [21c] mov ah,prstr mov dx,offset infms3 ; Plus a little cuteness. cmp flags.cxzflg,0 ; Completed or interrupted? [20c] je read13 ; Ended normally. [20c] mov dx,offset infms6 ; Say was interrupted. [20c] read13: int dos cmp flags.belflg,0 ; Bell desired? [17a] je readnb ; No. [17a] mov dx,offset ender ; Ring them bells. [4] int dos ; [4] readnb: call clrmod ; clear 25th line call rprpos ; Put prompt here. read51a:jmp rskp read6: call serrst ; Reset serial port. [14] cmp flags.xflg,0 ; Did we write out to screen? [21c] je read61 ; No so print status. [21c] mov flags.xflg,0 ; Reset it. [21c] jmp rskp ; Print onto screen. [21c] read61: cmp flags.remflg,0 ; remote mode? jne read7a ; yes, no printing. call stpos ; Position cursor. [21c] mov ah,prstr mov dx,offset infms4 ; Plus a little cuteness. int dos cmp flags.belflg,0 ; Bell desired? [17a] je read7 ; No. [17a] mov dx,offset ender ; Ring them bells. [4] int dos ; [4] read7: call clrmod ; clear mode line call rprpos ; Put prompt here. read7a: jmp rskp READ ENDP ; Receive routines ; Receive init RINIT PROC NEAR mov ah,pack.numtry ; Get the number of tries. cmp ah,imxtry ; Have we reached the maximum number of tries? jl rinit2 call erpos ; Position cursor. mov dx,offset ermes7 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rinit2: inc ah ; Increment it. mov pack.numtry,ah ; Save the updated number of tries. mov ax,pack.argbk2 ; get packet type if here from get cmp flags.getflg,1 ; Have we already read in the packet? [21a] je rin21a ; Yes, so don't call RPACK. [21a] mov ah,trans.chklen mov curchk,ah ; Save checksum length we want to use. mov trans.chklen,1 ; Use 1 char for init packet. call rpack ; Get a packet. jmp rin22 ; Trashed packet: nak, retry. push ax mov ah,curchk mov trans.chklen,ah ; Reset to desired value. pop ax rin21a: cmp ah,'S' ; Is it a send initiate packet? jne rinit3 ; If not see if its an error. rin21: mov flags.getflg,0 ; Reset flag. [21a] mov ah,pack.numtry ; Get the number of tries. mov pack.oldtry,ah ; Save it. mov pack.numtry,0 ; Reset the number of tries. mov ax,pack.argblk ; Returned packet number. (Synchronize them.) inc ax ; Increment it. and ax,3FH ; Turn off the two high order bits. mov pack.pktnum,ax ; Save modulo 64 of the number. mov bx,pack.numpkt inc bx ; Increment the number of packets. mov pack.numpkt,bx mov ax,pack.argbk1 ; Get the number of arguments received. mov bx,offset data ; Get a pointer to the data. call spar ; Get the data into the proper variables. mov bx,offset data ; Get a pointer to our data block. call rpar ; Set up the receive parameters. xchg ah,al mov ah,0 mov pack.argbk1,ax ; Store the returned number of arguments. mov ah,trans.chklen ; Checksum length we'll use. mov curchk,ah ; Save it. mov trans.chklen,1 ; Use 1 char for init packet. mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort mov ah,curchk ; Checksum length we'll use. mov trans.chklen,ah ; Reset to desired value. mov ah,'F' ; Set the state to file send. mov pack.state,ah ret rin22: mov ah,curchk mov trans.chklen,ah ; Reset to desired value. jmp nak0 ; Try again. rinit3: cmp ah,'E' ; Is it an error packet? jne rinit4 call error rinit4: jmp abort RINIT ENDP ; Receive file RFILE PROC NEAR cmp pack.numtry,maxtry ; Have we reached the maximum number of tries? jl rfile1 call erpos ; Position cursor. mov dx,offset ermes8 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rfile1: inc pack.numtry ; Save the updated number of tries. call rpack ; Get a packet. jmp nak0 ; Trashed packet: nak, retry. cmp ah,'S' ; Is it a send initiate packet? je rfil10 call dodec ; Decode all incoming packets. jmp rfile2 ; No, try next type. rfil10: cmp pack.oldtry,imxtry ; Have we reached the maximum number of tries? jl rfil12 ; If not proceed. call erpos ; Position cursor. mov dx,offset ermes7 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rfil12: inc pack.oldtry ; Save the updated number of tries. mov ax,pack.pktnum ; Get the present packet number. cmp ax,0 ; Had we wrapped around? [18 start] jne rfilx mov ax,64 rfilx: dec ax ; Decrement. [18 end -- new label] cmp ax,pack.argblk ; Is the packet's number one less than now? je rfil13 jmp nak0 ; No, NAK and try again. rfil13: call updrtr ; Update retry count. mov pack.numtry,0 ; Reset the number of tries. 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 ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort ret rfile2: cmp ah,'Z' ; Is it an EOF packet? jne rfile3 ; No, try next type. cmp pack.oldtry,maxtry ; Have we reached the maximum number of tries? jl rfil21 ; If not proceed. call erpos ; Position cursor. mov dx,offset ermes9 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rfil21: inc pack.oldtry ; Increment it. mov ax,pack.pktnum ; Get the present packet number. cmp ax,0 ; Had we wrapped around? [18 start] jne rfily mov ax,64 rfily: dec ax ; Decrement. [18 end -- new label] cmp ax,pack.argblk ; Is the packet's number one less than now? je rfil24 jmp nak0 ; No, NAK and try again. rfil24: call updrtr ; Update retry count. mov pack.numtry,0 mov pack.argbk1,0 ; No data. (The packet number is in argblk.) mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort ret rfile3: cmp ah,'F' ; Start of file? je rfil31 ; Yes. [21c] cmp ah,'X' ; Text header packet? [21c] jne rfile4 ; Neither one. rfil31: mov ax,pack.argblk ; Get the packet number. [21c] cmp ax,pack.pktnum ; Is it the right packet number? je rfil32 jmp nak ; No, NAK it and try again. rfil32: inc ax ; Increment the packet number. and ax,3FH ; Turn off the two high order bits. mov pack.pktnum,ax ; Save modulo 64 of the number. inc pack.numpkt ; Increment the number of packets. call gofil ; Get a file to write to. jmp abort call init1 ; Initialize all the buffers. mov ah,pack.numtry ; Get the number of tries. mov pack.oldtry,ah ; Save it. mov pack.numtry,0 ; Reset the number of tries. mov pack.argbk1,0 ; No data. (The packet number is in argblk.) mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort mov pack.state,'D' ; Set the state to data receive. ret rfile4: cmp ah,'B' ; End of transmission. jne rfile5 mov ax,pack.pktnum cmp ax,pack.argblk ; Do we match? je rfil41 jmp nak ; No, NAK it and try again. rfil41: mov pack.argbk1,0 ; No data. (Packet number already in argblk). mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort mov pack.state,'C' ; Set the state to complete. ret rfile5: cmp ah,'E' ; Is it an error packet. jne rfile6 call error rfile6: jmp abort RFILE ENDP ; Receive data RDATA PROC NEAR cmp pack.numtry,maxtry ; Get the number of tries. jl rdata1 call erpos ; Position cursor. mov dx,offset erms10 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rdata1: inc pack.numtry ; Save the updated number of tries. call rpack ; Get a packet. jmp nak0 ; Trashed packet: nak, retry. cmp ah,'D' ; Is it a data packet? je rdat11 call dodec ; Decode data. jmp rdata2 ; No, try next type. rdat11: mov ax,pack.pktnum ; Get the present packet number. cmp ax,pack.argblk ; Is the packet's number correct? jz rdat14 cmp pack.oldtry,maxtry ; Have we reached the maximum number of tries? jl rdat12 ; If not proceed. call erpos ; Position cursor. mov dx,offset erms10 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rdat12: inc pack.oldtry ; Save the updated number of tries. mov ax,pack.pktnum cmp ax,0 ; Had we wrapped around? [18 start] jne rdatx mov ax,64 rdatx: dec ax ; [14] [18 end -- new label] cmp ax,pack.argblk ; Is the packet's number one less than now? je rdat13 jmp nak0 ; No, NAK it and try again. rdat13: call updrtr ; Update retry count. mov pack.numtry,0 ; Reset number of tries. mov pack.argbk1,0 ; No data. (The packet number is in argblk.) mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort ret rdat14: inc ax ; Increment the packet number. and ax,3FH ; Turn off the two high order bits. mov pack.pktnum,ax ; Save modulo 64 of the number. inc pack.numpkt ; Increment the number of packets. mov ah,pack.numtry ; Get the number of tries. mov pack.oldtry,ah ; Save it. mov ax,pack.argbk1 ; Get the length of the data. cmp flags.cxzflg,0 ; Has the user typed a ^X or ^Z? [20c] je rdt14x ; No, write out the data. cmp flags.abfflg,1 ; Discard incomplete files? je rdat15 ; If yes don't write data out to file. [20c] rdt14x: mov bx,offset data ; Where the data is. [25] call ptchr jmp abort ; Unable to write out chars; abort. rdat15: mov pack.numtry,0 ; Reset the number of tries. mov pack.argbk1,0 ; No data. (Packet number still in argblk.) mov cx,0 cmp flags.cxzflg,0 ; Interrupt file transfer? [20c] je rdat16 ; Nope. [20c] mov bx,offset data ; Send data in ACK in case remote... [20c] mov ah,flags.cxzflg ; ... knows about ^X/^Z. [20c] mov [bx],ah ; Put data into the packet. [20c] mov pack.argbk1,1 ; Set data size to 1. [20c] mov cx,1 rdat16: call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort ret rdata2: cmp ah,'F' ; Start of file? je rdat20 ; Yup. [21c] cmp ah,'X' ; Text header packet? [21c] jne rdata3 ; No, try next type. rdat20: cmp pack.oldtry,maxtry ; Reached the max number of tries? [21c] jl rdat21 ; If not proceed. call erpos ; Position cursor. mov dx,offset ermes8 mov ah,prstr int dos ; Print an error message. mov bx,dx call errpack ; Send error packet just in case. jmp abort ; Change the state to abort. rdat21: inc pack.oldtry ; Save the updated number of tries. mov ax,pack.pktnum cmp ax,0 ; Had we wrapped around? [18 start] jne rdaty mov ax,64 rdaty: dec ax ; [14 Omitted accidentally - D.T.] [18 end] cmp ax,pack.argblk ; Is the packet's number one less than now? je rdat22 jmp nak0 ; No, NAK it and try again. rdat22: call updrtr ; Update retry count. mov pack.numtry,0 ; Reset number of tries. mov pack.argbk1,0 ; No data. (The packet number is in argblk.) mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort ret rdata3: cmp ah,'Z' ; Is it a EOF packet? je rdat3x ; [13] jmp rdata4 ; Try and see if its an error. [13] rdat3x: mov ax,pack.pktnum ; Get the present packet number. [13] cmp ax,pack.argblk ; Is the packet's number correct? je rdat32 jmp nak0 ; No, NAK it and try again. rdat32: inc ax ; Increment the packet number. and ax,3FH ; Turn off the two high order bits. mov pack.pktnum,ax ; Save modulo 64 of the number. inc pack.numpkt cmp flags.cxzflg,0 ; Do we want to discard the file? [20c] jne rdt32x ; Yes. [20c] cmp pack.argbk1,1 ; One piece of data? [20c] jne rdat33 ; Nope - finish writing out file? [20c] mov bx,offset data ; Get data area. [20c] mov ah,[bx] ; Get the data. [20c] cmp ah,'D' ; "D" for discard? [20c] jne rdat33 ; Nope - write out file. [20c] rdt32x: cmp flags.abfflg,0 ; Keep incomplete files? je rdat33 ; Yes, go write it out. mov ah,closf ; First, close the file. mov dx,offset fcb ; Give the file parameters. [20c] int dos ; Kill it, ignore errors. [20c] mov ah,delf ; Delete the file if opened. [20c] int dos cmp flags.cxzflg,'X' ; Kill one file or all? [20c] jne rdat36 ; No so leave flag alone. [20c] call cxmsg ; Clear msg about interrupt. [20c] mov flags.cxzflg,0 ; Reset - ^X only kills one file. [20c] jmp rdat36 rdat33: mov bx,bufpnt ; Get the dma pointer. mov ax,80H sub ax,chrcnt ; Get the number of chars left in the DMA. cmp flags.eofcz,0 ; should we write a ^Z? jz rdat35 ; no, keep going cmp flags.xflg,0 ; writing to a file? jne rdat35 ; no, skip ^Z cmp ax,80H ; [13 start] jne rdat34 call outbuf ; Write out buffer if no room for ^Z. jmp abort mov ax,0 ; [13 end] inc chrcnt ; Increment size by one (not two). [21b] rdat34: mov cl,'Z'-100O ; Put in a ^Z for EOF. mov [bx],cl ; Add it. [21c] inc ax dec chrcnt rdat35: mov cx,chrcnt mov temp,cx call outbuf ; Output the last buffer. jmp abort ; Give up if the disk is full. mov ax,temp ; Prepare for the function call. call fixfcb mov ah,closf ; Close up the file. mov dx,offset fcb int dos rdat36: cmp flags.destflg,1 ; Writing to disk? je rdat37 ; Yes, skip next part. cmp flags.xflg,1 ; Writing to screen? je rdat37 ; Yes, skip this part. mov dl,ff ; Send a form feed. mov ah,lstout ; Write out to first printer. int dos rdat37: mov ah,pack.numtry ; Get the number of tries. mov pack.oldtry,ah ; Save it. mov pack.numtry,0 ; Reset the number of tries. mov pack.argbk1,0 ; No data. (The packet number is in argblk.) mov cx,0 call doenc mov ah,'Y' ; Acknowledge packet. call spack ; Send the packet. jmp abort mov pack.state,'F' ret rdata4: cmp ah,'E' ; Is it an error packet. jne rdata5 call error rdata5: jmp abort RDATA 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 R PROC NEAR ret R ENDP code ends end