home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccsrcv.asm < prev    next >
Assembly Source File  |  2020-01-01  |  48KB  |  982 lines

  1.         NAME    ccsrcv
  2. ; File CCSRCV.ASM
  3.  
  4. ;CHINESE
  5. ifdef   MSDOS
  6.         include mssrcv.dat
  7. else
  8.         include ccsrcv.dat
  9. endif
  10.  
  11. code    segment public 'code'
  12.         extrn   gofil:near, outbuf:near, comnd:near
  13.         extrn   spack:near, rpack:near, serini:near, serrst:near
  14.         extrn   spar:near, rpar:near, init:near, cxmsg:near, perpos:near
  15.         extrn   error:near, error1:near, ptchr:near, erpos:near, rtpos:near
  16.         extrn   stpos:near, rprpos:near, nppos:near, nout:near
  17.         extrn   dodec:near, doenc:near, errpack:near, intmsg:near
  18.         extrn   send11:near, clrmod:near, ihostr:near
  19.         extrn   begtim:near, endtim:near, pktsize:near,strlen:near,strcpy:near
  20.         assume  cs:code, ds:datas
  21.  
  22. ; Update retry count and fall through to send a NAK
  23.  
  24. NAK0:   call    updrtr                  ; Update retry count
  25. nak1:   cmp     flags.cxzflg,'E'        ; Protocol abort sign?
  26.         jne     nak2                    ; ne = no
  27.         ret                             ; return to do current ('A') state
  28. nak2:   cmp     flags.cxzflg,'C'        ; Control-C abort?
  29.         jne     nak                     ; ne = no
  30.         mov     pack.state,'A'          ; set Abort state
  31.         ret
  32.  
  33. NAK:    mov     ax,pack.pktnum       ; Get the packet number we're waiting for
  34.         mov     pack.seqnum,ax
  35.         mov     pack.datlen,0           ; no data
  36.         add     fsta.nakscnt,1          ; count NAKs sent
  37.         mov     ah,'N'                  ; NAK that packet
  38.         call    spack
  39.          jmp    abort                   ; failed
  40.          nop
  41.         ret
  42.  
  43. updrtr: cmp     pack.state,'A'          ; Supposed to abort?
  44.         je      upd0                    ; Yes, don't bother with retry count
  45.         inc     pack.numrtr             ; Increment the number of retries
  46.         cmp     flags.xflg,1            ; Writing to screen?
  47.         je      upd0                    ; e = yes, skip this
  48.         cmp     pack.numrtr,0           ; non-zero item to display?
  49.         je      upd0                    ; nothing to display
  50.         push    ax                      ; save packet type in ah
  51.         call    rtpos                   ; Position cursor
  52.         mov     ax,pack.numrtr
  53.         call    nout                    ; Write the number of retries
  54.         pop     ax                      ; recover packet type in ah
  55. upd0:   ret
  56.  
  57. ;       Abort
  58. ABORT   PROC    NEAR
  59.         cmp     filopn,0                ; Disk file open?
  60.         je      abort0                  ; e = no so don't close
  61.         cmp     flags.xflg,1            ; Writing to the screen?
  62.         je      abort0                  ; Yes, don't close "file"
  63.         call    outbuf          ; flush last buffer to disk, ignore errors
  64.          nop
  65.          nop
  66.          nop
  67.         mov     ah,close2               ; DOS 2.0 file close
  68.         push    bx
  69.         mov     bx,diskio.handle        ; file handle
  70.         int     dos
  71.         pop     bx
  72.         mov     filopn,0                ; say file is no longer open
  73.         cmp     flags.abfflg,0          ; save file after closing?
  74.         je      abort0                  ; e = yes
  75.         push    dx
  76.         mov     dx,offset diskio.string ; get back file name
  77.         mov     ah,del2                 ; delete the file
  78.         int     dos
  79.         pop     dx
  80. abort0: mov     pack.state,'A'          ; Otherwise abort
  81.         mov     byte ptr locfil,0       ; clear local filename
  82.         or      errlev,2                ; set DOS error level
  83.         or      fsta.xstatus,2          ; set status
  84.         mov     kstatus,2               ; global status
  85.         xor     ax,ax           ; tell statistics this is a receive operation
  86.         call    endtim                  ; stop file timer
  87.         ret
  88. ABORT   ENDP
  89.  
  90. ackpak  proc    near                    ; send an ACK packet
  91.         mov     ah,'Y'                  ; ack packet
  92.         call    spack
  93.          jmp    abort                   ; failed
  94.          nop
  95.         ret
  96. ackpak  endp
  97.  
  98. ; init variables for read...
  99. rrinit  proc    near
  100.         mov     pack.numpkt,0           ; Set the number of packets to zero
  101.         mov     pack.numrtr,0           ; Set the number of retries to zero
  102.         mov     pack.pktnum,0           ; Set the packet number to zero
  103.         mov     pack.numtry,0           ; Set the number of tries to zero
  104.         mov     filopn,0                ; say no file opened yet
  105.         ret
  106. rrinit  endp
  107.  
  108. ;       RECEIVE command  --  Some code moved to the GET routine
  109.  
  110. READ    PROC    NEAR
  111.         mov     flags.nmoflg,0          ; Override file name from other host
  112. ;        mov     bx,offset filhlp2       ; Text of help message
  113.         mcmsgb   filhlp2, cfilhlp2
  114.  
  115.         mov     dx,offset locfil        ; local file name string
  116.         mov     byte ptr locfil,0       ; clear it first
  117.         mov     ah,cmfile               ; allow path names
  118.         call    comnd
  119.          ret
  120.          nop
  121.          nop
  122.         cmp     ah,0                    ; was an override filename given?
  123.         je      read0                   ; e = no
  124.         mov     flags.nmoflg,1          ; yes, set flag = use this filename
  125. read0:  mov     ah,cmcfm                ; Get a confirm
  126.         call    comnd
  127.          ret
  128.          nop
  129.          nop
  130.         mov     pack.state,'R'  ; Set the state to receive initiate
  131.         mov     flags.getflg,0          ; Reset flag (not a Get command)
  132.         mov     flags.xflg,0
  133.         call    serini                  ; initialize serial port
  134.         jnc     read0b                  ; nc = success
  135.         or      errlev,2                ; set DOS error level
  136.         or      fsta.xstatus,2          ; set status, failed
  137.         or      kstatus,2               ; global status
  138.         test    flags.remflg,dquiet     ; quiet display mode?
  139.         jnz     read0a                  ; nz = yes. Don't write to screen
  140.         mov     ah,prstr
  141. ;        mov     dx,offset infms4        ; Failed message
  142.         mcmsg   infms4, cinfms4
  143.  
  144.         int     dos
  145. read0a: ret                             ; return failure
  146. read0b: call    rrinit                  ; init variables for read
  147.         call    init                    ; setup display form
  148.         call    ihostr                  ; initialize the host
  149.  
  150. READ12:                                 ; Called by GET & SRVSND, display ok
  151.         mov     kstatus,0               ; global status, success
  152.         call    begtim                  ; start next statistics group
  153.         mov     flags.cxzflg,0          ; Reset ^X/^Z flag
  154.         mov     ah,trans.chklen         ; get desired checksum length
  155.         mov     curchk,ah               ; and remember it here
  156.         test    flags.remflg,dquiet     ; quiet display mode?
  157.         jnz     read2                   ; nz = yes, no printing
  158.         cmp     flags.destflg,2         ; Receiving to the screen?
  159.         je      read21                  ; e = yes, no formatted display
  160.         call    stpos
  161.         mov     ah,prstr                ; Be informative
  162. ;        mov     dx,offset infms1
  163.         mcmsg   infms1, cinfms1
  164.  
  165.         int     dos
  166.         test    flags.remflg,dserial    ; serial display mode?
  167.         jnz     read2                   ; nz = yes, skip initial retry display
  168.         call    rtpos                   ; Position cursor
  169.         mov     ax,pack.numrtr
  170.         call    nout                    ; Write the number of retries
  171.  
  172. READ2:                          ; Called by GENERIC server command dispatcher
  173.         cmp     flags.xflg,1            ; Are we receiving to the screen?
  174.         je      read21                  ; e = skip the screen stuff
  175.         call    nppos            ; Position cursor for number of packets msg
  176.         mov     ax,pack.numpkt
  177.         call    nout                    ; Write the number of packets
  178. read21: mov     ah,pack.state           ; Get the state
  179.         cmp     ah,'D'                  ; Data receive state?
  180.         jne     read3
  181.         call    rdata                   ; yes, get data packets
  182.         jmp     read2
  183. read3:  cmp     ah,'F'                  ; File receive state?
  184.         jne     read4
  185.         call    rfile                   ; Call receive file
  186.         jmp     read2
  187. read4:  cmp     ah,'R'                  ; Receive initiate state?
  188.         jne     read5                   ; ne = no
  189.         call    rinit
  190.         jmp     read2
  191.                                         ; Receive Complete state processor
  192. read5:  push    ax                      ; save status in ah
  193.         cmp     flags.cxzflg,0          ; Completed or interrupted?
  194.         je      read5a                  ; e = ended normally
  195.         or      errlev,2                ; set DOS error level
  196.         or      fsta.xstatus,2+80h      ; set status, failed + intervention
  197.         or      kstatus,2+80h           ; global status
  198. read5a: push    ax
  199.         xor     ax,ax           ; tell statistics this is a receive operation
  200.         call    endtim                  ; stop file timer
  201.         pop     ax
  202.         mov     ah,curchk               ; get working checksum
  203.         mov     trans.chklen,ah         ; and restore for next file
  204.         mov     byte ptr locfil,0       ; clear local filename
  205.         pop     ax                      ; recover status in ah
  206. ;        mov     dx,offset infms3        ; Completed message
  207.         mcmsg   infms3, cinfms3
  208.  
  209.         cmp     ah,'C'                  ; Receive complete state?
  210.         je      read6                   ; e = yes, else receive failed
  211.         or      errlev,2                ; set DOS error level
  212.         or      fsta.xstatus,2          ; set status, failed
  213.         or      kstatus,2               ; global status
  214. ;        mov     dx,offset infms4        ; Failed message
  215.         mcmsg   infms4, cinfms4
  216.  
  217.         cmp     filopn,2                ; file still open?
  218.         jne     read6                   ; ne = no
  219.         push    dx
  220.         call    abort                   ; close file & maybe delete
  221.         pop     dx
  222. read6:  cmp     flags.xflg,0            ; Did we write to the screen?
  223.         je      read6a                  ; e = no, so print status
  224.         cmp     flags.destflg,2         ; Receiving to screen?
  225.         je      read6d                  ; Yes don't reset
  226.         mov     flags.xflg,0            ; Reset it
  227.         jmp     read6d                  ; Yes, so just return
  228. read6a: test    flags.remflg,dquiet     ; quiet display mode?
  229.         jnz     read6d                  ; nz = yes, keep going
  230.         cmp     flags.destflg,2         ; Receiving to the screen?
  231.         je      read6d                  ; e = yes, no formatted display
  232.         push    dx                      ; save message pointer
  233.         call    stpos                   ; Position cursor
  234.         pop     dx
  235.         mov     ah,prstr
  236.         cmp     flags.cxzflg,0          ; Completed or interrupted?
  237.         je      read6b                  ; Ended normally
  238. ;        mov     dx,offset infms6        ; Say was interrupted
  239.         mcmsg   infms6, cinfms6
  240.  
  241. read6b: int     dos
  242.         cmp     flags.belflg,0          ; Bell desired?
  243.         je      read6c                  ; No
  244.         mov     dx,offset ender         ; Ring them bells
  245.         int     dos
  246. read6c: test    flags.remflg,dserial    ; serial display?
  247.         jnz     read6d                  ; nz = yes
  248.         call    clrmod                  ; clear Mode Line
  249.         call    rprpos                  ; Put prompt here
  250. read6d: jmp     rskp
  251. READ    ENDP
  252.  
  253. ;       Receive routines
  254.  
  255. ;       Receive init
  256. RINIT   PROC    NEAR
  257.         mov     ah,pack.numtry          ; Get the number of tries
  258.         cmp     ah,imxtry               ; Reached the maximum number of tries?
  259.         jl      rinit2
  260. ;        mov     dx,offset ermes7
  261.         mcmsg   ermes7, cermes7
  262.         test    flags.remflg,dquiet     ; quiet display mode?
  263.         jnz     rinit1                  ; nz = yes. Don't write to screen
  264.         cmp     flags.destflg,2         ; Receiving to the screen?
  265.         je      rinit1                  ; e = yes, no formatted display
  266.         call    erpos                   ; Position cursor
  267.         mov     ah,prstr
  268.         int     dos                     ; Print an error message
  269. rinit1: mov     bx,dx
  270.         mov     ah,trans.chklen
  271.         mov     curchk,ah               ; Store checksum length we want to use
  272.         mov     trans.chklen,1          ; Send init checksum is always 1 char
  273.         call    errpack                 ; Send error packet just in case
  274.         mov     ah,curchk
  275.         mov     trans.chklen,ah         ; Reset to desired value
  276.         jmp     abort                   ; Change the state to abort
  277. rinit2: inc     ah                      ; Increment it
  278.         mov     pack.numtry,ah          ; Save the updated number of tries
  279.         mov     ah,flags.getflg         ; Get cmd? (holds get pkt type in ah)
  280.         cmp     ah,0                    ; Have we already read in the packet?
  281.         jne     rin21a                  ; ne = yes, so don't call RPACK
  282.         mov     ah,dtrans.seol          ; restore default end-of-line char
  283.         mov     trans.seol,ah
  284.         mov     ah,trans.chklen
  285.         mov     curchk,ah               ; Save checksum length we want to use
  286.         mov     trans.chklen,1          ; Use 1 char for init packet
  287.         call    rpack                   ; Get a packet
  288.          jmp    rin22                   ; Trashed packet: nak, retry
  289.         call    pktsize                 ; report packet size
  290.         push    ax
  291.         mov     ah,curchk
  292.         mov     trans.chklen,ah         ; Reset to desired value
  293.         pop     ax
  294.         cmp     flags.cxzflg,0          ; does the user want out now?
  295.         jne     rinit4                  ; ne = yes, quit
  296. rin21a: cmp     ah,'S'                  ; Is it a send initiate packet?
  297.         jne     rinit3                  ; If not see if its an error
  298. rin21:  mov     flags.getflg,0          ; Reset flag
  299.         mov     pack.numtry,0           ; Reset the number of tries
  300.         mov     ax,pack.seqnum  ; Returned packet number. (Synchronize them.)
  301.         inc     ax                      ; Increment it
  302.         and     ax,3FH                  ; Turn off the two high order bits
  303.         mov     pack.pktnum,ax          ; Save modulo 64 of the number
  304.         inc     pack.numpkt             ; Increment the number of packets
  305.         mov     ax,pack.datlen          ; Get the number of arguments received
  306.         mov     bx,offset data          ; Get a pointer to the data
  307.         call    spar                    ; Get data into the proper variables
  308.         mov     bx,offset data          ; Get a pointer to our data block
  309.         call    rpar                    ; Set up the receive parameters
  310.         xchg    ah,al
  311.         mov     ah,0
  312.         mov     pack.datlen,ax          ; Store returned number of arguments
  313.         mov     ah,trans.chklen         ; Checksum length we'll use
  314.         mov     curchk,ah               ; Save it
  315.         mov     trans.chklen,1          ; Use 1 char for init packet
  316.         call    ackpak                  ; acknowledge the packet
  317.         mov     ah,curchk               ; Checksum length we'll use
  318.         mov     trans.chklen,ah         ; Reset to desired value
  319.         mov     pack.state,'F'          ; Set the state to file send
  320.         ret
  321. rin22:  call    nak0                    ; nak the packet
  322.         mov     ah,curchk               ; and only now change checksum from 1
  323.         mov     trans.chklen,ah         ; Reset to desired value
  324.         ret                             ; try again
  325.  
  326. rinit3: cmp     ah,'M'                  ; Message packet?
  327.         jne     rinit3e                 ; ne = no
  328.         call    dodec                   ; decode it
  329.         call    error1                  ; display it
  330.         ret
  331. rinit3e: cmp    ah,'E'                  ; Is it an error packet?
  332.         jne     rinit4                  ; ne = no
  333.         call    error                   ; yes
  334. rinit4: jmp     abort
  335. RINIT   ENDP
  336.  
  337.  
  338. ;       Receive file
  339.  
  340. RFILE   PROC    NEAR
  341.         mov     dl,maxtry
  342.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  343.         jl      rfile1
  344. ;        mov     dx,offset ermes8
  345.         mcmsg   ermes8, cermes8
  346.  
  347.         jmp     rcverr                  ; do error exit
  348. rfile1: inc     pack.numtry             ; Save the updated number of tries
  349.         call    rpack                   ; Get a packet
  350.          jmp    nak0                    ;  Trashed packet: nak, retry
  351.         call    pktsize                 ; report packet size
  352.         cmp     ah,'S'                  ; Is it a send initiate packet?
  353.         je      rfil10
  354.         cmp     ah,'I'                  ; An Initialization packet?
  355.         je      rfil10                  ; e = yes, don't decode it
  356.         call    dodec                   ; Decode all other incoming packets
  357.         jmp     rfile2                  ;  No, try next type
  358. rfil10: mov     dl,imxtry               ; S and I packets
  359.         cmp     pack.numtry,dl          ; Reached the maximum number of tries?
  360.         jl      rfil12                  ; If not proceed
  361. ;        mov     dx,offset ermes7
  362.         mcmsg   ermes7, cermes7
  363.  
  364.         jmp     rcverr                  ; do error exit
  365. rfil12: mov     ax,pack.pktnum          ; Get the present packet number
  366.         dec     ax                      ; Decrement
  367.         and     ax,3fh                  ; do module 64
  368.         cmp     ax,pack.seqnum  ; Is the packet's number one less than now?
  369.         je      rfil13
  370.         jmp     nak0                    ; No, NAK and try again
  371. rfil13: mov     pack.numtry,0           ; Reset the number of tries
  372.         mov     bx,offset data          ; Get a pointer to our data block
  373.         call    rpar                    ; Set up the parameter information
  374.         xchg    ah,al
  375.         mov     ah,0
  376.         mov     pack.datlen,ax          ; Save the number of arguments
  377.         jmp     ackpak                  ; acknowledge the packet
  378.  
  379. rfile2: cmp     ah,'Z'                  ; Is it an EOF packet?
  380.         jne     rfile3                  ;  No, try next type
  381.         mov     dl,maxtry               ; Z packets
  382.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  383.         jl      rfil21                  ; If not proceed
  384. ;        mov     dx,offset ermes9
  385.         mcmsg   ermes9, cermes9
  386.  
  387.         jmp     rcverr                  ; do error exit
  388. rfil21: mov     ax,pack.pktnum          ; Get the present packet number
  389.         dec     ax                      ; Decrement
  390.         and     ax,3fh                  ; do modulo 64
  391.         cmp     ax,pack.seqnum  ; Is the packet's number one less than now?
  392.         je      rfil24
  393.         jmp     nak0                    ; No, NAK and try again
  394. rfil24: mov     pack.numtry,0
  395.         mov     pack.datlen,0   ; No data. (The packet number is in seqnum.)
  396.         jmp     ackpak                  ; acknowledge the packet
  397.  
  398. rfile3: cmp     ah,'F'                  ; Start of file (F or X packet)?
  399.         je      rfil31                  ; e = yes
  400.         cmp     ah,'X'                  ; Text header packet?
  401.         jne     rfile4                  ; Neither one.
  402.         mov     flags.xflg,1            ; 'X', say receiving to the screen
  403. rfil31: mov     ax,pack.seqnum          ; Get the packet number
  404.         cmp     ax,pack.pktnum          ; Is it the right packet number?
  405.         je      rfil32
  406.         jmp     nak1                    ; No, NAK it and try again
  407. rfil32: inc     ax                      ; Increment the packet number
  408.         and     ax,3FH                  ; Turn off the two high order bits
  409.         mov     pack.pktnum,ax          ; Save modulo 64 of the number
  410.         inc     pack.numpkt             ; Increment the number of packets
  411.         mov     filopn,0                ; assume not writing to a disk file
  412.         call    dodec                   ; Decode incoming packet for filename
  413.         call    gofil                   ; Get a file to write to
  414.          jmp    abort
  415.         mov     chrcnt,maxpack          ; reset output buffer to be empty
  416.         cmp     flags.xflg,0            ; writing to a disk file?
  417.         jne     rfil32a                 ; ne = no
  418.         mov     filopn,2                ; Disk file open for writing
  419. rfil32a:
  420.         test    flags.remflg,dserial    ; serial display mode?
  421.         jz      rfil33                  ; z = no
  422.         mov     ah,prstr
  423.         mov     dx,offset crlf          ; display cr/lf
  424.         int     dos
  425. rfil33:
  426.         mov     pack.state,'D'          ; Set the state to data receive
  427.         mov     pack.numtry,0           ; Reset the number of tries
  428.         mov     pack.datlen,0   ; No data.  (The packet number is in seqnum.)
  429.         jmp     ackpak                  ; acknowledge the packet
  430.  
  431. rfile4: cmp     ah,'B'                  ; End of transmission?
  432.         jne     rfile5                  ; ne = no
  433.         mov     ax,pack.pktnum
  434.         cmp     ax,pack.seqnum          ; Do we match?
  435.         je      rfil41
  436.         jmp     nak1                    ; No, NAK it and try again
  437. rfil41: mov     pack.state,'C'          ; Set the state to complete
  438.         mov     pack.datlen,0   ; No data.  (Packet number already in seqnum)
  439.         jmp     ackpak                  ; acknowledge the packet
  440.  
  441. rfile5: cmp     ah,'M'                  ; Message packet?
  442.         jne     rfile5e                 ; ne = no
  443.         call    dodec                   ; decode it
  444.         jmp     error1                  ; display it and return
  445.  
  446. rfile5e:cmp     ah,'E'                  ; Is it an error packet?
  447.         jne     rfile6                  ; ne = no
  448.         call    error
  449. rfile6: jmp     abort
  450. RFILE   ENDP
  451.  
  452. ; Get file attributes from packet
  453. ; Recognize file size in bytes and kilobytes (used if bytes missing),
  454. ; file time and date. Reject Mail commands. Return carry clear for success,
  455. ; carry set for failure. If rejecting place reason code in byte temp.
  456. GETATT  PROC    NEAR
  457.         mov     bx,offset data          ; pointer
  458. getat0: push    bx
  459.         sub     bx,offset data
  460.         cmp     bx,pack.datlen          ; are we beyond end of data?
  461.         pop     bx
  462.         jl      getat1                  ; l = not yet
  463.         clc
  464.         ret                             ; has carry clear for success
  465.  
  466. getat1: cmp     byte ptr [bx],'1'       ; byte length field?
  467.         jne     getat2                  ; ne = no
  468.         mov     al,[bx]                 ; remember attribute
  469.         mov     attrib,al
  470.         inc     bx                      ; pointer
  471.         call    getas                   ; get file size
  472.         call    spchk                   ; check available disk space
  473.         jnc     getat0
  474.         ret                             ; return failure
  475.  
  476. getat2: cmp     byte ptr [bx],'!'       ; kilobyte length field?
  477.         jne     getat3                  ; ne = no
  478.         mov     al,[bx]                 ; remember attribute
  479.         mov     attrib,al
  480.         inc     bx                      ; pointer
  481.         call    getak                   ; get file size
  482.         jc      getat5;;;2a                     ; carry means decode rejected
  483.         call    spchk                   ; check available disk space
  484.         jnc     short getat0
  485. getat2a:ret                             ; return failure
  486.  
  487. getat3: cmp     byte ptr [bx],'#'       ; date field?
  488.         jne     getat4                  ; ne = no
  489.         mov     al,[bx]                 ; remember attribute
  490.         mov     attrib,al
  491.         inc     bx
  492.         call    getatd                  ; get file date
  493.         jmp     short getat0
  494.  
  495. getat4: cmp     byte ptr [bx],'+'       ; Disposition?
  496.         jne     getat5                  ; ne = no
  497.         mov     al,[bx]                 ; remember attribute
  498.         mov     attrib,al
  499.         cmp     byte ptr [bx+2],'M'     ; Mail indicator
  500.         jne     getat5                  ; ne = no, ignore field
  501.         stc                             ; set carry for failure
  502.         ret
  503.  
  504. getat5: inc     bx                      ; look at length field
  505.         mov     al,[bx]
  506.         sub     al,' '                  ; remove ascii bias
  507.         mov     ah,0
  508.         inc     ax                      ; include length field byte
  509.         add     bx,ax                   ; skip to next attribute
  510.         jmp     getat0
  511.                                         ; Decode File length (Byte) field
  512. getas:  mov     cl,[bx]                 ; length of file size field
  513.         inc     bx                      ; point at file size data
  514.         sub     cl,' '                  ; remove ascii bias
  515.         mov     ch,0
  516.         mov     ax,0                    ; current length, bytes
  517.         mov     dx,0
  518. getas2: push    cx
  519.         shl     dx,1                    ; high word of size, times two
  520.         mov     di,dx                   ; save
  521.         shl     dx,1
  522.         shl     dx,1                    ; times 8
  523.         add     dx,di                   ; yields dx * 10
  524.         mov     di,dx                   ; save dx
  525.         mov     dx,0
  526.         mov     cx,10                   ; also clears ch
  527.         mul     cx                      ; scale up previous result in ax
  528.         mov     cl,[bx]                 ; get a digit
  529.         inc     bx
  530.         sub     cl,'0'                  ; remove ascii bias
  531.         add     ax,cx                   ; add to current length
  532.         adc     dx,0                    ; extend result to dx
  533.         add     dx,di                   ; plus old high part
  534.         pop     cx
  535.         loop    getas2
  536.         mov     ofilsz+2,ax             ; low order word
  537.         mov     ofilsz,dx               ; high order word
  538.         ret
  539.                                         ; Decode Kilobyte attribute
  540. getak:  mov     ax,ofilsz+2             ; current filesize, low word
  541.         add     ax,ofilsz
  542.         cmp     ax,0                    ; zero if not used yet
  543.         je      getak1                  ; e = not used before
  544.         dec     bx                      ; backup pointer
  545.         stc                             ; set carry to ignore this field
  546.         ret
  547. getak1: call    getas                   ; parse as if Byte field
  548.         mov     ax,ofilsz+2             ; get low word of size
  549.         mov     dx,ofilsz               ; high word
  550.         mov     dh,dl                   ; times 256
  551.         mov     dl,ah
  552.         mov     ah,al
  553.         mov     al,0
  554.         shl     dx,1                    ; times four to make times 1024
  555.         shl     dx,1
  556.         rol     ax,1                    ; two high bits of ah to al
  557.         rol     ax,1
  558.         and     al,3                    ; keep them
  559.         or      dl,al                   ; insert into high word
  560.         mov     al,0
  561.         mov     ofilsz,dx               ; store high word
  562.         mov     ofilsz+2,ax             ; store low word
  563.         clc                             ; clear carry
  564.         ret
  565.  
  566. getatd:                                 ; File date and time
  567.         mov     word ptr ftime,1        ; two seconds past midnight
  568.         mov     word ptr fdate,0
  569.         mov     dl,[bx]                 ; field length
  570.         mov     dh,0
  571.         sub     dl,' '                  ; remove ascii bias
  572.         inc     bx                      ; next field
  573.         add     dx,bx                   ; where next field begins
  574.         mov     temp,dx                 ; save in temp
  575.         mov     ax,0                    ; recover file date and time
  576.         mov     dh,10                   ; multiplier
  577.         cmp     byte ptr[bx+6],' '      ; short form date (yymmdd)?
  578.         je      getad2                  ; e = yes
  579.         add     bx,2                    ; skip century digits (19)
  580. getad2: mov     ax,10
  581.         mov     dx,[bx]                 ; get year tens and units digits
  582.         add     bx,2                    ; dl has tens, dh has units
  583.         sub     dx,'00'                 ; remove ascii bias
  584.         mul     dl                      ; ax = high digit times ten
  585.         add     al,dh                   ; units digit
  586.         sub     ax,80                   ; remove rest of 1980 bias
  587.         jns     getad2a                 ; ns = no sign = non-negative result
  588.         mov     ax,0                    ; don't store less than 1980
  589. getad2a:shl     al,1                    ; adjust for DOS bit format
  590.         mov     fdate+1,al
  591.         mov     ax,[bx]                 ; get month digits
  592.         add     bx,2
  593.         sub     ax,'00'                 ; remove ascii bias
  594.         cmp     al,0                    ; tens digit set?
  595.         je      getad2b                 ; e = no
  596.         add     ah,10                   ; add to units digit
  597. getad2b:cmp     ah,8                    ; high bit of month set?
  598.         jb      getad3                  ; b = no
  599.         or      fdate+1,1
  600.         sub     ah,8                    ; and deduct it here
  601. getad3: mov     cl,5
  602.         shl     ah,cl                   ; normalize months bits
  603.         mov     fdate,ah
  604.         mov     dx,[bx]                 ; do day of the month
  605.         add     bx,2                    ; dh has units, dl has tens digit
  606.         sub     dx,'00'                 ; remove ascii bias
  607.         mov     ax,10
  608.         mul     dl                      ; ax = ten times tens digit
  609.         add     al,dh                   ; plus units digit
  610.         or      fdate,al
  611.         cmp     bx,temp                 ; are we at the end of this field?
  612.         jae     getad5                  ; ae = yes, prematurely
  613.         inc     bx                      ; skip space separator
  614. getad4: mov     ax,10                   ; prepare for hours
  615.         mov     dx,[bx]                 ; hh digits
  616.         add     bx,2
  617.         sub     dx,'00'                 ; remove ascii bias
  618.         mul     dl                      ; 10*high digit of hours
  619.         add     al,dh                   ; plus low digit of hours
  620.         mov     cl,3                    ; normalize bits
  621.         shl     al,cl
  622.         mov     ftime+1,al              ; store hours
  623.         inc     bx                      ; skip colon
  624.         mov     ax,10                   ; prepare for minutes
  625.         mov     dx,[bx]                 ; mm digits
  626.         add     bx,2
  627.         sub     dx,'00'                 ; remove ascii bias
  628.         mul     dl                      ; 10*high digit of minutes
  629.         add     al,dh                   ; plus low digit of minutes
  630.         mov     ah,0
  631.         mov     cl,5                    ; normalize bits
  632.         shl     ax,cl
  633.         or      ftime+1,ah              ; high part of minutes
  634.         mov     ftime,al                ; low part of minutes
  635.         cmp     bx,temp                 ; are we at the end of this field
  636.         jae     getad5                  ; ae = yes, quit here
  637.         inc     bx                      ; skip colon
  638.         mov     ax,10                   ; prepare for seconds
  639.         mov     dx,[bx]                 ; ss digits
  640.         add     bx,2
  641.         sub     dx,'00'                 ; remove ascii bias
  642.         mul     dl                      ; 10*high digit of seconds
  643.         add     al,dh                   ; plus low digit of seconds
  644.         shr     al,1                    ; store as double-seconds for DOS
  645.         or      ftime,al                ; store seconds
  646. getad5: ret
  647. GETATT  ENDP
  648.  
  649. ; Receive data
  650.  
  651. RDATA   PROC    NEAR
  652.         mov     dl,maxtry
  653.         cmp     pack.numtry,dl          ; Get the number of tries
  654.         jl      rdata1
  655. ;        mov     dx,offset erms10
  656.         mcmsg   erms10, cerms10
  657.  
  658.         jmp     rcverr                  ; do error exit
  659. rdata1: inc     pack.numtry             ; Save the updated number of tries
  660.         call    rpack                   ; Get a packet
  661.          jmp    nak0                    ;  Trashed packet: nak, retry
  662.          nop
  663.         call    pktsize                 ; report packet size
  664.         cmp     ah,'D'                  ; Is it a data packet?
  665.         je      rdat11                  ; e = yes
  666.         cmp     ah,'A'                  ; Attributes packet?
  667.         jne     rdata7                  ; ne = no
  668.         mov     ax,pack.pktnum
  669.         cmp     ax,pack.seqnum          ; Do we match?
  670.         je      rdata6
  671.         jmp     nak1                    ; No, NAK it and try again
  672. rdata6: call    getatt                  ; get file attributes from packet
  673.         mov     pack.numtry,0           ; Reset number of tries
  674.         jnc     rdata6a                 ; nc = success
  675.         mov     pack.datlen,2   ; 2 bytes (Packet number already in seqnum)
  676.         mov     data,'N'                ; Decline the transfer
  677.         mov     al,attrib               ; get attribute causing rejection
  678.         mov     data+1,al               ; report rejection reason to sender
  679.         or      fsta.xstatus,2          ; set status, failed
  680.         mov     kstatus,2               ; global status
  681.         jmp     short rdata6b
  682. rdata6a:mov     pack.datlen,0   ; No data. (Packet number already in seqnum)
  683. rdata6b:mov     ax,pack.pktnum
  684.         inc     ax                      ; Increment the packet number
  685.         and     ax,3FH                  ; Turn off the two high order bits
  686.         mov     pack.pktnum,ax          ; Save modulo 64 of the number
  687.         inc     pack.numpkt             ; Increment the number of packets
  688.         jmp     ackpak                  ; acknowledge the packet
  689.  
  690. rdata7: call    dodec                   ; Decode data
  691.         jmp     rdata2                  ; try next type
  692.                                         ; D packets
  693. rdat11: mov     ax,pack.pktnum          ; Get the present packet number
  694.         cmp     ax,pack.seqnum          ; Is the packet's number correct?
  695.         jz      rdat14
  696.         mov     dl,maxtry
  697.         cmp     pack.numtry,dl  ; Have we reached the maximum number of tries?
  698.         jl      rdat12                  ; If not proceed
  699. ;        mov     dx,offset erms10
  700.         mcmsg   erms10, cerms10
  701.  
  702.         jmp     rcverr                  ; do error exit
  703. rdat12: mov     ax,pack.pktnum
  704.         dec     ax
  705.         and     ax,3fh                  ; do modulo 64
  706.         cmp     ax,pack.seqnum  ; Is the packet's number one less than now?
  707.         je      rdat13
  708.         jmp     nak0                    ; No, NAK it and try again
  709. rdat13: mov     pack.numtry,0           ; Reset number of tries
  710.         mov     pack.datlen,0   ; No data.  (The packet number is in seqnum.)
  711.         jmp     ackpak                  ; acknowledge the packet
  712.  
  713. rdat14: inc     pack.pktnum             ; Increment the packet number
  714.         and     pack.pktnum,3fh         ; Save modulo 64 of the number
  715.         inc     pack.numpkt             ; Increment the number of packets
  716.         mov     ax,pack.datlen          ; Get the length of the data
  717.         cmp     flags.cxzflg,0          ; Has the user typed a ^X or ^Z?
  718.         je      rdt14x                  ; No, write out the data
  719.         or      fsta.xstatus,2+80h      ; set status, failed + intervention
  720.         mov     kstatus,2+80h           ; global status
  721.         cmp     flags.abfflg,1          ; Discard incomplete files?
  722.         je      rdat15          ; If yes don't write data out to file
  723. rdt14x: call    ptchr                   ; decode the data and output to file
  724.          jmp    abort                   ;  Unable to write out chars; abort
  725. rdat15: mov     pack.numtry,0           ; Reset the number of tries
  726.         mov     pack.datlen,0   ; No data.  (Packet number still in seqnum.)
  727.         cmp     flags.cxzflg,0          ; Interrupt file transfer?
  728.         je      rdat16                  ; Nope
  729.         or      fsta.xstatus,2+80h      ; set status, failed + intervention
  730.         mov     kstatus,2+80h           ; global status
  731.         mov     bx,offset data          ; Send data in ACK in case remote
  732.         mov     ah,flags.cxzflg         ;  knows about ^X/^Z
  733.         mov     [bx],ah                 ; Put data into the packet
  734.         mov     pack.datlen,1           ; Set data size to 1
  735.         mov     cx,1
  736.         call    doenc
  737. rdat16: jmp     ackpak                  ; acknowledge the packet
  738.  
  739. rdata2: cmp     ah,'F'                  ; Start of file?
  740.         je      rdat20                  ; e = yes
  741.         cmp     ah,'X'                  ; Text header packet?
  742.         jne     rdata3                  ;  No, try next type
  743. rdat20: mov     dl,maxtry               ; F or X packet
  744.         cmp     pack.numtry,dl          ; Reached the max number of tries?
  745.         jl      rdat21                  ; If not proceed
  746. ;        mov     dx,offset ermes8
  747.         mcmsg   ermes8, cermes8
  748.  
  749.         jmp     rcverr                  ; do error exit
  750. rdat21: mov     ax,pack.pktnum
  751.         dec     ax
  752.         and     ax,3fh                  ; modulo 64
  753.         cmp     ax,pack.seqnum  ; Is the packet's number one less than now?
  754.         je      rdat22
  755.         jmp     nak0                    ; No, NAK it and try again
  756. rdat22: mov     pack.numtry,0           ; Reset number of tries
  757.         mov     pack.datlen,0   ; No data.  (The packet number is in seqnum.)
  758.         jmp     ackpak                  ; acknowledge the packet
  759.  
  760. rdata3: cmp     ah,'Z'                  ; Is it a EOF packet?
  761.         je      rdat3x                  ; e = yes
  762.         jmp     rdata4                  ; Try and see if its an error
  763. rdat3x: mov     ax,pack.pktnum          ; Get the present packet number
  764.         cmp     ax,pack.seqnum          ; Is the packet's number correct?
  765.         je      rdat32
  766.         jmp     nak0                    ; No, NAK it and try again
  767. rdat32: inc     ax                      ; Increment the packet number
  768.         and     ax,3FH                  ; Turn off the two high order bits
  769.         mov     pack.pktnum,ax          ; Save modulo 64 of the number
  770.         inc     pack.numpkt
  771.         call    dodec                   ; Decode incoming packet
  772.         cmp     flags.cxzflg,0          ; Do we want to discard the file?
  773.         jne     rdt32x                  ; ne = yes
  774.         cmp     fmtdsp,0                ; formatted screen?
  775.         je      rdat32a                 ; e = no, no message
  776.         mov     ax,ofilsz               ; high word of attributes file size
  777.         or      ax,ofilsz+2             ; low word
  778.         cmp     ax,0                    ; was file size given by other side?
  779.         je      rdat32a                 ; e = no
  780.         call    perpos                  ; position cursor to percent done
  781.         mov     dx,offset donemsg       ; say 100%
  782.         mov     ah,prstr
  783.         int     dos
  784. rdat32a:cmp     pack.datlen,1           ; One piece of data?
  785.         jne     rdat33                  ; Nope - finish writing out file?
  786.         cmp     data,'D'                ; is the data "D" for discard?
  787.         jne     rdat33                  ; Nope - write out file
  788. rdt32x: cmp     flags.abfflg,0          ; Keep incomplete files?
  789.         je      rdat33                  ; Yes, go write it out
  790.         cmp     flags.xflg,1            ; Writing to the screen?
  791.         je      rdt32y                  ; Don't close "file"
  792.         cmp     flags.destflg,2         ; file destination = screen?
  793.         je      rdt32y                  ; e = yes, no file to close
  794.         push    bx
  795.         mov     ah,close2               ; DOS 2.0 file close
  796.         mov     bx,diskio.handle        ; file handle
  797.         int     dos                     ; Kill it, ignore errors
  798.         pop     bx
  799.         mov     filopn,0                ; File closed now
  800.         mov     dx,offset diskio.string ; get the filename
  801.         mov     ah,del2                 ; DOS 2.0 file delete
  802.         int     dos
  803. rdt32y: cmp     flags.cxzflg,'X'        ; Kill one file or all?
  804.         je      rdt32ya                 ; e = one (^X)
  805.         jmp     rdat36                  ; No so leave flag alone
  806. rdt32ya:call    cxmsg                   ; Clear msg about interrupt
  807.         or      errlev,2                ; set DOS error level
  808.         or      fsta.xstatus,2+80h      ; set status, failed + intervention
  809.         mov     kstatus,2+80h           ; global status
  810.         test    flags.remflg,dquiet     ; quiet display?
  811.         jnz     rdt32z                  ; nz = yes
  812.         cmp     flags.destflg,2         ; Receiving to the screen?
  813.         je      rdt32z                  ; e = yes, no formatted display
  814.         call    intmsg
  815. rdt32z: mov     flags.cxzflg,0          ; Reset - ^X only kills one file
  816.         jmp     rdat36
  817. rdat33: cmp     flags.eofcz,0           ; should we write a ^Z?
  818.         jz      rdat35                  ; no, keep going
  819.         cmp     flags.xflg,0            ; writing to a file?
  820.         jne     rdat35                  ; no, skip ^Z
  821. rdt33x: cmp     chrcnt,0                ; any space left in output buffer?
  822.         jg      rdat34                  ; g = yes
  823.         call    outbuf                  ; Write out buffer if no room for ^Z
  824.          jmp    abort
  825. rdat34: mov     cl,'Z'- 40h             ; Put in a ^Z for EOF
  826.         push    bx
  827.         mov     bx,bufpnt               ; Get the dma pointer
  828.         mov     [bx],cl                 ; Add it
  829.         pop     bx
  830.         dec     chrcnt
  831. rdat35: call    outbuf                  ; Output the last buffer
  832.          jmp    abort                   ; Give up if the disk is full
  833.         cmp     flags.xflg,1            ; Writing to the screen?
  834.         je      rdat37                  ; Yes, don't close "file"
  835.         cmp     flags.destflg,2         ; file destination = screen?
  836.         je      rdat37                  ; e = yes, no file to close
  837.         push    bx                      ; do file attributes and close
  838.         mov     cx,word ptr ftime       ; new time
  839.         mov     dx,word ptr fdate       ; new date
  840.         mov     word ptr fdate,0
  841.         mov     word ptr ftime,0        ; clear current time/date attributes
  842.         mov     ax,cx
  843.         or      ax,dx
  844.         jz      rdat35b                 ; z = no attributes to set
  845.         cmp     cx,0                    ; time set as null?
  846.         jne     rdat35a                 ; ne = no
  847.         inc     cl                      ; two seconds past midnight
  848. rdat35a:mov     ah,setattr              ; set file date/time attributes
  849.         mov     al,1                    ; set, not get
  850.         mov     bx,diskio.handle        ; file handle
  851.         int     dos                     ; end of file attributes
  852. rdat35b:mov     ah,close2               ; DOS 2.0 file close
  853.         mov     bx,diskio.handle        ; file handle
  854.         int     dos
  855.         pop     bx
  856.         mov     filopn,0                ; File closed now
  857. rdat36: cmp     flags.destflg,0         ; Writing to printer?
  858.         jne     rdat37                  ; ne = no, skip next part
  859.         cmp     flags.xflg,1            ; Writing to screen?
  860.         je      rdat37                  ; Yes, skip this part
  861.         mov     dl,ff                   ; Send a form feed
  862.         mov     ah,lstout               ; Write out to first printer
  863.         int     dos
  864. rdat37: mov     pack.numtry,0           ; Reset the number of tries
  865.         mov     pack.datlen,0   ; No data.  (The packet number is in seqnum.)
  866.         call    ackpak                  ; acknowledge the packet
  867.         mov     pack.state,'F'
  868.         mov     ax,0            ; tell statistics this was a receive operation
  869.         call    endtim                  ; get tod & size of file transfer
  870.         ret
  871. rdata4: cmp     ah,'M'                  ; Message packet?
  872.         jne     rdata4e                 ; ne = no
  873.         call    dodec                   ; decode it
  874.         jmp     error1                  ; display it and return
  875.  
  876. rdata4e: cmp    ah,'E'                  ; Is it an error packet?
  877.         jne     rdata5                  ; ne = no
  878.         call    error
  879. rdata5: jmp     abort
  880. RDATA   ENDP
  881.  
  882. ; Error exit. Enter with dx pointing to error message. [jrd]
  883. rcverr  proc    near
  884.         test    flags.remflg,dquiet     ; quiet display mode?
  885.         jnz     rcver1                  ; nz = yes. Don't write to screen
  886.         cmp     flags.destflg,2         ; Receiving to the screen?
  887.         je      rcver1                  ; e = yes, no formatted display
  888.         call    erpos                   ; Position cursor
  889.         mov     ah,prstr
  890.         int     dos                     ; Print an error message
  891. rcver1: mov     bx,dx                   ; set bx to error message
  892.         call    errpack                 ; Send error packet just in case
  893.         jmp     abort                   ; Change the state to abort
  894. rcverr  endp
  895.  
  896. ; Called by GETATT in receiver code to verify sufficient disk space.
  897. ; Gets file path from diskio.string setup in mssfil, remote size in ofilsz
  898. ; from getatt, and whether a disk file or not via ioctl on the file handle.
  899. ; Returns carry clear if enough space.
  900. spchk   proc    near                    ; check for enough disk space
  901.         push    ax
  902.         push    bx
  903.         push    cx
  904.         push    dx
  905.         mov     ah,ioctl                ; ask DOS about this file handle
  906.         mov     al,0                    ; get info
  907.         mov     bx,diskio.handle
  908.         int     dos
  909.         test    dl,80h                  ; handle is a disk file?
  910.         jnz     spchk5b                 ; nz = no, always enough space
  911.         inc     dl
  912.         and     dl,01fh                 ; get current drive from bits 5-0
  913.         mov     ah,36h                  ; get disk free space
  914.         int     dos
  915.         cmp     ax,0ffffh               ; error response?
  916.         je      spchk6                  ; e = yes
  917.         mul     bx                      ; sectors/cluster * clusters = sectors
  918.         mov     bx,dx                   ; save high word of sectors (> 64K)
  919.         mul     cx                      ; bytes = sectors * bytes/sector
  920.         push    ax                      ; save low word of bytes
  921.         mov     ax,bx                   ; recall sectors high word
  922.         mov     bx,dx                   ; save current bytes high word
  923.         mul     cx                      ; high word sectors * bytes/sector
  924.         add     ax,bx                   ; new high bytes + old high bytes
  925.         push    ax                      ; save high word, dx:ax
  926.         mov     dx,ofilsz               ; high word of file size dx:ax
  927.         mov     ax,ofilsz+2             ; low word
  928.         mov     cx,dx                   ; copy size long word to cx:bx
  929.         mov     bx,ax
  930.         shr     bx,1                    ; divide long word by two
  931.         shr     cx,1
  932.         jnc     spchk2                  ; nc = no carry down
  933.         or      bx,8000h                ; get carry down
  934. spchk2: shr     bx,1                    ; divide by two again
  935.         shr     cx,1
  936.         jnc     spchk3
  937.         or      bx,8000h                ; get carry down
  938. spchk3: shr     bx,1                    ; divide long word by two
  939.         shr     cx,1
  940.         jnc     spchk4                  ; nc = no carry down
  941.         or      bx,8000h                ; get carry down
  942. spchk4: shr     bx,1                    ; divide long word by two
  943.         shr     cx,1
  944.         jnc     spchk5                  ; nc = no carry down
  945.         or      bx,8000h                ; get carry down
  946. spchk5: add     ax,bx                   ; form dx:ax = (17/16) * dx:ax
  947.         adc     dx,cx
  948. spchk5a:pop     cx                      ; high word of disk space
  949.         pop     bx                      ; low word
  950.         sub     bx,ax                   ; minus inflated file size, low word
  951.         sbb     cx,dx                   ;  and high word
  952.         js      spchk6                  ; s = not enough space for file
  953. spchk5b:clc
  954.         jmp     short spchk7            ; enough space
  955. spchk6: call    erpos                   ; Position cursor
  956.         mov     ah,prstr
  957. ;        mov     dx,offset erms11        ; Not enough space for file
  958.         mcmsg   erms11, cerms11
  959.  
  960.         int     dos
  961.         stc
  962. spchk7: pop     dx
  963.         pop     cx
  964.         pop     bx
  965.         pop     ax
  966.         ret
  967. spchk   endp
  968.  
  969.  
  970. ; Jumping to this location is like retskp.  It assumes the instruction
  971. ;   after the call is a jmp addr
  972.  
  973. RSKP    PROC    NEAR
  974.         pop     bp
  975.         add     bp,3
  976.         push    bp
  977.         ret
  978. RSKP    ENDP
  979.  
  980. code    ends
  981.         end
  982.