home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / MSKERMIT.ZIP / MSSEND.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-05-17  |  32.2 KB  |  1,053 lines

  1.     public    spar, rpar, error, error1, nout, send, flags, trans, pack
  2.     public    dodec, doenc, curchk, inichk, packlen, send11
  3.     include msdefs.h
  4.  
  5. spmin    equ    20        ; Minimum packet size.
  6. spmax    equ    94        ; Maximum packet size.
  7.  
  8. datas    segment public 'datas'
  9.     extrn    buff:byte, data:byte, fcb:byte, cpfcb:byte, filbuf:byte
  10.     extrn    decbuf:byte, chrcnt:word, bufpnt:word, comand:byte
  11.     extrn    rptq:byte, origr:byte, rptct:byte, rptval:byte
  12.  
  13. flags    flginfo <>
  14. trans    trinfo    <>
  15. pack    pktinfo <>
  16. crlf    db    cr,lf,'$'
  17. ender    db    bell,bell,'$'                   ;  [4]
  18. erms14    db    '?Unable to receive an acknowledgment from the host$'
  19. erms15    db    '?Unable to find file$'
  20. erms20    db    'Unable to send init packet$'
  21. erms21    db    'Unable to send file header$'
  22. erms22    db    'Unable to send data$'
  23. erms23    db    'Unable to send end-of-file packet$'
  24. erms24    db    'Unable to send break packet$'
  25. infms2    db    cr,'             Sending: In progress$'
  26. infms3    db    'Completed$'
  27. infms4    db    'Failed$'
  28. infms6    db    'Interrupted$'
  29. infms7    db    cr,' Percent transferred: 100%$'
  30. remmsg1 db    'Kermit-MS: File not found$'
  31. filhlp    db    ' Input file spec (possibly wild) $'
  32. filmsg    db    ' File name to use on target system or confirm with'
  33.     db    ' a carriage return $'
  34.  
  35. curchk    db    0        ; Use to store checksum length.
  36. inichk    db    1        ; Original or set checksum length.
  37. chrptr    dw    ?        ; Position in character buffer.
  38. fcbpt    dw    ?        ; Position in FCB.
  39. datptr    dw    ?        ; Position in packet data buffer.
  40. siz    dw    ?        ; Size of data from gtchr.
  41. temp    dw    0
  42. temp4    dw    0
  43. sendas    dw    50 dup(0)    ; Buffer for file name.
  44. difnam    db    0        ; Send under different name?
  45. difsiz    db    0        ; Size of new file name.
  46. asmsg    db    '  as  $'
  47. datas    ends
  48.  
  49. code    segment public
  50.     extrn serini:near, serrst:near, comnd:near, init:near
  51.     extrn spack:near, rpack:near, gtnfil:near, gtchr:near
  52.     extrn getfil:near, clrfln:near, nppos:near, rprpos:near
  53.     extrn erpos:near, rtpos:near, cxmsg:near, stpos:near
  54.     extrn encode:near, nulref:near, decode:near, nulr:near
  55.     extrn errpack:near, updrtr:near, clrmod:near, fcbcpy:near
  56.     extrn perpos:near
  57.     assume    cs:code,ds:datas
  58.  
  59. ;    This routine sets up the data for init packet (either the
  60. ;    Send_init or ACK packet).
  61.  
  62. RPAR    PROC    NEAR
  63.     mov ah,trans.rpsiz    ; Get the receive packet size.
  64.     add ah,' '              ; Add a space to make it printable.
  65.     mov [bx],ah        ; Put it in the packet.
  66.     mov ah,trans.rtime    ; Get the receive packet time out.
  67.     add ah,' '              ; Add a space.
  68.     mov 1[bx],ah        ; Put it in the packet.
  69.     mov ah,trans.rpad    ; Get the number of padding chars.
  70.     add ah,' '
  71.     mov 2[bx],ah        ; Put it in the packet.
  72.     mov ah,trans.rpadch    ; Get the padding char.
  73.     add ah,100O        ; Uncontrol it.
  74.     and ah,7FH
  75.     mov 3[bx],ah        ; Put it in the packet.
  76.     mov ah,trans.reol    ; Get the EOL char.
  77.     add ah,' '
  78.     mov 4[bx],ah        ; Put it in the packet.
  79.     mov ah,trans.rquote    ; Get the quote char.
  80.     mov 5[bx],ah        ; Put it in the packet.
  81.     mov ah,trans.ebquot    ; Get 8-bit quote char. [21b]
  82.     mov 6[bx],ah        ; Add it to the packet. [21b]
  83.     mov ah,trans.chklen    ; Length of checksum.
  84.     add ah,48        ; Make into a real digit.
  85.     mov 7[bx],ah
  86.     mov ah,rptq        ; Repeat quote char.
  87.     cmp ah,0        ; Null means no.
  88.     jne rpar0
  89.     mov ah,' '              ; Send a blank instead.
  90. rpar0:    mov 8[bx],ah
  91.     mov ah,09H        ; Nine pieces of data.
  92.     ret
  93. RPAR    ENDP
  94.  
  95. ;    This routine reads in all the send_init packet information.
  96.  
  97. SPAR    PROC    NEAR
  98.     cmp ax,1
  99.     jge sparx
  100.     mov ah,dspsiz        ; Data not supplied by host, use default.
  101.     jmp sparx2
  102. sparx:    mov temp4,ax        ; Save the number of arguments.
  103.     mov ah,trans.spsiz
  104.     cmp ah,dspsiz        ; Is current value the default?
  105.     jne sparx2        ; No, assume changed by user.
  106.     mov ah,[bx]        ; Get the max packet size.
  107.     sub ah,' '              ; Subtract a space.
  108.     cmp ah,spmin        ; Can't be below the minimum.
  109.     jge sparx1
  110.     mov ah,spmin
  111.     jmp sparx2
  112. sparx1: cmp ah,spmax        ; Or above the maximum.
  113.     jle sparx2
  114.     mov ah,spmax
  115. sparx2: mov trans.spsiz,ah    ; Save it.
  116.     mov ax,temp4
  117.     cmp al,2        ; Fewer than two pieces?
  118.     jge spar0
  119.     mov ah,dstime        ; Data not supplied by host, use default.
  120.     jmp spar02
  121. spar0:    mov ah,trans.stime
  122.     cmp ah,dstime        ; Is current value the default?
  123.     jne spar02        ; No, assume changed by user.
  124.     mov ah,1[bx]        ; Get the timeout value.
  125.     sub ah,' '              ; Subtract a space.
  126.     cmp ah,0
  127.     ja spar01        ; Must be non-negative.
  128.     mov ah,0
  129. spar01: cmp ah,trans.rtime    ; Same as other side's timeout.
  130.     jne spar02
  131.     add ah,5        ; If so, make it a little different.
  132. spar02: mov trans.stime,ah    ; Save it.
  133.     mov ax,temp4
  134.     cmp al,3        ; Fewer than three pieces?
  135.     jge spar1
  136.     mov ah,dspad        ; Data not supplied by host, use default.
  137.     jmp spar11
  138. spar1:    mov ah,trans.spad
  139.     cmp ah,dspad        ; Is current value the default?
  140.     jne spar11        ; No, assume changed by user.
  141.     mov ah,2[bx]        ; Get the number of padding chars.
  142.     sub ah,' '
  143.     cmp ah,0
  144.     ja spar11        ; Must be non-negative.
  145.     mov ah,0
  146. spar11: mov trans.spad,ah
  147.     mov ax,temp4
  148.     cmp al,4        ; Fewer than four pieces?
  149.     jge spar2
  150.     mov ah,dspadc        ; Data not supplied by host, use default.
  151.     jmp spar21
  152. spar2:    mov ah,trans.spadch
  153.     cmp ah,dspadc        ; Is current value the default?
  154.     jne spar21        ; No, assume changed by user.
  155.     mov ah,3[bx]        ; Get the padding char.
  156.     add ah,100O        ; Re-controlify it.
  157.     and ah,7FH
  158.     cmp ah,del        ; Delete?
  159.     je spar21        ; Yes, then it's OK.
  160.     cmp ah,0
  161.     jge spar20
  162.     mov ah,0        ; Below zero is no good.
  163.     jmp spar21        ; Use zero (null).
  164. spar20: cmp ah,31        ; Is it a control char?
  165.     jle spar21        ; Yes, then OK.
  166.     mov ah,0        ; No, use null.
  167. spar21: mov trans.spadch,ah
  168.     mov ax,temp4
  169.     cmp al,5        ; Fewer than five pieces?
  170.     jge spar3
  171.     mov ah,dseol        ; Data not supplied by host, use default.
  172.     jmp spar31
  173. spar3:    mov ah,trans.seol
  174.     cmp ah,dseol        ; Is current value the default?
  175.     jne spar31        ; No, assume changed by user.
  176.     mov ah,4[bx]        ; Get the EOL char.
  177.     sub ah,' '
  178.     cmp ah,0
  179.     jge spar30        ; Cannot be negative.
  180.     mov ah,cr        ; If it is, use default of carriage return.
  181.     jmp spar31
  182. spar30: cmp ah,31        ; Is it a control char?
  183.     jle spar31        ; Yes, then use it.
  184.     mov ah,cr        ; Else, use the default.
  185. spar31: mov trans.seol,ah
  186.     mov ax,temp4
  187.     cmp al,6        ; Fewer than six pieces?
  188.     jge spar4
  189.     mov ah,dsquot        ; Data not supplied by host, use default.
  190.     jmp spar41
  191. spar4:    mov ah,trans.squote
  192.     cmp ah,dsquot        ; Is current value the default?
  193.     jne spar41        ; No, assume changed by user.
  194.     mov ah,5[bx]        ; Get the quote char.
  195.     cmp ah,' '              ; Less than a space?
  196.     jge spar40
  197.     mov ah,dsquot        ; Yes, use default.
  198.     jmp spar41
  199. spar40: cmp ah,'~'              ; Must also be less then a tilde.
  200.     jle spar41
  201.     mov ah,dsquot        ; Else, use default.
  202. spar41: mov trans.squote,ah
  203.     cmp al,7        ; Fewer than seven pieces? [21b begin]
  204.     jge spar5
  205.     mov trans.ebquot,'Y'    ; Data not supplied by host, use default.
  206.     jmp spar51
  207. spar5:    mov ah,6[bx]        ; Get other sides 8-bit quote request.
  208.     call doquo        ; And set quote char.  [21b end]
  209. spar51: cmp al,8        ; Fewer than eight pieces?
  210.     jge spar6
  211.     mov trans.chklen,1
  212.     jmp spar61
  213. spar6:    mov ah,inichk
  214.     mov trans.chklen,ah    ; Checksum length we really want to use.
  215.     mov ah,7[bx]        ; Get other sides checksum length.
  216.     call dochk        ; Determine what size to use.
  217. spar61: cmp al,9        ; Fewer than nine pieces?
  218.     jge spar7
  219.     mov rptq,0
  220.     ret
  221. spar7:    mov ah,8[bx]        ; Get other sides repeat count prefix.
  222.     mov ch,drpt
  223.     mov rptq,0
  224.     call dorpt
  225.     ret
  226. SPAR    ENDP
  227.  
  228. ; Set 8-bit quote character based on my capabilities and the other
  229. ; Kermit's request.   [21b]
  230.  
  231. DOQUO    PROC    NEAR
  232.     cmp trans.ebquot,'N'    ; Can I do 8-bit quoting at all?
  233.     je dq3            ; No - so forget it.
  234.     cmp trans.ebquot,'Y'    ; Can I do it if requested?
  235.     jne dq0         ; No - it's a must that I do it.
  236.     mov trans.ebquot,ah    ; Do whatever he wants.
  237.     jmp dq1
  238. dq0:    cmp ah,'Y'              ; I need quoting - can he do it?
  239.     je dq1            ; Yes - then all is settled.
  240.     cmp ah,'N'              ; No - then don't quote.
  241.     je dq3
  242.     cmp ah,trans.ebquot    ; Both need quoting - chars must match.
  243.     jne dq3
  244. dq1:    mov ah,trans.ebquot
  245.     cmp ah,'Y'              ; If Y or N, don't validate prefix.
  246.     je dq2
  247.     cmp ah,'N'
  248.     je dq2
  249.     call prechk        ; Is it in range 33-62, 96-126?
  250.      mov ah,'Y'             ; Failed, don't do quoting.
  251.      nop
  252.     cmp ah,trans.rquote    ; Same prefix?
  253.     je dq3            ; Not allowed, so don't do quoting.
  254.     cmp ah,trans.squote    ; Same prefix here?
  255.     je dq3            ; This is illegal too.
  256.     mov trans.ebquot,ah    ; Remember what we decided on.
  257. dq2:    ret
  258. dq3:    mov trans.ebquot,'N'    ; Quoting will not be done.
  259.     ret
  260. DOQUO    ENDP
  261.  
  262. ; Check if prefix in AH is in the proper range: 33-62, 96-126.
  263. ; RSKP if so else RETURN.
  264. prechk: cmp ah,33
  265.     jge prec0        ; It's above 33.
  266.     ret
  267. prec0:    cmp ah,62
  268.     jg prec1
  269.     jmp rskp        ; And below 62.  OK.
  270. prec1:    cmp ah,96
  271.     jge prec2        ; It's above 96.
  272.     ret
  273. prec2:    cmp ah,126
  274.     jg prec3
  275.     jmp rskp        ; And below 126.  OK.
  276. prec3:    ret
  277.  
  278. ; Set checksum length.
  279. dochk:    cmp ah,'1'              ; Must be 1, 2, or 3.
  280.     jl doc1
  281.     cmp ah,'3'
  282.     jle doc2
  283. doc1:    mov ah,'1'
  284. doc2:    sub ah,48        ; Don't want it printable.
  285.     cmp ah,trans.chklen    ; Do we want the same thing?
  286.     je dochk0        ; Yes, then we're done.
  287.     mov trans.chklen,1    ; No, use single character checksum.
  288. dochk0: ret            ; Just return for now.
  289.  
  290. ; Set repeat count quote character.  The one used must be different than
  291. ; the control and eight-bit quote characters.  Also, both sides must
  292. ; use the same character.
  293. dorpt:    call prechk        ; Is it in the valid range?
  294.      mov ah,0        ; No, don't use their value.
  295.      nop
  296.     cmp ah,trans.squote    ; Same as the control quote char?
  297.     je dorpt0        ; Yes, that's illegal, no repeats.
  298.     cmp ah,trans.rquote    ; How about this one?
  299.     je dorpt0        ; No good.
  300.     cmp ah,trans.ebquot    ; Same as eight bit quote char?
  301.     je dorpt0        ; Yes, that's illegal too, no repeats.
  302.     cmp ah,ch        ; Are we planning to use the same char?
  303.     jne dorpt0        ; No, that's no good either.
  304.     mov rptq,ch        ; Use repeat quote char now.
  305. dorpt0: ret
  306.  
  307. ;    Send command
  308.  
  309. SEND    PROC    NEAR
  310.     mov comand.cmcr,0    ; Filename must be specified.
  311.     mov difnam,0        ; Assume we'll use original filename.
  312.     mov flags.wldflg,0    ; Re-initialize every time.
  313.     mov ah,cmifi        ; Parse an input file spec.
  314.     mov dx,offset fcb    ; Give the address for the FCB.
  315.     mov bx,offset filhlp    ; Text of help message.
  316.     call comnd
  317.      jmp r            ;  Give up on bad parse.
  318.     cmp flags.wldflg,0FFH    ; Any wildcards seen?
  319.     je send1        ; Yes, get a confirm.
  320.     mov bx,offset sendas    ; See if want to send file under dif name.
  321.     mov dx,offset filmsg    ; In case user needs help.
  322.     mov ah,cmtxt
  323.     call comnd
  324.      jmp r
  325.     cmp ah,0        ; Different name supplied?
  326.     je send11        ; No - keep as it.
  327.     mov difnam,1        ; Yes - send different filename.
  328.     mov difsiz,ah        ; Remember length of new name.
  329.     jmp send11
  330. send1:    mov ah,cmcfm
  331.     call comnd        ; Get a confirm.
  332.      jmp r            ;  Didn't get a confirm.
  333. send11: mov flags.droflg,0    ; Reset flags from fn parsing. [21a]
  334.     mov flags.nmoflg,0    ; Reset flags from fn parsing. [21a]
  335.     mov ah,sfirst        ; Get the first file.
  336.     mov dx,offset fcb
  337.     int dos
  338.     cmp al,0FFH        ; Any found?
  339.     jne send12
  340.     cmp pack.state,'R'      ; was this from a remote GET?
  341.     jne sen11a        ; no, print error and continue
  342.     mov bx,offset remmsg1    ; else get error message
  343.     call errpack        ; go complain
  344.     jmp abort        ; and abort this
  345. sen11a: mov ah,prstr
  346.     mov dx,offset crlf
  347.     int dos
  348.     mov ah,prstr
  349.     mov dx,offset erms15
  350.     int dos
  351.     ret
  352. send12: cmp flags.wldflg,0    ; Any wildcards.      [7 start]
  353.     je send16        ; Nope, so no problem.
  354.     mov bx,offset fcb    ; Remember what FCB looked like.
  355.     mov di,offset cpfcb
  356.     mov cl,37        ; Size of FCB.
  357.     call fcbcpy
  358.     mov di,offset fcb+1    ; Copy filename from DTA to FCB.
  359.     mov bx,offset buff+1
  360.     mov cl,11
  361.     call fcbcpy                    ; [7 end]
  362. send16: call serini        ; Initialize serial port. [14]
  363.     mov pack.pktnum,0    ; Set the packet number to zero.
  364.     mov pack.numtry,0    ; Set the number of tries to zero.
  365.     mov pack.numpkt,0    ; Set the number of packets to zero.
  366.     mov pack.numrtr,0    ; Set the number of retries to zero.
  367.     mov pack.state,'S'      ; Set the state to receive initiate.
  368.     cmp flags.remflg,0    ; remote mode?
  369.     jne send2a        ; yes, continue below.
  370.     call init        ; Clear the line and initialize the buffers.
  371.     call rtpos        ; Position cursor.
  372.     mov ax,0
  373.     call nout        ; Write the number of retries.
  374.     call stpos        ; Print status of file transfer.
  375.     mov ah,prstr        ; Be informative.
  376.     mov dx,offset infms2
  377.     int dos
  378. send2:    cmp flags.remflg,0    ; remote mode?
  379.     jne send2a        ; yes, skip printing
  380.     call nppos        ; Number of packets sent.
  381.     mov ax,pack.numpkt
  382.     call nout        ; Write the packet number.
  383. send2a: cmp pack.state,'D'      ; Are we in the data send state?
  384.     jne send3
  385.     call sdata
  386.     jmp send2
  387. send3:    cmp pack.state,'F'      ; Are we in the file send state?
  388.     jne send4
  389.     call sfile        ; Call send file.
  390.     jmp send2
  391. send4:    cmp pack.state,'Z'      ; Are we in the EOF state?
  392.     jne send5
  393.     call seof
  394.     jmp send2
  395. send5:    cmp pack.state,'S'      ; Are we in the send initiate state?
  396.     jne send6
  397.     call sinit
  398.     jmp send2
  399. send6:    cmp pack.state,'B'      ; Are we in the eot state?
  400.     jne send7
  401.     call seot
  402.     jmp send2
  403. send7:    cmp pack.state,'C'      ; Are we in the send complete state?
  404.     jne send8
  405.     call serrst        ; Reset serial port.  [14]
  406.     cmp flags.remflg,0    ; remote mode?
  407.     jne send7a        ; yes, no printing.
  408.     cmp flags.cxzflg,0    ; completed normally?
  409.     jne send7b        ; no, don't bother with this
  410.     call perpos
  411.     mov ah,prstr
  412.     mov dx,offset infms7
  413.     int dos
  414. send7b: call stpos
  415.     mov ah,prstr
  416.     mov dx,offset infms3    ; Plus a little cuteness.
  417.     cmp flags.cxzflg,0    ; Completed or interrupted?
  418.     je snd71        ; Ended normally.
  419.     mov dx,offset infms6    ; Say was interrupted.
  420. snd71:    int dos         ; New label.
  421.     cmp flags.belflg,0    ; Bell desired? [17a]
  422.     je sendnb        ; [17a]
  423.     mov dx,offset ender    ; Ring them bells.   [4]
  424.     int dos
  425. sendnb: call clrmod
  426.     call rprpos
  427. send7a: jmp rskp
  428. send8:    call serrst        ; Reset serial port.  [14]
  429.     cmp flags.remflg,0    ; remote mode?
  430.     jne send9a        ; no, no printing.
  431.     call stpos
  432.     mov ah,prstr
  433.     mov dx,offset infms4    ; Plus a little cuteness.
  434.     int dos
  435.     cmp flags.belflg,0    ; Bell desired?  [17a]
  436.     je send9        ; No.  [17a]
  437.     mov dx,offset ender    ; Ring them bells.   [4]
  438.     int dos         ;  [4]
  439. send9:    call clrmod
  440.     call rprpos
  441. send9a: jmp rskp
  442. SEND    ENDP
  443.  
  444.  
  445. ;    Send routines
  446.  
  447. ;    Send initiate
  448.  
  449.  
  450. SINIT    PROC    NEAR
  451.     cmp pack.numtry,imxtry    ; Have we reached the maximum number of tries?
  452.     jl sinit2
  453.     call erpos
  454.     mov dx,offset erms14
  455.     mov ah,prstr
  456.     int dos         ; Print an error message.
  457.     mov bx,offset erms20
  458.     call errpack        ; Send error packet just in case.
  459.     jmp abort        ; Change the state to abort.
  460. sinit2: inc pack.numtry     ; Save the updated number of tries.
  461.     mov bx,offset data    ; Get a pointer to our data block.
  462.     call rpar        ; Set up the parameter information.
  463.     xchg ah,al
  464.     mov ah,0
  465.     mov pack.argbk1,ax    ; Save the number of arguments.
  466.     mov ax,pack.numpkt    ; Get the packet number.
  467.     mov pack.argblk,ax
  468.     mov ah,trans.chklen
  469.     mov curchk,ah        ; Store checksum length we want to use.
  470.     mov trans.chklen,1    ; Send init checksum is always 1 char.
  471.     mov ah,'S'              ; Send initiate packet.
  472.     call spack        ; Send the packet.
  473.      jmp abort
  474.     call rpack        ; Get a packet.
  475.      jmp sini23        ; Trashed packet don't change state, retry.
  476.     push ax
  477.     mov ah,curchk
  478.     mov trans.chklen,ah    ; Checksum length we want to use.
  479.     pop ax
  480.     cmp ah,'Y'              ; ACK?
  481.     jne sinit3        ; If not try next.
  482.     mov ax,pack.pktnum    ; Get the packet number.
  483.     cmp ax,pack.argblk    ; Is it the right packet number?
  484.     je sini22
  485.     ret            ; If not try again.
  486. sini22: inc ax            ; Increment the packet number.
  487.     and ax,3FH        ; Turn off the two high order bits.
  488.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  489.     inc pack.numpkt     ; Increment the number of packets.
  490.     mov ax,pack.argbk1    ; Get the number of pieces of data.
  491.     mov bx,offset data    ; Pointer to the data.
  492.     call spar        ; Read in the data.
  493.     call packlen        ; Get max send packet size. [21b]
  494.     mov ah,pack.numtry    ; Get the number of tries.
  495.     mov pack.oldtry,ah    ; Save it.
  496.     mov pack.numtry,0    ; Reset the number of tries.
  497.     mov pack.state,'F'      ; Set the state to file send.
  498.     call getfil        ; Open the file.
  499.      jmp abort        ;  Something is wrong, die.
  500.     ret
  501. sini23: mov ah,curchk        ; Restore desired checksum length.
  502.     mov trans.chklen,ah
  503.     call updrtr        ; Update retry counter.
  504.     ret            ; And retry.
  505. sinit3: cmp ah,'N'              ; NAK?
  506.     jne sinit4        ; If not see if its an error.
  507.     call rtpos        ; Position cursor.
  508.     inc pack.numrtr     ; Increment the number of retries
  509.     mov ax,pack.numrtr
  510.     call nout        ; Write the number of retries.
  511.     ret
  512. sinit4: cmp ah,'E'              ; Is it an error packet.
  513.     jne sinit5
  514.     call error
  515. sinit5: jmp abort
  516. SINIT    ENDP
  517.  
  518.  
  519.  
  520. ;    Send file header
  521.  
  522. SFILE    PROC    NEAR
  523.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  524.     jl sfile1
  525.     call erpos
  526.     mov dx,offset erms14
  527.     mov ah,prstr
  528.     int dos         ; Print an error message.
  529.     mov bx,offset erms21
  530.     call errpack        ; Send error packet just in case.
  531.     jmp abort        ; Change the state to abort.
  532. sfile1: inc pack.numtry     ; Increment it.
  533.     mov flags.cxzflg,0    ; Clear ^X,^Z flag.
  534.     mov datptr,offset data    ; Get a pointer to our data block.
  535.     mov bx,offset fcb+1        ; Pointer to file name in FCB.
  536.     mov fcbpt,bx        ; Save position in FCB.
  537.     mov cl,0        ; Counter for chars in file name.
  538.     mov ch,0        ; Counter for number of chars in FCB.
  539. sfil11: cmp ch,8H        ; Ninth char?
  540.     jne sfil12
  541.     mov ah,'.'
  542.     mov bx,datptr
  543.     mov [bx],ah        ; Put dot in data packet.
  544.     inc bx
  545.     mov datptr,bx        ; Save new position in data packet.
  546.     inc cl
  547. sfil12: inc ch
  548.     cmp ch,0CH        ; Twelve?
  549.     jns sfil13
  550.     mov bx,fcbpt
  551.     mov ah,[bx]        ; Get char of filename.
  552.     inc bx
  553.     mov fcbpt,bx        ; Save position in FCB.
  554.     cmp ah,'!'              ; Is it a good char?
  555.     jl sfil11        ; If not, get the next.
  556.     mov bx,datptr
  557.     mov [bx],ah        ; Put char in data buffer.
  558.     inc cl            ; Increment counter.
  559.     inc bx
  560.     mov datptr,bx        ; Save new position.
  561.     jmp sfil11        ; Get another char.
  562. sfil13: mov ch,0
  563.     cmp flags.remflg,0    ; remote mode?
  564.     jne sfil13a        ; yes, no printing.
  565.     push cx         ; Don't forget the size.
  566.     mov bx,datptr
  567.     mov ah,'$'
  568.     mov [bx],ah        ; Put dollar sign for printing.
  569.     call clrfln
  570.     mov ah,prstr
  571.     mov dx,offset data    ; Print file name.
  572.     int dos
  573.     pop cx
  574. sfil13a:cmp difnam,0        ; Sending file under different name.
  575.     je sfl13x        ; No, so don't give new name.
  576.     call newfn
  577. sfl13x: call doenc        ; Do encoding.
  578.     mov ax,pack.pktnum    ; Get the packet number.
  579.     mov pack.argblk,ax
  580.     mov ah,'F'              ; File header packet.
  581.     call spack        ; Send the packet.
  582.      jmp abort
  583.     call rpack        ; Get a packet.
  584.      jmp tryagn        ; Trashed packet don't change state, retry.
  585.     call dodec        ; Do all decoding.
  586.     cmp ah,'Y'              ; ACK?
  587.     jne sfile2        ; If not try next.
  588.     mov ax,pack.pktnum    ; Get the packet number.
  589.     cmp ax,pack.argblk
  590.     je sfil14
  591.     ret            ; If not hold out for the right one.
  592. sfil14: inc ax            ; Increment the packet number.
  593.     and ax,3FH        ; Turn off the two high order bits.
  594.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  595.     inc pack.numpkt     ; Increment the number of packets.
  596.     mov ah,pack.numtry    ; Get the number of tries.
  597.     mov pack.oldtry,ah    ; Save it.
  598.     mov pack.numtry,0    ; Reset the number of tries.
  599.  
  600. sfil15: mov ah,0        ; Get a zero.
  601.     mov bx,offset fcb
  602.     add bx,20H
  603.     mov [bx],ah        ; Set the record number to zero.
  604. ;    mov flags.eoflag,ah    ; Indicate not EOF.  (Done in GETFIL).
  605.     mov ah,0FFH
  606.     mov flags.filflg,ah    ; Indicate file buffer empty.
  607.     call gtchr
  608.      jmp sfil16        ; Error go see if its EOF.
  609.      nop
  610.     jmp sfil17        ; Got the chars, proceed.
  611. sfil16: cmp ah,0FFH        ; Is it EOF?
  612.     je sfl161
  613.     jmp abort        ; If not give up.
  614. sfl161: mov ah,'Z'              ; Set the state to EOF.
  615.     mov pack.state,ah
  616.     ret
  617. sfil17: mov siz,ax
  618.  
  619.     mov pack.state,'D'      ; Set the state to data send.
  620.     ret
  621. sfile2: cmp ah,'N'              ; NAK?
  622.     jne sfile3        ; Try if error packet.
  623.     call rtpos        ; Position cursor.
  624.     inc pack.numrtr     ; Increment the number of retries
  625.     mov ax,pack.numrtr
  626.     call nout        ; Write the number of retries.
  627.     mov ax,pack.pktnum    ; Get the present packet number.
  628.     inc ax            ; Increment.
  629.     and ax,03FH        ; Account for wraparound.  [18]
  630.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  631.     jz sfil14        ; Just as good as a ACK; go to the ACK code.
  632.     ret            ; If not go try again.
  633. sfile3: cmp ah,'E'              ; Is it an error packet.
  634.     jne sfile4
  635.     call error
  636. sfile4: jmp abort
  637. SFILE    ENDP
  638.  
  639.  
  640. ;    Send data
  641.  
  642. SDATA    PROC    NEAR
  643.     cmp flags.cxzflg,0    ; Have we seen ^X or ^Z?
  644.     je sdata2        ; Nope, just continue.
  645.     cmp flags.cxzflg,'C'    ; Stop it all? [25]
  646.     jne sdata1        ; It was a ^X or ^Z.
  647.     mov pack.state,'A'      ; It was a ^C -- abort [25]
  648.     ret
  649. sdata1: mov pack.state,'Z'      ; Else, abort sending the file.
  650.     ret
  651. sdata2: cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  652.     jl sdata3
  653.     call erpos
  654.     mov dx,offset erms14
  655.     mov ah,prstr
  656.     int dos         ; Print an error message.
  657.     mov bx,offset erms22
  658.     call errpack        ; Send error packet just in case.
  659.     jmp abort        ; Change the state to abort.
  660. sdata3: inc pack.numtry     ; Increment it.
  661.     mov datptr,offset data    ; Get a pointer to our data block.
  662.     mov chrptr,offset filbuf ; Pointer to chars to be sent.
  663.     mov cx,siz        ; number to transfer
  664.     mov si,chrptr        ; source of characters
  665.     mov di,datptr        ; destination
  666.     cmp flags.eofcz,0    ; stopping on ctl-z's?
  667.     jz sdata6        ; no, do blind copy
  668. sdata4: lodsb            ; get a byte
  669.     cmp al,'Z'-40H          ; is it a ctl-z?
  670.     je sdata5        ; yes, break loop
  671.     stosb            ; else copy it
  672.     loop sdata4        ; and keep going
  673. sdata5: mov ax,siz        ; size to send
  674.     sub ax,cx        ; minus actually sent...
  675.     jmp short sdata7
  676. sdata6: rep movsb        ; just copy data
  677.     mov ax,siz        ; this is how many were moved
  678. sdata7: mov pack.argbk1,ax
  679.     mov ax,pack.pktnum    ; Get the packet number.
  680.     mov pack.argblk,ax
  681.     mov ah,'D'              ; Data packet.
  682.     call spack        ; Send the packet.
  683.      jmp tryagn        ; if can't send it, retry before giving up
  684.     call rpack        ; Get a packet.
  685.      jmp tryagn        ; Trashed packet don't change state, retry.
  686.     call dodec        ; Do all decoding.
  687.     cmp ah,'Y'              ; ACK?
  688.     jne sdat14        ; If not try next.
  689.     mov ax,pack.pktnum    ; Get the packet number.
  690.     cmp ax,pack.argblk    ; Is it the right packet number?
  691.     jz sdata8
  692.     ret            ; If not hold out for the right one.
  693. sdata8: inc ax            ; Increment the packet number.
  694.     and ax,3FH        ; Turn off the two high order bits.
  695.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  696.     inc pack.numpkt     ; Increment the number of packets.
  697.     mov ah,pack.numtry    ; Get the number of tries.
  698.     mov pack.oldtry,ah    ; Save it.
  699.     mov pack.numtry,0    ; Reset the number of tries.
  700.     cmp pack.argbk1,1    ; Does the ACK contain data?
  701.     jne sdat11        ; Nope, so continue.
  702.     mov bx,offset data    ; If yes, check the data field.
  703.     mov ah,[bx]        ; Pick it up.
  704.     cmp ah,'X'              ; Other side requests ^X?
  705.     jne sdata9        ; Nope.
  706.     jmp sdat10        ; And leave.
  707. sdata9: cmp ah,'Z'              ; Other side requests ^Z?
  708.     jne sdat11        ; Nope.
  709. sdat10: mov flags.cxzflg,ah    ; Yes remember it.
  710.     mov pack.state,'Z'      ; Abort sending file(s).
  711.     ret
  712. sdat11: call gtchr
  713.      jmp sdat12        ; Error go see if its EOF.
  714.     mov siz,ax        ; Save the size of the data gotten.
  715.     ret
  716.  
  717. sdat12: cmp ah,0FFH        ; Is it EOF?
  718.     je sdat13
  719.     jmp abort        ; If not give up.
  720.  
  721. sdat13: mov pack.state,'Z'      ; Set the state to EOF.
  722.     ret
  723. sdat14: cmp ah,'N'              ; NAK?
  724.     jne sdat15        ; See if is an error packet.
  725.     call rtpos        ; Position cursor.
  726.     inc pack.numrtr     ; Increment the number of retries
  727.     mov ax,pack.numrtr
  728.     call nout        ; Write the number of retries.
  729.     mov ax,pack.pktnum    ; Get the present packet number.
  730.     inc ax            ; Increment.
  731.     and ax,03FH        ; Account for wraparound.  [18]
  732.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  733.     jz sdata8        ; Just as good as ACK; goto ACK code.
  734.     ret            ; If not go try again.
  735. sdat15: cmp ah,'E'              ; Is it an error packet.
  736.     jne sdat16
  737.     call error
  738. sdat16: jmp abort
  739. SDATA    ENDP
  740.  
  741.  
  742. ;    Send EOF
  743.  
  744. SEOF    PROC    NEAR
  745.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  746.     jl seof1
  747.     call erpos        ; Position cursor.
  748.     mov dx,offset erms14
  749.     mov ah,prstr
  750.     int dos         ; Print an error message.
  751.     mov bx,offset erms23
  752.     call errpack        ; Send error packet just in case.
  753.     jmp abort        ; Change the state to abort.
  754. seof1:    inc pack.numtry     ; Increment it.
  755.     mov ax,pack.pktnum    ; Get the packet number.
  756.     mov pack.argblk,ax
  757.     mov pack.argbk1,0    ; No data.
  758.     cmp flags.cxzflg,0    ; Seen a ^X or ^Z?
  759.     je seof11        ; Nope, send normal EOF packet.
  760.     mov bx,offset data    ; Get data area of packet.
  761.     mov ah,'D'              ; Use "D" for discard.
  762.     mov [bx],ah        ; And add it to the packet.
  763.     mov pack.argbk1,1    ; Set data size to 1.
  764. seof11: mov cx,pack.argbk1    ; Put size in CX.
  765.     call doenc        ; Encode the packet.
  766.     mov ah,'Z'              ; EOF packet.
  767.     call spack        ; Send the packet.
  768.      jmp abort
  769.     call rpack        ; Get a packet.
  770.      jmp tryagn        ;  Trashed packet don't change state, retry.
  771.     call dodec        ; Do decoding.
  772.     cmp ah,'Y'              ; ACK?
  773.     jne seof2        ; If not try next.
  774.     mov ax,pack.pktnum    ; Get the packet number.
  775.     cmp ax,pack.argblk    ; Is it the right packet number?
  776.     jz seof12
  777.     ret            ; If not hold out for the right one.
  778. seof12: inc ax            ; Increment the packet number.
  779.     and ax,3FH        ; Turn off the two high order bits.
  780.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  781.     inc pack.numpkt     ; Increment the number of packets.
  782.     mov ah,pack.numtry    ; Get the number of tries.
  783.     mov pack.oldtry,ah    ; Save it.
  784.     mov pack.numtry,0    ; Reset the number of tries.
  785.     mov ah,closf        ; Close the file.
  786.     mov dx,offset fcb
  787.     int dos
  788.     call gtnfil        ; Get the next file.
  789.      jmp seof13        ;  No more.
  790.     mov pack.state,'F'      ; Set the state to file send.
  791.     cmp flags.cxzflg,'X'    ; Control-X seen?
  792.     jne seof14
  793.     call cxmsg        ; Clear out the interrupt msg.
  794. seof14: mov flags.cxzflg,0    ; Reset the flag.
  795.     ret
  796. seof13: mov pack.state,'B'      ; Set the state to EOT.
  797.     ret
  798. seof2:    cmp ah,'N'              ; NAK?
  799.     jne seof3        ; Try and see if its an error packet.
  800.     call rtpos        ; Position cursor.
  801.     inc pack.numrtr     ; Increment the number of retries
  802.     mov ax,pack.numrtr
  803.     call nout        ; Write the number of retries.
  804.     mov ax,pack.pktnum    ; Get the present packet number.
  805.     inc ax            ; Increment.
  806.     and ax,03FH        ; Account for wraparound.  [18]
  807.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  808.     jz seof12        ; Just as good as a ACK; go to the ACK code.
  809.     ret            ; If not go try again.
  810. seof3:    cmp ah,'E'              ; Is it an error packet?
  811.     jne seof4
  812.     call error
  813. seof4:    jmp abort
  814. SEOF    ENDP
  815.  
  816.  
  817. ;    Send EOT
  818.  
  819. SEOT    PROC    NEAR
  820.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  821.     jl seot1
  822.     call erpos           ; Position cursor.
  823.     mov dx,offset erms14
  824.     mov ah,prstr
  825.     int dos         ; Print an error message.
  826.     mov bx,offset erms24
  827.     call errpack        ; Send error packet just in case.
  828.     jmp abort        ; Change the state to abort.
  829. seot1:    inc pack.numtry     ; Increment it.
  830.     mov ax,pack.pktnum    ; Get the packet number.
  831.     mov pack.argblk,ax
  832.     mov pack.argbk1,0    ; No data.
  833.     mov cx,pack.argbk1
  834.     call doenc        ; Encode packet.
  835.     mov ah,'B'              ; EOF packet.
  836.     call spack        ; Send the packet.
  837.      jmp abort
  838.     call rpack        ; Get a packet.
  839.      jmp tryagn        ; Trashed packet don't change state, retry.
  840.     call dodec        ; Decode packet.
  841.     cmp ah,'Y'              ; ACK?
  842.     jne seot2        ; If not try next.
  843.     mov ax,pack.pktnum    ; Get the packet number.
  844.     cmp ax,pack.argblk    ; Is it the right packet number?
  845.     jz seot12
  846.     ret            ; If not hold out for the right one.
  847. seot12: inc ax            ; Increment the packet number.
  848.     and ax,3FH        ; Turn off the two high order bits.
  849.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  850.     inc pack.numpkt     ; Increment the number of packets.
  851.     mov ah,pack.numtry    ; Get the number of tries.
  852.     mov pack.oldtry,ah    ; Save it.
  853.     mov pack.numtry,0    ; Reset the number of tries.
  854.     mov pack.state,'C'      ; Set the state to file send.
  855.     ret
  856. seot2:    cmp ah,'N'              ; NAK?
  857.     jne seot3        ; Is it error.
  858.     call rtpos        ; Position cursor.
  859.     inc pack.numrtr     ; Increment the number of retries
  860.     mov ax,pack.numrtr
  861.     call nout        ; Write the number of retries.
  862.     mov ax,pack.pktnum    ; Get the present packet number.
  863.     inc ax            ; Increment.
  864.     and ax,03FH        ; Account for wraparound.  [18]
  865.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  866.     jz seot12        ; Just as good as a ACK; go to the ACK code.
  867.     ret            ; If not go try again.
  868. seot3:    cmp ah,'E'              ; Is it an error packet.
  869.     jne seot4
  870.     call error
  871. seot4:    jmp abort
  872. SEOT    ENDP
  873.  
  874. tryagn: call updrtr
  875.     ret
  876.  
  877. newfn:    mov ah,prstr
  878.     mov dx,offset asmsg
  879.     int dos
  880.     mov ah,dconio
  881.     mov si,offset sendas    ; Buffer where the name is.
  882.     mov di,offset data
  883.     mov ch,0
  884.     mov cl,difsiz        ; Length of name.
  885. newf0:    lodsb            ; Get a char.
  886.     cmp al,61H
  887.     jb newf1        ; Leave alone if less than 'a'?
  888.     cmp al,7AH
  889.     ja newf1        ; Leave alone if over 'z'.
  890.     sub al,20H        ; Uppercase the letters.
  891. newf1:    stosb
  892.     mov dl,al
  893.     cmp flags.remflg,0    ; should we print?
  894.     jne newf2        ; no, we're in remote mode.
  895.     int dos         ; Print them.
  896. newf2:    loop newf0
  897.     mov ch,0
  898.     mov cl,difsiz        ; Reset the length field.
  899.     ret
  900.  
  901. ; Do encoding.    Expectx CX to be the data size.
  902. doenc:    jcxz doen0
  903.     mov chrcnt,cx        ; Number of chars in filename.
  904.     mov bx,offset data    ; Source of data.
  905.     mov bufpnt,bx
  906.     mov bx,offset nulref    ; Null routine for refilling buffer.
  907.     mov ah,rptq
  908.     mov origr,ah        ; Save repeat prefix here.
  909.     mov rptct,1        ; Number of times char is repeated.
  910.     mov rptval,0        ; Value of repeated char.
  911.     call encode        ; Make a packet with size in AX.
  912.      nop
  913.      nop
  914.      nop
  915.     mov pack.argbk1,ax    ; Save number of char in filename.
  916.     mov cx,ax
  917.     call movpak        ; Move to data part of packet.
  918. doen0:    ret
  919.  
  920. ; CX is set before this is called.
  921. movpak: push es
  922.     mov ax,ds
  923.     mov es,ax
  924.     mov si,offset filbuf    ; Move from here
  925.     mov di,offset data    ; to here
  926.     repne movsb
  927.     pop es
  928.     ret
  929.  
  930. ; Do decoding.
  931. dodec:    cmp pack.argbk1,0
  932.     je dodc0
  933.     push ax         ; Save packet size.
  934.     mov cx,pack.argbk1    ; Size of data.
  935.     mov bx,offset data    ; Address of data.
  936.     mov ax,offset nulr    ; Routine to dump buffer (null routine).
  937.     mov bufpnt,offset decbuf  ; Where to put output.
  938.     mov chrcnt,80H        ; Buffer size.
  939.     call decode
  940.      nop
  941.      nop
  942.      nop
  943.     call decmov        ; Move decoded data back to "data" buffer.
  944.     pop ax
  945. dodc0:    ret
  946.  
  947. ; Move decoded data from decode buffer back to "data".
  948. decmov: push si
  949.     push di
  950.     push es
  951.     mov ax,ds
  952.     mov es,ax
  953.     mov cx,bufpnt        ; Last char we added.
  954.     sub cx,offset decbuf    ; Get actual number of characters.
  955.     mov pack.argbk1,cx    ; Remember size of real data.
  956.     lea si,decbuf        ; Data is here.
  957.     lea di,data        ; Move to here.
  958.     repne movsb        ; Copy the data.
  959.     pop es
  960.     pop di
  961.     pop si
  962.     ret
  963.  
  964. ;    Abort
  965.  
  966. ABORT    PROC    NEAR
  967.     mov pack.state,'A'      ; Otherwise abort.
  968.     ret
  969. ABORT    ENDP
  970.  
  971. ; This is where we go if we get an error packet.  A call to ERROR
  972. ; positions the cursor and prints the message.    A call to ERROR1
  973. ; just prints a CRLF and then the message.  [8]
  974.  
  975. ERROR    PROC    NEAR
  976.     mov pack.state,'A'      ; Set the state to abort.
  977.     call erpos        ; Position the cursor.
  978.     jmp error2
  979. error1: mov ah,prstr
  980.     mov dx,offset crlf
  981.     int dos
  982. error2: mov bx,pack.argbk1    ; Get the length of the data.
  983.     add bx,offset data    ; Get to the end of the string.
  984.     mov ah,'$'              ; Put a dollar sign at the end.
  985.     mov [bx],ah
  986.     mov ah,prstr        ; Print the error message.
  987.     mov dx,offset data
  988.     int dos
  989.     ret
  990. ERROR    ENDP
  991.  
  992. ; Set the maximum data packet size. [21b]
  993.  
  994. PACKLEN PROC    NEAR
  995.     mov ah,trans.spsiz    ; Maximum send packet size.
  996.     sub ah,4        ; Size minus control info.
  997.     sub ah,trans.chklen    ; And minus checksum chars.
  998.     sub ah,2        ; Leave room at end: 2 for possible #X.
  999.     cmp trans.ebquot,'N'    ; Doing 8-bit quoting?
  1000.     je pack0        ; Nope so we've got our size.
  1001.     cmp trans.ebquot,'Y'
  1002.     je pack0        ; Not doing it in this case either.
  1003.     sub ah,1        ; Another 1 for 8th-bit quoting.
  1004. pack0:    cmp rptq,0        ; Doing repeat character quoting?
  1005.     je pack1        ; Nope, so that's all for now.
  1006.     sub ah,2        ; Another 2 for repeat prefix.
  1007. pack1:    mov trans.maxdat,ah    ; Save max length for data field.
  1008.     ret
  1009. PACKLEN ENDP
  1010.  
  1011.  ; Print the number in AX on the screen in decimal rather that hex. [19a]
  1012.  
  1013. NOUT    PROC    NEAR
  1014.     cmp flags.xflg,1    ; Writing to screen? [21c]
  1015.     je nout1        ; Yes, just leave. [21c]
  1016.     push ax
  1017.     push dx
  1018.     mov temp,10        ; Divide quotient by 10.
  1019. ;    cwd            ; Convert word to doubleword.
  1020.     mov dx,0        ; High order word should be zero.
  1021.     div temp        ; AX <-- Quo, DX <-- Rem.
  1022.     cmp ax,0        ; Are we done?
  1023.     jz nout0        ; Yes.
  1024.     call nout        ; If not, then recurse.
  1025. nout0:    add dl,'0'              ; Make it printable.
  1026.     mov temp,ax
  1027.     mov ah,conout
  1028.     int dos
  1029.     mov ax,temp
  1030.     pop dx
  1031.     pop ax
  1032. nout1:    ret            ; We're done. [21c]
  1033. NOUT    ENDP
  1034.  
  1035. ; Jumping to this location is like retskp.  It assumes the instruction
  1036. ;   after the call is a jmp addr.
  1037.  
  1038. RSKP    PROC    NEAR
  1039.     pop bp
  1040.     add bp,3
  1041.     push bp
  1042.     ret
  1043. RSKP    ENDP
  1044.  
  1045. ; Jumping here is the same as a ret.
  1046.  
  1047. R    PROC    NEAR
  1048.     ret
  1049. R    ENDP
  1050.  
  1051. code    ends
  1052.     end
  1053.