home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / cpm86 / c86pro.a86 < prev    next >
Text File  |  2011-08-09  |  43KB  |  1,443 lines

  1. ; C86PRO.A86
  2. ; * * * * * * * * * * * * * * * * version 3.0 * * ** * * * * * * * * * * * *
  3. ; Allows packet echo - CGL
  4. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  5. ; [34c] Add sorted wildcard SENDs with initial filename
  6. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  7. ; [31] Fix display on file renaming.
  8. ; RonB, 05/05/84
  9. ; [30c] Isolate ANSI escape sequences for machine independence.
  10. ; [29g]  Add 8th bit quoting.
  11. ; [29d]  Enlarge receive buffer and check for packet overruns.
  12. ; [29b]  Add TAKE processing (close command file when aborting).
  13. ; [29a]  Send error packet when aborting.
  14. ; RonB, 04/08/84
  15. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  16. ; [28b]  Make file-not-found error more informative (include filename).
  17. ; [28a]  Clear attribute bits from filename before sending
  18. ; RonB, 03/27/84
  19. ; [25] - make KERCMD more modular by eliminating some use of text
  20. ; strings by other modules (KERPRO, KERSYS), and moving some
  21. ; parsing into KERCMD (ESCAPE and EOLSET logic in KERSYS)
  22. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  23. ;  [21a] Add timeout enable/disable
  24. ; RonB,03/05/84
  25. ;  [20a] Fix version & send/receive header
  26. ;  [20e] Clean up environment better before rebooting in KABORT
  27. ; RonB,03/02/84
  28. ;  [19f] Add ^X/^Z file interruption - adapted from PC Kermit V1.20
  29. ;  Put in Help line for above.
  30. ;  [19g] Put in timeouts.
  31. ; R. Garland 2/84
  32. ; * * * * * * * * * * * * * * *  version 2.1  * * * * * * * * * * * * * * *
  33. ;  [14] Fix nout to print decimal.
  34. ; RonB,12/28/83
  35. ;  [13] Use control-Z's for filler in partial sectors instead of nulls.
  36. ; RonB,12/27/83
  37. ;  [12] Allow user abort from the keyboard in the send and receive routines.
  38. ; RonB,12/27/83
  39. ;  [9] Fix filename parsing, and add wildcard ability.
  40. ; RonB,12/26/83
  41. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  42. ; This module contains the routines that actually implement the Kermit
  43. ; protocol.
  44.  
  45. ; Packet definitions.
  46.  
  47. maxpkt equ '~'-' '+2O ;Maximum size of a packet.
  48. maxtry equ 05O  ;Default number of retries on a packet.
  49. imxtry equ 20O  ;Default number of retries send initiate.
  50. drpsiz equ 5EH  ;Default receive packet size.
  51. dspsiz equ 20H  ;Default send packet size.
  52. dstime equ 0AH  ;Default send time out interval.
  53. drtime equ 05H  ;Default receive time out interval.
  54. dspad equ 00H  ;Default send padding.
  55. drpad equ 00H  ;Default receive padding.
  56. dspadc equ 00H  ;Default send padding char.
  57. drpadc equ 00H  ;Default receive padding char.
  58. dseol equ cr  ;Default send EOL char.
  59. dreol equ cr  ;Default receive EOL char.
  60. dsquot equ '#'  ;Default send quote char.
  61. drquot equ '#'  ;Default receive quote char.
  62. dqbin equ '&'  ;Default 8th-bit quote char. ;[29g]
  63.  
  64. bufsiz equ 80H  ;Size of DMA.
  65.  
  66. ; A few control characters
  67.  
  68. ctlc equ 03H  ;[19f]
  69. ctlx equ 18H  ;[19f]
  70. ctlz equ 1AH  ;[19f]
  71.  
  72.  DSEG $
  73.  
  74. ; Program storage.
  75.  
  76. belflg db 1  ;Use bell.
  77. incmod db 0  ;Insert Character mode.
  78. hierr db 0  ;Non-ascii char (non-zero if yes).
  79. parflg db defpar  ;Parity flag (default none.)
  80. flwflg db 0  ;File warning flag (default off).
  81. ibmflg db 0  ;IBM flag (default off).
  82. vmeflg db 0  ;VME flag (default off);
  83. incnt dw 0  ;Number of chars read in from port.
  84. pktptr dw 0  ;Position in receive packet.
  85. spsiz db dspsiz  ;Send packet size.
  86. rpsiz db drpsiz  ;Receive packet size.
  87. stime db dstime  ;Send time out.
  88. rtime db drtime  ;Receive time out.
  89. spad db dspad  ;Send padding.
  90. rpad db drpad  ;Receive padding.
  91. spadch db dspadc  ;Send padding char.
  92. rpadch db drpadc  ;Receive padding char.
  93. seol db dseol  ;Send EOL char.
  94. reol db dreol  ;Receive EOL char.
  95. squote db dsquot  ;Send quote char.
  96. rquote db drquot  ;Receive quote char.
  97. ebquot db 'Y'  ;Send 8th-bit quote char.  ;[29g]
  98. pktnum dw 0  ;Packet number.
  99. numpkt dw 0  ;Total number of packets sent.
  100. numrtr dw 0  ;Total number of retries.
  101. numtry db 0  ;Number of tries on this packet.
  102. oldtry db 0  ;Number of tries on previous packet.
  103. cxzflg db 0  ;[19f] flag for ^X/^Z file interruption
  104. state db 0  ;Present state of the automaton.
  105. packet rb 4  ;Packet (data is part of it).
  106. data rb 60H  ;Data and checksum field of packet. ;[29d]
  107. recpkt rb 100H  ;Receive packet storage.  ;[29d]
  108. temp dw 0
  109. argblk dw 0  ;For subroutine arguments.
  110. argbk1 dw 0
  111. argbk2 dw 0
  112. argbk3 dw 0
  113. tickst dw 10*(7470/clckrt);[19g] "magic" formula for loops/tick
  114.     ;[19g] CLCKRT is the system clock rate ...
  115.     ;[19g] ... defined in KERIO
  116. ticklp dw 0  ;[19g] Dynamic loop count for tick
  117. tickct db dstime  ;[19g] # ticks for timeout to occur
  118. tmodon db 0  ;[19g] flag for time-out message
  119.  
  120.  CSEG $
  121.  
  122. ; Check for a user abort or interrupt during the send or receive ;[12] begin
  123. ;   modified by Rg.
  124. kabort:
  125.  call dbinst  ;Check if a char has been typed.
  126.   jmp r  ;[19f]  Merrily return.
  127.  call dbin  ;Get the character.
  128.  cmp al, ctlc ;Abort if control-C [19f]
  129.  je kabrt2
  130.  cmp al, ctlx ;[19f] Is it control-x ?
  131.  je kabrta  ;[19f] yes
  132.  cmp al, ctlz ;[19f] control-z ?
  133.  jne kabrtb  ;[19f] no
  134. kabrta: add al, 100O ;[19f] make into 'X' or 'Z'
  135.  mov cxzflg, al ;[19f] set the flag
  136.  call intmsg  ;[19f] reassure the user
  137.  ret   ;[19f] return
  138. kabrtb: cmp al, cr  ;if <cr> do a timeout  ;[29a] begin
  139.  jne kabrtc
  140.  pop bx  ;return of kabort
  141.  pop bx  ;receive packet pointer
  142.     ;... next is return of inpkt
  143.  ret   ;return to timeout routine ;[29a] end
  144. kabrtc: cmp al, escchr ;or the escape character followed by 'C'.
  145.  jne kabrt9
  146.  mov cx, 1000 ;Only wait just so long for the next char.
  147. kabrt1: push cx
  148.  call dbin
  149.  pop cx
  150.  cmp al, 0
  151.  loope kabrt1
  152.  cmp al, ctlc ;Control-C also works here. [19f]
  153.  je kabrt2
  154.  and al, 137O ;Capitalize it.
  155.  cmp al, 'C'  ;If not a 'C' then continue.
  156.  jne kabrt9
  157. kabrt2: cmp tkflg, 0 ;Close any command file in use ;[29b] begin
  158.  je kabrt3
  159.  call tkcls      ;[29b] end
  160. kabrt3: call binst  ;Clear out extraneous input ;[29a] begin
  161.   jmp kabrt4 ;If none, go abort this transmission.
  162.  call bin
  163.  jmps kabrt2
  164. kabrt4: pop bx  ;return from kabort
  165.  pop bx  ;receive packet pointer
  166.  pop bx  ;return from inpkt
  167.  pop bx  ;return from rpack
  168.     ;... next is return from r??? to read
  169.  mov dx, offset erms21 ;Print '* aborted *' message.
  170.  jmp fatal      ;[29a] end
  171. kabrt9: mov dl, bell ;beep    [19f]
  172.  call dbout  ;    [19f]
  173.  ret   ;return no error  [19f]
  174.  
  175.  
  176. ; Send the generic finish command to the remote Kermit.
  177.  
  178. finsen: mov ah, 'F'  ;Ask for the finish command.
  179.  call gensen
  180.  ret
  181.  
  182.  
  183. ; Send the generic logout command to the remote Kermit.
  184.  
  185. byesen: mov ah, 'L'  ;Ask for the logout command.
  186.  call gensen
  187.  ret
  188.  
  189.  
  190. ; This procedure processes all the generic single packet sends.
  191.  
  192. gensen: mov temp, ax ;Save the specific generic command.
  193.  mov numtry, 0 ;Initialize count.
  194.  call cfibf  ;Clear out input buffer of extra NAKs.
  195. fins1: mov ah, numtry
  196.  cmp ah, maxtry ;Too many times?
  197.  js fins3  ;Nope, try it.
  198. fins2: mov dx, offset erms18
  199.  call tcrmsg
  200.  ret
  201.  
  202. fins3: inc numtry  ;Increment number of tries.
  203.  mov argblk, 0 ;Packet number zero.
  204.  mov argbk1, 1 ;One piece of data.
  205.  mov bx, offset data
  206.  mov ax, temp ;Get the generic command.
  207.  mov [bx], ah ;Finish running Kermit.
  208.  mov ah, 'G'  ;Generic command packet.
  209.  call spack
  210.   jmp fins2 ;Tell user and die.
  211.  call rpack  ;Get ACK.
  212.   jmp fins1  ;Go try again.
  213.  cmp ah, 'Y'  ;Got an ACK?
  214.  jnz fins4
  215.  ret   ;Yes, then we're done.
  216. fins4: cmp ah, 'E'  ;Error packet?
  217.  jnz fins1  ;Try sending it again.
  218.  call error1
  219.  ret
  220.  
  221. ; Packet routines
  222.  
  223. ; Send_Packet
  224. ; This routine assembles a packet from the arguments given and sends it
  225. ; to the host.
  226. ;
  227. ; Expects the following:
  228. ; AH     - Type of packet (D,Y,N,S,R,E,F,Z,T)
  229. ; ARGBLK - Packet sequence number
  230. ; ARGBK1 - Number of data characters
  231. ;
  232. ; Returns: +1 always
  233.  
  234. spack: push ax  ;Save the packet type.
  235.  mov bx, offset packet ;Get address of the send packet.
  236.  mov ah, soh  ;Get the start of header char.
  237.  mov [bx], ah ;Put in the packet.
  238.  inc bx  ;Point to next char.
  239.  mov ax, argbk1 ;Get the number of data chars.
  240.  xchg ah, al
  241.  add ah, ' '+3 ;Real packet character count made printable.
  242.  mov [bx], ah ;Put in the packet.
  243.  inc bx  ;Point to next char.
  244.  mov cl, ah  ;Start the checksum.
  245.  mov ax, argblk ;Get the packet number.
  246.  xchg ah, al
  247.  add ah, ' '  ;Add a space so the number is printable.
  248.  mov [bx], ah ;Put in the packet.
  249.  inc bx  ;Point to next char.
  250.  add cl, ah  ;Add the packet number to the checksum.
  251.  pop ax  ;Get the packet type.
  252.  mov [bx], ah ;Put in the packet.
  253.  inc bx  ;Point to next char.
  254.  add cl, ah  ;Add the type to the checksum.
  255.  mov dx, argbk1 ;Get the packet size.
  256. spack2: cmp dx, 0  ;Are there any chars of data?
  257.   jz spack3  ; No, finish up.
  258.  dec dx  ;Decrement the char count.
  259.  mov ah, [bx] ;Get the next char.
  260.  inc bx  ;Point to next char.
  261.  add cl, ah  ;Add the char to the checksum.
  262.  jmp spack2  ;Go try again.
  263. spack3:
  264. sp3x: mov ah, cl  ;Get the character total.
  265.  mov ch, cl  ;Save here too (need 'cl' for shift).
  266.  and ah, 0C0H ;Turn off all but the two high order bits.
  267.  mov cl, 6
  268.  shr ah, cl  ;Shift them into the low order position.
  269.  mov cl, ch
  270.  add ah, cl  ;Add it to the old bits.
  271.  and ah, 3FH  ;Turn off the two high order bits.  (MOD 64)
  272.  add ah, ' '  ;Add a space so the number is printable.
  273.  mov [bx], ah ;Put in the packet.
  274.  inc bx  ;Point to next char.
  275.  mov ah, seol ;Get the EOL the other host wants.
  276.  mov [bx], ah ;Put in the packet.
  277.  inc bx  ;Point to next char.
  278.  mov ah, 0  ;Get a null.
  279.  mov [bx], ah ;Put in the packet.
  280.  cmp debug, 0 ;debug mode.
  281.  je spack4
  282.  inc bx
  283.  mov ah, '$'
  284.  mov [bx], ah
  285.  mov dx, offset scrsp ;Print string to move cursor.
  286.  call poscur      ;[30c] begin
  287.  call clreol  ;Clear current line
  288.  mov dl, lf  ;  and next one
  289.  call bout
  290.  call clreol
  291.  mov dx, offset scrsp ;Print string to move cursor.
  292.  call poscur      ;[30c] end
  293.  mov dx, offset spmes
  294.  call tmsg
  295.  mov dx, offset packet
  296.  call tmsg  ;Debug end.
  297. spack4: call outpkt  ;Call the system dependent routine.
  298.  jmp rskp
  299.  
  300.  
  301. ; Write out a packet.
  302.  
  303. outpkt: mov dh, spad ;Get the number of padding chars.
  304. outpk2: dec dh
  305.  cmp dh, 0
  306.  jl outpk3  ;If none left proceed.
  307.  mov al, spadch ;Get the padding char.
  308.  call prtout  ;Output it.
  309.  jmp outpk2
  310. outpk3: mov bx, offset packet ;Point to the packet.
  311. outlup: mov al, [bx] ;Get the next character.
  312.  cmp al, 0  ;Is it a null?
  313.  jnz outlp2
  314.  ret
  315. outlp2: call prtout  ;Output the character.
  316.  inc bx  ;Increment the char pointer.
  317.  jmp outlup
  318.  
  319.  
  320. ; Receive_Packet
  321. ; This routine waits for a packet arrive from the host.
  322.  
  323. rpack: call inpkt  ;Read up to a carriage return.
  324.   jmp rptimo  ; User timed us out.
  325. rpack0: call getchr  ;Get a character.
  326.   jmp rpack  ; Hit the carriage return, go try again.
  327.  cmp ah, soh  ;Is the char the start of header char?
  328.   jne rpack0  ; No, go until it is.
  329. rpack1: call getchr  ;Get a character.
  330.   jmp r  ; Hit the carriage return, return bad.
  331.  cmp ah, soh  ;Is the char the start of header char?
  332.   jz rpack1  ; Yes, then go start over.
  333.  mov cl, ah  ;Start the checksum.
  334.  sub ah, ' '+3 ;Get the real data count.
  335.  mov dh, ah  ;Save it for later.
  336.  mov al, ah  ;Swap halves.
  337.  mov ah, 0
  338.  mov argbk1, ax ;Save the data count.
  339.  call getchr  ;Get a character.
  340.   jmp r  ; Hit the carriage return, return bad.
  341.  cmp ah, soh  ;Is the char the start of header char?
  342.   jz rpack1  ; Yes, then go start over.
  343.  add cl, ah  ;Add it to the checksum.
  344.  sub ah, ' '  ;Get the real packet number.
  345.  mov al, ah  ;Swap halves.
  346.  mov ah, 0
  347.  mov argblk, ax ;Save the packet number.
  348.  call getchr  ;Get a character.
  349.   jmp r  ; Hit the carriage return, return bad.
  350.  cmp ah, soh  ;Is the char the start of header char?
  351.   jz rpack1  ; Yes, then go start over.
  352.  mov temp, ax ;Save the message type.
  353.  ; CGL mod for VME packet echo
  354.  cmp ah, packet + 3       ; compare with the type of this received one
  355.  je rpack           ; if the same go back and get next
  356.  ; end of CGL mod
  357.  add cl, ah  ;Add it to the checksum.
  358.  mov bx, offset data ;Point to the data buffer.
  359. rpack2: dec dh  ;Any data characters?
  360.   js rpack3  ; If not go get the checksum.
  361.  call getchr  ;Get a character.
  362.   jmp r  ; Hit the carriage return, return bad.
  363.  cmp ah, soh  ;Is the char the start of header char?
  364.   jz rpack1  ; Yes, then go start over.
  365.  mov [bx], ah ;Put the char into the packet.
  366.  inc bx  ;Point to the next character.
  367.  add cl, ah  ;Add it to the checksum.
  368.  jmp rpack2  ;Go get another.
  369. rpack3: call getchr  ;Get a character.
  370.   jmp r  ; Hit the carriage return, return bad.
  371.  cmp ah, soh  ;Is the char the start of header char?
  372.   jz rpack1  ; Yes, then go start over.
  373.  sub ah, ' '  ;Turn the char back into a number.
  374.  mov dh, cl  ;Get the character total.
  375.  and dh, 0C0H ;Turn off all but the two high order bits.
  376.  mov ch, cl
  377.  mov cl, 6
  378.  shr dh, cl  ;Shift them into the low order position.
  379.  mov cl, ch
  380.  add dh, cl  ;Add it to the old bits.
  381.  and dh, 3FH  ;Turn off the two high order bits.  (MOD 64)
  382.  cmp dh, ah  ;Are they equal?
  383.   jz rpack4  ; If so finish up.
  384.  call cfibf  ;Clear out any other characters on the line.
  385.  ret   ;And return failure.
  386.  
  387. rpack4: mov ah, 0
  388.  mov [bx], ah ;Put a null at the end of the data.
  389.  mov ax, temp ;Get the type.
  390.  call cfibf  ;Clear out any other characters on the line.
  391.  jmp rskp
  392.  
  393. rptimo: call cfibf  ;On a time out clear out any remaining chars.
  394.  ret
  395.  
  396. inpkt: mov bx, offset recpkt ;Point to the beginning of the packet.
  397.  mov incnt, 0
  398. inpkt2: mov al, stime ;[19g] set up timeout loop.
  399.  mov tickct, al ;[19g]
  400.  mov ax, tickst ;[19g] "magic" number loops/tick
  401.  mov ticklp, ax ;[19g]
  402. inpkta: cmp tmrflg, 0 ;Is timeout disabled?   ;[21a]
  403.  je inpktb  ;  If so, skip tick routine  ;[21a]
  404.  dec ticklp  ;[19g]
  405.  cmp ticklp, 0 ;[19g] done this tick?
  406.  jne inpktb  ;[19g] not yet
  407.  mov ax, tickst ;[19g] reload loop count
  408.  mov ticklp, ax ;[19g]
  409.  call ticmsg  ;[19g] beep for debugging
  410.  dec tickct  ;[19g]
  411.  cmp tickct, 0 ;[19g] timed-out?
  412.  jne inpktb  ;[19g] not yet
  413.  call tmomsg  ;[19g] alert user
  414.  jmp inpkt9  ;[19g] go time-out
  415. inpktb: push bx  ;[19g][12] bx gets trashed by kb status check.
  416.  call kabort  ;[19g] Doesn't return if user aborted.
  417.  pop bx  ;[19g]
  418.  call instat  ;Any char there?
  419.   jmp inpkta  ; Go until there is one.
  420.  call inchr  ;Get the character.
  421.  mov [bx], al ;Put the char in the packet.
  422.  inc bx
  423.  inc incnt
  424.  cmp incnt, length recpkt ;Have we overrun the input buffer? ;[29d]
  425.  jb inpktc
  426.  jmp inpkt  ;If so, just clear and restart
  427. inpktc: cmp al, reol ;Is it the EOL char?  ;[29d] end
  428.  jne inpkt2  ;If not loop for another.
  429.  cmp incnt, 1 ;Ignore bare CR.
  430.  jne inpkt6
  431.  jmp  inpkt
  432. inpkt6: cmp ibmflg, 0 ;Is this the (dumb) IBM mainframe?
  433.  jz inpkt4  ;If not then proceed.
  434. inpkt5: cmp state, 'S' ;Check if this is the Send-Init packet.
  435.  jz inpkt4  ;If so don't wait for the XON.
  436. inpkt3: call instat  ;Wait for the turn around char.
  437.   jmp inpkt3
  438.  call inchr
  439.  cmp al, xon  ;Is it the IBM turn around character?
  440.  jne inpkt3  ;If not, go until it is.
  441. inpkt4: cmp debug, 0
  442.  jz inpkt7  ;If not debugging don't print the packet.
  443.  mov al, '$'  ;Get a dollar sign.
  444.  mov [bx], al ;Put in the packet.
  445.  inc bx  ;Point to next char.
  446.  mov dx, offset scrrp ;Print the packet.
  447.  call poscur      ;[30c] begin
  448.  call clreol  ;Clear current line
  449.  mov dl, lf  ;  and next one
  450.  call bout
  451.  call clreol
  452.  mov dx, offset scrrp ;Print string to move cursor.
  453.  call poscur      ;[30c] end
  454.  mov dx, offset rpmes
  455.  call tmsg
  456.  mov dx, offset recpkt
  457.  call tmsg
  458.  
  459. inpkt7: mov bx, offset recpkt
  460.  mov pktptr, bx ;Save the packet pointer.
  461.  call tmoclr  ;[19g] Clear timeout message
  462.  jmp rskp  ;If so we are done.
  463.  
  464. inpkt9: ret   ;return failure on time out.
  465.  
  466.  
  467. getchr: push bx
  468.  mov bx, pktptr ;Get the packet pointer.
  469.  mov ah, [bx] ;Get the char.
  470.  inc bx
  471.  mov pktptr, bx
  472.  pop bx  ;Restore BX.
  473.  cmp ah, reol ;Is it the EOL char?
  474.  jne getcr2  ;If not return retskp.
  475.  ret   ;If so return failure.
  476. getcr2: jmp rskp
  477.  
  478.  
  479. ;This is where we go if we get an error packet.  A call to ERROR
  480. ; positions the cursor and prints the message.  A call to ERROR1
  481. ; just prints a CRLF and then the message.
  482.  
  483. error: mov state, 'A' ;Set the state to abort.
  484.  mov dx, offset screrr
  485.  call poscur      ;[30c]
  486.  jmp error2
  487. error1: call tcrlf
  488. error2: mov bx, offset data ;Get to the string.
  489.  add bx, argbk1 ;Add the length of the data.
  490.  mov ah, '$'  ;Put a dollar sign at the end.
  491.  mov [bx], ah
  492.  mov dx, offset data ;Print the error message.
  493.  call tmsg
  494.  ret
  495.  
  496. ; Jump here if we die during a transfer.  Print the error message in
  497. ; DX and abort.
  498.  
  499. fatal: push dx  ;Save the error message.
  500.  mov dx, offset screrr
  501.  call poscur      ;[30c]
  502.  pop dx
  503.  call tmsg
  504.  jmp abort  ;Change the state to abort.
  505.  
  506. ; Print the status message in DX, ring the bell and position of the prompt.
  507.  
  508. fnstat: push dx
  509.  mov dx, offset scrst ;Print string to move cursor.
  510.  call poscur      ;[30c]
  511.  pop dx
  512.  call tmsg
  513.  mov dx, offset ender ;Ring them bells.
  514.  call tmsg
  515.  mov dx, offset scrhlp ;[19f] Cursor position
  516.  call poscur      ;[30c]
  517.  call clreol  ;[19f] Clear help line  ;[30c]
  518.  mov dx, offset scrrpr ;Put cursor back
  519.  call poscur      ;[30c]
  520.  ret
  521.  
  522.  
  523. ; This routine sets up the data for init packet (either the
  524. ; Send_init or ACK packet).
  525.  
  526. rpar: mov ah, rpsiz ;Get the receive packet size.
  527.  add ah, ' '  ;Add a space to make it printable.
  528.  mov [bx], ah ;Put it in the packet.
  529.  mov ah, rtime ;Get the receive packet time out.
  530.  add ah, ' '  ;Add a space.
  531.  mov 1[bx], ah ;Put it in the packet.
  532.  mov ah, rpad ;Get the number of padding chars.
  533.  add ah, ' '
  534.  mov 2[bx], ah ;Put it in the packet.
  535.  mov ah, rpadch ;Get the padding char.
  536.  add ah, 100O ;Uncontrol it.
  537.  and ah, 7FH
  538.  mov 3[bx], ah ;Put it in the packet.
  539.  mov ah, reol ;Get the EOL char.
  540.  add ah, ' '
  541.  mov 4[bx], ah ;Put it in the packet.
  542.  mov ah, rquote ;Get the quote char.
  543.  mov 5[bx], ah ;Put it in the packet.
  544.  mov ah, ebquot ;Get 8th-bit quote char ;[29g] begin
  545.  mov 6[bx], ah ;Put it in the packet.
  546.  mov ah, '1'  ;Set single character check type
  547.  mov 7[bx], ah ;Put it in the packet.
  548.  mov ah, ' '  ;Set no repeat prefix
  549.  mov 8[bx], ah ;Put it in the packet.
  550.  mov ah, 0  ;Initialize capability byte
  551.  cmp tmrflg, 0 ;Are we able to time out?
  552.  je rpar1  ;  No, leave bit set to zero
  553.  or ah, 20h  ;  Otherwise set timeout capability flag
  554. rpar1: add ah, ' '  ;Add space to make it printable
  555.  mov 9[bx], ah ;Put it in the packet.
  556.  mov ah, 10  ;Ten pieces of data.  ;[29g] end
  557.  ret
  558.  
  559. ; This routine reads in all the send_init packet information.
  560.  
  561. spar: push cx  ;Save CX.
  562.  mov cx, ax  ;Save the number of arguments.
  563.  mov ah, [bx] ;Get the max packet size.
  564.  sub ah, ' '  ;Subtract a space.
  565.  mov spsiz, ah ;Save it.
  566.  mov ax, cx  ;[19g]
  567.  cmp al, 2  ;[19g] Fewer than two pieces?
  568.  jge spar1  ;[19g]    ;[29g]
  569.  jmp sparx1      ;[29g]
  570. spar1: mov ah, 1[bx] ;[19g] Get the timeout value
  571.  sub ah, ' '  ;[19g]
  572.  mov stime, ah ;[19g] save it.
  573.  mov ax, cx
  574.  cmp al, 3  ;Fewer than three pieces?
  575.  jge spar2      ;[29g]
  576.  jmp sparx2      ;[29g]
  577. spar2: mov ah, 2[bx] ;Get the number of padding chars.
  578.  sub ah, ' '
  579.  mov spad, ah
  580.  mov ax, cx
  581.  cmp al, 4  ;Fewer than four pieces?
  582.  jge spar3      ;[29g]
  583.  jmp sparx3      ;[29g]
  584. spar3: mov ah, 3[bx] ;Get the padding char.
  585.  add ah, 100O ;Re-controlify it.
  586.  and ah, 7FH
  587.  mov spadch, ah
  588.  mov ax, cx
  589.  cmp al, 5  ;Fewer than five pieces?
  590.  jge spar4      ;[29g]
  591.  jmp sparx4      ;[29g]
  592. spar4: mov ah, 4[bx] ;Get the EOL char.
  593.  sub ah, ' '
  594.  mov seol, ah
  595.  mov ax, cx
  596.  cmp al, 6  ;Fewer than six pieces?
  597.  jge spar5      ;[29g]
  598.  jmp sparx5      ;[29g]
  599. spar5: mov ah, 5[bx] ;Get the quote char.
  600.  mov squote, ah
  601.  mov ax, cx      ;[29g] begin
  602.  cmp al, 7  ;Fewer than seven pieces?
  603.  jge spar6
  604.  jmp sparx6
  605. spar6: mov ah, 6[bx] ;Get the 8th-bit quote char.
  606.  call doquo  ;Set the quote character.
  607.  jmp sparxx
  608. sparx1: mov stime, dstime ;Default timeout interval
  609. sparx2: mov spad, dspad ;Default number of padding chars
  610. sparx3: mov spadch, dspadc ;Default pad character
  611. sparx4: mov seol, dseol ;Default eol character
  612. sparx5: mov squote, dsquot ;Default send quote character.
  613. sparx6: mov ebquot, 'N' ;No 8th bit quoting.
  614. sparxx: pop cx      ;[29g] end
  615.  ret   ;If so we are done.
  616.  
  617. ; Set 8-bit quote character based on my capabilities  ;[29g] begin
  618. ; and the other Kermit's request.
  619.  
  620. doquo: cmp ebquot,'N' ;Can I do 8-bit quoting at all?
  621.  je dq2  ;No - so forget it.
  622.  cmp ebquot,'Y' ;Can I do it if requested?
  623.  jne dq0  ;No - it's a must that I do it.
  624.  mov ebquot,ah ;Do whatever he wants.
  625.  jmp dq2
  626. dq0: cmp ah,'Y'  ;I need quoting - can he do it?
  627.  je dq2  ;Yes - then all is settled.
  628.  cmp ah,'N'  ;No - then don't quote.
  629.  je dq1
  630.  cmp ah,ebquot ;Both need quoting - chars must match.
  631.  je dq2
  632.  mov ah,'N'
  633. dq1: mov ebquot,ah
  634. dq2: mov ah,ebquot
  635.  cmp ah,rquote ;Same prefix?
  636.  je dq3  ;Not allowed, so don't do quoting.
  637.  cmp ah,squote ;Same prefix here?
  638.  je dq3  ;This is illegal too.
  639.  ret
  640. dq3: mov ebquot,'N' ;Quoting will not be done.
  641.  ret       ;[29g] end
  642.  
  643. ; These are some utility routines.
  644.  
  645. ; Increment the packet number.
  646.  
  647. incpkt: inc ax  ;Increment it.
  648.  and ax, 3FH  ;Turn off the two high order bits.
  649.  mov pktnum, ax ;Save modulo 64 of the number.
  650.  inc numpkt  ;Increment the number of packets.
  651.  ret
  652.  
  653. ; Check if the packet number is the present packet.
  654.  
  655. chkpeq: mov ax, argblk ;Get the packet number.
  656.  cmp ax, pktnum ;Is it the right packet number?
  657.  je chkpe2
  658.  ret   ;No.
  659. chkpe2: jmp rskp  ;Yes.
  660.  
  661. ; Is the packet number one more than present.
  662.  
  663. chkpom: mov ax, pktnum ;Get the present packet number.
  664.  inc ax  ;Increment.
  665.  and ax, 03FH ;Account for wraparound.
  666.  cmp ax, argblk ;Is the packet's number one more than now?
  667.  jz chkpm2  ;Yes, success.
  668.  ret
  669. chkpm2: jmp rskp
  670.  
  671. ; Check if the packet number is the previous packet.
  672.  
  673. chkpol: inc oldtry  ;Save the updated number of tries.
  674.  mov ax, pktnum ;Get the present packet number.
  675.  cmp ax, 0  ;Had we wrapped around?
  676.  jne chkpl2
  677.  mov ax, 64
  678. chkpl2: dec ax  ;Decrement.
  679.  cmp ax, argblk ;Is the packet's number one less than now?
  680.  je chkpl3
  681.  jmp rskp
  682. chkpl3: ret
  683.  
  684. ; Abort
  685.  
  686. abort: mov argblk, 0 ;packet number 0  ;[29a] begin
  687.  mov argbk1, 0 ;no data
  688.  mov ah, 'E'  ;error type
  689.  call spack
  690.   jmp $       ;[29a] end
  691.  mov state, 'A' ;Otherwise abort.
  692.  ret
  693.  
  694. ; ACK the packet.
  695.  
  696. uupack: call updat  ;[19f] entry which doesn't zero argbk1
  697.  jmp ack1  ;[19f]
  698. upack: call updat  ;Update the number of tries.
  699. ack: mov argbk1, 0 ;No data.  (Packet number already in argblk).
  700. ack1: mov ah, 'Y'  ;Acknowledge packet.
  701.  call spack  ;Send the packet.
  702.   jmp r
  703.  jmp rskp
  704.  
  705. updat: mov ah, numtry ;Get the number of tries.
  706.  mov oldtry, ah ;Save it.
  707.  mov numtry, 0 ;Reset the number of tries.
  708.  ret
  709.  
  710. ; Re-ACK the previous packet.
  711.  
  712. reack: call nretry  ;Increment and print the number of retries.
  713.  mov numtry, 0 ;Reset the number of tries.
  714.  mov ah, 'Y'  ;Acknowledge packet.
  715.  call spack  ;Send the packet.
  716.   jmp r
  717.  jmp rskp
  718.  
  719. ; NAK that packet.
  720.  
  721. nak: mov ax, pktnum ;Get the packet number we're waiting for.
  722.  mov argblk, ax
  723.  mov argbk1, 0
  724.  mov ah, 'N'  ;NAK that packet.
  725.  call spack
  726.   jmp abort
  727.  call nretry  ;Increment and print the number of retries.
  728.  ret   ;Go around again.
  729.  
  730. ; Print the number of retries.
  731.  
  732. nretry: inc numrtr  ;Increment the number of retries.
  733. pretry: mov dx, offset scrnrt
  734.  call poscur      ;[30c]
  735.  mov ax, numrtr
  736.  call nout  ;Write the number of retries.
  737.  ret
  738.  
  739. ; Print the number of packets.
  740.  
  741. pnmpkt: mov dx, offset scrnp ;Print string to move cursor.
  742.  call poscur      ;[30c]
  743.  mov ax, numpkt
  744.  call nout  ;Write the number of packets.
  745.  ret
  746.  
  747. ; This routine prints the number in AX on the screen.
  748.  
  749. nout: push ax  ;save all registers  ;[14] begin
  750.  push bx
  751.  push cx
  752.  push dx
  753.  mov cx, 0  ;number of digits to print
  754.  mov bx, 10  ;radix to use for dividing
  755. nout1: mov dx, 0  ;clear high word of dividend
  756.  div bx  ;divide dx:ax by 10
  757.  push dx  ;push this remainder
  758.  inc cx  ;count it
  759.  cmp ax, 0  ;anything left in the quotient?
  760.  jne nout1  ;   if so, keep dividing
  761. nout2: pop dx  ;get a digit
  762.  add dl, '0'  ;make it ascii
  763.  push cx  ;save our count
  764.  call bout  ;print the digit
  765.  pop cx  ;repeat until all digits printed
  766.  loop nout2
  767.  pop dx  ;restore all registers
  768.  pop cx
  769.  pop bx
  770.  pop ax
  771.  ret
  772.  
  773. ; Initialize file buffers and paint screen.
  774.  
  775. init:
  776.  call dspver  ;Clear screen and display version header
  777.  mov dx, offset scrnp ;Position to packet location
  778.  call poscur
  779.  mov dx, offset pktlin      ;[20a]
  780.  call tmsg
  781.  mov dx, offset scrhlp ;[19f] Cursor position
  782.  call poscur  ;[19f] for help line   ;[30c]
  783.  call revon  ;Bottom line reverse   ;[30c]
  784.  mov dx, offset infm10 ;[19f] Help for file transfer
  785.  call tmsg  ;[19f]
  786.  call revoff       ;[30c]
  787.  
  788. init1: mov chrcnt, bufsiz ;Number of chars left.
  789.  mov bufpnt, offset dma ;Addr for beginning.
  790.  ret
  791.  
  792.  
  793. ;  Clear out the old filename on the screen.
  794.  
  795. clrfln: mov dx, offset scrfr ;Move cursor to file rename. ;[31] begin
  796.  call poscur
  797.  call clreol  ;Clear to EOL.   ;[31] end
  798.  mov dx, offset scrfln ;Move cursor to file name position.
  799.  call poscur      ;[30c]
  800.  call clreol  ;Clear to EOL.   ;[30c]
  801.  ret
  802.  
  803. ; acknowledge ^X/^Z with a message  [19f] start
  804. intmsg: mov dx, offset scrint ;position info
  805.  call poscur  ;output it   ;[30c]
  806.  mov dx, offset infms8 ;File message
  807.  cmp cxzflg, 'X' ;but first check
  808.  je intm01  ;yes it was X
  809.  mov dx, offset infms9 ;no it was 'Z' - file group.
  810.  cmp cxzflg, 'Z' ;or was it?
  811.  je intm01  ;yes - go output
  812.  call clreol  ;anything else - clear line ;[30c]
  813.  jmps intm02      ;[30c]
  814. intm01: call tmsg  ;output it
  815. intm02: ret   ;goodbye [19f] end
  816.  
  817. ; let the time-out clock "tick" ;[19g] start
  818. ticmsg: mov dl, bell ;output a ...
  819.  call dbout  ;... beep!
  820.  ret
  821.  
  822. ; notify of time-out
  823. tmomsg: mov dx, offset scrst ;cursor position
  824.  call poscur      ;[30c]
  825.  mov dx, offset timoms ;timeout message
  826.  call tmsg
  827.  mov tmodon, 1 ;flag for message
  828.  ret
  829.  
  830. ; clear time-out message
  831. tmoclr: cmp tmodon, 0 ;message on screen?
  832.  jne tmocl1  ;yes - go get it
  833.  ret   ;nothing to clear - return
  834. tmocl1: mov dx, offset scrst ;cursor position
  835.  call poscur      ;[30c]
  836.  call clreol  ;clear line   ;[30c]
  837.  mov tmodon, 0 ;indicate line is clear
  838.  ret   ;[19g] end
  839.  
  840. ; RECEIVE command
  841.  
  842. read: call init  ;Paint the screen and initialize file buffers.
  843.  call cfibf  ;Clear out any stacked NAKs.
  844. read1: mov numpkt, 0 ;Set the number of packets to zero.
  845.  mov numrtr, 0 ;Set the number of retries to zero.
  846.  mov pktnum, 0 ;Set the packet number to zero.
  847.  mov numtry, 0 ;Set the number of tries to zero.
  848.  mov cxzflg, 0 ;[19f] reset ^X/^Z flag
  849.  call pretry
  850.  mov state, 'R' ;Set the state to receive initiate.
  851. read2: call pnmpkt
  852.  mov ah, state ;Get the state.
  853.  cmp ah, 'D'  ;Are we in the data send state?
  854.  jne read3
  855.  call rdata
  856.  jmp read2
  857. read3: cmp ah, 'F'  ;Are we in the file receive state?
  858.  jne read4
  859.  call rfile  ;Call receive file.
  860.  jmp read2
  861. read4: cmp ah, 'R'  ;Are we in the receive initiate state?
  862.  jne read5
  863.  call rinit
  864.  jmp read2
  865. read5: cmp ah, 'C'  ;Are we in the receive complete state?
  866.  jne read6
  867.  mov dx, offset infms3 ;Plus a little cuteness.
  868.  cmp cxzflg,0 ;[19f] an interruption?
  869.  je read59  ;[19f] no - do normal thing
  870.  mov dx, offset infms7 ;[19f] substitute 'interrupted' message.
  871. read59: call fnstat
  872.  ret
  873. read6: mov dx, offset infms4 ;Plus a little cuteness.
  874.  call fnstat
  875.  ret
  876.  
  877.  
  878. ; Receive routines
  879.  
  880. ; Receive init
  881.  
  882. rinit: mov ah, numtry ;Get the number of tries.
  883.  cmp ah, imxtry ;Have we reached the maximum number of tries?
  884.  jl rinit2
  885.  mov dx, offset ermes7 ;Print this error and die.
  886.  jmp fatal
  887.  
  888. rinit2: inc ah  ;Increment it.
  889.  mov numtry, ah ;Save the updated number of tries.
  890.  call rpack  ;Get a packet.
  891.   jmp nak  ; Trashed packet: nak, retry.
  892.  cmp ah, 'S'  ;Is it a send initiate packet?
  893.  jne rinit3  ;If not see if its an error.
  894.  mov ebquot, 'Y' ;Initialize my 8th-bit quote flag ;[29g]
  895.  mov ah, numtry ;Get the number of tries.
  896.  mov oldtry, ah ;Save it.
  897.  mov numtry, 0 ;Reset the number of tries.
  898.  mov ax, argblk ;Returned packet number.  (Synchronize them.)
  899.  call incpkt  ;Increment the packet number.
  900.  mov ax, argbk1 ;Get the number of arguments received.
  901.  mov bx, offset data ;Get a pointer to the data.
  902.  call spar  ;Get the data into the proper variables.
  903.  mov bx, offset data ;Get a pointer to our data block.
  904.  call rpar  ;Set up the receive parameters.
  905.  xchg ah, al
  906.  mov ah, 0
  907.  mov argbk1, ax ;Store the returned number of arguments.
  908.  call ack1  ;ACK the packet.
  909.   jmp abort
  910.  mov ah, 'F'  ;Set the state to file send.
  911.  mov state, ah
  912.  ret
  913. rinit3: cmp ah, 'E'  ;Is it an error packet?
  914.  jne rinit4
  915.  call error
  916. rinit4: jmp abort
  917.  
  918.  
  919. ; Receive file
  920.  
  921. rfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  922.  jl rfile1
  923.  mov dx, offset ermes8 ;Print this error and die.
  924.  jmp fatal
  925.  
  926. rfile1: inc numtry  ;Save the updated number of tries.
  927.  call rpack  ;Get a packet.
  928.   jmp nak  ; Trashed packet: nak, retry.
  929.  
  930.  cmp ah, 'S'  ;Is it a send initiate packet?
  931.  jne rfile2  ; No, try next type.
  932.  cmp oldtry, imxtry ;Have we reached the maximum number of tries?
  933.  jl rfil12  ;If not proceed.
  934.  mov dx, offset ermes7 ;Print this error and die.
  935.  jmp fatal
  936. rfil12: call chkpol  ;Check the packet number, is it right?
  937.   jmp nak  ;No, NAK and try again.
  938.  mov bx, offset data ;Get a pointer to our data block.
  939.  call rpar  ;Set up the parameter information.
  940.  xchg ah, al
  941.  mov ah, 0
  942.  mov argbk1, ax ;Save the number of arguments.
  943.  call reack  ;Re-ACK the old packet.
  944.   jmp abort
  945.  ret
  946.  
  947. rfile2: cmp ah, 'Z'  ;Is it an EOF packet?
  948.  jne rfile3  ; No, try next type.
  949.  cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  950.  jl rfil21  ;If not proceed.
  951.  mov dx, offset ermes9 ;Print this error and die.
  952.  jmp fatal
  953. rfil21: call chkpol  ;Check the packet number, is it right?
  954.   jmp nak  ;No, NAK and try again.
  955.  mov argbk1, 0 ;No data.
  956.  call reack  ;Re-ACK the previous packet
  957.   jmp abort
  958.  ret
  959.  
  960. rfile3: cmp ah, 'F'  ;Start of file?
  961.  jne rfile4
  962.  call chkpeq  ;Packet numbers equal?
  963.   jmp nak  ; No, NAK it and try again.
  964.  call incpkt  ;Increment the number of packets.
  965.  call gofil  ;Get a file to write to.
  966.   jmp abort
  967.  call init1  ;Initialize all the file buffers.
  968.  call upack  ;Update counters and ACK the packet.
  969.   jmp abort
  970.  mov state, 'D' ;Set the state to data receive.
  971.  ret
  972.  
  973. rfile4: cmp ah, 'B'  ;End of transmission?
  974.  jne rfile5
  975.  call chkpeq  ;Packet numbers equal?
  976.   jmp nak  ; No, NAK it and try again.
  977.  call ack  ;ACK the packet.
  978.   jmp abort
  979.  mov state, 'C' ;Set the state to complete.
  980.  ret
  981.  
  982. rfile5: cmp ah, 'E'  ;Is it an error packet?
  983.  jne rfile6
  984.  call error
  985. rfile6: jmp abort
  986.  
  987.  
  988. ; Receive data
  989.  
  990. rdata: cmp numtry, maxtry ;Get the number of tries.
  991.  jl rdata1
  992.  mov dx, offset erms10 ;Print this error and die.
  993.  jmp fatal
  994.  
  995. rdata1: inc numtry  ;Save the updated number of tries.
  996.  call rpack  ;Get a packet.
  997.   jmp nak  ; Trashed packet: nak, retry.
  998.  
  999.  cmp ah, 'D'  ;Is it a data packet?
  1000.  je rdat11
  1001.  jmp rdata2  ; No, try next type.
  1002. rdat11: call chkpeq  ;Packet numbers equal?
  1003.   jmp rdat12  ; No, check if previous packet.
  1004.  call incpkt  ;Increment the number of packets.
  1005.  mov ax, argbk1 ;Get the length of the data.
  1006.  cmp cxzflg, 0 ;[19f] interrupt requested?
  1007.  jne rdat1a  ;[19f] yes - skip put to file.
  1008.  call ptchr
  1009.   jmp abort  ; Unable to write out chars;abort.
  1010.  call upack  ;ACK the packet.
  1011.   jmp abort
  1012.  ret
  1013. rdat1a: mov bx, offset data ;[19f] data location
  1014.  mov ah, cxzflg ;[19f] get the ^X/^Z flag
  1015.  mov [bx], ah ;[19f] stick it in the packet
  1016.  mov argbk1, 1 ;[19f] data length is 1
  1017.  call uupack  ;[19f] ACK the packet (without zeroing argbk1)
  1018.   jmp abort  ;[19f]
  1019.  ret   ;[19f]
  1020.  
  1021. rdat12: cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  1022.  jl rdat13  ;If not proceed.
  1023.  mov dx, offset erms10 ;Print this error and die.
  1024.  jmp fatal
  1025. rdat13: call chkpol  ;Check the packet number, is it right?
  1026.   jmp nak  ;No, NAK it and try again.
  1027.  mov argbk1, 0 ;No data.
  1028.  call reack  ;Re-ACK the previous packet.
  1029.   jmp abort
  1030.  ret
  1031.  
  1032. rdata2: cmp ah, 'F'  ;Start of file?
  1033.  jne rdata3  ; No, try next type.
  1034.  cmp oldtry, maxtry ;Have we reached the maximum number of tries?
  1035.  jl rdat21  ;If not proceed.
  1036.  mov dx, offset ermes8 ;Print this error and die.
  1037.  jmp fatal
  1038. rdat21: call chkpol  ;Check the packet number, is it right?
  1039.   jmp nak  ; No, NAK it and try again.
  1040.  mov argbk1, 0 ;No data.
  1041.  call reack  ;Re-ACK the previous packet
  1042.   jmp abort
  1043.  ret
  1044.  
  1045. rdata3: cmp ah, 'Z'  ;Is it a EOF packet?
  1046.  je rdat32
  1047.  jmp rdata4  ;Try and see if its an error.
  1048. rdat32: call chkpeq  ;Packet numbers equal?
  1049.   jmp nak  ; No, NAK it and try again.
  1050.  call incpkt  ;Increment the packet number.
  1051.  cmp cxzflg, 0 ;This file interrupted? [19f] start
  1052.  jne rdat3a  ;yes jump
  1053.  cmp argbk1, 1 ;1 byte of data in EOF packet?
  1054.  jmp rdat3b  ;no - finish up file
  1055.  mov bx, offset data ;pointer to data
  1056.  mov ah, [bx] ;get the data
  1057.  cmp ah, 'D'  ;is it D as in Discard?
  1058.  jne rdat3b  ;no - finish writing file
  1059. rdat3a: mov dx, offset fcb ;get file's fcb
  1060.  call delete  ;delete the file.
  1061.  cmp cxzflg, 'X' ;Kill one file or batch?
  1062.  jne rdat37  ;whole batch - leave flag
  1063.  mov cxzflg, 0 ;clear flag
  1064.  call intmsg  ;clear message
  1065.  jmp rdat37  ;go to clean up.  [19f] end
  1066. rdat3b: mov bx, bufpnt ;Get the dma pointer.
  1067.  mov ax, 80H
  1068.  sub ax, chrcnt ;Get the number of chars left in the DMA.
  1069.  cmp ax, 80H
  1070.  jne rdat34
  1071.  call outbuf  ;Write out buffer if no room for ^Z.
  1072.   jmp abort
  1073.  jmp rdat36  ;Go close the file.
  1074. rdat34: mov cl, 'Z'-100O ;Put in a ^Z for EOF.
  1075.  mov [bx], cl
  1076.  inc ax
  1077.  dec chrcnt
  1078.  mov cx, chrcnt
  1079.  mov temp, cx
  1080.  inc bx
  1081. rdt3: inc ax
  1082.  cmp ax, 80H
  1083.  jg rdat35  ;Pad till full.
  1084.  mov cl, 1AH  ;Use control-Z's  ;[13]
  1085.  mov [bx], cl
  1086.  inc bx
  1087.  jmp rdt3
  1088. rdat35: call outbuf  ;Output the last buffer.
  1089.   jmp abort  ; Give up if the disk is full.
  1090. rdat36: mov dx, offset fcb
  1091.  call closf  ;Close up the file.
  1092. rdat37: call upack  ;ACK the packet.
  1093.   jmp abort
  1094.  mov state, 'F'
  1095.  ret
  1096.  
  1097. rdata4: cmp ah, 'E'  ;Is it an error packet.
  1098.  jne rdata5
  1099.  call error
  1100. rdata5: jmp abort
  1101.  
  1102.  
  1103. ; Send a file.
  1104.  
  1105. send: cmp wldflg,0FFh
  1106.  je send12
  1107.  mov dircnt,0 ;If not wild, just use the name in the FCB
  1108.  mov dindex,0
  1109.  call getopn  ;Open the file
  1110.  jmps send19
  1111. send12: call getwld  ;If wild, get sorted list of matching names
  1112.   jmp r  ;  on error, message already printed
  1113.  mov dindex,0 ;Start at first one
  1114.  call getfil  ;Get and open first file
  1115.   jmp r
  1116. send19: call init  ;Paint the screen and initialize file buffers.
  1117.  call cfibf  ;Clear out any stacked NAKs.
  1118.  mov pktnum, 0 ;Set the packet number to zero.
  1119.  mov numtry, 0 ;Set the number of tries to zero.
  1120.  mov numpkt, 0 ;Set the number of packets to zero.
  1121.  mov numrtr, 0 ;Set the number of retries to zero.
  1122.  call pretry  ;Print the number of retries.
  1123.  mov state,'S' ;Set the state to receive initiate.
  1124. send2: call pnmpkt  ;Print the number of packets.
  1125.  cmp state, 'S' ;Are we in the send initiate state?
  1126.  jne send3
  1127.  call sinit
  1128.  jmp send2
  1129. send3: cmp state, 'F' ;Are we in the file send state?
  1130.  jne send4
  1131.  call sfile  ;Call send file.
  1132.  jmp send2
  1133. send4: cmp state, 'D' ;Are we in the data send state?
  1134.  jne send5
  1135.  call sdata
  1136.  jmp send2
  1137. send5: cmp state, 'Z' ;Are we in the EOF state?
  1138.  jne send6
  1139.  call seof
  1140.  jmp send2
  1141. send6: cmp state, 'B' ;Are we in the eot state?
  1142.  jne send7
  1143.  call seot
  1144.  jmp send2
  1145. send7: cmp state, 'C' ;Are we in the send complete state?
  1146.  jne send8
  1147.  mov dx, offset infms3 ;Plus a little cuteness.
  1148.  cmp cxzflg, 0 ;[19f] Interrupted?
  1149.  je send7a  ;[19f] no
  1150.  mov dx, offset infms7 ;[19f] substitute "interrupted" message
  1151. send7a: call fnstat
  1152.  ret
  1153. send8: mov dx, offset infms4 ;Plus a little cuteness.
  1154.  call fnstat
  1155.  ret
  1156.  
  1157.  
  1158. ; Send routines
  1159.  
  1160. ; Send initiate
  1161.  
  1162.  
  1163. sinit: cmp numtry, imxtry ;Have we reached the maximum number of tries?
  1164.  jl sinit2
  1165.  mov dx, offset erms14
  1166.  jmp fatal
  1167. sinit2: mov ah, 'Y'  ;Reset our quote capability ;[29g] begin
  1168.  cmp parflg, parnon ;If we have parity,
  1169.  je sini21  ;  send our quote preference
  1170.  mov ah, dqbin
  1171. sini21: mov ebquot, ah ;Set our quote capability ;[29g] end
  1172.  inc numtry  ;Save the updated number of tries.
  1173.  mov bx, offset data ;Get a pointer to our data block.
  1174.  call rpar  ;Set up the parameter information.
  1175.  xchg ah, al
  1176.  mov ah, 0
  1177.  mov argbk1, ax ;Save the number of arguments.
  1178.  mov ax, numpkt ;Get the packet number.
  1179.  mov argblk, ax
  1180.  mov ah, 'S'  ;Send initiate packet.
  1181.  call spack  ;Send the packet.
  1182.   jmp abort
  1183.  call rpack  ;Get a packet.
  1184.   jmp r  ; Trashed packet don't change state, retry.
  1185.  cmp ah, 'Y'  ;ACK?
  1186.  jne sinit3  ;If not try next.
  1187.  call chkpeq  ;Is it the right packet number?
  1188.   jmp nretry  ;Increment the retries and go try again.
  1189.  call incpkt  ;Increment the packet number.
  1190.  mov ax, argbk1 ;Get the number of pieces of data.
  1191.  mov bx, offset data ;Pointer to the data.
  1192.  call spar  ;Read in the data.
  1193.  mov ah, numtry ;Get the number of tries.
  1194.  mov oldtry, ah ;Save it.
  1195.  mov numtry, 0 ;Reset the number of tries.
  1196.  mov state, 'F' ;Set the state to file send.
  1197.  ret
  1198.  
  1199. sinit3: cmp ah, 'N'  ;NAK?
  1200.  jne sinit4  ;If not see if its an error.
  1201.  call nretry
  1202.  ret
  1203.  
  1204. sinit4: cmp ah, 'E'  ;Is it an error packet?
  1205.  jne sinit5
  1206.  call error
  1207. sinit5: jmp abort
  1208.  
  1209.  
  1210. ; Send file header
  1211.  
  1212. sfile: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  1213.  jl sfile1
  1214.  mov dx, offset erms14
  1215.  jmp fatal
  1216. sfile1: inc numtry  ;Increment it.
  1217.  mov cxzflg, 0 ;[19f] clear ^X/^Z flag
  1218.  push ds
  1219.  pop es
  1220.  mov di, offset data ;Get a pointer to our data block.
  1221.  mov si, offset fcb+1 ;Pointer to file name in FCB.
  1222.  mov cx,11
  1223. sfil11: cmp cx,3  ;Separate file type with period
  1224.  jne sfil12
  1225.  mov al,'.'
  1226.  stosb
  1227. sfil12: lodsb
  1228.  and al,7Fh  ;Strip off attribute bits
  1229.  cmp al,' '  ;Printable, nonspace characters only
  1230.  jbe sfil13
  1231.  cmp al,7Fh
  1232.  jae sfil13
  1233.  stosb
  1234. sfil13: loop sfil11
  1235.  mov byte ptr [di],'$' ;Terminate filename for printing
  1236.  sub di, offset data
  1237.  mov argbk1, di ;Save number of characters in name
  1238.  call clrfln
  1239.  mov dx, offset data ;Print file name.
  1240.  call tmsg
  1241.  
  1242.  mov ax, pktnum ;Get the packet number.
  1243.  mov argblk, ax
  1244.  mov ah, 'F'  ;File header packet.
  1245.  call spack  ;Send the packet.
  1246.   jmp abort
  1247.  call rpack  ;Get a packet.
  1248.   jmp r  ; Trashed packet don't change state, retry.
  1249.  cmp ah, 'Y'  ;ACK?
  1250.  jne sfile2  ;If not try next.
  1251.  call chkpeq  ;Packet number right.
  1252.   jmp nretry  ;Increment the retries and go try again.
  1253. sfil14: call incpkt  ;Increment the packet number.
  1254.  call updat  ;Update the number of tries.
  1255.  
  1256. sfil15: mov byte ptr fcb+20h,0 ;Set the record number to zero.
  1257.  mov eoflag, 0 ;Indicate not EOF.
  1258.  mov filflg, 0FFh ;Indicate file buffer empty.
  1259.  call gtchr
  1260.   jmp sfil16  ;Error go see if its EOF.
  1261.  jmp sfil18  ;Got the chars, proceed.
  1262. sfil16: cmp ah, 0FFH ;Is it EOF?
  1263.  je sfil17
  1264.  jmp abort  ;If not give up.
  1265. sfil17: mov state, 'Z' ;Set the state to EOF.
  1266.  ret
  1267. sfil18: mov siz, ax
  1268.  mov state, 'D' ;Set the state to data send.
  1269.  ret
  1270.  
  1271. sfile2: cmp ah, 'N'  ;NAK?
  1272.  jne sfile3  ;Try if error packet.
  1273.  call chkpom  ;Is the packet's number one more than now?
  1274.   jmp nretry  ;Increment the retries and go try again.
  1275.  jmp sfil14  ;If so, join the ACK.
  1276.  
  1277. sfile3: cmp ah, 'E'  ;Is it an error packet.
  1278.  jne sfile4
  1279.  call error
  1280. sfile4: jmp abort
  1281.  
  1282.  
  1283. ; Send data
  1284.  
  1285. sdata: cmp cxzflg, 0 ;[19f] Interrupt flag on?
  1286.  je sdata0  ;[19f] no
  1287.  mov state, 'Z' ;[19f] yes - abort sending file
  1288.  ret
  1289. sdata0: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  1290.  jl sdata1
  1291.  mov dx, offset erms14
  1292.  jmp fatal
  1293. sdata1: inc numtry  ;Increment it.
  1294.  mov dx, offset data ;Get a pointer to our data block.
  1295.  mov datptr, dx
  1296.  mov dx, offset filbuf ;Pointer to chars to be sent.
  1297.  mov cbfptr, dx
  1298.  mov cx, 1  ;First char.
  1299. sdat11: mov bx, cbfptr
  1300.  mov ah, [bx]
  1301.  inc cbfptr
  1302.  mov bx, datptr
  1303.  mov [bx], ah ;Put the char in the data packet.
  1304.  inc datptr  ;Save position in data packet.
  1305.  inc cx  ;Increment the count.
  1306.  cmp cx, siz  ;Have we transfered that many?
  1307.  jle sdat11  ;If not get another.
  1308.  mov ax, siz  ;Number of char in char buffer.
  1309.  mov argbk1, ax
  1310.  mov ax, pktnum ;Get the packet number.
  1311.  mov argblk, ax
  1312.  mov ah, 'D'  ;Data packet.
  1313.  call spack  ;Send the packet.
  1314.   jmp abort
  1315.  call rpack  ;Get a packet.
  1316.   jmp r  ; Trashed packet don't change state, retry.
  1317.  cmp ah, 'Y'  ;ACK?
  1318.  jne sdata2  ;If not try next.
  1319.  call chkpeq  ;Right packet number?
  1320.   jmp nretry  ;Increment the retries and go try again.
  1321. sdat12: call incpkt  ;Increment the packet number.
  1322.  call updat  ;Update the number of tries.
  1323.  cmp argbk1,1 ;1 byte of data there?  [19f] start
  1324.  jne sdt12b  ;no - go on
  1325.  mov bx, offset data ;pointer to data
  1326.  mov ah, [bx] ;get the data
  1327.  cmp ah, 'X'  ;an 'X'?
  1328.  je sdt12a  ;yes - go
  1329.  cmp ah, 'Z'  ;or a 'Z'
  1330.  je sdt12a  ;also go
  1331.  jmp sdt12b  ;neither one - go on
  1332. sdt12a: mov cxzflg, ah ;'X' or 'Z' - set the interrupt flag [19f] end
  1333.  ret
  1334. sdt12b: call gtchr
  1335.   jmp sdat13  ;Error go see if its EOF.
  1336.  mov siz, ax  ;Save the size of the data gotten.
  1337.  ret
  1338.  
  1339. sdat13: cmp ah, 0FFH ;Is it EOF?
  1340.  je sdat14
  1341.  jmp abort  ;If not give up.
  1342.  
  1343. sdat14: mov state, 'Z' ;Set the state to EOF.
  1344.  ret
  1345. sdata2: cmp ah, 'N'  ;NAK?
  1346.  jne sdata3  ;See if is an error packet.
  1347.  call chkpom  ;Is the packet's number one more than now?
  1348.   jmp nretry  ;Increment the retries and go try again.
  1349.  jmp sdat12
  1350.  
  1351. sdata3: cmp ah, 'E'  ;Is it an error packet.
  1352.  jne sdata4
  1353.  call error
  1354. sdata4: jmp abort
  1355.  
  1356.  
  1357. ; Send EOF
  1358.  
  1359. seof: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  1360.  jl seof1
  1361.  mov dx, offset erms14
  1362.  jmp fatal
  1363. seof1: inc numtry  ;Increment it.
  1364.  mov ax, pktnum ;Get the packet number.
  1365.  mov argblk, ax
  1366.  mov argbk1, 0 ;No data.
  1367.  cmp cxzflg, 0 ;[19f] interrupt flag set?
  1368.  je seof1a  ;[19f] no - go on
  1369.  mov bx, offset data ;[19f] point to data
  1370.  mov ah, 'D'  ;[19f] get 'D' as in Discard
  1371.  mov [bx], ah ;[19f] stuff it into packet
  1372.  mov argbk1, 1 ;[19f] set data length of 1
  1373. seof1a: mov ah, 'Z'  ;EOF packet.
  1374.  call spack  ;Send the packet.
  1375.  jmp abort
  1376.  call rpack  ;Get a packet.
  1377.   jmp r  ; Trashed packet don't change state, retry.
  1378.  cmp ah, 'Y'  ;ACK?
  1379.  jne seof2  ;If not try next.
  1380.  call chkpeq  ;Is it the right packet number?
  1381.   jmp nretry  ;Increment the retries and go try again.
  1382. seof12: call incpkt  ;Increment the packet number.
  1383.  call updat  ;Update the number of tries.
  1384.  mov dx, offset fcb ;Close the file.
  1385.  call closf
  1386.  call getfil  ;Get and open the next file.
  1387.   jmp seof13  ; No more.
  1388.  mov state, 'F' ;Set the state to file send.
  1389.  cmp cxzflg, 'X' ;[19f] 'X' in interrupt flag?
  1390.  mov cxzflg, 0 ;[19f] meantime reset it
  1391.  jne sef13a  ;[19f] no - go on
  1392.  call intmsg  ;[19f] clear interrupt message
  1393. sef13a: ret   ;[19f] goodbye
  1394. seof13: mov state, 'B' ;Set the state to EOT.
  1395.  ret
  1396.  
  1397. seof2: cmp ah, 'N'  ;NAK?
  1398.  jne seof3  ;Try and see if its an error packet.
  1399.  call chkpom  ;Is the packet's number one more than now?
  1400.   jmp nretry  ;Increment the retries and go try again.
  1401.  jmp seof12
  1402.  
  1403. seof3: cmp ah, 'E'  ;Is it an error packet?
  1404.  jne seof4
  1405.  call error
  1406. seof4: jmp abort
  1407.  
  1408.  
  1409. ; Send EOT
  1410.  
  1411. seot: cmp numtry, maxtry ;Have we reached the maximum number of tries?
  1412.  jl seot1
  1413.  mov dx, offset erms14
  1414.  jmp fatal
  1415. seot1: inc numtry  ;Increment it.
  1416.  mov ax, pktnum ;Get the packet number.
  1417.  mov argblk, ax
  1418.  mov argbk1, 0 ;No data.
  1419.  mov ah, 'B'  ;EOF packet.
  1420.  call spack  ;Send the packet.
  1421.   jmp abort
  1422.  call rpack  ;Get a packet.
  1423.   jmp r  ;Trashed packet don't change state, retry.
  1424.  cmp ah, 'Y'  ;ACK?
  1425.  jne seot2  ;If not try next.
  1426.  call chkpeq  ;Is it the right packet number.
  1427.   jmp nretry  ;Increment the retries and go try again.
  1428. seot12: call incpkt  ;Increment the packet number.
  1429.  call updat  ;Update the number of tries.
  1430.  mov state, 'C' ;Set the state to file send.
  1431.  ret
  1432.  
  1433. seot2: cmp ah, 'N'  ;NAK?
  1434.  jne seot3  ;Is it error.
  1435.  call chkpom  ;Is the packet's number one more than now?
  1436.   jmp nretry  ;Increment the retries and go try again.
  1437.  jmp seot12
  1438.  
  1439. seot3: cmp ah, 'E'  ;Is it an error packet.
  1440.  jne seot4
  1441.  call error
  1442. seot4: jmp abort
  1443.