home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s1.zip / MSSSEN.ASM < prev    next >
Assembly Source File  |  1988-02-12  |  59KB  |  1,235 lines

  1.         NAME    msssen
  2. ; File MSSSEN.ASM
  3. ; Edit history:
  4. ; Last edit: 1 Jan 1988
  5. ; 1 Jan 1988 version 2.30
  6. ; 26 Dec 1987 clean ups [jrd]
  7. ; 8 Oct 1987 Ensure error pkts use 1 byte chksum at init stage. [jrd]
  8. ; 21 Sept 1987 Add error return to doenc for filenames too long for pkt. [jrd]
  9. ; 6 July 1987 Fix bug of 9 Dec below for case of short S/I packets. [jrd]
  10. ; 27 June 1987 Correct statistics gathering for last file. [jrd]
  11. ; 7 June 1987 Return DOS errlev of 1 if sending fails. [jrd]
  12. ; 24 May 1987 Add Delay seconds before starting local Send file. [jrd]
  13. ; 7 May 1987 Add statistics gathering functions. [jrd]
  14. ; 9 Dec 1986 Version 2.29a
  15. ; 9 Dec 1986 Add final check on packet length in Spar to avoid sending
  16. ; packets longer than the local user wishes. [jrd]
  17. ; 5 Sept 1986 minor cleanup in spar regular pkt size calculation. [jrd]
  18. ; 14 August 1986 Fix Send/Receive EOL, padding, pad-char [rjd]
  19. ; 3 August 86 modify for long packets, fix 8 bit quoting negotiations. [jrd]
  20. ; 26 May 1986 Revise code to permit serial display. [jrd]
  21. ;  Also, remove case conversion of "as" filename being sent. [rjd]
  22. ; [2.29] code frozen on 6 May 1986 [jrd]
  23.  
  24.         public  spar, rpar, error, error1, nout, send, flags, trans, pack
  25.         public  dodec, doenc, curchk, inichk, packlen, send11, dtrans
  26.         include mssdef.h
  27.  
  28. spmin   equ     20              ; Minimum packet size.
  29. spmax   equ     94              ; Maximum packet size.
  30.  
  31. datas   segment public 'datas'
  32.         extrn   buff:byte, data:byte, filbuf:byte, fsta:word
  33.         extrn   decbuf:byte, chrcnt:word, bufpnt:word, errlev:byte
  34.         extrn   rptq:byte, origr:byte, rptct:byte, rptval:byte
  35.         extrn   diskio:byte, maxtry:byte, imxtry:byte, portval:word
  36.  
  37. flags   flginfo <>
  38. trans   trinfo  <>
  39. dtrans  trinfo  <>                      ; default trans info
  40. pack    pktinfo <>
  41. crlf    db      cr,lf,'$'
  42. ender   db      bell,bell,'$'
  43. erms14  db      '?Unable to receive an acknowledgment from the host$'
  44. erms15  db      '?Unable to find file$'
  45. erms20  db      'Unable to send init packet$'
  46. erms21  db      'Unable to send file header$'
  47. erms22  db      'Unable to send data$'
  48. erms23  db      'Unable to send end-of-file packet$'
  49. erms24  db      'Unable to send break packet$'
  50. infms2  db      cr,'             Sending: In progress',cr,lf,'$'
  51. infms3  db      'Completed',cr,lf,'$'
  52. infms4  db      'Failed',cr,lf,'$'
  53. infms6  db      'Interrupted$'
  54. remmsg1 db      'Kermit-MS: File not found$'
  55. filhlp  db      ' A filename (possibly wild) $'
  56. filmsg  db      ' Local Source File  or a carriage return $'
  57. remfnm  db      ' Remote Destination File: $'
  58. lclfnm  db      ' Local Source File: $'
  59.  
  60. curchk  db      0               ; Use to store checksum length.
  61. inichk  db      1               ; Original or set checksum length.
  62. siz     dw      ?               ; Size of data from gtchr.
  63. difsiz  dw      0               ; Size of new exported file name.
  64. sendas  dw      50 dup(0)       ; Buffer for file name.
  65. temp    dw      0
  66. temp4   dw      0
  67. asmsg   db      '  as  $'
  68. filopn  db      0               ; Says if disk file is open.
  69. ninefive dw     95              ; constant word for long packets
  70. datas   ends
  71.  
  72. code    segment public 'code'
  73.         extrn serini:near, serrst:near, comnd:near, init:near
  74.         extrn spack:near, rpack:near, gtnfil:near, gtchr:near
  75.         extrn getfil:near, clrfln:near, nppos:near, rprpos:near
  76.         extrn erpos:near, rtpos:near, cxmsg:near, stpos:near, decout:near
  77.         extrn encode:near, nulref:near, decode:near, nulr:near
  78.         extrn errpack:near, updrtr:near, clrmod:near, prompt:near
  79.         extrn prtfn:near, strcpy:near, strlen:near, pktsize:near
  80.         extrn pcwait:near, ihosts:near, begtim:near, endtim:near
  81.  
  82.         assume  cs:code, ds:datas
  83.  
  84. ;       This routine sets up the data for init packet (either the
  85. ;       Send_init or ACK packet).
  86. ; trans.rxxx are items we are prepared to receive
  87. RPAR    PROC    NEAR
  88.         mov     ah,trans.rpsiz          ; Get the receive packet size.
  89.         add     ah,' '                  ; Add a space to make it printable.
  90.         mov     [bx],ah                 ; Put it in the packet.
  91.         mov     ah,trans.rtime          ; Get the receive packet time out.
  92.         add     ah,' '                  ; Add a space.
  93.         mov     1[bx],ah                ; Put it in the packet.
  94.         mov     ah,trans.rpad           ; Get the number of padding chars.
  95.         add     ah,' '
  96.         mov     2[bx],ah                ; Put it in the packet.
  97.         mov     ah,trans.rpadch         ; Get the padding char.
  98.         add     ah,40h                  ; Uncontrol it.
  99.         and     ah,7FH
  100.         mov     3[bx],ah                ; Put it in the packet.
  101.         mov     ah,trans.reol           ; Get the EOL char.
  102.         add     ah,' '
  103.         mov     4[bx],ah                ; Put it in the packet.
  104.         mov     ah,trans.rquote         ; Get the quote char.
  105.         mov     5[bx],ah                ; Put it in the packet.
  106.         mov     ah,trans.ebquot         ; Get 8-bit quote char.
  107.         mov     6[bx],ah                ; Add it to the packet.
  108.         mov     ah,trans.chklen         ; Length of checksum.
  109.         add     ah,48                   ; Make into a real digit.
  110.         mov     7[bx],ah
  111.         mov     ah,rptq                 ; Repeat quote char.
  112.         cmp     ah,0                    ; Null means no.
  113.         jne     rpar0
  114.         mov     ah,' '                  ; Send a blank instead.
  115. rpar0:  mov     8[bx],ah
  116.                                         ; begin long packet changes
  117.         mov     ah,02h                  ; CAPAS, bit1 = can do long packets
  118.         add     ah,20h                  ; apply tochar() to byte
  119.         mov     9[bx],ah                ; add to packet
  120.                                         ; additional CAPAS go in here
  121.         mov     ah,20h          ; WINDO field, null applied through tochar()
  122.         mov     10[bx],ah               ; put into packet
  123.  
  124.         push    ax                      ; save some regs
  125.         push    dx
  126.         mov     ax,trans.rlongp     ; long packet length which we can receive
  127.         xor     dx,dx                   ; clear extended part for division
  128.         div     ninefive                ; divide by 95. quo = ax, rem = dx
  129.         add     al,20h                  ; apply tochar() to quotient
  130.         mov     11[bx],al               ; add to packet
  131.         add     dl,20h                  ; apply tochar() to remainder
  132.         mov     12[bx],dl               ; add to packet
  133.         pop     dx                      ; restore regs
  134.         pop     ax
  135.         mov     ah,13                   ; 13 bytes of data
  136.         ret
  137. RPAR    ENDP
  138.  
  139. ; This routine reads in all the send init packet information.
  140. ; Enter with BX/ packet address, AX/ packet length
  141. ; This could probably be done much more legibly if it were table
  142. ; driven, but I'm afraid to touch it...
  143. ;
  144. ; dtrans.xxx are the default parameters if the other side says nothing.
  145. ; trans.sxxx are the active negotiated parameters we will use for sending.
  146. SPAR    PROC    NEAR
  147.         mov     temp4,ax                ; Save the number of arguments
  148.         cmp     ax,1
  149.         jge     spara                   ; ge = want more than bare minimum
  150.         mov     ah,dspsiz             ; Data not supplied by host, use default
  151.         jmp     short sparc
  152. spara:  mov     ah,[bx]                 ; Get the max packet size.
  153.         sub     ah,' '                  ; Subtract a space.
  154.         cmp     ah,spmin                ; Can't be below the minimum.
  155.         jge     sparb
  156.         mov     ah,spmin
  157.         jmp     short sparc
  158. sparb:  cmp     ah,spmax                ; Or above the maximum.
  159.         jle     sparc
  160.         mov     ah,spmax
  161. sparc:  mov     trans.spsiz,ah          ; Save it.
  162.         mov     ax,temp4
  163.         mov     ah,dtrans.stime         ; pick up default stime
  164.         cmp     al,2                    ; Fewer than two pieces?
  165.         jl      spar02                  ; yes, use default
  166. spar0:  cmp     ah,dstime               ; Is current value the default?
  167.         jne     spar02                  ; No, assume changed by user.
  168.         mov     ah,1[bx]                ; Get the timeout value.
  169.         sub     ah,' '                  ; Subtract a space.
  170.         cmp     ah,0
  171.         ja      spar01                  ; Must be non-negative.
  172.         mov     ah,0
  173. spar01: cmp     ah,trans.rtime          ; Same as other side's timeout.
  174.         jne     spar02
  175.         add     ah,5                    ; If so, make it a little different.
  176. spar02: mov     trans.stime,ah          ; Save it.
  177.         mov     ax,temp4
  178.         mov     ah,dtrans.spad          ; get default send padding
  179.         cmp     al,3                    ; Fewer than three pieces?
  180.         jl      spar11                  ; yes, use default
  181. spar1:  mov     ah,2[bx]                ; Get the number of padding chars.
  182.         sub     ah,' '
  183.         cmp     ah,0
  184.         jge     spar11                  ; Must be non-negative.
  185.         mov     ah,0
  186. spar11: mov     trans.spad,ah
  187.         mov     ax,temp4
  188.         mov     ah,dtrans.spadch        ; pick up default send pad character
  189.         cmp     al,4                    ; Fewer than four pieces?
  190.         jl      spar21
  191. spar2:  mov     ah,3[bx]                ; Get the padding char.
  192.         add     ah,40h                  ; Re-controlify it.
  193.         and     ah,7FH
  194.         cmp     ah,del                  ; Delete?
  195.         je      spar21                  ; Yes, then it's OK.
  196.         cmp     ah,0
  197.         jge     spar20
  198.         mov     ah,0                    ; Below zero is no good.
  199.         jmp     spar21                  ; Use zero (null).
  200. spar20: cmp     ah,31                   ; Is it a control char?
  201.         jle     spar21                  ; Yes, then OK.
  202.         mov     ah,0                    ; No, use null.
  203. spar21: mov     trans.spadch,ah
  204.         mov     ax,temp4
  205.         mov     ah,dtrans.seol          ; get default send eol char
  206.         cmp     al,5                    ; Fewer than five pieces?
  207.         jl      spar31                  ; yes, use default
  208. spar3:  mov     ah,4[bx]                ; Get the EOL char.
  209.         sub     ah,' '
  210.         cmp     ah,0
  211.         jge     spar30                  ; Cannot be negative.
  212.         mov     ah,cr                 ; If so, use default of carriage return
  213.         jmp     spar31
  214. spar30: cmp     ah,31                   ; Is it a control char?
  215.         jle     spar31                  ; Yes, then use it.
  216.         mov     ah,cr                   ; Else, use the default.
  217. spar31: mov     trans.seol,ah
  218.         mov     ax,temp4
  219.         mov     ah,dtrans.squote        ; send quote
  220.         cmp     al,6                    ; Fewer than six pieces?
  221.         jl      spar41
  222. spar4:  mov     ah,5[bx]                ; Get the quote char.
  223.         cmp     ah,' '                  ; Less than a space?
  224.         jge     spar40
  225.         mov     ah,dsquot               ; Yes, use default.
  226.         jmp     spar41
  227. spar40: cmp     ah,7eh                  ; Must also be less than a tilde.
  228.         jle     spar41
  229.         mov     ah,dsquot               ; Else, use default.
  230. spar41: mov     trans.squote,ah
  231.         cmp     al,7                    ; Fewer than seven pieces?
  232.         jge     spar5
  233.         mov     trans.ebquot,'Y'      ; Data not supplied by host, use default
  234.         jmp     short spar51
  235. spar5:  mov     ah,6[bx]                ; Get other sides 8-bit quote request
  236.         call    doquo                   ; And set quote char.
  237. spar51: cmp     al,8                    ; Fewer than eight pieces?
  238.         jge     spar6
  239.         mov     trans.chklen,1
  240.         jmp     short spar61
  241. spar6:  mov     ah,inichk
  242.         mov     trans.chklen,ah         ;Checksum length we really want to use
  243.         mov     ah,7[bx]                ; Get other sides checksum length.
  244.         call    dochk                   ; Determine what size to use.
  245. spar61: cmp     al,9                    ; Fewer than nine pieces?
  246.         jge     spar7
  247.         mov     rptq,0
  248.         jmp     short spar71
  249. spar7:  mov     ah,8[bx]                ; Get other sides repeat count prefix.
  250.         mov     ch,drpt
  251.         mov     rptq,0
  252.         call    dorpt
  253. ;;; begin long packet changes - update this for strict ELP protocol
  254. spar71: mov     ah,0                    ; get default operating capabilities
  255.         cmp     al,10                   ; 10 or more pieces?
  256.         jl      spar81                  ; l = no
  257.         mov     ah,9[bx]                ; get capas bitmap from other side
  258.         sub     ah,20h                  ; apply unchar()
  259.         call    decapa                  ; negotiate them back into ah
  260. spar81: mov     trans.capas,ah          ; store result in active byte
  261.  
  262.         mov     ah,0                    ; setup default window size
  263.         cmp     al,11                   ; 11 or more pieces?
  264.         jl      spar9                   ; l = no, use default
  265.         mov     ah,10[bx]               ; get other side's window size
  266.         sub     ah,20h                  ; apply unchar()
  267.         call    dewind                  ; negotiate window size back into ah
  268. spar9:  mov     trans.windo,ah          ; store it
  269.                                         ; decode window info
  270.         push    cx                      ; save a reg
  271.         xor     ch,ch
  272.         mov     cl,trans.spsiz          ; normal packet size
  273.         mov     trans.slongp,cx         ; assume not using long packets
  274.         pop     cx                      ; restore reg
  275.         cmp     al,13           ; 13 or more pieces (long packet needs two)?
  276.         jae     spar9d                  ; ae = more to look at
  277.         mov     ax,trans.slongp ; put above size in ax for final checks
  278.         push    ax
  279.         jmp     spar9a          ; do final checks (they want longer than us)
  280. spar9d: test    trans.capas,2   ; do they have long packet capability?
  281.         jz      sparx           ; z = no, skip following lp length fields.
  282.         push    ax                      ; save al
  283.         xor     ah,ah
  284.         mov     al,11[bx]               ; long packet length, high order byte
  285.         sub     al,20h                  ; apply unchar()
  286.         mul     ninefive                ; times 95 to dx(hi),ax(lo)
  287.         mov     trans.slongp,ax         ; store that much
  288.         xor     ah,ah
  289.         mov     al,12[bx]               ; long packet length, low order byte
  290.         sub     al,20h                  ; apply unchar()
  291.         add     ax,trans.slongp         ; plus high order part
  292.         mov     trans.slongp,ax         ; store it
  293.         or      ax,ax           ; if result is zero then use regular packets
  294.         jnz     spar9a                  ; non-zero, use what they want
  295.         mov     ah,0
  296.         mov     al,trans.spsiz          ; default to regular packet size
  297.         mov     trans.slongp,ax ;  and ignore the CAPAS bit (no def 500 bytes)
  298. spar9a: cmp     ax,trans.slong          ; longer than we want to do?
  299.         jbe     spar9b                  ; be = no
  300.         mov     ax,trans.slong          ; limit to our longest sending size
  301.         mov     trans.slongp,ax         ; and use it
  302. spar9b: cmp     ax,94                   ; shorter than normal packet too?
  303.         ja      spar9c                  ; a = no
  304.         mov     trans.spsiz,al          ; update normal packet size, again.
  305. spar9c: pop     ax                      ; recover al
  306. sparx:  ret
  307. SPAR    ENDP
  308.  
  309. ; Set 8-bit quote character based on my capabilities and the other
  310. ; Kermit's request.
  311.  
  312. DOQUO   PROC    NEAR
  313.         cmp     trans.ebquot,'N'        ; Can I do 8-bit quoting at all?
  314.         je      dq3                     ; No - so forget it.
  315.         cmp     trans.ebquot,'Y'        ; Can I do it if requested?
  316.         jne     dq0                     ; No - it's a must that I do it.
  317.         mov     trans.ebquot,ah         ; Do whatever he wants.
  318.         jmp     dq1
  319. dq0:    cmp     ah,'Y'                  ; I need quoting - can he do it?
  320.         je      dq1                     ; Yes - then all is settled.
  321.         cmp     ah,'N'                  ; No - then don't quote.
  322.         je      dq3
  323.         cmp     ah,trans.ebquot         ; Both need quoting - chars must match
  324.         jne     dq3
  325. dq1:    mov     ah,trans.ebquot
  326.         cmp     ah,'Y'                  ; If Y or N, don't validate prefix.
  327.         je      dq2
  328.         cmp     ah,'N'
  329.         je      dq2
  330.         call    prechk                  ; Is it in range 33-62, 96-126?
  331.          mov    ah,'Y'                  ; Failed, don't do quoting.
  332.          nop
  333.         cmp     ah,trans.rquote         ; Same prefix?
  334.         je      dq3                     ; Not allowed, so don't do quoting.
  335.         cmp     ah,trans.squote         ; Same prefix here?
  336.         je      dq3                     ; This is illegal too.
  337.         mov     trans.ebquot,ah         ; Remember what we decided on.
  338. dq2:    ret
  339. dq3:    mov     trans.ebquot,'N'        ; Quoting will not be done.
  340.         ret
  341. DOQUO   ENDP
  342.  
  343. ; Check if prefix in AH is in the proper range: 33-62, 96-126.
  344. ; RSKP if so else RETURN.
  345. prechk: cmp     ah,33
  346.         jge     prec0                   ; It's above 33.
  347.         ret
  348. prec0:  cmp     ah,62
  349.         jg      prec1
  350.         jmp     rskp                    ; And below 62.  OK.
  351. prec1:  cmp     ah,96
  352.         jge     prec2                   ; It's above 96.
  353.         ret
  354. prec2:  cmp     ah,126
  355.         jg      prec3
  356.         jmp     rskp                    ; And below 126.  OK.
  357. prec3:  ret
  358.  
  359. ; Set checksum length.
  360. dochk:  cmp     ah,'1'                  ; Must be 1, 2, or 3.
  361.         jl      doc1
  362.         cmp     ah,'3'
  363.         jle     doc2
  364. doc1:   mov     ah,'1'
  365. doc2:   sub     ah,48                   ; Don't want it printable.
  366.         mov     trans.chklen,ah         ; other side's request is do-able here
  367.         cmp     ah,trans.chklen         ; Do we want the same thing?
  368.         je      dochk0                  ; Yes, then we're done.
  369.         mov     trans.chklen,1          ; No, use single character checksum.
  370. dochk0: ret                             ; Just return for now.
  371.  
  372. ; Set repeat count quote character.  The one used must be different than
  373. ; the control and eight-bit quote characters.  Also, both sides must
  374. ; use the same character.
  375. dorpt:  call    prechk                  ; Is it in the valid range?
  376.          mov    ah,0                    ; No, don't use their value.
  377.          nop
  378.         cmp     ah,trans.squote         ; Same as the control quote char?
  379.         je      dorpt0                  ; Yes, that's illegal, no repeats.
  380.         cmp     ah,trans.rquote         ; How about this one?
  381.         je      dorpt0                  ; No good.
  382.         cmp     ah,trans.ebquot         ; Same as eight bit quote char?
  383.         je      dorpt0                  ; Yes, that's illegal too, no repeats.
  384.         cmp     ah,ch                   ; Are we planning to use same char?
  385.         jne     dorpt0                  ; No, that's no good either.
  386.         mov     rptq,ch                 ; Use repeat quote char now.
  387. dorpt0: ret
  388.                                         ; negotiate capas byte in ah
  389. decapa: ret                             ; nothing for now
  390.  
  391.                                         ; negotiate window size in ah
  392. dewind: xor     ah,ah                   ; no windowing at our end
  393.         ret
  394.  
  395. ;       Send command
  396.  
  397. SEND    PROC    NEAR
  398.         mov     difsiz,0                ; Assume we'll use original filename.
  399.         mov     byte ptr sendas,0       ; clear sendas name (in case none)
  400.         mov     ah,cmfile               ; get an input file spec
  401.         mov     dx,offset diskio.string ; address of filename string
  402.         mov     bx,offset filmsg        ; Text of help message.
  403.         call    comnd
  404.          jmp    r                       ;  Give up on bad parse.
  405.         cmp     flags.cxzflg,0          ; ^X, ^Z, ^C typed?
  406.         je      send0                   ; e = no, continue
  407.         or      errlev,1                ; say send failed
  408.         jmp     rskp                    ; yes, quit
  409. send0:  cmp     ah,0                    ; any text given?
  410.         ja      send0c                  ; a = yes
  411.  
  412.         mov     dx,offset lclfnm        ; prompt for local filename
  413.         call    prompt
  414.         mov     dx,offset diskio.string ; reload destination of user's text
  415.         mov     bx,offset filhlp        ; help file
  416.         mov     ah,cmfile               ; allow paths
  417.         call    comnd                   ; try again for a local filename
  418.          jmp    r
  419.         cmp     flags.cxzflg,0          ; ^X, ^Z, ^C typed?
  420.         je      send0a                  ; e = no, continue
  421.         or      errlev,1                ; say send failed
  422.         jmp     rskp                    ; yes, quit
  423. send0a: cmp     ah,0                    ; user's byte count
  424.         jne     send0b                  ; something was typed
  425.         jmp     r                   ; else return (gives "not confirmed" msg)
  426.  
  427. send0b: mov     dx,offset remfnm        ; ask for remote name first
  428.         call    prompt
  429.  
  430. send0c: mov     bx,offset sendas     ; See if want to send file under dif name
  431.         mov     dx,offset filhlp        ; In case user needs help.
  432.         mov     ah,cmtxt                ; allow embedded white space
  433.         call    comnd
  434.          jmp    r
  435.         cmp     flags.cxzflg,0          ; ^X, ^Z, ^C typed?
  436.         je      send1                   ; e = no, continue
  437.         or      errlev,1                ; say send failed
  438.         jmp     rskp                    ; yes, quit
  439. send1:  mov     al,ah                   ; store count of user's chars.
  440.         mov     ah,0
  441.         mov     difsiz,ax               ; Remember length of new name.
  442.         mov     bx,offset sendas        ; look at string again.
  443.         push    es
  444.         push    di
  445.         push    si
  446.         mov     ax,ds                   ; use segment 'datas' for es:
  447.         mov     es,ax
  448.         mov     si,bx           ; look at start of string, remove whitespace
  449. send1c: cmp     byte ptr [si],0         ; at terminator?
  450.         je      send1d                  ; e = yes
  451.         cmp     byte ptr [si],' '       ; text (greater than space)?
  452.         ja      send1d                  ; a = yes.
  453.         inc     si                      ; look at next char
  454.         jmp     send1c                  ; look some more
  455. send1d: cmp     bx,si                   ; did we find leading whitespace?
  456.         je      send1e                  ; e = no
  457.         mov     di,bx                   ; place to copy chars
  458.         call    strcpy                  ;   from ds:si to ds:di
  459. send1e: mov     dx,bx                   ; address of string
  460.         call    strlen                  ; get its new length (returned in cx)
  461.         mov     difsiz,cx               ; store it
  462.         pop     si
  463.         pop     di
  464.         pop     es
  465.         mov     ah,trans.sdelay         ; seconds to delay before sending
  466.         shl     ah,1                    ; times 4*256 to get millisec
  467.         shl     ah,1                    ;  for pcwait
  468.         mov     al,1                    ; set low byte to 1 for no delay case
  469.         call    pcwait                  ; wait number of millisec in ax
  470.         mov     flags.xflg,0            ; Reset flag for normal file send[mtd]
  471.         mov     flags.cxzflg,0          ; clear interrupt flag too.
  472.         mov     bx,offset diskio.string
  473.         cmp     byte ptr [bx],'#'       ; Is first char a replacement for '?'?
  474.         jne     send1f                  ; ne = no
  475.         mov     byte ptr [bx],'?'       ; yes. Change '#' for '?'
  476. send1f: mov     bx,offset sendas
  477.         cmp     byte ptr [bx],'#'       ; Is first char a replacement for '?'?
  478.         jne     snd11a
  479.         mov     byte ptr [bx],'?'       ; yes. Change '#' for '?'
  480.         jmp     snd11a
  481.                                 ; SEND11 is an entry point for REMote cmds.
  482. SEND11: mov     flags.nmoflg,0          ; Reset flags from fn parsing.
  483.         mov     difsiz,0                ; clear any old 'sendas' filespec
  484. snd11a: mov     ah,setdma               ; set dta address
  485.         mov     dx,offset diskio.dta
  486.         int     dos
  487.         mov     ah,first2               ; search for first
  488.         mov     cx,0                    ; consider only regular files
  489.         mov     dx,offset diskio.string ; full filename, inc paths
  490.         int     dos
  491.         pushf                           ; save flags
  492.         push    dx
  493.         mov     ah,setdma               ; restore dta to offset buff
  494.         mov     dx,offset buff
  495.         int     dos
  496.         pop     dx
  497.         popf                            ; restore flags
  498.         jnc     send16                  ; carry reset = file found
  499.         cmp     pack.state,'R'          ; was this from a remote GET?
  500.         jne     sen11a                  ; no, print error and continue
  501.         mov     bx,offset remmsg1       ; else get error message
  502.         mov     ah,trans.chklen
  503.         mov     curchk,ah               ; Store checksum length we want to use
  504.         mov     trans.chklen,1          ; Send init checksum is always 1 char.
  505.         call    errpack                 ; go complain
  506.         mov     ah,curchk
  507.         mov     trans.chklen,ah         ; Checksum length we want to use.
  508.         jmp     abort                   ; and abort this
  509. sen11a: mov     ah,prstr
  510.         mov     dx,offset crlf
  511.         int     dos
  512.         mov     ah,prstr
  513.         mov     dx,offset erms15        ; '?Unable to find file'
  514.         int     dos
  515.         or      errlev,1                ; set DOS error level
  516.         mov     ax,1            ; tell statistics this was a send operation
  517.         call    endtim                  ; stop statistics counter
  518.         jmp     rskp                    ; pretend successful completion
  519.  
  520. send16: call    serini                  ; Initialize serial port
  521.         mov     ax,1                    ; say this is a send operation
  522.         call    endtim                  ; get tod for end of transfer
  523.         call    begtim                  ; get tod for start of transfer
  524.         mov     pack.pktnum,0           ; Set the packet number to zero.
  525.         mov     pack.numtry,0           ; Set the number of tries to zero.
  526.         mov     pack.numpkt,0           ; Set the number of packets to zero.
  527.         mov     pack.numrtr,0           ; Set the number of retries to zero.
  528.         mov     pack.state,'S'          ; Set the state to receive initiate.
  529.         call    ihosts                  ; initialize the host (clear NAKs)
  530.         call    init            ; Clear the line and initialize the buffers.
  531.         test    flags.remflg,dquiet+dserial ; quiet or serial display mode?
  532.         jnz     send2                   ; nz = yes, suppress 0 retry msg
  533.         call    stpos                   ; Print status of file transfer.
  534.         mov     ah,prstr                ; Be informative.
  535.         mov     dx,offset infms2
  536.         int     dos
  537. send18: test    flags.remflg,dquiet+dserial ; quiet or serial display mode?
  538.         jnz     send2                   ; nz = yes, suppress 0 retry msg
  539.         call    rtpos                   ; Position cursor.
  540.         mov     ax,0                    ; set retry counts to zero
  541.         call    nout                    ; Write the number of retries.
  542. send2:  call    nppos                   ; Number of packets sent.
  543.         mov     ax,pack.numpkt
  544.         call    nout                    ; Write the packet number.
  545.         cmp     pack.state,'D'          ; Are we in the data send state?
  546.         jne     send3                   ; ne = no
  547.         call    sdata                   ; send data
  548.         jmp     send2
  549.  
  550. send3:  cmp     pack.state,'F'          ; Are we in the file send state?
  551.         jne     send4
  552.         call    sfile                   ; Call send file.
  553.         jmp     send2
  554. send4:  cmp     pack.state,'Z'          ; Are we in the EOF state?
  555.         jne     send5
  556.         call    seof
  557.         jmp     send2
  558. send5:  cmp     pack.state,'S'          ; Are we in the send initiate state?
  559.         jne     send6
  560.         call    sinit
  561.         jmp     send2
  562. send6:  cmp     pack.state,'B'          ; Are we in the eot state?
  563.         jne     send7
  564.         call    seot
  565.         jmp     send2
  566.                                         ; Completion processor section
  567. send7:  push    ax
  568.         mov     ax,1            ; tell statistics this was a send operation
  569.         call    endtim                  ; stop statistics counter
  570.         call    serrst                  ; Reset serial port.
  571.         pop     ax
  572.         mov     dx,offset infms3        ; Completed message
  573.         cmp     pack.state,'C'          ; Are we in the send complete state?
  574.         je      send8                   ; e = yes, else failure
  575.         mov     dx,offset infms4        ; Failed message
  576.         or      errlev,1                ; say send failed
  577.  
  578. send8:  cmp     flags.cxzflg,0          ; completed normally?
  579.         jne     send8b                  ; ne = no, don't bother with this
  580.         or      errlev,1                ; say send failed
  581. send8b: test    flags.remflg,dquiet     ; quiet display mode?
  582.         jnz     send8f                  ; nz = yes, no printing.
  583.         test    flags.remflg,dserial    ; serial display mode?
  584.         jnz     send8c                  ; nz = yes, skip positioning
  585.         push    dx
  586.         call    stpos
  587.         pop     dx
  588. send8c: mov     ah,prstr
  589.         cmp     flags.cxzflg,0          ; Completed or interrupted?
  590.         je      send8d                  ; e = no interruption
  591.         mov     dx,offset infms6        ; Say transfer was interrupted.
  592. send8d: int     dos
  593.         cmp     flags.belflg,0          ; Bell desired?
  594.         je      send8e                  ; e = no
  595.         mov     dx,offset ender         ; Ring them bells.
  596.         int     dos
  597. send8e: test    flags.remflg,dserial    ; serial display mode?
  598.         jnz     send8f                  ; nz = yes, no cursor positioning
  599.         call    clrmod
  600.         call    rprpos
  601. send8f: jmp     rskp
  602. SEND    ENDP
  603.  
  604. ;       Send routines
  605.  
  606. ;       Send initiate
  607. SINIT   PROC    NEAR
  608.         mov     dl,imxtry
  609.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  610.         jl      sinit2                  ; l = no
  611.         test    flags.remflg,dquiet     ; quiet display mode?
  612.         jnz     sinit1                  ; nz = yes. Don't write to screen.
  613.         call    erpos
  614.         mov     dx,offset erms14
  615.         mov     ah,prstr
  616.         int     dos                     ; Print an error message.
  617. sinit1: mov     ah,trans.chklen
  618.         mov     curchk,ah               ; Store checksum length we want to use
  619.         mov     trans.chklen,1          ; Send init checksum is always 1 char.
  620.         mov     bx,offset erms20
  621.         call    errpack                 ; Send error packet just in case.
  622.         mov     ah,curchk
  623.         mov     trans.chklen,ah         ; Checksum length we want to use.
  624.         jmp     abort                   ; Change the state to abort.
  625. sinit2: inc     pack.numtry             ; Save the updated number of tries.
  626.         mov     bx,offset data          ; Get a pointer to our data block.
  627.         call    rpar                    ; Set up the parameter information.
  628.         xchg    ah,al
  629.         mov     ah,dtrans.seol          ; restore default end-of-line char
  630.         mov     trans.seol,ah
  631.         mov     ah,0
  632.         mov     pack.argbk1,ax          ; Save the number of arguments.
  633.         mov     ax,pack.numpkt          ; Get the packet number.
  634.         mov     pack.argblk,ax
  635.         mov     trans.ebquot,'Y'        ; say we can do 8 bit quoting
  636.         push    bx
  637.         mov     bx,portval
  638.         cmp     [bx].parflg,parnon      ; using parity=none locally?
  639.         pop     bx
  640.         je      sinit2a                 ; e = no parity
  641.         mov     trans.ebquot,dqbin      ; def 8 bit quot, needed with parity
  642. sinit2a:mov     ah,trans.chklen
  643.         mov     curchk,ah               ; Store checksum length we want to use
  644.         mov     trans.chklen,1          ; Send init checksum is always 1 char.
  645.         call    pktsize                 ; report packet size
  646.         mov     ah,'S'                  ; Send initiate packet.
  647.         call    spack                   ; Send the packet.
  648.          jmp    abort
  649.         call    rpack                   ; Get a packet.
  650.          jmp    sini23          ; Trashed packet don't change state, retry.
  651.         push    ax
  652.         mov     ah,curchk
  653.         mov     trans.chklen,ah         ; Checksum length we want to use.
  654.         pop     ax
  655.         call    acknak                  ; was it ok?
  656.         cmp     al,0                    ; maybe an ack?
  657.         je      sini22                  ; yes, go handle it
  658.         cmp     al,1                    ; maybe a nak?
  659.         jne     sinit4                  ; no, check for error or something
  660.         ret                             ; else just return and try again
  661. sini22: mov     ax,pack.argbk1
  662.         mov     bx,offset data          ; point to data for spar
  663.         call    spar                    ; Read in the data.
  664.         call    packlen                 ; Get max send packet size.
  665.         mov     pack.numtry,0           ; Reset the number of tries.
  666.         mov     pack.state,'F'          ; Set the state to file send.
  667.         call    getfil                  ; Open the file.
  668.          jmp    abort                   ;  Something is wrong, die.
  669.         mov     filopn,1                ; Disk file is open.
  670.         ret
  671. sini23: mov     ah,curchk               ; Restore desired checksum length.
  672.         mov     trans.chklen,ah
  673.         call    updrtr                  ; Update retry counter.
  674.         ret                             ; And retry.
  675. sinit4: cmp     ah,'E'                  ; Is it an error packet.
  676.         jne     sinit5
  677.         call    error
  678. sinit5: jmp     abort
  679. SINIT   ENDP
  680.  
  681. ;       Send file header
  682.  
  683. SFILE   PROC    NEAR
  684.         mov     dl,maxtry
  685.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  686.         jl      sfile1                  ; l = no
  687.         test    flags.remflg,dquiet     ; quiet display mode?
  688.         jnz     sfile0                  ; nz = yes. Don't write to screen
  689.         call    erpos
  690.         mov     dx,offset erms14
  691.         mov     ah,prstr
  692.         int     dos                     ; Print an error message.
  693. sfile0: mov     bx,offset erms21
  694.         call    errpack                 ; Send error packet just in case.
  695.         jmp     abort                   ; Change the state to abort.
  696. sfile1: inc     pack.numtry             ; Increment it.
  697.         mov     flags.cxzflg,0          ; Clear ^X,^Z flag.
  698.         mov     si,offset diskio.fname  ;addr of asciiz filename without paths
  699.         mov     di,offset data          ; destination
  700.         call    strcpy                  ; copy filename there
  701.         push    dx
  702.         mov     dx,offset data
  703.         call    strlen                  ; get length (w/o terminator) into cx
  704.         pop     dx
  705.         mov     ch,0
  706.         test    flags.remflg,dquiet     ; quiet display mode?
  707.         jnz     sfil13                  ; nz = yes, no printing.
  708.         call    prtfn                   ; print filename in data
  709. sfil13: call    newfn           ; show possible new filename, put length in cx
  710.         call    doenc                   ; Do encoding; length is in cx.
  711.         mov     ax,pack.pktnum          ; Get the packet number.
  712.         mov     pack.argblk,ax
  713.         mov     ah,'F'                  ; File header packet.
  714.         cmp     flags.xflg,0            ; remote display requested?
  715.         je      sfl13y                  ; e = no
  716.         mov     ah,'X'          ; use X rather than F packet for remote
  717. sfl13y: call    pktsize                 ; report packet size
  718.         call    spack                   ; Send the packet.
  719.          jmp    abort
  720.         call    rpack                   ; Get a packet.
  721.          jmp    tryagn          ; Trashed packet don't change state, retry.
  722.         call    dodec                   ; Do all decoding.
  723.         call    acknak                  ; see what they had to say
  724.         cmp     al,0                    ; ack'd ok?
  725.         je      sfil14                  ; yes, on to next state
  726.         cmp     al,1                    ; maybe a nak?
  727.         jne     sfile3                  ; no, check for error
  728.         ret                             ; if nak, just return and try again
  729.  
  730. sfil14: mov     flags.filflg,0FFH       ; Indicate file buffer empty.
  731.         call    gtchr
  732.          jmp    sfil16                  ; Error go see if its EOF.
  733.          nop
  734.         jmp     sfil17                  ; Got the chars, proceed.
  735. sfil16: cmp     ah,0FFH                 ; Is it EOF?
  736.         je      sfl161
  737.         jmp     abort                   ; If not give up.
  738.  
  739. sfl161: mov     ah,'Z'                  ; Set the state to EOF.
  740.         mov     pack.state,ah
  741.         ret
  742.  
  743. sfil17: mov     siz,ax
  744.         mov     pack.state,'D'          ; Set the state to data send.
  745.         ret
  746.  
  747. sfile3: cmp     ah,'E'                  ; Is it an error packet.
  748.         jne     sfile4
  749.         call    error
  750. sfile4: jmp     abort
  751. SFILE   ENDP
  752.  
  753.  
  754. ;       Send data
  755.  
  756. SDATA   PROC    NEAR
  757.         cmp     flags.cxzflg,0          ; Have we seen ^X or ^Z?
  758.         je      sdata2                  ; Nope, just continue.
  759.         cmp     flags.cxzflg,'C'        ; Stop it all?
  760.         jne     sdata1                  ; It was a ^X or ^Z.
  761.         mov     pack.state,'A'          ; It was a ^C -- abort
  762.         ret
  763. sdata1: mov     pack.state,'Z'          ; Else, abort sending the file.
  764.         ret
  765. sdata2: mov     dl,maxtry
  766.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  767.         jl      sdata3                  ; l = no
  768.         test    flags.remflg,dquiet     ; quiet display mode?
  769.         jnz     sdat2a                  ; nz = yes. Don't write to screen
  770.         call    erpos
  771.         mov     dx,offset erms14
  772.         mov     ah,prstr
  773.         int     dos                     ; Print an error message.
  774. sdat2a: mov     bx,offset erms22
  775.         call    errpack                 ; Send error packet just in case.
  776.         jmp     abort                   ; Change the state to abort.
  777. sdata3: inc     pack.numtry             ; Increment it.
  778.         mov     cx,siz                  ; number to transfer
  779.         mov     si,offset filbuf        ; source of characters
  780.         mov     di,offset data          ; destination
  781.         push    es                      ; save es
  782.         push    ds
  783.         pop     es                      ; make es:di point to datas segment
  784.         cld
  785.         rep     movsb                   ; just copy data
  786.         pop     es                      ; restore reg
  787.         mov     ax,siz                  ; this is how many were moved
  788. sdata7: mov     pack.argbk1,ax
  789.         mov     ax,pack.pktnum          ; Get the packet number.
  790.         mov     pack.argblk,ax
  791.         call    pktsize                 ; report packet size
  792.         mov     ah,'D'                  ; Data packet.
  793.         call    spack                   ; Send the packet.
  794.          jmp    tryagn          ; if can't send it, retry before giving up
  795.         call    rpack                   ; Get a packet.
  796.          jmp    tryagn          ; Trashed packet don't change state, retry.
  797.         call    dodec                   ; Do all decoding.
  798.         call    acknak          ; see if ack or nak, check packet number
  799.         cmp     al,0                    ; 0 => ack ok, go on
  800.         je      sdat11
  801.         cmp     al,1            ; 1 => nak, retry count incremented, try again
  802.         jne     sdat15                  ; else look for other packet types...
  803.         ret                             ; else return
  804.  
  805. sdat11: cmp     pack.argbk1,1           ; any data?
  806.         jne     sdat23
  807.         mov     bl,data                 ; get 1st byte
  808.         cmp     bl,'X'                  ; someone typed control X?
  809.         je      sdat24                  ; e = yes.
  810.         cmp     bl,'Z'          ; Control Z? Corrects earlier proto error
  811.         jne     sdat23                  ; not X or Z, just keep going
  812. sdat24: mov     flags.cxzflg,bl         ; set flag appropriately
  813.         mov     pack.state,'Z'          ; simulate eof
  814.         ret                             ; and return
  815.  
  816. sdat23: call    gtchr
  817.          jmp    sdat12                  ; Error go see if its EOF.
  818.          nop                            ; make  three bytes
  819.         mov     siz,ax                  ; Save the size of the data gotten.
  820.         ret
  821.  
  822. sdat12: cmp     ah,0FFH                 ; Is it EOF?
  823.         je      sdat13
  824.         jmp     abort                   ; If not give up.
  825.  
  826. sdat13: mov     pack.state,'Z'          ; Set the state to EOF.
  827.         ret
  828.  
  829. sdat15: cmp     ah,'E'                  ; Is it an error packet.
  830.         jne     sdat16
  831.         call    error
  832. sdat16: jmp     abort
  833. SDATA   ENDP
  834.  
  835. ; check the current packet for an ack or nak and handle it from any of
  836. ; the send states.  Returns: 0 if an ack received with the correct expected
  837. ; packet number, or if a nak received with the NEXT packet number (the
  838. ; packet number is incremented, retry count reset); 1 if a nak or ack
  839. ; with a bad packet number is received, retry count is updated and displayed.
  840. ; Finally, 2 is returned if anything else is seen.
  841. ;
  842.  
  843. ACKNAK  PROC    NEAR
  844.         cmp     ah,'Y'                  ; ack packet?
  845.         jne     ackna1                  ; no, keep going
  846.         mov     bx,pack.pktnum
  847.         cmp     bx,pack.argblk          ; is it what we were expecting?
  848.         jne     ackna2                  ; no, update retries and punt
  849.                                         ; packet ok, increment packet number
  850. ackna0: mov     bx,pack.pktnum          ; reload packet number (!!!)
  851.         inc     bx
  852.         and     bx,03fh                 ; increment packet number
  853.         mov     pack.pktnum,bx          ; store back
  854.         inc     pack.numpkt             ; increment # of packets
  855.         mov     pack.numtry,0
  856.         mov     al,0                    ; ack'd ok
  857.         ret
  858.                                         ; not a 'Y'...
  859. ackna1: cmp     ah,'N'                  ; a nak?
  860.         je      ackna5                  ; yes, go on
  861.         mov     al,2
  862.         ret                             ; unknown packet type
  863. ackna5: mov     bx,pack.pktnum
  864.         inc     bx
  865.         and     bx,3fh
  866.         cmp     bx,pack.argblk          ; maybe a nak for pktnum+1?
  867.         je      ackna0                  ; yes, treat as ack
  868.                                         ; nak or bad ack, update retry stuff
  869. ackna2: call    rtpos                   ; Position cursor.
  870.         inc     pack.numrtr             ; Increment the number of retries
  871.         mov     ax,pack.numrtr
  872.         call    nout                    ; Write the number of retries.
  873.         mov     al,1                    ; nak code
  874.         inc     fsta.nakrcnt            ; count received NAK for statistics
  875.         ret                             ; and return
  876. ACKNAK  ENDP
  877.  
  878. ;       Send EOF
  879.  
  880. SEOF    PROC    NEAR
  881.         mov     dl,maxtry
  882.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  883.         jl      seof1                   ; l = no
  884.         test    flags.remflg,dquiet; quiet display mode?
  885.         jnz     seof0                   ; nz = yes. Don't write to screen
  886.         call    erpos                   ; Position cursor.
  887.         mov     dx,offset erms14
  888.         mov     ah,prstr
  889.         int     dos                     ; Print an error message.
  890. seof0:  mov     bx,offset erms23
  891.         call    errpack                 ; Send error packet just in case.
  892.         jmp     abort                   ; Change the state to abort.
  893. seof1:  inc     pack.numtry             ; Increment it.
  894.         mov     ax,pack.pktnum          ; Get the packet number.
  895.         mov     pack.argblk,ax
  896.         mov     pack.argbk1,0           ; No data.
  897.         cmp     flags.cxzflg,0          ; Seen a ^X or ^Z?
  898.         je      seof11                  ; Nope, send normal EOF packet.
  899.         mov     data,'D'                ; Use "D" for discard.
  900.         mov     pack.argbk1,1           ; Set data size to 1.
  901. seof11: mov     cx,pack.argbk1          ; Put size in CX.
  902.         call    doenc                   ; Encode the packet.
  903.         call    pktsize                 ; report packet size
  904.         mov     ah,'Z'                  ; EOF packet.
  905.         call    spack                   ; Send the packet.
  906.          jmp    abort
  907.         call    rpack                   ; Get a packet.
  908.          jmp    tryagn          ;  Trashed packet don't change state, retry.
  909.         call    dodec                   ; Do decoding.
  910.         call    acknak                  ; see what they had to say
  911.         cmp     al,0                    ; ack?
  912.         je      seof12                  ; yes, go close file and proceed
  913.         cmp     al,1                    ; maybe a nak?
  914.         jne     seof3                   ; no, check for error packet
  915.         ret                             ; if nak, just return...
  916.  
  917. seof12: mov     ah,close2               ; DOS 2.0 close file
  918.         push    bx
  919.         mov     bx,diskio.handle        ; file handle
  920.         int     dos
  921.         pop     bx
  922.         mov     ax,1            ; tell statistics this was a send operation
  923.         call    endtim                  ; get tod of end of file transfer
  924.         call    GTNFIL                  ; Get the next file.
  925.          jmp    seof13                  ;  No more.
  926.          nop                            ; make three bytes
  927.         call    begtim                  ; start statistics counter
  928.  
  929.         mov     pack.state,'F'          ; Set the state to file send.
  930.         cmp     flags.cxzflg,'X'        ; Control-X seen?
  931.         jne     seof14
  932.         call    cxmsg                   ; Clear out the interrupt msg.
  933. seof14: mov     flags.cxzflg,0          ; Reset the flag.
  934.         ret
  935. seof13: mov     pack.state,'B'          ; Set the state to EOT.
  936.         mov     filopn,0                ; No files open.
  937.         mov     difsiz,0                ; clear original filename
  938.         mov     byte ptr sendas,0       ; clear sendas name
  939.         ret
  940. seof3:  cmp     ah,'E'                  ; Is it an error packet?
  941.         jne     seof4
  942.         call    error
  943. seof4:  jmp     abort
  944. SEOF    ENDP
  945.  
  946.  
  947. ; Send EOT
  948.  
  949. SEOT    PROC    NEAR
  950.         mov     dl,maxtry
  951.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  952.         jl      seot1                   ; l = no
  953.         test    flags.remflg,dquiet     ; quiet display mode?
  954.         jnz     seot0                   ; nz = yes. Don't write to screen
  955.         call    erpos                   ; Position cursor.
  956.         mov     dx,offset erms14
  957.         mov     ah,prstr
  958.         int     dos                     ; Print an error message.
  959. seot0:  mov     bx,offset erms24
  960.         call    errpack                 ; Send error packet just in case.
  961.         jmp     abort                   ; Change the state to abort.
  962. seot1:  inc     pack.numtry             ; Increment it.
  963.         mov     ax,pack.pktnum          ; Get the packet number.
  964.         mov     pack.argblk,ax
  965.         mov     pack.argbk1,0           ; No data.
  966.         call    pktsize                 ; report packet size
  967.         mov     ah,'B'                  ; EOF packet.
  968.         call    spack                   ; Send the packet.
  969.          jmp    abort
  970.         call    rpack                   ; Get a packet.
  971.          jmp    tryagn          ; Trashed packet don't change state, retry.
  972.         call    dodec                   ; Decode packet.
  973.         call    acknak                  ; see if good ack or nak
  974.         cmp     al,0                    ; ack'd ok?
  975.         je      seot12                  ; yes, done with this
  976.         cmp     al,1                    ; maybe a nak?
  977.         jne     seot3                   ; no, check for error
  978.         ret                             ; else just return
  979. seot12: mov     pack.state,'C'          ; Set the state to file send.
  980.         ret
  981.  
  982. seot3:  cmp     ah,'E'                  ; Is it an error packet.
  983.         jne     seot4
  984.         call    error
  985. seot4:  jmp     abort
  986. SEOT    ENDP
  987.  
  988. tryagn: call    updrtr
  989.         ret
  990.  
  991. ; newfn -- move replacement name from buffer sendas to buffer data
  992.  
  993. newfn:  cmp     difsiz,0                ; Sending file under different name?
  994.         je      newf4                   ; e = no, so don't give new name
  995.         test    flags.remflg,dquiet     ; quiet display mode?
  996.         jnz     newfa                   ; nz = yes. Don't write to screen
  997.         mov     ah,prstr
  998.         mov     dx,offset asmsg ; display ' as '
  999.         int     dos
  1000.         mov     ah,conout               ; use printable output
  1001. newfa:  mov     si,offset sendas        ; Buffer where the name is
  1002.         mov     di,offset data
  1003.         mov     cx,difsiz               ; Length of name.
  1004.         inc     cx                      ; plus null terminator
  1005. newf0:  lodsb                           ; Get a character into al.
  1006.         stosb
  1007.         test    flags.remflg,dquiet    ; quiet display mode (should we print)?
  1008.         jnz     newf2                   ; nz = yes
  1009.         mov     dl,al                   ; set into dl for display
  1010.         int     dos                     ; Print them.
  1011. newf2:  loop    newf0
  1012.         mov     cx,difsiz               ; Reset the length field.
  1013. newf4:  test    flags.remflg,dserial    ; serial display mode?
  1014.         jz      newf5                   ; z = no
  1015.         push    ax
  1016.         push    dx
  1017.         mov     dx,offset crlf          ; start with cr/lf for serial display
  1018.         mov     ah,prstr
  1019.         int     dos
  1020.         pop     dx
  1021.         pop     ax
  1022. newf5:  ret
  1023.  
  1024. ; Do encoding.  Expect CX to be the data size.
  1025.  
  1026. doenc:  jcxz    doen0
  1027.         mov     chrcnt,cx               ; Number of bytes of source data
  1028.         mov     bufpnt,offset data      ; Source of data.
  1029.         mov     bx,offset nulref        ; Null routine for refilling buffer.
  1030.         mov     ah,rptq
  1031.         mov     origr,ah                ; Save repeat prefix here.
  1032.         mov     rptct,1                 ; Number of times char is repeated.
  1033.         mov     rptval,0                ; Value of repeated char.
  1034.         call    encode                  ; Make a packet with size in AX.
  1035.          nop
  1036.          nop
  1037.          nop
  1038.         mov     pack.argbk1,ax          ; Store length of data field
  1039.         mov     cx,ax
  1040.         call    movpak                  ; Move to data part of packet.
  1041.         cmp     chrcnt,0                ; Did all chars fit into the buffer?
  1042.         jne     doen1                   ; ne = no, we have an error condition
  1043.         clc                             ; clear c bit for success
  1044. doen0:  ret
  1045. doen1:  stc                             ; set c bit for did not fit condition
  1046.         ret
  1047. ; CX is set before this is called.
  1048. movpak: push    es
  1049.         mov     ax,ds
  1050.         mov     es,ax
  1051.         cld
  1052.         mov     si,offset filbuf        ; Move from here
  1053.         mov     di,offset data          ; to here
  1054.         cmp     cx,0
  1055.         jle     movpak1
  1056.         repne   movsb
  1057. movpak1:pop     es
  1058.         ret
  1059.  
  1060. ; Dodecoding.
  1061. dodec:
  1062.         mov     cx,pack.argbk1          ; Size of data.
  1063.         jcxz    dodc0                   ; z = nothing to transfer
  1064.         push    ax                      ; Save packet size.
  1065.         mov     bx,offset data          ; Address of data.
  1066.         mov     ax,offset nulr          ; Routine to dump buffer (null)
  1067.         mov     bufpnt,offset decbuf    ; Where to put output.
  1068.         mov     chrcnt,maxpack          ; Buffer size
  1069.         call    decode
  1070.          nop
  1071.          nop
  1072.          nop
  1073.         call    decmov          ; Move decoded data back to "data" buffer.
  1074.         pop     ax
  1075. dodc0:  ret
  1076.  
  1077. ; Move decoded data from decode buffer back to "data".
  1078. decmov: push    si
  1079.         push    di
  1080.         push    es
  1081.         mov     ax,ds
  1082.         mov     es,ax
  1083.         cld
  1084.         mov     cx,bufpnt               ; Last char we added.
  1085.         sub     cx,offset decbuf        ; Get actual number of characters.
  1086.         mov     pack.argbk1,cx          ; Remember size of real data.
  1087.         mov     si,offset decbuf        ; Data is here
  1088.         mov     di,offset data          ; Move to here
  1089.         cmp     cx,0
  1090.         jle     decmov1                 ; le = none to do
  1091.         repne   movsb                   ; Copy the data.
  1092. decmov1:mov     al,0                    ; Null to end the string.
  1093.         stosb
  1094.         pop     es
  1095.         pop     di
  1096.         pop     si
  1097.         ret
  1098.  
  1099. ;       Abort
  1100.  
  1101. ABORT   PROC    NEAR
  1102.         mov     difsiz,0                ; clear original filename
  1103.         mov     byte ptr sendas,0       ; clear sendas name
  1104.         cmp     filopn,0                ; Any disk files open?
  1105.         je      abort0                  ; No so don't do a close.
  1106.         mov     ah,close2               ; DOS 2.0 close file
  1107.         push    bx
  1108.         mov     bx,diskio.handle        ; file handle
  1109.         int     dos
  1110.         pop     bx
  1111.         mov     filopn,0                ; say file is closed now
  1112. abort0: mov     pack.state,'A'          ; Otherwise abort.
  1113.         or      errlev,1                ; set DOS error level
  1114.         ret
  1115. ABORT   ENDP
  1116.  
  1117. ; This is where we go if we get an error packet.  A call to ERROR
  1118. ; positions the cursor and prints the message.  A call to ERROR1
  1119. ; just prints a CRLF and then the message.
  1120.  
  1121. ERROR   PROC    NEAR
  1122.         mov     pack.state,'A'          ; Set the state to abort.
  1123.         test    flags.remflg,dquiet     ; quiet display mode?
  1124.         jnz     errorx                  ; nz = yes. Don't write to screen
  1125.         call    erpos                   ; Position the cursor.
  1126.         jmp     error2
  1127. ERROR1: mov     ah,prstr                ; entry point for Server Generic cmds.
  1128.         mov     dx,offset crlf
  1129.         int     dos
  1130. error2: push    bx
  1131.         mov     bx,pack.argbk1          ; Get the length of the data.
  1132.         add     bx,offset data          ; Get to the end of the string.
  1133.         mov     ah,'$'                  ; Put a dollar sign at the end.
  1134.         mov     [bx],ah
  1135.         mov     ah,prstr                ; Print the error message.
  1136.         mov     dx,offset data
  1137.         int     dos
  1138.         pop     bx
  1139. errorx: ret
  1140. ERROR   ENDP
  1141.  
  1142. ; Set the maximum send data packet size; modified for long packets.
  1143. PACKLEN PROC    NEAR
  1144.         push    ax
  1145.         push    cx
  1146.         xor     ah,ah
  1147.         mov     al,trans.spsiz  ; Maximum send packet size for Regular pkts.
  1148.         cmp     ax,trans.slongp         ; negotiated long packet max size
  1149.         jae     pack2                   ; ae = use regular packets
  1150.         mov     ax,trans.slongp         ; else use long kind
  1151.         sub     ax,3                    ; minus extended count & checksum
  1152.         cmp     ax,(95*94-1-2)          ; longer than Long?
  1153.         jle     pack2                   ; le = no, Long will do
  1154.         dec     ax                      ; minus one more for extra long count
  1155. pack2:  sub     ax,2                    ; minus Sequence, Type
  1156.         sub     al,trans.chklen         ; And minus Checksum chars.
  1157.         sbb     ah,0                    ; borrow propagate
  1158.         cmp     trans.ebquot,'N'        ; Doing 8-bit Quoting?
  1159.         je      pack0                   ; Nope so we've got our size.
  1160.         cmp     trans.ebquot,'Y'
  1161.         je      pack0                   ; Not doing it in this case either.
  1162.         dec     ax                      ; Another 1 for 8th-bit Quoting.
  1163. pack0:  cmp     rptq,0                  ; Doing repeat character Quoting?
  1164.         je      pack1                   ; Nope, so that's all for now.
  1165.         dec     ax                      ; minus repeat prefix
  1166.         dec     ax                      ;  and repeat count
  1167. pack1:  dec     ax                  ; for last char might being a control code
  1168.         mov     trans.maxdat,ax         ; Save max length for data field.
  1169.         pop     cx
  1170.         pop     ax
  1171.         ret
  1172. PACKLEN ENDP
  1173.  
  1174.  ; Print the number in AX on the screen in decimal rather that hex.
  1175.  
  1176. NOUT    PROC    NEAR
  1177.         test    flags.remflg,dserial    ; serial display mode?
  1178.         jnz     pnout               ; nz = use "dot and plus" for serial mode
  1179.         test    flags.remflg,dquiet     ; quiet display mode?
  1180.         jnz     nout1                   ; nz = yes. Don't write to screen
  1181.         call    decout                  ; call standard decimal output routine
  1182. nout1:  ret
  1183.  
  1184.  
  1185. pnout:  or      ax,ax                   ; display packet in serial display mode
  1186.         jz      pnoutx                  ; z = nothing to display
  1187.         push    ax                      ; for serial mode display
  1188.         push    dx                      ; output .........+.........+  etc
  1189.         mov     temp,10
  1190.         mov     dx,0
  1191.         div     temp                    ; number/10. (AX=quo, DX=rem)
  1192.         push    ax                      ; save around printing
  1193.         push    dx                      ; save around initial printing
  1194.         cmp     dx,0                    ; remainder non-zero?
  1195.         jne     pnout1                  ; ne = yes
  1196.         mov     dl,'+'                  ; symbol plus for tens
  1197.         jmp     pnout2                  ; display it
  1198. pnout1: mov     dl,'.'                  ; symbol for between tens
  1199. pnout2: mov     ah,conout               ; output to console
  1200.         int     dos
  1201.         pop     dx                      ; recover remainder
  1202.         pop     ax                      ; recover quotient
  1203.         or      dx,dx           ; check for multiples of 70, to break lines
  1204.         jnz     pnout3                  ; nz = non-zero remainder, just exit
  1205.         mov     temp,7          ; divide ax by 7 (dx is zero by construction)
  1206.         div     temp                    ; ax = quotient, dx = remainder
  1207.         or      dx,dx                   ; zero remainder?
  1208.         jnz     pnout3                  ; nz = non-zero remainder, just exit
  1209.         mov     ah,prstr                ; output cr/lf after every 70th chars
  1210.         mov     dx,offset crlf
  1211.         int     dos
  1212. pnout3: pop     dx
  1213.         pop     ax
  1214. pnoutx: ret
  1215. NOUT    ENDP
  1216.  
  1217. ; Jumping to this location is like retskp.  It assumes the instruction
  1218. ;   after the call is a jmp addr.
  1219.  
  1220. RSKP    PROC    NEAR
  1221.         pop     bp
  1222.         add     bp,3
  1223.         push    bp
  1224.         ret
  1225. RSKP    ENDP
  1226.  
  1227. ; Jumping here is the same as a ret.
  1228.  
  1229. R       PROC    NEAR
  1230.         ret
  1231. R       ENDP
  1232.  
  1233. code    ends
  1234.         end
  1235.