home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccsfil.asm < prev    next >
Assembly Source File  |  2020-01-01  |  99KB  |  2,134 lines

  1.         NAME    ccsfil
  2. ; Fle CCSFIL.ASM
  3. ;CHINESE
  4. ifdef   MSDOS
  5.         include mssfil.dat
  6. else
  7.         include ccsfil.dat
  8. endif
  9.  
  10. code    segment public 'code'
  11.         extrn   spack:near, cmblnk:near, locate:near, decout:near, comnd:near
  12.         extrn   putmod:near, poscur:near, clearl:near, isfile:near
  13.         assume  cs:code, ds:datas
  14.  
  15. ; Position cursor for an error message
  16.  
  17. ERPOS   PROC    NEAR
  18.         test    flags.remflg,dquiet     ; quiet screen?
  19.         jnz     erpx                    ; nz = yes
  20.         push    dx              ; save any preexisting message pointer
  21.         test    flags.remflg,dserial    ; serial mode display?
  22.         jnz     erpo1                   ; nz = yes
  23.         test    flags.remflg,dserver    ; are we a server
  24.         jnz     erp0                    ; nz = yes, and display is regular
  25.         cmp     flags.xflg,1            ; Packet header seen?
  26.         jne     erp0                    ; No, do as normal
  27. erpo1:  mov     dx,offset crlf
  28.         mov     ah,prstr
  29.         int     dos
  30.         mcmsg   erword ,cerword         ; put out word Error
  31.         int     dos
  32.         pop     dx                      ; restore old pointer
  33.         ret
  34. erp0:   
  35. ;       mov     dx,screrr
  36.         mcscr   screrr,cscrerr
  37.  
  38.         call    poscur
  39.         pop     dx                      ; restore old pointer
  40. erpx:   ret
  41. ERPOS   ENDP
  42.  
  43. ; Position cursor for number of retries message
  44.  
  45. RTPOS   PROC    NEAR
  46.         test    flags.remflg,dquiet     ; quiet display mode?
  47.         jnz     rtpx                    ; nz = yes
  48.         test    flags.remflg,dserver    ; in server mode?
  49.         jnz     rtp0                    ; nz = yes
  50.         cmp     flags.xflg,1            ; Packet header seen?
  51.         jne     rtp0                    ; No, do as normal
  52.         ret
  53. rtp0:   test    flags.remflg,dserial    ; serial mode display?
  54.         jnz     rtp1                    ; nz = yes
  55. ;        mov     dx,scrnrt
  56.         mcscr   scrnrt,cscrnrt
  57.  
  58.         call    poscur
  59.         jmp     clearl
  60. rtp1:   mcmsg   rtword,crtword         ; display word Retry
  61.         mov     ah,prstr
  62.         int     dos
  63. rtpx:   ret
  64. RTPOS   ENDP
  65.  
  66. ; Reassure user that we acknowledge his ^X/^Z
  67.  
  68. INTMSG  PROC    NEAR
  69.         cmp     fmtdsp,0                ; non-formatted screen?
  70.         je      int5                    ; e = yes
  71.         test    flags.remflg,dserver    ; server mode?
  72.         jnz     int4                    ; nz = yes
  73.         cmp     flags.xflg,0            ; Writing to screen?
  74.         jne     int1                    ; Yes. Don't do anything
  75. int4:   test    flags.remflg,dquiet     ; quiet screen?
  76.         jnz     int1                    ; yes, supress msg
  77.         test    flags.remflg,dserial    ; serial mode display?
  78.         jz      int2                    ; ne = no
  79. int5:   mov     dx,offset crlf          ; yes. output initial cr/lf
  80.         mov     ah,prstr
  81.         int     dos
  82.         jmp     int3                    ; display the message
  83. int2:   
  84. ;       mov     dx,scrint
  85.         mcscr   scrint,cscrint
  86.  
  87.         call    poscur
  88.         call    clearl
  89. int3:   mcmsg   infms7,cinfms7          ; File interrupted?
  90.         cmp     flags.cxzflg,'X'        ; Yes.
  91.         je      int0
  92.         mcmsg   infms8,cinfms8          ; File group interrupted?
  93.         cmp     flags.cxzflg,'Z'
  94.         je      int0
  95.         cmp     flags.cxzflg,'C'        ; just a control-C?
  96.         je      int1                    ; e = yes, suppress msg
  97.         mov     dl,flags.cxzflg
  98.         mov     infms9+6,dl             ; store interrupt code letter
  99.         mcmsg   infms9, cinfms9
  100. int0:   mov     ah,prstr
  101.         int     dos
  102. int1:   ret
  103. INTMSG  ENDP
  104.  
  105. ; Print error message that a high bit set char was found in the file
  106.  
  107. BITERR  PROC    NEAR
  108.         test    flags.remflg,dquiet     ; remote mode?
  109.         jnz     biter1                  ; nz = yes, no printing
  110.         push    bx
  111.         cmp     fmtdsp,0                ; non-formatted display?
  112.         je      biter3                  ; e = yes
  113.         test    flags.remflg,dserial    ; serial mode display?
  114.         jz      biter2                  ; z = no
  115.         mov     ah,prstr                ; display an initial cr/lf
  116.         mov     dx,offset crlf
  117.         int     dos
  118.         jmp     biter3
  119. biter2: 
  120. ;       mov     dx,scrhi
  121.         mcscr   scrhi,cscrhi
  122.  
  123.         call    poscur
  124.         call    clearl
  125. biter3: mov     ah,prstr
  126.         mcmsg   hibit,chibit
  127.         int     dos
  128.         pop     bx
  129. biter1: ret
  130. BITERR  ENDP
  131.  
  132. ;  Clear out message about interrupted file
  133.  
  134. CXMSG   PROC    NEAR
  135.         test    flags.remflg,dserver    ; server mode?
  136.         jnz     cxm1                    ; nz = yes
  137.         cmp     flags.xflg,0            ; Writing to screen?
  138.         jne     cxm0                    ; Yes. Don't do anything
  139. cxm1:   test    flags.remflg,dquiet+dserial ; quiet or serial display?
  140.         jnz     cxm0                    ; nz = yes
  141. ;       mov     dx,scrint
  142.         mcscr   scrint,cscrint
  143.         call    poscur
  144.         call    clearl
  145. cxm0:   ret
  146. CXMSG   ENDP
  147.  
  148. ;  Clear out the old filename on the screen.
  149.  
  150. CLRFLN  PROC    NEAR
  151.         test    flags.remflg,dquiet     ; quiet display?
  152.         jnz     clrflnx                 ; nz = yes
  153.         test    flags.remflg,dserial    ; serial display mode?
  154.         jnz     clrfln1                 ; nz = yes, use just cr/lf
  155. ;        mov     dx,scrfln
  156.         mcscr   scrfln,cscrfln
  157.  
  158.         call    poscur
  159.         call    clearl                  ; Clear to end of line
  160.         ret
  161. clrfln1:push    ax                      ; for serial display, does cr/lf
  162.         mov     ah,prstr
  163.         mov     dx,offset crlf
  164.         int     dos
  165.         pop     ax
  166. clrflnx:ret
  167. CLRFLN  ENDP
  168.  
  169. PKTSIZE PROC    NEAR                    ; display packet size
  170.         cmp     fmtdsp,0                ; formatted display?
  171.         je      pktsiz3                 ; e = no, no display
  172.         push    ax
  173.         push    dx
  174.         mov     ax,pack.datlen          ; packet size (data part)
  175.         add     al,trans.chklen         ; plus checksum
  176.         adc     ah,0
  177.         add     ax,3                    ; plus LEN, SEQ, TYPE
  178.         cmp     ax,94                   ; larger than Regular?
  179.         jbe     pktsiz1                 ; be = no
  180.         add     ax,3                    ; add Long Packet len and chksum
  181. pktsiz1:cmp     ax,prepksz              ; same as previous packet?
  182.         je      pktsiz2                 ; e = yes, skip display
  183.         mov     prepksz,ax              ; remember new value
  184.         push    ax
  185. ;        mov     dx,scrsz                ; position cursor
  186.         mcscr   scrsz,cscrsz
  187.         call    poscur
  188.         call    clearl                  ; clear to end of line
  189.         pop     ax
  190.         call    decout                  ; show packet length
  191. pktsiz2:pop     dx
  192.         pop     ax
  193. pktsiz3:ret
  194. PKTSIZE ENDP
  195.  
  196. ; some random screen positioning functions
  197. kbpos: 
  198. ;     mov     dx,scrkb                ; KBytes transferred
  199.         mcscr   scrkb,cscrkb
  200.  
  201.         test    flags.remflg,dquiet+dserial ; quiet or serial display mode?
  202.         jnz     kbpos1
  203.         jmp      setup2                  ; z = no
  204. kbpos1: ret                             ; else ignore postioning request
  205. perpos: 
  206. ;       mov     dx,scrper               ; Percent transferred
  207.         mcscr   scrper,cscrper
  208.  
  209.         test    flags.remflg,dquiet+dserial ; quiet or serial display mode?
  210.         jnz     perpos1
  211.         jmp      setup2                  ; z = no
  212. perpos1: ret                             ; else ignore postioning request
  213. frpos:  
  214. ;       mov     dx,scrfr                ; Say renamed file
  215.         mcscr   scrfr,cscrfr
  216.  
  217.         jmp     setup2
  218. stpos:  
  219. ;       mov     dx,scrst                ; Print status of file transfer
  220.         mcscr   scrst,cscrst
  221.  
  222.         jmp     setup2
  223. nppos: 
  224. ;       mov     dx,scrnp                ; Number of packets sent
  225.         mcscr   scrnp,cscrnp
  226.  
  227.         test    flags.remflg,dquiet+dserial ; quiet or serial display mode?
  228.         jz      setup1                  ; z = no
  229.         ret
  230. rprpos: 
  231. ;       mov     dx,scrrpr               ; Reprompt position
  232.         mcscr   scrrpr,cscrrpr
  233.  
  234.         call    setup1                  ; position cursor
  235.         mov     fmtdsp,0                ; turn off formatted display flag
  236.         ret
  237. nrtpos: 
  238. ;       mov     dx,scrnrt               ; Number of retries
  239.         mcscr   scrnrt,cscrnrt
  240.  
  241.         jmp     short setup2
  242. sppos:  
  243. ;       mov     dx,scrsp                ; Send packet location
  244.         mcscr   scrsp,cscrsp
  245.  
  246.         jmp     short setup1
  247. rppos:  
  248. ;       mov     dx,scrrp                ; Receive packet location
  249.         mcscr   scrrp,cscrrp
  250.  
  251.         jmp     short setup1
  252.                                 ; common service routines for positioning
  253. setup1: test    flags.remflg,dquiet+dserial; quiet or serial display mode?
  254.         jnz     setupa                  ; nz = yes
  255.         cmp     fmtdsp,0                ; non-formatted display?
  256.         je      setupa                  ; e = yes
  257.         jmp     poscur
  258. setup2: test    flags.remflg,dquiet+dserial; quiet or serial display mode?
  259.         jnz     setupa                  ; nz = yes
  260.         cmp     fmtdsp,0                ; non-formatted display?
  261.         je      setupa                  ; e = yes
  262.         call    poscur                  ; no
  263.         jmp     clearl
  264. setupa: test    flags.remflg,dquiet     ; quiet mode?
  265.         jnz     setupx                  ; nz = yes, do nothing
  266.         push    ax                      ; display cr/lf and return
  267.         push    dx
  268.         mov     dx,offset crlf
  269.         mov     ah,prstr
  270.         int     dos
  271.         pop     dx
  272.         pop     ax
  273. setupx: ret
  274.  
  275. ; Start recording of statistics for this operation. [jrd]
  276. begtim  proc    near
  277.         test    sflag,80h               ; is this a duplicate call?
  278.         jz      begtim1                 ; z = no
  279.         ret                             ; else just return
  280. begtim1:push    ax
  281.         push    cx
  282.         push    dx
  283.         xor     ax,ax           ; clear statistics counters for this file
  284.         mov     fsta.prbyte,ax          ; bytes received from serial port
  285.         mov     fsta.prbyte+2,ax
  286.         mov     fsta.psbyte,ax          ; bytes sent out serial port
  287.         mov     fsta.psbyte+2,ax
  288.         mov     fsta.frbyte,ax          ; bytes received for this file
  289.         mov     fsta.frbyte+2,ax
  290.         mov     fsta.fsbyte,ax          ; bytes sent for this file
  291.         mov     fsta.fsbyte+2,ax
  292.         mov     fsta.prpkt,ax           ; packets received for this file
  293.         mov     fsta.prpkt+2,ax
  294.         mov     fsta.pspkt,ax           ; packets sent for this file
  295.         mov     fsta.pspkt+2,ax
  296.         mov     fsta.nakrcnt,ax         ; NAKs received for this file
  297.         mov     fsta.nakscnt,ax         ; NAKs sent for this file
  298.         mov     fsta.xstatus,al         ; clear status byte
  299.         mov     ah,getdate              ; get current date, convert to ascii
  300.         int     dos
  301.         mov     date+9,'0'              ; init day of month
  302. begtim2:cmp     dl,10                   ; day of month. Ten or more days?
  303.         jl      begtim3                 ; l = no
  304.         sub     dl,10
  305.         inc     date+9                  ; add up tens of days
  306.         jmp     short begtim2           ; repeat for higher order
  307. begtim3:add     dl,'0'                  ; ascii bias
  308.         mov     date+10,dl              ; day units
  309.         mov     dl,dh                   ; months (1-12)
  310.         dec     dl                      ; start at zero to index table
  311.         mov     dh,0
  312.         mov     di,dx                   ; months
  313.         shl     di,1
  314.         add     di,dx                   ; times three chars/month
  315.         mov     al,months[di]           ; get text string for month
  316.         mov     date+12,al
  317.         mov     ax,word ptr months[di+1]
  318.         mov     word ptr date+13,ax
  319.         mov     ax,cx                   ; year since 1980
  320.         mov     dx,0
  321.         mov     di,offset date+16       ; destination
  322.         call    lnout                   ; convert number to asciiz in buffer
  323.                                         ; start time
  324.         mov     ah,gettim               ; DOS time of day, convert to ascii
  325.         int     dos
  326.         mov     fsta.btime,dx           ; store ss.s   low word of seconds
  327.         mov     fsta.btime+2,cx         ; store hhmm   high word of seconds
  328.         mov     date,'0'                ; init begin hours field
  329. begtim4:cmp     ch,10                   ; ten or more hours?
  330.         jl      begtim5                 ; l = no
  331.         sub     ch,10
  332.         inc     date                    ; add up tens of hours
  333.         jmp     short begtim4           ; repeat for twenties
  334. begtim5:add     ch,'0'                  ; ascii bias
  335.         mov     date+1,ch               ; store units of hours
  336.         mov     date+3,'0'              ; minutes field
  337. begtim6:cmp     cl,10                   ; ten or more minutes?
  338.         jl      begtim7                 ; l = no
  339.         sub     cl,10
  340.         inc     date+3                  ; add up tens of minutes
  341.         jmp     short begtim6           ; repeat for higher orders
  342. begtim7:add     cl,'0'                  ; ascii bias
  343.         mov     date+4,cl               ; store units of minutes
  344.         mov     date+6,'0'              ; seconds field
  345. begtim8:cmp     dh,10                   ; ten or more seconds?
  346.         jl      begtim9                 ; l = no
  347.         sub     dh,10
  348.         inc     date+6                  ; add up tens of seconds
  349.         jmp     short begtim8           ; repeat for higher orders
  350. begtim9:add     dh,'0'                  ; ascii bias
  351.         mov     date+7,dh
  352.         mov     sflag,80h               ; say begtim has been run
  353.         pop     dx
  354.         pop     cx
  355.         pop     ax
  356.         ret
  357. begtim  endp
  358.  
  359. ; Take snapshot of statistics counters at end of an operation
  360. ; Enter with ax = 0 for a receive operation, ax = 1 for a send. [jrd]
  361. endtim  proc    near
  362.         test    sflag,80h       ; called more than once without calling begtim?
  363.         jnz     endtim1                 ; ne = no, so do statistics snapshot
  364.         ret                             ; yes, do nothing
  365. endtim1:and     sflag,not (1)           ; assume receive operation
  366.         or      ax,ax                   ; send (ax > 0), receive (ax = 0) flag
  367.         jz      endtim2                 ; z = receive opeation
  368.         or      sflag,1                 ; say send operation
  369. endtim2:
  370.         push    ax
  371.         push    cx
  372.         push    dx
  373.         mov     ah,gettim               ; get DOS time of day
  374.         int     dos
  375.         mov     fsta.etime,dx           ; store ss. s
  376.         mov     fsta.etime+2,cx         ; hhmm
  377.         cmp     cx,fsta.btime+2         ; end time less than start time?
  378.         ja      endtim2a        ; a = above (no need to test low order word)
  379.         cmp     dx,fsta.btime           ; be. How about low order word
  380.         jae     endtim2a                ; ae = no wrap around of time
  381.         add     ch,24                   ; add one day to hours field
  382. endtim2a:sub    dl,byte ptr fsta.btime ; 0.01 sec difference
  383.         jns     endtim2b
  384.         dec     dh                      ; borrow a second
  385.         add     dl,100                  ; make difference positive
  386. endtim2b:sub    dh,byte ptr fsta.btime+1; seconds difference
  387.         jns     endtim2c
  388.         dec     cl                      ; borrow a minute
  389.         add     dh,60                   ; make difference positive
  390. endtim2c:mov    bh,0
  391.         mov     bl,dh                   ; bx has seconds difference
  392.         sub     cl,byte ptr fsta.btime+2 ; minutes
  393.         jns     endtim2d
  394.         dec     ch                      ; borrow an hour
  395.         add     cl,60
  396. endtim2d:mov    al,cl
  397.         mov     ah,0
  398.         mul     sixty                   ; minutes to seconds
  399.         add     bx,ax                   ; seconds to bx
  400.         sub     ch,byte ptr fsta.btime+3 ; hours difference
  401.         jns     endtim2e
  402.         add     ch,24
  403. endtim2e:mov    al,ch
  404.         mov     ah,0
  405.         mul     sixty                   ; hours to minutes in ax
  406.         mul     sixty                   ; minutes to seconds in dx,ax
  407.         add     ax,bx                   ; ax = seconds
  408.         adc     dx,0                    ; dx = high word of seconds
  409.         mov     fsta.etime,ax           ; store elapsed time, seconds, low wd
  410.         mov     fsta.etime+2,dx         ; high word
  411.         add     ssta.etime,ax           ; add to session time, low word
  412.         adc     ssta.etime+2,dx         ; add to session time, high word
  413.  
  414.         mov     ax,fsta.prbyte          ; port bytes received for this file
  415.         add     ssta.prbyte,ax          ; port bytes received for this session
  416.         mov     ax,fsta.prbyte+2        ; high word
  417.         adc     ssta.prbyte+2,ax
  418.         mov     ax,fsta.psbyte  ; port bytes sent for this file, low word
  419.         add     ssta.psbyte,ax  ; port bytes sent for this session, low word
  420.         mov     ax,fsta.psbyte+2        ; high word
  421.         adc     ssta.psbyte+2,ax
  422.  
  423.         test    sflag,1                 ; completing a receive operation?
  424.         jnz     endtim3                 ; nz = no, a send operation
  425.         mov     ax,tfilsz+2             ; file bytes received, low word
  426.         mov     fsta.frbyte,ax
  427.         add     ssta.frbyte,ax          ; session received file bytes, low word
  428.         mov     ax,tfilsz               ; high word
  429.         mov     fsta.frbyte+2,ax
  430.         adc     ssta.frbyte+2,ax
  431.         jmp     short endtim4
  432.  
  433. endtim3:mov     ax,tfilsz+2             ; file bytes sent, low word
  434.         mov     fsta.fsbyte,ax          ; file bytes sent
  435.         add     ssta.fsbyte,ax          ; session sent file bytes, low word
  436.         mov     ax,tfilsz               ; high word
  437.         mov     fsta.fsbyte+2,ax
  438.         adc     ssta.fsbyte+2,ax
  439.  
  440. endtim4:mov     ax,fsta.prpkt           ; packets received for this file
  441.         add     ssta.prpkt,ax           ; session received packets
  442.         mov     ax,fsta.prpkt+2
  443.         adc     ssta.prpkt+2,ax
  444.         mov     ax,fsta.pspkt           ; packets sent for this file
  445.         add     ssta.pspkt,ax           ; session sent packets
  446.         mov     ax,fsta.pspkt+2
  447.         adc     ssta.pspkt+2,ax
  448.         mov     ax,fsta.nakrcnt         ; NAKs received for this file
  449.         add     ssta.nakrcnt,ax         ; session received NAKs
  450.         mov     ax,fsta.nakscnt         ; NAKs sent for this file
  451.         add     ssta.nakscnt,ax         ; session sent NAKs
  452.                                         ; do transaction logging
  453.         cmp     tloghnd,0               ; logging transaction? -1 = not opened
  454.         jg      endtim5                 ; g = logging
  455.         jmp     endtim12                ; skip logging
  456. endtim5:push    di                      ; kind of transaction
  457.         push    bx                      ; save these registers
  458.         mov     bx,tloghnd              ; handle for transaction log
  459.         mov     dx,offset rcvmsg        ; assume receive message
  460.         test    sflag,1                 ; 1 for send, 0 for receive
  461.         jz      endtim6                 ; z = receive
  462.         mov     dx,offset sndmsg        ; send message
  463. endtim6:call    strlen                  ; length of message to cx
  464.         mov     ah,write2
  465.         int     dos                     ; write kind of transfer
  466.                                         ; File names
  467.         cmp     diskio.string,0         ; local filename
  468.         je      endtim9                 ; e = no filename
  469.         test    sflag,1                 ; a send operation?
  470.         jnz     endtim8                 ; nz = yes
  471.                                         ; Receive
  472.         mov     dx,offset fsta.xname    ; remote name
  473.         call    strlen                  ; length to cx
  474.         jcxz    endtim7                 ; no name
  475.         mov     ah,write2
  476.         int     dos
  477.         mov     dx,offset diskio.string ; local name
  478.         call    strlen                  ; length to cx
  479.         mov     si,offset fsta.xname    ; compare these two names
  480.         mov     di,dx
  481.         push    ds
  482.         pop     es
  483.         repe    cmpsb                   ; compare
  484.         je      endtim9                 ; e = same, so no 'as' msg
  485.         mcmsg   fasmsg,cfasmsg          ; give 'as' message
  486.         mov     cx,faslen               ; length
  487.         mov     ah,write2
  488.         int     dos
  489. endtim7:mov     dx,offset diskio.string ; local name
  490.         call    strlen                  ; get length
  491.         mov     ah,write2               ; write local name
  492.         int     dos
  493.         jmp     short endtim9
  494.  
  495. endtim8:mov     dx,offset diskio.string ; Send. local name
  496.         call    strlen
  497.         mov     ah,write2
  498.         int     dos
  499.         cmp     fsta.xname,0            ; using an alias?
  500.         je      endtim9                 ; e = no
  501. ;        mov     dx,offset fasmsg        ; give 'as' message
  502.         mcmsg   fasmsg,cfasmsg
  503.  
  504.         mov     cx,faslen
  505.         mov     ah,write2
  506.         int     dos
  507.         mov     dx,offset fsta.xname    ; get alias
  508.         call    strlen
  509.         mov     ah,write2
  510.         int     dos
  511.                                         ; status of transfer
  512. endtim9:mov     dx,offset atmsg         ; say At
  513.         mov     cx,atlen                ; length
  514.         mov     bx,tloghnd              ; handle
  515.         mov     ah,write2
  516.         int     dos
  517.         mov     dx,offset date          ; write time and date field
  518.         mov     cx,datelen              ; length
  519.         mov     ah,write2
  520.         int     dos
  521.         mcmsg   fsucmsg ,cfsucmsg       ; assume success message
  522.         cmp     fsta.xstatus,0          ; 0 = completed?
  523.         je      endtim10                ; e = completed
  524.         mcmsg   fbadmsg,cfbadmsg         ; failed message
  525.         test    fsta.xstatus,80h        ; interrupted?
  526.         jz      endtim10                ; z = no
  527.         mcmsg   fintmsg,  cfintmsg       ; interrupted message
  528. endtim10:call   strlen                  ; get length to cx
  529.         mov     ah,write2
  530.         int     dos
  531.                                         ; file bytes transferred
  532.         mov     ax,tfilsz+2             ; file bytes, low word
  533.         mov     dx,tfilsz               ; high word
  534.         mov     di,offset temprp        ; work buffer
  535.         call    lnout                   ; transform to ascii
  536.         mov     [di],0a0dh              ; append cr/lf
  537.         add     di,2                    ; count them
  538.         mov     dx,offset temprp        ; start of work buffer
  539.         mov     cx,di                   ; next free byte
  540.         sub     cx,dx                   ; compute length
  541.         mov     ah,write2
  542.         int     dos
  543.         pop     bx
  544.         pop     di
  545. endtim12:mov    tfilsz,0                ; clear file size area
  546.         mov     tfilsz+2,0
  547.         mov     sflag,0                 ; say have done ending once already
  548.         mov     fsta.xname,0            ; clear statistics "as" name
  549.         pop     dx
  550.         pop     cx
  551.         pop     ax
  552.         ret
  553. endtim  endp
  554.  
  555. ; SHOW STATISTICS command. Displays last operation and session statistics
  556. ; 9 March 1987 [jrd]
  557. shosta  proc    near                    ; show file transfer statistics
  558.         mov     ah,cmcfm                ; confirm with carriage return
  559.         call    comnd
  560.          ret                            ; not confirmed
  561.          nop
  562.          nop
  563.         call    endtim                  ; update statistics, just in case
  564.         push    bx
  565.         push    cx
  566.         push    dx
  567.         mov     bx,offset fsta          ; pointer to file (Last op) statistics
  568.         mov     cx,2                    ; two sets to display
  569. shosta0:push    cx                      ; save loop counter
  570.         cmp     cx,2                    ; doing Last operation set?
  571. ;--Pay attention to the next instructon ' je ... '(eflag), Sept.14,1990[zqf]
  572. ;       mov     cx,offset lastmsg       ; totals for last transfer
  573.         pushf
  574.         mcmsgc   lastmsg,clastmsg       
  575.         popf
  576.         je      shosta1                 ; e = yes
  577. ;-----------
  578.         mov     bx,offset ssta          ; point to Session statistics area
  579. ;       mov     cx,offset sessmsg       ; totals for whole session
  580.         mcmsgc   sessmsg,csessmsg       
  581. shosta1:
  582.         mov     ax,[bx].etime           ; elapsed time of operation
  583.         mov     dx,[bx].etime+2
  584.         call    shoprt                  ; show result
  585. ;       mov     cx,offset pinmsg        ; port bytes received
  586.         mcmsgc   pinmsg,cpinmsg        
  587.         mov     ax,[bx].prbyte
  588.         mov     dx,[bx].prbyte+2
  589.         call    shoprt                  ; show result
  590. ;        mov     cx,offset poutmsg       ; port bytes sent
  591.         mcmsgc  poutmsg,cpoutmsg
  592.  
  593.         mov     ax,[bx].psbyte
  594.         mov     dx,[bx].psbyte+2
  595.         call    shoprt                  ; show result
  596. ;        mov     cx,offset finmsg        ; file bytes received
  597.         mcmsgc  finmsg,cfinmsg
  598.  
  599.         mov     ax,[bx].frbyte
  600.         mov     dx,[bx].frbyte+2
  601.         call    shoprt                  ; show result
  602. ;       mov     cx,offset foutmsg       ; file bytes sent
  603.         mcmsgc  foutmsg,cfoutmsg
  604.  
  605.         mov     ax,[bx].fsbyte
  606.         mov     dx,[bx].fsbyte+2
  607.         call    shoprt                  ; show result
  608. ;       mov     cx,offset pkimsg        ; packets received
  609.         mcmsgc  pkimsg,cpkimsg
  610.  
  611.         mov     ax,[bx].prpkt
  612.         mov     dx,[bx].prpkt+2
  613.         call    shoprt                  ; show result
  614. ;       mov     cx,offset pkomsg        ; packets sent
  615.         mcmsgc  pkomsg,cpkomsg
  616.  
  617.         mov     ax,[bx].pspkt
  618.         mov     dx,[bx].pspkt+2
  619.         call    shoprt                  ; show result
  620. ;        mov     cx,offset nakimsg       ; naks received
  621.         mcmsgc  nakimsg,cnakimsg
  622.  
  623.         mov     ax,[bx].nakrcnt
  624.         xor     dx,dx
  625.         call    shoprt                  ; show result
  626. ;        mov     cx,offset nakomsg       ; naks sent
  627.         mcmsgc  nakomsg,cnakomsg
  628.  
  629.         mov     ax,[bx].nakscnt
  630.         xor     dx,dx
  631.         call    shoprt
  632.                 ; compute baud rate as  10 * total port bytes / elapsed time
  633.         mov     ax,[bx].prbyte          ; port bytes received, low
  634.         mov     dx,[bx].prbyte+2        ; port bytes received, high
  635.         add     ax,[bx].psbyte          ; port bytes sent, low
  636.         adc     dx,[bx].psbyte+2        ;  high. [dx,ax] = total port bytes
  637.  
  638.         mov     cx,[bx].etime           ; low word of sec in cx
  639.         cmp     [bx].etime+2,0  ; is high word of sec zero (e.t. < 65536 sec)?
  640.         jz      shosta3                 ; z = yes, ready for arithmetic
  641.         push    ax                      ; else scale values, save byte count
  642.         push    dx
  643.         mov     ax,[bx].etime           ; elapsed time for file, low word
  644.         mov     dx,[bx].etime+2         ;  high word
  645.         shr     ax,1                    ; divide seconds by two, low word
  646.         ror     dx,1                    ; get low bit of high word
  647.         and     dx,8000                 ; pick out just that bit
  648.         or      ax,dx           ; mask in that bit, new time in ax (dx = 0)
  649.         mov     cx,ax                   ; save elapsed time (double-seconds)
  650.         pop     dx                      ; get byte count again
  651.         pop     ax
  652.         shr     ax,1                    ; divide byte count by two also
  653.         push    dx
  654.         ror     dx,1                    ; rotate low bit to high position
  655.         and     dx,8000h                ; get low bit of high word
  656.         or      ax,dx                   ; byte count divided by two, low word
  657.         pop     dx
  658.         shr     dx,1                    ; and high word
  659. shosta3:or      cx,cx                  ; is elapsed time (in cx) zero seconds?
  660.         jnz     shosta4                 ; nz = no
  661.         inc     cx                      ; set time to one second (no div by 0)
  662. shosta4:div     cx                     ; bytes div seconds, ax = quo, dx = rem
  663.         push    dx                      ; save remainder of bytes/second
  664.         mul     ten                     ; quotient times ten to dx,ax
  665.         pop     dx                      ; discard overflow, recover remainder
  666.         push    ax                      ; save partial baud rate
  667.         xchg    ax,dx                   ; remainder to ax
  668.         xor     dx,dx                   ; clear extension
  669.         mul     ten             ; remainder times ten too (keep only overflow)
  670.         pop     ax                      ; recover main partial result
  671.         add     ax,dx                   ; add two partial results
  672.         xor     dx,dx                   ; clear extension ( < 65536 baud )
  673. ;        mov     cx,offset baudmsg
  674.         mcmsgc  baudmsg,cbaudmsg
  675.  
  676.         call    shoprt                  ; show result
  677.         pop     cx                      ; recover loop counter
  678.         dec     cx
  679.         jcxz    shostax                 ; cx = 0 means we are done
  680.         jmp     shosta0         ; do next set of statistics (session stuff)
  681. shostax:
  682.         pop     dx
  683.         pop     cx
  684.         pop     bx
  685.         jmp     rskp
  686. shosta  endp
  687.  
  688. ; Print show statistics line. Enter with CX=offset of initial message,
  689. ; dx,ax with long value
  690. shoprt  proc    near
  691.         push    ax
  692.         push    dx
  693.         mov     dx,cx                   ; setput initial print
  694.         mov     ah,prstr                ; display title line (dx is ptr)
  695.         int     dos
  696.         pop     dx
  697.         pop     ax
  698.         push    di
  699.         mov     di,offset temprp        ; work space for output
  700.         call    lnout                   ; show long integer
  701.         pop     di
  702.         mov     dx,offset temprp
  703.         call    prtasz                  ; print asciiz string
  704.         ret
  705. shoprt  endp
  706.  
  707. ; LNOUT - Table driven unsigned long integer (32 bit) display
  708. ; Register dx holds high order word and ax holds low order word of unsigned
  709. ; long integer to be stored in decimal. Storage area is given by DS:[DI]
  710. ; DI is incremented for each storage, null terminated
  711. ; Table TENS holds set of double word values of ten raised to powers 0 to 9
  712. ; TENSLEN holds the number of these double words
  713. ; All registers preserved.      8 March 1987 [jrd]
  714. lnout   proc    near
  715.         push    ax
  716.         push    bx
  717.         push    cx
  718.         push    dx
  719.         push    si
  720.         xor     si,si           ; flag to say start printing (no leading 0's)
  721.         mov     cx,tenslen      ; number of table entries
  722. lnout1: push    cx              ; save loop counter
  723.         mov     bx,cx           ; index into tens double word table
  724.         dec     bx              ; index starts at zero
  725.         add     bx,bx
  726.         add     bx,bx           ; bx times four (double words to bytes)
  727.         xor     cx,cx           ; cx is now a counter of subtractions
  728.  
  729. lnout2: cmp     dx,word ptr tens[bx+2]  ; pattern 10**(bx/4), high order part
  730.         jb      lnout4          ; b = present number is less than pattern
  731.         ja      lnout3          ; a = present number is larger than pattern
  732.         cmp     ax,word ptr tens[bx] ; high words match, how about lows
  733.         jb      lnout4          ; b = present number is smaller than pattern
  734. lnout3: sub     ax,word ptr tens[bx]    ; subtract low order words
  735.         sbb     dx,word ptr tens[bx+2]  ; subtract high order words, w/borrow
  736.         inc     cl                      ; count number of subtractions
  737.         inc     si              ; flag to indicate printing needed
  738.         jmp     lnout2          ; try again to deduct present test pattern
  739.  
  740. lnout4: or      bx,bx           ; doing least significant digit?
  741.         jz      lnout5          ; z = yes, always print this one
  742.         or      si,si           ; should we print?
  743.         jz      lnout6          ; z = no, not yet
  744. lnout5: add     cl,'0'          ; get number of subtractions
  745.         mov     [di],cx         ; store it (ch is still zero), asciiz
  746.         inc     di
  747. lnout6: pop     cx              ; recover loop counter
  748.         loop    lnout1
  749.         pop     si
  750.         pop     dx
  751.         pop     cx
  752.         pop     bx
  753.         pop     ax
  754.         ret
  755. lnout   endp
  756.  
  757. ;       Initialize buffers and clear line
  758.  
  759. INIT    PROC    NEAR
  760.         mov     hierr,0                 ; clear high-bit-seen flag
  761.         test    flags.remflg,dquiet     ; quiet display mode?
  762.         jnz     init3                   ; nz = yes
  763.         test    flags.remflg,dserial    ; serial mode display?
  764.         jnz     init2                   ; nz = yes
  765.         call    cmblnk
  766.         mcmsg   cxzhlp,ccxzhlp
  767.         call    putmod                  ; write mode line
  768.         mov     fmtdsp,1                ; say doing formatted display
  769.         test    flags.remflg,dserver    ; server mode?
  770.         jz      init1                   ; z = no
  771. ;        mov     dx,scrser               ; move cursor to top of screen
  772.         mcscr   scrser,cscrser
  773.  
  774.         call    poscur
  775.         mov     ah,prstr
  776.         mcmsg   infms1,cinfms1        ; say now in server mode
  777.         int     dos
  778. init1:  call    locate
  779.         mov     ah,prstr                ; Put statistics headers on the screen
  780.         mcmsg   outlin, coutlin
  781.         int     dos
  782.         mov     wrpmsg,0                ; haven't printed the messsage yet
  783.         mov     prepksz,0               ; set previous packet size to zero
  784.         ret
  785. init2:  mov     ah,prstr                ; print string
  786.         mcmsg   cxzser,ccxzser          ; status line as a text string
  787.         int     dos
  788. init3:  mov     wrpmsg,1                ; suppress display of percentage msg
  789.         mov     fmtdsp,0                ; say doing unformatted display
  790.         ret
  791. INIT    ENDP
  792.  
  793.  
  794. ;       Output the chars in a packet
  795.  
  796. ; Called with AX = size of the data, BX = address of source
  797.  
  798. FILEIO  PROC    NEAR
  799.  
  800. ptchr:  mov     cx,ax
  801.         mov     ax,offset outbuf       ; routine to call when buffer gets full
  802.         mov     chrcnt,maxpack          ; size of buffer Data
  803.         mov     bufpnt,offset decbuf ; decoded data placed here pending output
  804.         mov     bx,offset data          ; source of data
  805.         jmp     short decode
  806.  
  807.  
  808. ; CX = Size of data, BX = Address of data, AX = Routine to call to
  809. ; dump data
  810.  
  811. decode: push    si
  812.         push    di
  813.         push    es
  814.         push    dx
  815.         push    ax
  816.         mov     ax,ds
  817.         mov     es,ax
  818.         pop     ax
  819.         mov     si,bx                   ; Source of data
  820.         mov     bx,ax                   ; Coroutine to call
  821.         mov     di,bufpnt               ; Destination of data
  822.         mov     dh,0                    ; assume no quote char
  823.         cmp     trans.ebquot,'N'        ; no quoting?
  824.         je      decod1                  ; yes, keep going
  825.         cmp     trans.ebquot,'Y'        ; or not doing it?
  826.         je      decod1                  ; yes, keep going
  827.         mov     dh,trans.ebquot         ; otherwise use quote char
  828.  
  829. decod1: mov     rptct,0                 ; Reset repeat count
  830.         cmp     cx,0                    ; any more chars in source?
  831.         jg      decod2                  ; g = yes
  832.         jmp     decod6                  ; Else, we're through
  833. decod2: cld                             ; forward direction
  834.         lodsb                           ; Pick up a char
  835.         dec     cx                      ; count number left
  836.         cmp     rptq,0                  ; Doing repeat quoting?
  837.         je      dcod21                  ; Nope, skip this part
  838.         cmp     al,rptq                 ; Did we pick up the repeat quote char?
  839.         jne     dcod21                  ; No, continue processing it
  840.         lodsb                           ; Get the size
  841.         dec     cx                      ; Modify buffer count
  842.         sub     al,20H                  ; Was made printable
  843.         mov     rptct,al                ; Remember how many repetitions
  844.         lodsb                           ; Get the char to repeat
  845.         dec     cx                      ; Modify buffer count
  846. dcod21: mov     ah,0                    ; Assume no 8-bit quote char
  847.         cmp     al,dh                   ; This the 8-bit quot char?
  848.         jne     decod3                  ; ne = no
  849.         lodsb                           ; Get the real character
  850.         dec     cx                      ; Decrement # chars in packet
  851.         mov     ah,80H                  ; Turn on 8-bit quot char flag
  852. decod3: cmp     al,trans.squote         ; Is it the quote char?
  853.         jne     decod4                  ; ne = no, proceed
  854.         lodsb                           ; Get the quoted character
  855.         dec     cx                      ; Decrement # of chars in packet
  856.         or      ah,al                   ; save parity (combine with prefix)
  857.         and     ah,80h                  ; only parity
  858.         and     al,7FH                  ; Turn off the parity bit
  859.         cmp     al,trans.squote         ; Is it the quote char?
  860.         je      decod4                  ; If so just go write it out
  861.         cmp     al,dh                   ; This the 8-bit quot char?
  862.         je      decod4                  ; If so, just go write it out
  863.         cmp     al,rptq                 ; Is is the repeat quote character?
  864.         je      decod4                  ; If so, just write it out
  865.         cmp     al,3fh                  ; char less than '?' ?
  866.         jl      decod4                  ; l = yes; leave it intact
  867.         cmp     al,5fh                  ; char greater than '_' ?
  868.         jg      decod4                  ; g = yes; leave it alone
  869.         add     al,40H                  ; Make it a control char again
  870.         and     al,7FH                  ; Modulo 128
  871. decod4: or      al,ah                   ; or in parity
  872. dcod41: stosb                           ; store the character
  873.         dec     rptct                   ; Repeat counter
  874.         dec     chrcnt                  ; Decrement number of chars in dta
  875.         cmp     chrcnt,0                ; space left in output buffer?
  876.         jg      dcod42                  ; g = yes
  877.         push    ax                      ; Save the char
  878.         push    cx                      ; flush output buffer
  879.         push    dx
  880.         push    bx
  881.         call    bx                      ; Output it if full
  882.          jmp    decod5                  ;  Error return if disk is full
  883.          nop
  884.         pop     bx
  885.         pop     dx
  886.         pop     cx
  887.         mov     di,bufpnt
  888.         pop     ax                      ; recover repeated char
  889. dcod42: cmp     rptct,0                 ; Write out char again?
  890.         jg      dcod41                  ; g = yes
  891.         jmp     decod1                  ; No, get next char
  892. decod5: pop     bx
  893.         pop     dx                      ; dx is pushed twice (really)
  894.         pop     cx
  895.         pop     dx
  896.         pop     es
  897.         pop     di
  898.         pop     si
  899.         ret
  900. decod6: mov     bufpnt,di               ; store address for next output char
  901.         push    cx
  902.         push    dx
  903.         push    bx
  904.         call    bx                      ; flush output buffer before final ret
  905.          jmp    decod5                  ;  Error return if disk is full
  906.          nop
  907.         pop     bx
  908.         pop     dx
  909.         pop     cx
  910.  
  911.         pop     dx
  912.         pop     es
  913.         pop     di
  914.         pop     si
  915.         jmp     rskp                    ; Return successfully if done
  916.  
  917.                                 ; output the buffer, reset bufpnt and chrcnt
  918.  
  919. outbuf: mov     cx,maxpack              ; get full size of buffer
  920.         sub     cx,chrcnt               ; minus space remaining = # to write
  921.         jnc     outbu7
  922.         jmp     outbf0                  ; c = bad buffer pointers
  923. outbu7: jnz     outbu6
  924.         jmp     outb11                  ; cx = 0 means nothing to do
  925. outbu6: cmp     flags.xflg,1            ; Writing to screen?
  926.         jne     outbu0
  927.         jmp     outbf2                  ; Yes, handle specially
  928. outbu0:
  929.         mov     cx,maxpack              ; get full size of buffer
  930.         sub     cx,chrcnt               ; minus space remaining = # to write
  931.         jc      outbf0                  ; c = bad buffer pointers
  932.         jnz     outbu1
  933.         jmp     outb11                  ; cx = 0 means nothing to do
  934. outbu1: push    bx
  935.         mov     dx,offset decbuf        ; address of buffer
  936.         cmp     flags.destflg,1         ; disk destination?
  937.         je      outbu5                  ; e = yes
  938.         cmp     flags.eofcz,0           ; end on Control-Z?
  939.         jne     outbu5                  ; ne = yes, let DOS do it
  940.         push    cx                      ; else map Control-Z to space
  941.         push    di
  942.         push    es
  943.         push    ds
  944.         pop     es                      ; datas to es
  945.         mov     di,dx                   ; scan buffer es:di, cx chars worth
  946.         mov     al,ctlz                 ; look for Control-Z
  947.         cld
  948. outbu3: repne   scasb
  949.         jne     outbu4                  ; ne = found no Control-Z's
  950.         mov     byte ptr [di-1],' '     ; replace Control-Z with space
  951.         jcxz    outbu4                  ; z = examined all chars
  952.         jmp     short outbu3            ; until examined everything
  953. outbu4: pop     es
  954.         pop     di
  955.         pop     cx
  956. outbu5: mov     bx,diskio.handle        ; file handle
  957.         mov     ah,write2               ; DOS 2.0 write
  958.         int     dos                     ; Write the record
  959.         pop     bx
  960.         jc      outbf0                  ; c set means disk writing error
  961.         cmp     ax,cx                   ; did we write all the bytes?
  962.         je      outbf1                  ; e = yes
  963.         call    erpos                   ; no
  964.         mcmsg   erms11,erms11           ; Disk full error
  965.         cmp     flags.destflg,1         ; writing to disk?
  966.         je      outbu0a                 ; e = yes
  967.         push    bx
  968.         mov     bx,offset decbuf
  969.         add     bx,ax                   ; look at break character
  970.         cmp     byte ptr [bx],ctlz      ; ended on Control-Z?
  971.         pop     bx
  972.         je      outbf1                  ; e = yes, say no error
  973.         mcmsg   ermes9,cermes9          ; Printer not ready message
  974. outbu0a:mov     ah,prstr                ; Tell about it
  975.         int     dos
  976.         jmp     abfil                   ; Fix things up before aborting
  977.  
  978. outbf0: call    erpos
  979.         mov     ah,prstr                ; Tell about it
  980.         mcmsg   erms13,cerms13          ; Disk writing error
  981.         cmp     flags.destflg,0         ; writing to printer?
  982.         jne     outbf0a                 ; ne = no
  983. ;        mov     dx,offset ermes9        ; Printer not ready message
  984.         mcmsg   ermes9,cermes9
  985.  
  986. outbf0a:int     dos
  987.         jmp     abfil                   ; Fix things up before aborting
  988.  
  989. outbf1: add     tfilsz+2,cx             ; count received chars
  990.         adc     tfilsz,0
  991.         test    flags.remflg,dserial    ; serial mode display?
  992.         jnz     outb11                  ; nz = yes, skip kbyte and % displays
  993.         call    kbpr                    ; Print the kilobytes received
  994.         call    perpr                   ; Print the percent
  995. outb11: mov     bufpnt,offset decbuf    ; Addr for beginning
  996.         mov     chrcnt,maxpack          ; size of empty buffer
  997.         jmp     rskp
  998.  
  999. outbf2:                                 ; writing to screen
  1000.         mov     cx,maxpack              ; size of full buffer
  1001.         sub     cx,chrcnt               ; minus # of unused in buffer
  1002.         jle     outb11                  ; none to print, don't try
  1003.         add     tfilsz+2,cx             ; count received chars
  1004.         adc     tfilsz,0
  1005.         mov     di,offset decbuf        ; Where they are
  1006.         call    prtscr                  ; Output buffer to screen
  1007.         jmp     outb11                  ; Reset counter & pointer
  1008.  
  1009. ;  Tidy up before aborting. Retidied by [jrd]
  1010. ABFIL   PROC    NEAR
  1011.         cmp     flags.xflg,1            ; Writing to screen?
  1012.         je      abfil1                  ; Yes don't delete "file"
  1013.         mov     bx,diskio.handle        ; get file handle
  1014.         cmp     bx,4                    ; writing to DOS set of files?
  1015.         jbe     abfil1                  ; be = yes, never close them
  1016.         mov     ah,close2               ; DOS 2.0 file close
  1017.         int     dos
  1018.         cmp     flags.abfflg,1          ; Delete what got across or keep it?
  1019.         jne     abfil1                  ; Nope, keep it
  1020.         push    dx
  1021.         mov     dx,offset diskio.string ; the full file name
  1022.         mov     ah,del2                 ; DOS 2.0 file delete
  1023.         int     dos
  1024.         pop     dx
  1025. abfil1: mcmsg   erms10, cerms10         ; Text of message to send
  1026.         call    errpack                 ; Send an error packet
  1027.         ret
  1028. ABFIL   ENDP
  1029.  
  1030. ; General routine for sending an error packet.  Register BX should
  1031. ; point to the text of the message being sent in the packet
  1032.  
  1033. ERRPACK PROC    NEAR
  1034.         push    di
  1035.         mov     di,offset data          ; Where to put the message
  1036.         mov     al,0
  1037. errp1:  mov     ah,[bx]
  1038.         cmp     ah,'$'                  ; At end of message?
  1039.         je      errp2
  1040.         inc     al                      ; Remember number of chars in msg
  1041.         mov     [di],ah
  1042.         inc     bx
  1043.         inc     di
  1044.         jmp     errp1
  1045. errp2:  pop     di
  1046.         mov     ah,0
  1047.         mov     pack.datlen,ax
  1048.         mov     ah,'E'                  ; And send an error packet
  1049.         call    spack
  1050.          nop                            ; Return if succeed or fail
  1051.          nop
  1052.          nop
  1053.         ret
  1054. ERRPACK ENDP
  1055.  
  1056. ;       Get the chars from the file
  1057.  
  1058. gtchr:  cmp     flags.filflg,0          ; Is there anything in the DMA?
  1059.         je      gtchr0                  ; e = yes, proceed
  1060.         mov     ah,rptq
  1061.         mov     origr,ah                ; Save repeat prefix here
  1062.         mov     rptct,1                 ; Number of times char is repeated
  1063.         mov     rptval,0                ; Value of repeated char
  1064.         call    inbuf
  1065.          jmp    gtchr1                  ; No more chars, go return EOF
  1066.          nop                            ; Make  three bytes long
  1067. gtchr0: mov     bx,offset inbuf
  1068.         jmp     encode
  1069. gtchr1: mov     ax,0ffffh
  1070.         ret
  1071.  
  1072. ; encode - writes data portion of kermit packet into filbuf
  1073. ; expects BX to contain the address of a routine to refill the buffer,
  1074. ; chrcnt to be the # of chars in the buffer, trans.maxdat to contain
  1075. ; the maximum size of the data packet, bufpnt to contain a pointer to
  1076. ; the source of the characters
  1077. ; Returns: AX/ the number of characters actually written to the buffer
  1078.  
  1079. encode: mov     cx,trans.maxdat         ; Maximum packet size
  1080.         push    ds
  1081.         pop     es                      ; make es:di point to datas segment
  1082.         mov     di,offset filbuf        ; Where to put the data
  1083.         mov     si,bufpnt               ; pointer into source buffer
  1084.         mov     dl,trans.rquote         ; send quote char
  1085.         mov     dh,0                    ; assume no 8-bit quoting
  1086.         cmp     trans.ebquot,'N'        ; not doing 8-bit quoting
  1087.         je      encod1
  1088.         cmp     trans.ebquot,'Y'        ; or can but won't?
  1089.         je      encod1
  1090.         mov     dh,0ffh                 ; remember we have to do it
  1091. encod1: cmp     cx,0                    ; any space left in output buffer?
  1092.         jg      encod2                  ; g = yes
  1093.         sub     di,offset filbuf
  1094.         mov     ax,di
  1095.         mov     bufpnt,si               ; update pointer into DMA
  1096.         jmp     rskp
  1097. encod2: cmp     chrcnt,0                ; Any data in buffer?
  1098.         jg      encod3                  ; yes, skip over buffer refill
  1099.         call    bx                      ; Get another buffer full
  1100.          jmp    encod8
  1101.         mov     si,bufpnt               ; update position in DMA
  1102.         cmp     chrcnt,0                ; no characters returned?
  1103.         jne     encod3                  ; Got some, keep going
  1104.         jmp     encod8                  ; none, assume eof
  1105. encod3: dec     chrcnt                  ; Decrement input count
  1106.         cld                             ; forward direction
  1107.         lodsb
  1108.         cmp     flags.eofcz,0           ; Is a control-z an end of file?
  1109.         je      encd30                  ; No, don't have to look for one
  1110.         cmp     al,'Z'-40H              ; Is this a control-Z?
  1111.         jne     encd30                  ; No, skip eof-processing
  1112.         mov     flags.eoflag,0FFH       ; Yes, set eof flag
  1113.         mov     flags.filflg,0FFH       ; No more input in buffer
  1114.         mov     chrcnt,0                ; Ditto
  1115.         jmp     encod8                  ; Go set character count and return
  1116. encd30: cmp     rptq,0                  ; Are we doing repeat prefixing?
  1117.         je      encd3x                  ; Nope, skip next part
  1118.         cmp     chrcnt,0                ; Are we on the last character?
  1119.         jle     encd31                  ; Yes, so there's no next character
  1120.         cmp     rptct,94                ; Max number that we can put in a byte
  1121.         je      encd31                  ; Then that's it
  1122.         mov     ah,[si]                 ; Get the next character
  1123.         cmp     al,ah                   ; Is current char == next char?
  1124.         jne     encd31
  1125.         inc     rptct                   ; Number of times char appears
  1126.         mov     rptval,al               ; Remember the character
  1127.         jmp     encod1                  ; Keep checking for more
  1128. encd31: cmp     rptct,1                 ; Were previous characters repeats?
  1129.         je      encd3x                  ; No, so just add this char
  1130.         cmp     rptct,rptmin    ; Are we within bounds for repeat prefixing?
  1131.         jge     encd32                  ; Yes, use repeat prefixing
  1132.         mov     al,rptct
  1133.         mov     ah,0
  1134.         sub     si,ax                   ; Not enough characters to warrant it
  1135.         mov     rptval,0                ; Clear out this value
  1136.         mov     al,rptq
  1137.         mov     origr,al                ; Save original repeat prefix
  1138.         mov     rptq,0                  ; Pretend we're not doing prefixing
  1139.         mov     al,rptct
  1140.         mov     ah,0
  1141.         add     chrcnt,ax               ; Adjust input buffer pointer
  1142.         jmp     encod1                  ; Reprocess those characters
  1143. encd32: push    ax                      ; Do repeat prefixing - save data
  1144.         mov     al,rptq                 ; Add repeat prefix char
  1145.         stosb
  1146.         dec     cx                      ; Account for it in buffer size
  1147.         mov     al,rptct                ; Get the repeat count
  1148.         add     al,20H                  ; Make it printable
  1149.         stosb                           ; Add to buffer
  1150.         dec     cx
  1151.         pop     ax                      ; Get back the actual character
  1152.         mov     rptct,1                 ; Reset repeat count
  1153.         mov     rptval,0                ; And this
  1154. encd3x: cmp     dh,0                    ; are we doing 8-bit quoting?
  1155.         je      encod4                  ; e = no, forget this
  1156.         test    al,80h                  ; parity on?
  1157.         je      encod4                  ; no, don't bother with this
  1158.         and     al,7fh                  ; turn off parity
  1159.         mov     ah,trans.ebquot         ; get quote char
  1160.         mov     [di],ah                 ; put in packet
  1161.         inc     di
  1162.         dec     cx                      ; decrement # of chars left
  1163. encod4: mov     ah,al                   ; save character
  1164.         and     ah,80h                  ; only parity
  1165.         and     al,7fh                  ; turn off parity in character
  1166.         cmp     al,' '                  ; Compare to a space
  1167.         jl      encod5                  ; If less then its a control char
  1168.         cmp     al,del                  ; Is the char a delete?
  1169.         je      encod5                  ; e = yes, go quote it
  1170.         cmp     al,dl                   ; Is it the quote char?
  1171.         je      encod6                  ; e = yes, go add it
  1172.         cmp     dh,0                    ; are we doing 8-bit quoting?
  1173.         je      encd41                  ; e = no, don't translate it
  1174.         cmp     al,trans.ebquot         ; Is it the 8-bit quote char?
  1175.         je      encod6                  ; e = yes, just output with quote
  1176. encd41: cmp     origr,0                 ; Doing repeat prefixing?
  1177.         je      encod7                  ; e = no, don't check for quote char
  1178.         cmp     al,origr                ; Is this the repeat quote character
  1179.         je      encod6                  ; e = yes, then quote it
  1180.         jmp     short encod7            ; else don't quote it
  1181.  
  1182. encod5: xor     al,40h                  ; control char, uncontrollify
  1183. encod6: mov     [di],dl                 ; insert control quote char
  1184.         inc     di
  1185.         dec     cx
  1186. encod7: or      al,ah                   ; put parity back
  1187.         stosb
  1188.         dec     cx                      ; Decrement output buffer counter
  1189.         cmp     rptct,1                 ; One occurence of this char?
  1190.         jne     encd7x
  1191.         mov     al,origr
  1192.         mov     rptq,al                 ; Restore repeat quote char
  1193.         jmp     encod1                  ; Yes, so loop around for some more
  1194. encd7x: dec     rptct                   ; Add another entry of this char
  1195.         jmp     encod1                  ; With quoting and all
  1196.  
  1197. encod8: sub     di,offset filbuf
  1198.         or      di,di                   ; buffer empty?
  1199.         je      encod9                  ; e = yes
  1200.         mov     ax,di                   ; report size encoded
  1201.         jmp     rskp                    ; return success
  1202. encod9: mov     ax,-1                   ; Get a minus one
  1203.         ret                             ; return failure
  1204.  
  1205.  
  1206. inbuf:  cmp     flags.eoflag,0          ; Have we reached the end?
  1207.         jz      inbuf0
  1208.         ret                             ; Return if set
  1209. inbuf0: push    si
  1210.         push    dx
  1211.         push    bx
  1212.         push    cx
  1213.         mov     bx,offset buff          ; Set the r/w buffer pointer
  1214.         mov     bufpnt,bx
  1215.         mov     bx,diskio.handle        ; get file handle
  1216.         mov     cx,buffsz               ; record size
  1217.         mov     dx,bufpnt               ; buffer address
  1218.         mov     ah,readf2               ; DOS 2.0 read a record
  1219.         int     dos
  1220.         jc      inbuf1                  ; c = error, ie file not open
  1221.         or      ax,ax                   ; any bytes read?
  1222.         jne     inbuf2                  ; ne = yes (the number read)
  1223. inbuf1: mov     flags.eoflag,0FFH       ; Set End-of-file
  1224.         mov     flags.filflg,0ffh       ; Buffer empty
  1225.         mov     chrcnt,0                ; zero bytes left in buffer
  1226.         pop     cx
  1227.         pop     bx
  1228.         pop     dx
  1229.         pop     si
  1230.         ret
  1231. inbuf2: add     tfilsz+2,ax             ; total the # bytes transferred so far
  1232.         adc     tfilsz,0                ; it's a double word
  1233.         mov     chrcnt,ax               ; Number of chars read from file
  1234.         mov     flags.filflg,0          ; Buffer not empty
  1235.         test    flags.remflg,dserial    ; serial display mode?
  1236.         jnz     inbuf3                  ; nz = yes, skip kbyte and % display
  1237.         push    ax
  1238.         call    kbpr                    ; Print the kilobytes sent
  1239.         call    perpr                   ; Print the percent sent
  1240.         pop     ax
  1241. inbuf3: pop     cx
  1242.         pop     bx
  1243.         pop     dx
  1244.         pop     si
  1245.         jmp     rskp
  1246.  
  1247. nulref: mov     chrcnt,0                ; No data to return
  1248.         jmp     rskp
  1249.  
  1250. nulr:   ret                             ; dummy buffer emptier
  1251.  
  1252. ; Print the number of Kilobytes transferred
  1253.  
  1254. kbpr:   test    flags.remflg,dquiet     ; quiet display mode?
  1255.         jnz     kbpr1                   ; nz = yes, no printing
  1256.         push    bx
  1257.         mov     ax,tfilsz+2             ; low order word
  1258.         mov     bx,tfilsz               ; high order word
  1259.         add     ax,512                  ; round up, add half the denominator
  1260.         adc     bx,0
  1261.         mov     al,ah                   ; divide double word by 1024, in steps
  1262.         mov     ah,bl
  1263.         shr     ax,1
  1264.         shr     ax,1
  1265.         ror     bh,1
  1266.         ror     bh,1
  1267.         and     bh,not (3fh)
  1268.         or      ah,bh                   ; ax has the result
  1269.         pop     bx
  1270.         cmp     ax,oldkbt               ; is it the same?
  1271.         je      kbpr1                   ; yes, skip printing
  1272.         mov     oldkbt,ax               ; save new # of kb
  1273.         push    ax
  1274.         call    kbpos                   ; Postion the cursor
  1275.         pop     ax
  1276.         call    decout                  ; Print number of KBytes transferred
  1277. kbpr1:  ret
  1278.  
  1279.  
  1280. ; Print the percent transferred
  1281.  
  1282. perpr:  test    flags.remflg,dquiet     ; quiet display mode?
  1283.         jz      perpr1                  ; z = no. allow printing
  1284.         ret                             ; skip printing in remote mode
  1285. perpr1: cmp     ofilsz,0                ; high word of original file size > 0 ?
  1286.         jne     perpr3                  ; ne = yes, use big file code
  1287.         cmp     ofilsz+2,0              ; anything here at all?
  1288.         jne     perpr2                  ; ne = yes, use small file code
  1289.         ret                             ; otherwise, quit now
  1290. perpr2: push    dx                      ; case for files < 64 Kb
  1291.         mov     ax,ofilsz+2             ; original size (low word)
  1292.         mov     denom,ax
  1293.         mov     dx,tfilsz               ;transferred size times 256 in [dx,ax]
  1294.         mov     ax,tfilsz+2
  1295.         mov     dh,dl                   ; whole value multiplied by 256
  1296.         mov     dl,ah
  1297.         mov     ah,al
  1298.         mov     al,0
  1299.         mov     cx,denom                ; round up, add half the denominator
  1300.         shr     cx,1
  1301.         add     ax,cx
  1302.         adc     dx,0
  1303.         div     denom                   ; (256*xfer)/orig. ax = quo, dx = rem
  1304.         mul     onehun                  ; multiply quotient above by 100
  1305.         mov     al,ah                   ; divide result (ax) by 256
  1306.         mov     ah,0                    ; percentage is in ax
  1307.         jmp     perpr4                  ; finish in common code
  1308. perpr3: push    dx                      ; case for file size > 64 KB
  1309.         mov     ax,ofilsz+2             ; original file size low order word
  1310.         shr     ax,1                    ; divide by 2
  1311.         mov     al,ah                   ; divide again by 256 for total of 512
  1312.         mov     ah,0                    ; clear ah
  1313.         mov     dx,ofilsz               ; high order word
  1314.         xchg    dh,dl                   ; do shl dx,cl=7
  1315.         ror     dx,1                    ; old low bit of dh to high bit of dh
  1316.         and     dl,80h                  ; clear lower bits. divided by two
  1317.         or      ax,dx                   ; paste together the two parts into ax
  1318.         mov     denom,ax                ; denom = original size divided by 512
  1319.         mov     dx,tfilsz               ; high order word of transferred size
  1320.         mov     ax,tfilsz+2             ; low order word
  1321.         mov     cx,denom                ; round up, add half the denominator
  1322.         shr     cx,1
  1323.         add     ax,cx
  1324.         adc     dx,0
  1325.         div     denom                   ; xfer/(512*orig). ax=quot, dx=rem
  1326.         mul     onehun                  ; times 100 for 512*percentage, in ax
  1327.         mov     al,ah                   ; divide ax by 512
  1328.         mov     ah,0
  1329.         shr     ax,1                    ; final percentage, in ax
  1330. perpr4: pop     dx
  1331.         cmp     ax,oldper               ; same as it was before?
  1332.         je      perpr7                  ; yes, don't bother printing
  1333.         mov     oldper,ax               ; remember this for next time
  1334.         cmp     wrpmsg,0                ; did we write the percentage message?
  1335.         jne     perpr5                  ; ne = yes, skip this part
  1336.         push    ax
  1337.         call    perpos                  ; position cursor
  1338.         mcmsg   permsg,cpermsg
  1339.         mov     ah,prstr
  1340.         int     dos                     ; write out message
  1341.         pop     ax
  1342.         mov     wrpmsg,1                ; init flag so we don't do it again
  1343. perpr5: push    ax
  1344.         call    perpos                  ; Position the cursor
  1345.         pop     ax
  1346.         cmp     ax,onehun               ; > 100% ?
  1347.         jle     perpr6                  ; no, accept it
  1348.         mov     ax,onehun               ; else just use 100
  1349. perpr6: call    decout
  1350.         mov     dl,25h                  ; Load a percent sign
  1351.         mov     ah,conout               ; Print the character
  1352.         int     dos
  1353. perpr7: ret
  1354.                                 ; GETFIL, called only by send code
  1355. getfil: mov     flags.filflg,0ffh       ; Say nothing is in the buffer
  1356.         mov     flags.eoflag,0          ; Not the end of file
  1357.         mov     dx,offset diskio.dta    ; data transfer address
  1358.         mov     ah,setdma               ; set disk transfer address
  1359.         int     dos                     ; do it
  1360.         mov     cx,0                    ; attributes: find only normal files
  1361.         mov     dx,offset diskio.string ; filename string (may have wild cards)
  1362.         mov     ah,first2               ; DOS 2.0 search for first
  1363.         int     dos                     ; get file's characteristics
  1364.         pushf                           ; save c flag
  1365.         mov     ah,setdma               ; reset dta address
  1366.         mov     dx,offset buff          ; restore dta
  1367.         int     dos
  1368.         popf                            ; restore status of search for first
  1369.         jnc     getfi1                  ; nc = ok so far
  1370.         ret                             ; else take error exit
  1371. getfi1:
  1372.         mov     dx,offset diskio.string ; original file spec (may be wild)
  1373.         mov     di,offset templp        ; place for path part
  1374.         mov     si,offset templf        ; place for filename part
  1375.         call    fparse                  ; split them
  1376.         mov     si,offset diskio.fname  ; current filename from DOS
  1377.         call    strcat                  ; local path + diskio.fname
  1378.         mov     si,di                   ; make it a source
  1379.         mov     di,offset diskio.string ; new destination
  1380.         call    strcpy                ; new string = old path + DOS's filename
  1381.         mov     ah,open2                ; DOS 2.0 file open
  1382.         mov     al,0                    ; open readonly
  1383.         cmp     dosnum,2                ; above DOS 2?
  1384.         jna     getfi1a                 ; na = no, so no shared access
  1385.         mov     al,0+40h                ; open readonly, deny none
  1386. getfi1a:mov     dx,offset diskio.string ; filename string
  1387.         int     dos
  1388.         jnc     getfi2                  ; nc = opened the file
  1389.         ret                             ; else take error return
  1390. getfi2: mov     diskio.handle,ax        ; save file handle
  1391.         mov     ax,diskio.sizehi        ; get file size (high order word)
  1392.         mov     ofilsz,ax               ; new form
  1393.         mov     ax,diskio.sizelo        ; low order word
  1394.         mov     ofilsz+2,ax             ; new form
  1395.         mov     ax,0
  1396.         mov     tfilsz,ax               ; Set bytes sent to zero
  1397.         mov     tfilsz+2,ax
  1398.         mov     ax,-1                   ; get a minus one
  1399.         mov     oldkbt,ax
  1400.         mov     oldper,ax
  1401.         cmp     ofilsz,0                ; Null file?
  1402.         jne     getfl0                  ; Nope
  1403.         cmp     ofilsz+2,0              ; Null file?
  1404.         jne     getfl0                  ; Nope
  1405.         mov     flags.eoflag,0FFH       ; yes. Set EOF
  1406. getfl0: jmp     rskp
  1407.  
  1408. ; GTNFIL called by send code to get next file. Rewritten by [jrd]
  1409.  
  1410. gtnfil: cmp     flags.cxzflg,'Z'        ; Did we have a ^Z?
  1411.         jne     gtn1                    ; ne = no, else done sending files
  1412.         ret                             ; take failure exit
  1413.  
  1414. gtn1:   mov     flags.filflg,0ffh       ; Nothing in the DMA
  1415.         mov     flags.eoflag,0          ; Not the end of file
  1416.         mov     dx,offset diskio.dta    ; point at dta
  1417.         mov     ah,setdma               ; set the dta address
  1418.         int     dos
  1419.         mov     ah,next2                ; DOS 2.0 search for next
  1420.         int     dos
  1421.         pushf                           ; save carry flag
  1422.         mov     ah,setdma               ; restore dta
  1423.         mov     dx,offset buff
  1424.         int     dos
  1425.         popf                            ; recover carry flag
  1426.         jc      gtn4                    ; carry set means no more files found
  1427.         call    endtim                  ; get tod of end of file transfer
  1428.         mov     di,offset templp        ; place for path part
  1429.         mov     si,offset templf        ; place for filename part
  1430.         mov     dx,offset diskio.string ; current full filename
  1431.         call    fparse                  ; split them
  1432.         mov     si,offset diskio.fname  ; new filename part from DOS
  1433.         call    strcat                  ; rejoin path and new filename
  1434.         mov     si,di                   ; new source
  1435.         mov     di,offset diskio.string ; place for whole new name
  1436.         call    strcpy                  ; copy new string
  1437.         mov     dx,offset diskio.string ; address of new string
  1438.         mov     ah,open2                ; DOS 2.0 file open
  1439.         mov     al,0                    ; open readonly
  1440.         cmp     dosnum,2                ; above DOS 2?
  1441.         jna     gtn3                    ; na = no, so no shared access
  1442.         mov     al,0+40h                ; open readonly, deny none
  1443. gtn3:   int     dos
  1444.         jc      gtn4                    ; c = could not open the file
  1445.  
  1446.         mov     diskio.handle,ax        ; save file handle
  1447.         call    begtim                  ; start statistics counter
  1448.         mov     ax,diskio.sizehi        ; get file size (high order word)
  1449.         mov     ofilsz,ax               ; save as original file size
  1450.         mov     ax,diskio.sizelo        ; low order word
  1451.         mov     ofilsz+2,ax
  1452.         mov     tfilsz,0                ; Set bytes sent to zero
  1453.         mov     tfilsz+2,0
  1454.         mov     oldkbt,-1
  1455.         mov     oldper,-1
  1456.         mov     ax,1            ; tell statistics this was a send operation
  1457.         cmp     ofilsz,0                ; Null file?
  1458.         jne     gtn2                    ; Nope
  1459.         cmp     ofilsz+2,0              ; Null file?
  1460.         jne     gtn2                    ; Nope
  1461.         mov     flags.eoflag,0FFH       ; Set EOF
  1462. gtn2:   jmp     rskp                    ; set success condition
  1463. gtn4:   ret                             ; set failure condition
  1464.  
  1465.  
  1466. ; Get the file name from the data portion of the F packet or from locally
  1467. ; specified override filename (in locfil)
  1468. ; prints the filename, handles any manipulation of the filename
  1469. ; necessary, including changing the name to prevent collisions
  1470. ; Called by READ (receive a file, at rfil32)
  1471.  
  1472. gofil:  push    si
  1473.         push    di
  1474.         mov     si,offset data          ; filename in packet
  1475.         cmp     flags.xflg,0            ; receiving to screen
  1476.         je      gofil0a                 ; e = no
  1477.         mov     diskio.handle,1         ; screen is stdout, handle 1
  1478.         cmp     data,0                  ; filename given?
  1479.         jne     gofil0a                 ; ne = yes
  1480.         mov     si,offset toscreen      ; then use this dummy name
  1481. gofil0a:mov     di,offset diskio.string ; place where prtfn prints name
  1482.         call    strcpy                  ; copy pkt filename to diskio.string
  1483.         mov     di,offset fsta.xname    ; statistics filespec save area
  1484.         call    strcpy                  ; record external name
  1485.         pop     di
  1486.         pop     si
  1487.         cmp     flags.xflg,0            ; Receiving to screen? (X versus F)
  1488.         je      gofil1                  ; e = no
  1489.         jmp     gofi20                  ; Yes. so skip this stuff
  1490. gofil0: cmp     flags.destflg,2         ; file destination = screen?
  1491.         jne     gofil1                  ; ne = no
  1492.         jmp     gofi20                  ; yes
  1493. gofil1: test    flags.remflg,dquiet     ; quiet display mode?
  1494.         jnz     gofi1c                  ; nz = yes, don't display filename
  1495.         call    prtfn                   ; display the packet's filename
  1496. gofi1c: mov     byte ptr diskio.string,0 ; clear final filename
  1497.         cmp     flags.destflg,0         ; writing to printer?
  1498.         jne     gofi1a                  ; ne = no, go on
  1499.         mov     ax,offset printer       ; this is filename now
  1500.         mov     diskio.handle,4         ; system printer is handle 4
  1501.         jmp     gofi16                  ; and do it directly
  1502. gofi1a: mov     flags.nmoflg,0          ; assume no override name
  1503.         cmp     byte ptr locfil,0       ; overriding name from other side?
  1504.         jne     gofi1e                  ; ne = yes
  1505.         jmp     gofil4                  ; e = No. get the other end's filename
  1506. gofi1e: mov     flags.nmoflg,0ffh       ; say using an override name
  1507.         mov     ax,offset locfil        ; get local override filename
  1508.         cmp     word ptr locfil+1,003ah ; colon+null?(primative drive spec A:)
  1509.         je      gofil3          ; e = yes, skip screwy DOS response (No Path)
  1510.         cmp     word ptr locfil,'..'    ; parent directory?
  1511.         jne     gofi1g                  ; ne = noo
  1512.         cmp     word ptr locfil+1,002eh ; dot dot + null?
  1513.         je      gofi1b                  ; e = yes, process as directory
  1514. gofi1g: cmp     word ptr locfil,002eh   ; dot + null (parent dir)?
  1515.         je      gofi1b                  ; e = yes, process as directory
  1516.         call    isfile                  ; does it exist?
  1517.         jnc     gofi1f                  ; nc = file exists
  1518.         test    filtst.fstat,80h        ; serious error?
  1519.         jz      gofil3                  ; z = no, just no such file
  1520.         jmp     gofi18a                 ; else quit here
  1521. gofi1f: test    byte ptr filtst.dta+21,10H      ; subdirectory name?
  1522.         jnz     gofi1b                  ; nz = yes
  1523.         cmp     byte ptr locfil+2,5ch ; could it be a root directory like b:\?
  1524.         jne     gofi1d              ; ne = no. (DOS is not helpful with roots)
  1525.         cmp     byte ptr locfil+3,0     ; and is it terminated in a null?
  1526.         je      gofi1b                  ; e = yes, so it is a root spec
  1527. gofi1d: test    byte ptr filtst.dta+21,0fh   ; r/o, hidden, system, vol label?
  1528.         jz      gofil3                  ; z = no
  1529.         jmp     gofi18a                ; yes. Complain and don't transfer file
  1530. gofi1b: mov     dx,offset locfil        ; locfil is a subdirectory name
  1531.         call    strlen                  ; get its length w/o terminator
  1532.         jcxz    gofil2                  ; zero length
  1533.         dec     cx                      ; examine last char
  1534.         push    bx                      ; save bx
  1535.         mov     bx,cx
  1536.         add     bx,dx
  1537.         cmp     byte ptr [bx],5ch       ; ends in backslash?
  1538.         je      gofil2                  ; e = yes
  1539.         cmp     byte ptr [bx],2fh       ; maybe forward slash?
  1540.         je      gofil2                  ; e = yes
  1541.         mov     byte ptr [bx + 1],5ch   ; no slash yet. use backslash
  1542.         mov     byte ptr [bx + 2],0     ; plant new terminator
  1543. gofil2: pop     bx
  1544.  
  1545. gofil3: mov     di,offset templp        ; local path
  1546.         mov     si,offset templf        ; local filename
  1547.         mov     dx,offset locfil        ; local string
  1548.         call    fparse                  ; split local string
  1549.         mov     di,offset temprp        ; remote path
  1550.         mov     si,offset temprf        ; remote file
  1551.         mov     dx,offset data          ; remote string
  1552.         push    bx                      ; guard against long filenames
  1553.         mov     bx,offset data
  1554.         mov     byte ptr [bx+64],0     ; force filename to be <= 64 text chars
  1555.         pop     bx
  1556.         call    fparse                  ; split remote string
  1557.         mov     si,offset templp        ; copy local path to
  1558.         mov     di,offset data          ; final filename
  1559.         call    strcpy                  ; do the copy
  1560. gofi3a: mov     si,offset templf        ; assume using local file name
  1561.         cmp     byte ptr templf,0       ; local file name given?
  1562.         jne     gofi3b                  ; ne = yes
  1563.         mov     si,offset temprf        ; else use remote file name
  1564. gofi3b: call    strcat                  ; do the append
  1565.                                 ; now offset data holds the new filename
  1566.                                         ;
  1567. gofil4: mov     ax,offset data          ; assume we're writing to disk
  1568.         push    bx                      ; guard against long filenames
  1569.         mov     bx,offset data
  1570.         mov     byte ptr [bx+64],0      ; force filename to be <= 64 text char
  1571.         pop     bx
  1572.                                 ; recheck legality of filename in 'data'
  1573. gofil5: mov     di,offset temprp        ; remote path
  1574.         mov     si,offset temprf        ; remote file
  1575.         mov     dx,offset data          ; remote string
  1576.         call    strlen                  ; get original size
  1577.         push    cx                      ; remember it
  1578.         call    fparse                  ; further massage filename
  1579.         push    si                      ; put pieces back together
  1580.         call    verfil                  ; verify each char in temprf string
  1581.         mov     si,di                   ; get path part first
  1582.         mov     di,dx                   ; set destination
  1583.         call    strcpy                  ; copy in path part
  1584.         pop     si                      ; recover (new) filename
  1585.         cmp     byte ptr [si],'.'       ; does filename part start with a dot?
  1586.         jne     gofil5a                 ; ne = no
  1587.         push    di                      ; save regs
  1588.         push    si
  1589.         mov     di,offset rdbuf         ; a work area
  1590.         mov     byte ptr [di],'X'       ; start name with letter X
  1591.         inc     di
  1592.         call    strcpy                  ; copy rest of filename
  1593.         mov     di,si
  1594.         mov     si,offset rdbuf      ; copy new name back to original location
  1595.         call    strcpy
  1596.         pop     si                      ; restore regs
  1597.         pop     di
  1598. gofil5a:call    strcat                  ; append it
  1599.         call    strlen                  ; see if we chopped out something
  1600.         pop     si                  ; get original length (from push cx above)
  1601.         cmp     cx,si                   ; same size?
  1602.         je      gofil9                  ; e = yes
  1603.         mov     flags.nmoflg,0ffh       ; say that we have a replacement name
  1604.                                 ; filename is now in 'data', all converted
  1605. gofil9: test    flags.remflg,dquiet     ; quiet display mode?
  1606.         jnz     gofi10                  ; nz = yes, don't print it
  1607.         cmp     flags.nmoflg,0          ; using local override name?
  1608.         je      gofi10                  ; e = no
  1609.         mov     ah,prstr
  1610. ;        mov     dx,offset asmsg         ; print " as "
  1611.         mcmsg   asmsg,casmsg
  1612.  
  1613.         int     dos
  1614.         mov     dx,offset data          ; plus the local filename
  1615.         call    prtasz                  ; print asciiz string
  1616. gofi10: mov     ax,offset data          ; point to name
  1617.         cmp     flags.flwflg,0          ; Is file warning on?
  1618.         jne     gofi100
  1619.         jmp     gofi16                  ; e = no, just proceed
  1620. gofi100:call    isfile                  ; does it exist?
  1621.         mov     ax,offset data          ; reload ptr in case
  1622.         jc      gofi16                  ; carry set = no, just proceed
  1623.         mov     ah,open2                ; could it be a device name?
  1624.         mov     al,0                    ; open readonly
  1625.         cmp     dosnum,2                ; above DOS 2?
  1626.         jna     gofi10a                 ; na = no, so no shared access
  1627.         mov     al,0+40h                ; open for reading, deny none
  1628. gofi10a:mov     dx,offset data          ; the filename
  1629.         int     dos
  1630.         jc      gofi11                  ; c = cannot open so just proceed
  1631.         mov     bx,ax                   ; file handle
  1632.         mov     ah,ioctl
  1633.         mov     al,0                    ; get info
  1634.         int     dos
  1635.         mov     ah,close2               ; close it
  1636.         int     dos
  1637.         mov     ax,offset data          ; point to filename again
  1638.         test    dl,80h                  ; ISDEV bit set?
  1639.         jz      gofi11                  ; z = no, not a device
  1640.         jmp     gofi16                  ; device, use name as given
  1641. gofi11: call    unique                  ; generate unique name
  1642.         jc      gofi14                  ; could not generate a unique name
  1643.         test    flags.remflg,dquiet     ; quiet display mode?
  1644.         jnz     gofi13                  ; nz = yes, skip printing
  1645.         push    ax                      ; save unique name again
  1646.         call    frpos                   ; Position cursor.
  1647.         mov     ah,prstr           ; Inform the user we are renaming the file
  1648.         mcmsg   infms5,cinfms5
  1649.         int     dos
  1650.         pop     ax                      ; get name back into ax again
  1651.         push    ax                      ; save around these calls
  1652.         mov     dx,ax                   ; print current filename
  1653.         call    prtasz                  ; display filename
  1654.         pop     ax                      ; pointer to name, again
  1655. gofi13: jmp     gofi16                  ; and go handle file
  1656.  
  1657. gofi14:  mcmsg   ermes4, cermes4
  1658.         test    flags.remflg,dquiet     ; quiet display mode?
  1659.         jnz     gofi15                  ; nz = yes, no printing
  1660.         call    erpos                   ; Position cursor
  1661.         mov     ah,prstr                ; Tell the user we can't rename it
  1662.         int     dos
  1663. gofi15: mov     bx,dx                   ; Tell host can't rename
  1664.         call    errpack                 ; Send error packet before abort
  1665.         ret
  1666.  
  1667. gofi16: mov     si,ax                   ; pointer to (maybe new) name
  1668.         mov     di,offset diskio.string ; filename, used in open
  1669.         mov     dx,di                   ;  for isfile and open below
  1670.         call    strcpy                  ; copy name to diskio.string
  1671.         mov     ax,0
  1672.         mov     ofilsz,ax               ; original file size is unknown
  1673.         mov     ofilsz+2,ax             ; double word
  1674.         mov     tfilsz,ax               ; Set bytes received to zero
  1675.         mov     tfilsz+2,ax
  1676.         mov     ax,-1                   ; get a minus one
  1677.         mov     oldkbt,ax
  1678.         mov     oldper,ax
  1679.         mov     diskio.handle,ax        ; clear handle of previous usage
  1680.         mov     ax,dx                   ; filename for isfile
  1681.         call    isfile          ; check for read-only/system/vol-label/dir
  1682.         jc      gofi16a                 ; c = file does not exist
  1683.         test    byte ptr filtst.dta+21,1fh      ; the no-no file attributes
  1684.         jz      gofi16b                 ; z = ok
  1685.         jmp     gofi18          ; nz = shouldn't write over one of these
  1686. gofi16a:test    filtst.fstat,80h        ; access problem?
  1687.         jnz     gofi18                  ; nz = yes, quit here
  1688.         mov     diskio.handle,-1        ; clear handle of previous usage
  1689.         mov     ah,creat2               ; DOS 2.0 create file
  1690.         mov     cx,0                    ; attributes bits
  1691.         int     dos
  1692.         jc      gofi16b                 ; c = did not work, try regular open
  1693.         mov     diskio.handle,ax        ; save file handle here
  1694.         call    begtim                  ; start file loggging
  1695.         jmp     rskp
  1696. gofi16b:test    byte ptr filtst.dta+21,1bh      ; r/o, hidden, volume label?
  1697.         jnz     gofi18                  ; we won't touch these
  1698.         mov     ah,open2               ; open existing file (usually a device)
  1699.         mov     al,1+1                  ; open for writing
  1700.         int     dos
  1701.         jc      gofi18                  ; carry set means can't open
  1702.         mov     diskio.handle,ax        ; file handle
  1703.         call    begtim                  ; start file loggging
  1704.         jmp     rskp
  1705.  
  1706. gofi18a:mov     si,ax                   ; pointer to local override name
  1707.         mov     di,offset diskio.string ; filename, used in open
  1708.         call    strcpy                  ; copy name to diskio.string
  1709.                                         ; fall  through to gofi18
  1710. gofi18: test    flags.remflg,dquiet     ; quiet display mode?
  1711.         jnz     gofi19                  ; nz = yes, don't try printing
  1712.         call    erpos                   ; Position cursor
  1713.         mov     ah,prstr                ; tell the user
  1714.         mcmsg   erms12,cerms12
  1715.         int     dos
  1716.         mov     dx,offset diskio.string ; print offending name
  1717.         call    prtasz                  ; display filename
  1718. gofi19: 
  1719. ;mov     dx,offset erms12        ; reset error message for packet
  1720.         mcmsg   erms12,cerms12
  1721.         mov     bx,dx
  1722.         call    errpack                 ; Send an error packet
  1723.         ret
  1724. gofi20: cmp     pack.datlen,0           ; Any data in "X" packet?
  1725.         je      gofi21                  ; Nothing to print.
  1726.         mov     ah,prstr
  1727.         mov     dx,offset crlf
  1728.         int     dos
  1729.         int     dos                     ; Print another crlf
  1730.         mov     di,offset data          ; Where data is
  1731.         mov     cx,pack.datlen          ; How much data we have
  1732.         call    prtscr                  ; Print it on the screen
  1733.         mov     ah,prstr
  1734.         mov     dx,offset crlf
  1735.         int     dos
  1736. gofi21: jmp     rskp                    ; And done
  1737.  
  1738. FILEIO  ENDP
  1739.  
  1740. ; Given incoming filename in 'data'.  Verify that each char is legal
  1741. ; (if not change it to an "X"), force max of three chars after a period (dot)
  1742. ; Source is at ds:si (si is changed here). [jrd]
  1743.  
  1744. VERFIL  PROC    NEAR
  1745.         push    es                      ; verify each char in 'data'
  1746.         push    cx
  1747.         mov     ax,ds
  1748.         mov     es,ax
  1749.         mov     havdot,0                ; say no dot found in name yet
  1750.         cld
  1751. verfi1: lodsb                           ; get a byte of name from si
  1752.         and     al,7fH                  ; strip any eight bit
  1753.         cmp     al,0                    ; end of name?
  1754.         je      verfi5                  ; e = yes
  1755.         cmp     al,'.'                  ; a dot?
  1756.         jne     verfi2                  ; ne = no
  1757.         cmp     havdot,0                ; have one dot already?
  1758.         jne     verfi3                  ; ne = yes, change to X
  1759.         mov     byte ptr [si+3],0    ; forceably end filename after 3 char ext
  1760.         mov     havdot,1                ; say have a dot now
  1761.         jmp     verfi4                  ; continue
  1762. verfi2: cmp     al,3ah                  ; colon?
  1763.         je      verfi4
  1764.         cmp     al,5ch                  ; backslash path separator?
  1765.         je      verfi4
  1766.         cmp     al,2fh                  ; or forward slash?
  1767.         je      verfi4
  1768.         cmp     al,'0'
  1769.         jb      verfi3                  ; See if it's a legal char < '0'
  1770.         cmp     al,'9'
  1771.         jbe     verfi4                  ; It's between 0-9 so it's OK
  1772.         cmp     al,'A'
  1773.         jb      verfi3                  ; Check for a legal punctuation char
  1774.         cmp     al,'Z'
  1775.         jbe     verfi4                  ; It's A-Z so it's OK
  1776.         cmp     al,'a'
  1777.         jb      verfi3                  ; Check for a legal punctuation char
  1778.         cmp     al,'z'
  1779.         ja      verfi3
  1780.         and     al,5FH                  ; It's a-z, capitalize
  1781.         jmp     verfi4                  ; continue with no change
  1782.  
  1783. verfi3: push    di                      ; special char. Is it on the list?
  1784.         mov     di,offset spchar2       ; list of acceptable special chars
  1785.         mov     cx,spc2len
  1786.         cld
  1787.         repne   scasb                   ; Search string for input char
  1788.         pop     di
  1789.         je      verfi4                  ; e = in table, return it
  1790.         mov     al,'X'                  ; else illegal, replace with "X"
  1791.         mov     flags.nmoflg,0FFH       ; say we have a replacement filename
  1792. verfi4: mov     [si-1],al               ; update name
  1793.         jmp     verfi1                  ; loop thru rest of name
  1794. verfi5: mov     byte ptr[si-1],0        ; make sure it's null terminated
  1795.         pop     cx
  1796.         pop     es
  1797.         ret
  1798. VERFIL  ENDP
  1799.  
  1800. ; find a unique filename...     Upgraded by [jrd]
  1801. ; Enter with a pointer to a (null-terminated) filename in ax
  1802. ; Return with same pointer but with a new name (or old if failure)
  1803. ; Success = carry clear; failure = carry set
  1804. ; The idea is to pad out the main name part (8 chars) with ascii zeros and
  1805. ; then change the last chars successively to a 1, 2, etc. until
  1806. ; a unique name is found. All registers are preserved
  1807. ; Add patch to make empty main name fields start with letter X, not digit 0
  1808. ; 23 March 1986 [jrd]
  1809. unique  proc    near
  1810.         push    bx
  1811.         push    cx
  1812.         push    dx
  1813.         push    si
  1814.         push    di
  1815.         push    es
  1816.         push    ax                      ; save address of source string
  1817.         mov     dx,ds                   ; make es use ds segment
  1818.         mov     es,dx
  1819.         mov     dx,ax                   ; point at original filename string
  1820.         mov     di,offset templp        ; place for path
  1821.         mov     si,offset templf        ; place for filename
  1822.         call    fparse                  ; separate path (di) and filename (si)
  1823.         mov     dx,di                   ; point at path part
  1824.         call    strlen                  ; put length in cx
  1825.         mov     si,ax                   ; point to original string
  1826.         add     si,cx                   ; point to filename part
  1827.         mov     di,offset templf        ; destination is temporary location
  1828.         mov     cx,0                    ; a counter
  1829.         cld                             ; set direction to be forward
  1830. uniq1:  lodsb                           ; get a byte
  1831.         cmp     al,'.'                  ; have a dot?
  1832.         je      uniq2                   ; e = yes
  1833.         cmp     al,0                    ; maybe null at end?
  1834.         jne     uniq3                   ; ne = no. continue loop
  1835.  
  1836. uniq2:  cmp     cl,8                    ; have we copied any chars before dot?
  1837.         jge     uniq3                   ; ge = all 8
  1838.         mov     byte ptr [di],'0'       ; avoid clobbers; pad with 0's
  1839.         cmp     cl,0                    ; first char of filename?
  1840.         jne     uniq2a                  ; ne = no
  1841.         mov     byte ptr [di],'X'       ; start name with letter X, not 0
  1842. uniq2a: inc     di                      ; and count the output chars
  1843.         inc     cl                      ; and this counter too
  1844.         jmp     uniq2                   ; continue until filled 8 slots
  1845. uniq3:  inc     cl                      ; cl = # char in destination
  1846.         stosb                           ; store the char
  1847.         cmp     al,0                    ; null at end?
  1848.         jne     uniq1                   ; ne = no, continue copying
  1849.  
  1850.         mov     di,offset templf
  1851.         add     di,7                    ; address of last name char
  1852.         mov     byte ptr [di],'1'       ; put '1' in last name char
  1853.         mov     unum,1                  ; start with this generation digit
  1854.  
  1855. uniq4:  mov     di,offset rdbuf         ; build a temporary full filename
  1856.         mov     si,offset templp        ; path part
  1857.         call    strcpy                  ; copy that much
  1858.         mov     si,offset templf        ; get rebuilt filename part
  1859.         call    strcat                  ; paste that to the end
  1860.         mov     ax,offset rdbuf         ; point to full name
  1861.         call    isfile                  ; does it exist?
  1862.         jc      uniq6                   ; c = no, succeed now
  1863.  
  1864.         inc     unum                    ; move to next generation
  1865.         mov     di,offset templf        ; position for characters
  1866.         add     di,7                    ; point to last name char
  1867.         mov     cx,7                    ; max # of digits to play with
  1868.         mov     bx,10                   ; divisor (16 bits)
  1869.         mov     ax,unum                 ; low order part of generation #
  1870. uniq5:  mov     dx,0                    ; high order part of generation #
  1871.         div     bx                      ; compute digit (unum / 10)
  1872.         add     dl,'0'                  ; make remainder part printable
  1873.         mov     byte ptr [di],dl        ; put into right place
  1874.         cmp     ax,0                    ; any more to do? (quotient nonzero)
  1875.         jz      uniq4                   ; z = no, try this name
  1876.         dec     di                      ; else decrement char position
  1877.         loop    uniq5                   ;   and keep making a number
  1878.         stc                             ; failure: set carry, keep old name
  1879.         jmp     short uniq7             ;   and exit
  1880.  
  1881. uniq6:  pop     di                      ; address of original filename
  1882.         push    ax                      ; save for exit clean up
  1883.         mov     si,offset rdbuf
  1884.         call    strcpy                  ; copy new filename over old
  1885.         clc                             ; success: clear carry flag
  1886. uniq7:  pop     ax
  1887.         pop     es
  1888.         pop     di
  1889.         pop     si
  1890.         pop     dx
  1891.         pop     cx
  1892.         pop     bx
  1893.         ret
  1894. unique  endp
  1895.  
  1896.  
  1897. ;       [jrd]
  1898. ; strlen -- computes the length, excluding the terminator, of an asciiz
  1899. ;       string. Input: dx = offset of the string
  1900. ;               Output: cx = the byte count
  1901. ;       Normal 'ret' return. All registers except cx are preserved
  1902. ;
  1903. STRLEN  PROC    NEAR
  1904.         push    di
  1905.         push    es
  1906.         push    ax
  1907.         mov     ax,ds                   ; use proper segment address
  1908.         mov     es,ax
  1909.         mov     di,dx
  1910.         mov     cx,0ffffh               ; large byte count
  1911.         cld                             ; set direction to be forward
  1912.         mov     al,0                    ; item sought is a null
  1913.         repne   scasb                   ; search for it
  1914.         add     cx,2                    ; add for -1 and auto dec in scasb
  1915.         neg     cx                    ; convert to count, excluding terminator
  1916.         pop     ax
  1917.         pop     es
  1918.         pop     di
  1919.         ret
  1920. STRLEN  ENDP
  1921.  
  1922. ;       [jrd]
  1923. ; strcat -- concatenates asciiz string 2 to the end of asciiz string 1
  1924. ;       offset of string 1 is expected to be in ds:di. input & output
  1925. ;       offset of string 2 is expected to be in ds:si. input only (unchanged)
  1926. ;       Preserves all registers. No error returns, returns normally via ret
  1927. ;
  1928. STRCAT  PROC    NEAR
  1929.         push    di                      ; save work registers
  1930.         push    si
  1931.         push    es
  1932.         push    dx
  1933.         push    cx
  1934.         push    ax
  1935.         mov     ax,ds                   ; get data segment value
  1936.         mov     es,ax                   ; set es to ds for implied es:di usage
  1937.         mov     dx,di
  1938.         call    strlen          ; get length (w/o terminator) of dest string
  1939.         add     di,cx                   ; address of first terminator
  1940.         mov     dx,si                   ; start offset of source string
  1941.         call    strlen                  ; find its length too (in cx)
  1942.         inc     cx                      ; include its terminator in the count
  1943.         rep     movsb           ; copy source string to end of output string
  1944.         pop     ax
  1945.         pop     cx
  1946.         pop     dx
  1947.         pop     es
  1948.         pop     si
  1949.         pop     di
  1950.         ret
  1951. STRCAT  ENDP
  1952.  
  1953. ;       [jrd]
  1954. ; strcpy -- copies asciiz string pointed to by ds:si into area pointed to by
  1955. ;       ds:di. Returns via ret. All registers are preserved
  1956. ;
  1957. STRCPY  PROC    NEAR
  1958.         mov     byte ptr [di],0         ; clear destination string
  1959.         call    strcat                  ; let strcat do the real work
  1960.         ret
  1961. STRCPY  ENDP
  1962.  
  1963. ;       [jrd]
  1964. ; fparse -- separate the drive:path part from the filename.ext part of an
  1965. ;       asciiz string. Characters separating parts are  \ or / or :
  1966. ;       Inputs: asciiz input full filename string offset in ds:dx
  1967. ;               asciiz path offset in ds:di
  1968. ;               asciiz filename offset in ds:si
  1969. ;       Outputs: the above strings in the indicated spots
  1970. ;       Strategy is simple. Reverse scan input string until one of the
  1971. ;       three separators is encountered and then cleave at that point
  1972. ;       Simple filename construction restrictions added 30 Dec 1985;
  1973. ;       to wit: mainname limited to 8 chars or less,
  1974. ;       extension field limited to 3 chars or less and is found by searching
  1975. ;       for first occurence of a dot in the filename field. Thus the whole
  1976. ;       filename part is restricted to 12 (8+dot+3) chars plus a null
  1977. ;       All registers are preserved. Return is always via ret
  1978. ;       (Microsoft should have written this for DOS 2.x et seq.)
  1979.  
  1980. FPARSE  PROC    NEAR
  1981.         push    cx                      ; local counter
  1982.         push    ax                      ; local work area
  1983.         push    es                      ; implied segment register for di
  1984.         push    di                      ; offset of path part of output
  1985.         push    si                      ; offset of file name part of output
  1986.         mov     ax,ds                   ; get data segment value
  1987.         mov     es,ax                   ; set es to ds for implied es:di usage
  1988.         mov     byte ptr [si],0         ; clear outputs
  1989.         mov     byte ptr [di],0
  1990.  
  1991.         push    si                      ; save original file name address
  1992.         mov     si,dx                   ; get original string address
  1993.         call    strcpy                  ; copy string to original di
  1994.         call    strlen                  ; find length (w/o terminator), in cx
  1995.         mov     si,di                   ; address of string start
  1996.         add     si,cx
  1997.         dec     si                      ; si = address of last non-null char
  1998.         jcxz    fpars5                  ; if null skip the path scan
  1999.                                         ; now find last path char, if any
  2000.                                         ; start at the end of input string
  2001.         std                             ; set direction to be backward
  2002. fpars4: lodsb                           ; get a byte (dec's si afterward)
  2003.         cmp     al,5ch                  ; is it a backslash ('\')?
  2004.         je      fpars6                  ; e = yes
  2005.         cmp     al,2fh                  ; or forward slash ('/')?
  2006.         je      fpars6                  ; e = yes
  2007.         cmp     al,3ah                  ; or even the drive terminator colon?
  2008.         je      fpars6                  ; e = yes
  2009.         loop    fpars4                  ; else keep looking until cx == 0
  2010.                                         ; si is at beginning of file name
  2011. fpars5: dec     si                      ; dec for inc below
  2012. fpars6: inc     si
  2013.         inc     si                      ; si now points at first filename char
  2014.                                         ; cx holds number of path chars
  2015.                                         ; get original file name address (si)
  2016.         pop     di                      ; and make it place to copy filename
  2017.         cld                             ; reset direction to be forward
  2018.         mov     ax,si                   ; ax holds filename address for awhile
  2019.         push    dx
  2020.         mov     dx,si                   ; strlen wants string pointer in dx
  2021.         call    strlen                  ; get length of filename part into cx
  2022.         pop     dx
  2023.         jcxz    fpar7a                  ; any chars to look at? z = no
  2024. fpars7: cmp     byte ptr [si],'.'       ; look for a dot in filename
  2025.         je      fpars8                  ; e = found one
  2026.         inc     si                      ; look at next filename char
  2027.         loop    fpars7                  ; keep looking until cx = zero
  2028. fpar7a: mov     si,ax                   ; no dot. recover starting address
  2029.         mov     byte ptr [si+8],0       ; forcably truncate mainname to 8 char
  2030.         call    strcpy                  ; copy this part to filename field
  2031.         jmp     fparsx                  ;  and exit
  2032. fpars8: mov     byte ptr [si+4],0   ; plant terminator after dot + 3 ext chars
  2033.         mov     cx,si
  2034.         sub     cx,ax           ; cx now = number of chars in mainname field
  2035.         cmp     cx,9                    ; more than 8?
  2036.         jb      fpars9                  ; b = no, we're safe
  2037.         mov     cx,8                 ; limit ourselves to 8 chars in mainname
  2038. fpars9: push    si                   ; remember address of dot and extension
  2039.         mov     si,ax                   ; point to start of input filename
  2040.         rep     movsb                   ; copy cx chars from si to di (output)
  2041.         mov     byte ptr [di],0         ; plant terminator where dot goes
  2042.         pop     si                      ; source = dot and extension address
  2043.         call    strcat          ; append the dot & ext to the filename field
  2044. fparsx: mov     si,ax           ; recover start of filename in input string
  2045.         mov     byte ptr [si],0         ; terminate path field
  2046.         pop     si
  2047.         pop     di
  2048.         pop     es
  2049.         pop     ax
  2050.         pop     cx
  2051.         ret
  2052. FPARSE  ENDP
  2053.  
  2054. ; Print filename in offset data. Shortened by [jrd]
  2055. PRTFN   PROC    NEAR
  2056.         push    ax                      ; saves for messy clrfln routine
  2057.         push    bx
  2058.         push    cx
  2059.         push    dx
  2060.         push    di
  2061.         call    clrfln                  ; Position cursor & blank out the line
  2062.         mov     dx,offset diskio.string
  2063.         call    strlen                 ; compute length of asciiz string in cx
  2064.         mov     di,dx                   ; where prtscr wants its string
  2065.         call    prtscr
  2066.         pop     di
  2067.         pop     dx
  2068.         pop     cx
  2069.         pop     bx
  2070.         pop     ax
  2071.         ret
  2072. PRTFN   ENDP
  2073.  
  2074.  
  2075. ; Print string to screen from offset ds:di for # bytes given in cx,
  2076. ; regardless of $'s.  All registers are preserved.              [jrd]
  2077.  
  2078. PRTSCR  PROC    NEAR
  2079.         jcxz    prtscr4                 ; cx = zero means nothing to show
  2080.         push    ax
  2081.         push    bx
  2082.         push    dx
  2083.         mov     dx,di                   ; source ptr for DOS
  2084.         cmp     flags.eofcz,0           ; end on Control-Z?
  2085.         jne     prtscr3                 ; ne = yes, let DOS do it
  2086.         push    cx                      ; else map Control-Z to space
  2087.         push    di
  2088.         push    es
  2089.         push    ds
  2090.         pop     es                      ; datas to es
  2091.         mov     al,ctlz                 ; look for Control-Z
  2092.         cld                             ; scan buffer es:di, cx chars worth
  2093. prtscr1:repne   scasb
  2094.         jne     prtscr2                 ; ne = found no Control-Z's
  2095.         mov     byte ptr [di-1],' '     ; replace Control-Z with space
  2096.         jcxz    prtscr2                 ; z = examined all chars
  2097.         jmp     short prtscr1           ; until examined everything
  2098. prtscr2:pop     es
  2099.         pop     di
  2100.         pop     cx
  2101. prtscr3:mov     bx,1                    ; stdout file handle
  2102.         mov     ah,write2
  2103.         int     dos
  2104.         pop     dx
  2105.         pop     bx
  2106.         pop     ax
  2107. prtscr4:ret
  2108. PRTSCR  ENDP
  2109.  
  2110. ; Print to screen asciiz string given in ds:dx. Everything preserved. [jrd]
  2111. PRTASZ  PROC    NEAR
  2112.         push    cx
  2113.         push    di
  2114.         call    strlen                  ; get length of asciiz string
  2115.         mov     di,dx                   ; where prtscr looks
  2116.         call    prtscr                  ; print counted string
  2117.         pop     di
  2118.         pop     cx
  2119.         ret
  2120. PRTASZ  ENDP
  2121.  
  2122.  
  2123. ; Jumping to this location is like retskp.  It assumes the instruction
  2124. ;   after the call is a jmp addr
  2125.  
  2126. RSKP    PROC    NEAR
  2127.         pop     bp
  2128.         add     bp,3
  2129.         push    bp
  2130.         ret
  2131. RSKP    ENDP
  2132. code    ends
  2133.         end
  2134.