home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccsker.asm < prev    next >
Assembly Source File  |  2020-01-01  |  55KB  |  1,243 lines

  1.         NAME    ccsker
  2. ; File CCSKER.ASM
  3.  
  4. ;CHINESE
  5. ifdef   MSDOS
  6.         include mssker.dat
  7. else
  8.         include ccsker.dat
  9. endif
  10.  
  11. code    segment public 'code'
  12.         extrn   cmblnk:near, locate:near, logout:near, mail:near
  13.         extrn   bye:near, telnet:near, finish:near, comnd:near, prompt:near
  14.         extrn   read:near, remote:near, send:near, status:near, get:near
  15.         extrn   dodisk:near, serrst:near, setcom:near, dtrlow:near
  16.         extrn   clscpi:near, clscpt:near, getbaud:near
  17.         extrn   dodef:near, setcpt:near, docom:near, shomodem:near
  18.         extrn   server:near, lclini:near, shokey:near, shomac:near, shosta:near
  19.         extrn   packlen:near, strlen:near, strcpy:near, shserv:near
  20.         extrn   strcat:near, prtasz:near, shorx:near, lnout:near
  21.         extrn   scout:near,scinp:near,scpau:near,scecho:near,scclr:near
  22.         extrn   scxmit:near, scwait:near, srvdsa:near, srvena:near
  23.         extrn   shcom:near, shlog:near, shpro:near, shterm:near, shscpt:near
  24.         extrn   shfile:near, takopen:near, takclos:near, ask:near, assign:near
  25.         extrn   goto:near, screinp:near, ifcmd:near, isdev:near
  26.         extrn   chkos:near      ; Jun. 1990
  27.         assume  cs:code, ds:datas, ss:cstack, es:nothing
  28.  
  29. START   PROC    FAR
  30.         mov     ax,datas                ; Initialize DS
  31.         mov     ds,ax
  32.         mov     psp,es                  ; remember psp address
  33.  
  34.         mov     ah,dosver
  35.         int     dos
  36.         mov     dosnum,al               ; remember dos version
  37.         cmp     dosnum,2                ; earlier than DOS 2.0?
  38.         jge     start1                  ; ge = no
  39.         mov     ah,prstr
  40. ;        mov     dx,offset erms34        ; Complain
  41.         mcmsg   erms34,  cerms34
  42.         int     dos
  43.         mov     ax,psp                  ; set up exit for DOS 1
  44.         push    ax                      ; push the segment
  45.         mov     ax,0                    ; and the IP
  46.         push    ax                      ; make return addr of psp:0 for DOS 1
  47.         ret                             ; and return far to exit now
  48. start1:
  49.         call    chkos                   ; check if MS-DOS or CC-DOS ? Jun.1990
  50.         mov     ah,prstr
  51.         mov     dx,offset machnam       ; print machine name
  52.         int     dos
  53.         mov     ah,prstr                ; Print the version header
  54. ;        mov     dx,offset versio
  55.         mcmsg   versio, cversio
  56.         int     dos
  57.         mov     ah,setdma               ; Set disk transfer address
  58.         mov     dx,offset buff
  59.         int     dos
  60.  
  61.         call    setint
  62.         mov     ah,gcurdsk              ; Get current disk
  63.         int     dos
  64.         inc     al                      ; We want 1 == A (not zero)
  65.         mov     curdsk,al
  66.         mov     origd,al                ; Remember original disk we started on
  67.         mov     si,offset orgdir     ; place for directory path w/o drive code
  68.         add     al,'A'-1                ; make al alphabetic disk drive again
  69.         mov     [si],al                 ; put it into original path descriptor
  70.         inc     si
  71.         mov     byte ptr [si],':'       ; add drive specifier too
  72.         inc     si
  73.         mov     byte ptr [si],'\'       ; add root indicator as well
  74.         inc     si
  75.         mov     ah,gcd                  ; get current directory (path really)
  76.         xor     dl,dl                   ; use current drive
  77.         int     dos
  78.         call    getpath                 ; get the path from the environment
  79.         call    getcsp                  ; get comspec from environment
  80.         call    memini                  ; init our memory usage
  81.         call    lclini                  ; do local initialization
  82.         call    packlen              ; Packet length in case do server comand
  83.         mov     ah,gswitch
  84.         mov     al,0                    ; pick up switch character
  85.         int     dos
  86.         mov     slashc+1,dl
  87.         mov     al,maxtry               ; limit # packet retries
  88.         and     al,3fh                  ; 63 max
  89.         mov     maxtry,al
  90.         shl     al,1                    ; times two. I packets get more tries
  91.         mov     imxtry,al               ; keep that much
  92.         add     al,maxtry               ; try three times
  93.         js      start2                  ; s = sign bit set, too large
  94.         mov     imxtry,al               ; imxtry = 3 * maxtry
  95. start2: mov     comand.cmrprs,offset krmend ; address to go to on reparse
  96.         mov     comand.cmostp,sp        ; Save for reparse too
  97.         call    gcmdlin                 ; read command line
  98.         cmp     taklev,0                ; in a Take file?
  99.         jne     start3                  ; ne = yes, skip help msg
  100.         mov     ah,prstr
  101.       ;  mov     dx,offset hlpmsg
  102.         mcmsg   hlpmsg,chlpmsg
  103.         int     dos
  104. start3: call    serrst                  ; reset serial port (if active)
  105.         call    rdinit                  ; read kermit init file
  106.  
  107.  ; This is the main KERMIT loop.  It prompts for and gets the users commands
  108.  
  109. kermit: mov     ax,ds
  110.         mov     es,ax                  ; make sure this addresses data segment
  111.         cmp     taklev,0                ; keep port open between script cmds
  112.         jne     kermt1                  ; ne = in Take or Macro
  113.         call    serrst                  ; reset serial port for CTTY DOS use
  114. kermt1: mov     dx,prmptr               ; get prompt
  115.         call    chkos                   ; check if MS-DOS or CC-DOS ? Jun.1990
  116.         call    prompt                  ; Prompt the user, set reparse address
  117.         mov     pack.state,0            ; Clear the state
  118.         mov     flags.cxzflg,0          ; Reset each time
  119.         and     flags.remflg,not dserver ; turn off server mode bit
  120.         mov     ah,inichk               ; Original or set checksum length
  121.         mov     trans.chklen,ah         ; Reset just in case
  122.         mov     dx,offset comtab
  123. ;        mov     bx,offset tophlp
  124.         mcmsgb  tophlp,ctophlp
  125.         cmp     flags.extflg,0          ; Check if the exit flag is set
  126.         jne     krmend                  ; If so jump to KRMEND
  127.         mov     comand.cmcr,1           ; Allow bare CR's
  128.         mov     ah,cmkey
  129.         mov     comand.impdo,1          ; allow implied "DO macro"
  130.         call    comnd
  131.          jmp    kermt3
  132.          nop
  133.         mov     comand.impdo,0          ; only on initial keyword, not here
  134.         mov     comand.cmcr,0           ; no more bare CR's
  135.         call    bx                      ; Call the routine returned
  136.          jmp    kermt3
  137.          nop
  138.         cmp     flags.extflg,0          ; Check if the exit flag is set
  139.         jne     krmend                  ; If so jump to KRMEND
  140.         jmp     short kermt5            ; Do it again
  141.  
  142. kermt3: mov     kstatus,8               ; global status
  143.         cmp     flags.cxzflg,'C'        ; got here via Control-C?
  144.         jne     kermt7                  ; ne = no
  145. kermt4: cmp     flags.extflg,0          ; Check if the exit flag is set
  146.         jne     kermt5                  ; ne = yes, skip msg, do cleanup
  147. ;        mov     dx,offset ermes3        ; Say command not executed
  148.         mcmsg   ermes3,cermes3
  149.         mov     ah,prstr                ; print the error message in dx
  150.         int     dos
  151. kermt5: cmp     flags.cxzflg,'C'        ; user Control-C abort?
  152.         jne     kermt7                  ; ne = no, do normal operations
  153.         cmp     taklev,0                ; in a Take file?
  154.         je      kermt7                  ; e = no
  155.         call    takclos                 ; close take file, release buffer
  156.         jmp     kermt5                  ; close any other take files
  157. kermt7: mov     flags.nmoflg,0          ; Reset filename override flag
  158.         mov     flags.getflg,0          ; May as well do this one
  159.         cmp     flags.extflg,0          ; Check if the exit flag is set
  160.         jne     krmend                  ; ne = yes, Exit now
  161.         jmp     kermit                  ; get next command
  162.  
  163. krmend: call    serrst                  ; Just in case the port wasn't reset
  164.         test    flags.capflg,0FFH       ; Logging active?
  165.         jz      krmend2                 ; z = no
  166.         call    clscpi                  ; close log files
  167.          nop                            ; this skip returns..
  168.          nop
  169.          nop
  170. krmend2:cmp     lclexit,0               ; sys dependent routines want service?
  171.         je      krmend3                 ; e = no
  172.         mov     bx,lclexit              ; addr of sys dependent exit routine
  173.         call    bx                      ; call it
  174. krmend3:mov     dl,origd                ; Original disk drive
  175.         dec     dl                      ; Want A == 0
  176.         mov     ah,seldsk               ; Reset original disk just in case
  177.         int     dos
  178.         mov     dx,offset orgdir        ; restore original directory
  179.         mov     ah,chdir
  180.         int     dos
  181.         mov     dx,offset in3ad         ; restore Control-C interrupt vector
  182.         mov     al,23H                  ; interrupt 23H
  183.         mov     ah,25H                  ; set interrupt vector
  184.         int     dos                     ; ah, that's better
  185.         mov     dx,offset ceadr         ; DOS's Critical Error handler
  186.         mov     al,24h                  ; interrupt 24h
  187.         mov     ah,25h                  ; do replacement (put it back)
  188.         int     dos
  189.         mov     ah,4cH                  ; terminate process
  190.         mov     al,errlev               ; return error level
  191.         int     dos
  192.         ret
  193. START   ENDP
  194.  
  195. ; This is the 'EXIT' command.  It leaves KERMIT and returns to DOS
  196.  
  197. EXIT    PROC    NEAR
  198.         mov     ah,cmcfm
  199.         call    comnd                   ; Get a confirm
  200.          jmp    r
  201.          nop
  202.         mov     flags.extflg,1          ; Set the exit flag
  203.         jmp     rskp                    ; Then return to system
  204. EXIT    ENDP
  205.  
  206. ; TAKE commands from a file, and allow a path name
  207. TAKE    PROC    NEAR
  208.         mov     kstatus,0               ; global status, success
  209.         cmp     taklev,maxtak           ; Hit our limit?
  210.         jl      take1                   ; Continue if still OK
  211.         mov     ah,prstr
  212.        ;mov     dx,offset erms30        ; Complain
  213.         mcmsg   erms30, cerms30
  214.         int     dos
  215.         ret
  216. take1:  mov     dx,offset tmpbuf        ; work buffer
  217.         mov     tmpbuf,0
  218. ;        mov     bx,offset filmsg        ; Help in case user types "?"
  219.         mcmsgb  filmsg,cfilmsg
  220.         mov     ah,cmfile               ; get file name
  221.         call    comnd
  222.          jmp    r
  223.          nop
  224.         mov     ah,cmcfm
  225.         call    comnd
  226.          jmp    r
  227.          nop
  228.         mov     ax,offset tmpbuf        ; point to name again
  229.         cmp     tmpbuf,0                ; empty filespec?
  230.         jne     take2                   ; ne = no
  231.         mov     ah,prstr
  232.        ; mov     dx,offset ermes1        ; say more parameters needed
  233.         mcmsg   ermes1,cermes1
  234.         int     dos
  235.         jmp     rskp
  236.                                         ; TAKE2: enter with ax=filename ptr
  237. TAKE2:  call    spath                   ; is it around?
  238.         jc      take3                   ; no, go complain
  239.         mov     dx,ax                   ; point to name from spath
  240.         mov     ah,open2                ; 2.0 open call
  241.         cmp     dosnum,2                ; above DOS 2?
  242.         mov     al,0                    ; open for reading
  243.         jna     take2a                  ; na = no, so no shared access
  244.         mov     al,0+40h                ; open for reading, deny none
  245. take2a: int     dos
  246.         jnc     take4                   ; nc = opened ok, keep going
  247.         mov     ax,dx                   ; recover filename pointer
  248. take3:  push    ax
  249.         mov     ah,prstr
  250. ;        mov     dx,offset erms31
  251.         mcmsg   erms31, cerms31
  252.         int     dos
  253.         pop     ax
  254.         mov     dx,ax                   ; asciiz file name
  255.         call    prtasz                  ; display it
  256.         mov     kstatus,8               ; global status
  257.         jmp     rskp                    ; we've done all error displays
  258.                                         ; TAKE4: enter with ax=filename ptr
  259. TAKE4:  call    takopen                 ; open take buffer in macro space
  260.         jc      take6                   ; c = failure
  261.         push    bx
  262.         mov     bx,takadr               ; get current frame ptr
  263.         mov     [bx].takhnd,ax          ; save file handle
  264.         mov     [bx].taktyp,0feh        ; mark as 2.0 file handle
  265.         pop     bx
  266.         cmp     flags.takflg,0          ; echoing Take files?
  267.         je      take5                   ; e = no
  268.         mov     ah,prstr
  269.         mov     dx,offset crlf
  270.         int     dos
  271. take5:  call    takrd                   ; Get a buffer full of data
  272. take6:  jmp     rskp
  273. TAKE    ENDP
  274.  
  275. TAKRD   PROC    NEAR
  276.         push    ax
  277.         push    bx
  278.         push    cx
  279.         push    dx
  280.         mov     bx,takadr
  281.         cmp     [bx].taktyp,0feh        ; get type of take (file?)
  282.         jne     takrd1                  ; ne = no, do not read from disk
  283.         mov     dx,[bx].takbuf          ; address of buffer to read into
  284.         inc     dx                      ; skip count byte in takbuf
  285.         mov     cx,dmasiz               ; # of bytes to read
  286.         push    si
  287.         mov     si,dx                   ; fill buffer with spaces for
  288. takrd0: mov     byte ptr [si],' '       ; Show Macro
  289.         inc     si
  290.         loop    takrd0
  291.         pop     si
  292.         mov     cx,dmasiz
  293.         push    bx                      ; save frame address
  294.         mov     bx,[bx].takhnd          ; file handle is stored here
  295.         mov     ah,readf2               ; 2.0 read call
  296.         int     dos
  297.         pop     bx                      ; restore frame address
  298.         jnc     takrd2                  ; nc = successful read
  299. takrd1: mov     ax,0                    ; error, say zero bytes read
  300. takrd2: mov     [bx].takcnt,ax          ; number of bytes read
  301.         mov     ax,[bx].takbuf
  302.         inc     ax                      ; skip count byte in takbuf
  303.         mov     [bx].takptr,ax          ; first new character
  304.         pop     dx
  305.         pop     cx
  306.         pop     bx
  307.         pop     ax
  308.         ret
  309. TAKRD   ENDP
  310.  
  311. ; TAKE-QUIT     Exit all Take files immediately but gracefully
  312.  
  313. TAKEQIT PROC    NEAR
  314.         mov     ah,cmcfm
  315.         call    comnd
  316.          jmp    r
  317.          nop
  318. takqit1:mov     ch,0
  319.         mov     cl,taklev               ; number of Take levels active
  320.         jcxz    takqit2                 ; z = none
  321.         call    takclos                 ; close current Take file
  322.         jmp     short takqit1           ; repeat until all are closed
  323. takqit2:jmp     rskp
  324. TAKEQIT ENDP
  325.  
  326. ; put mskermit.ini onto take stack if it exists.  Just like
  327. ; the take command, except it doesn't read a filename
  328.  
  329. rdinit  proc    near                    ; read kermit init file..
  330.         mov     ax,offset ininm2        ; default name to try
  331.         cmp     decbuf,0                ; alternate init file given?
  332.         je      rdini1                  ; ne = no
  333.         mov     ax,offset decbuf        ; yes, use it
  334.         call    take2                   ; Let Take do error msgs
  335.          nop
  336.          nop
  337.          nop
  338.         ret
  339. rdini1: call    spath                   ; is it around?
  340.         jc      rdini2                  ; no, ignore file
  341.         mov     dx,ax                   ; point to name from spath
  342.         mov     ah,open2                ; 2.0 open call
  343.         mov     al,0                    ; open for reading
  344.         cmp     dosnum,2                ; above DOS 2?
  345.         jna     rdini1a                 ; na = no, so no shared access
  346.         mov     al,0+40h                ; open for reading, deny none
  347. rdini1a:int     dos
  348.         jc      rdini2                  ; c = no ini file found, ignore
  349.         call    take4                   ; use TAKE command to complete work
  350.          nop                            ; ignore errors
  351.          nop
  352.          nop
  353. rdini2: ret
  354. rdinit  endp
  355.  
  356. ; Get command line into a Take macro buffer. Allow "-f filspec" to override
  357. ; normal mskermit.ini initialization filespec, allow command "stay" to
  358. ; suppress automatic exit to DOS at end of command line execution. [jrd]
  359.  
  360. gcmdlin proc    near
  361.         mov     word ptr decbuf,0       ; storage for new init filename
  362.         push    es
  363.         cld
  364.         mov     es,psp                  ; address psp
  365.         mov     ch,0
  366.         mov     cl,es:byte ptr[cline]   ; length of cmd line from DOS
  367.         jcxz    gcmdl1                  ; z = empty line
  368.         mov     si,cline+1              ; point to actual line
  369. gcmdl0: cmp     byte ptr es:[si],' '    ; skip over leading whitespace
  370.         ja      gcmdl2                  ; a = non-whitespace
  371.         inc     si
  372.         loop    gcmdl0                  ; fall through on all whitespace
  373. gcmdl1: jmp     gcmdl14                 ; common exit jump point
  374. gcmdl2: inc     cx                      ; include DOS's c/r
  375.         call    takopen                 ; open take buffer in macro space
  376.         mov     bx,takadr
  377.         mov     byte ptr [bx].taktyp,0ffh ; mark as a macro
  378.         mov     [bx].takcnt,0           ; length of text
  379.         mov     di,[bx].takbuf          ; offset of buffer, from takopen
  380.         inc     di                      ; skip count byte
  381.         mov     ax,ds
  382.         mov     dx,es                   ; swap ds and es
  383.         mov     es,ax
  384.         mov     ds,dx                   ; ds = PSP, es = datas
  385. gcmdl3: cmp     cx,0                    ; anything left?
  386.         jbe     gcmdl10                 ; be = no
  387.         lodsb                           ; get a byte
  388.         dec     cx                      ; one less char in input string
  389.         cmp     al,','                  ; comma?
  390.         jne     gcmdl4                  ; no, keep going
  391.         mov     al,cr                   ; convert to cr
  392.         jmp     gcmdl9                  ; store it
  393. gcmdl4: cmp     al,'-'                  ; starting a flag?
  394.         jne     gcmdl9                  ; ne = no
  395.         mov     ah,byte ptr[si]         ; get flag letter
  396.         or      ah,20h                  ; convert to lower case
  397.         cmp     ah,'f'                  ; 'f' for init file replacement?
  398.         jne     gcmdl9                  ; ne = no
  399.         mov     ah,byte ptr[si+1]       ; need space or tab separator
  400.         cmp     ah,' '                  ; separator?
  401.         ja      gcmdl9                  ; a = no, not a flag
  402.                                         ; strip out and analyze flag info
  403.         inc     si                      ; point at separator
  404.         dec     cx
  405. gcmdl5: cmp     cx,0                    ; anything to read?
  406.         jle     gcmdl10                 ; le = exhausted supply
  407.         lodsb                           ; get filespec char from psp
  408.         dec     cx                      ; one less char in source buffer
  409.         cmp     al,' '                  ; in whitespace?
  410.         jbe     gcmdl5                  ; be = yes, scan it off
  411.         dec     si                      ; backup to real text
  412.         inc     cx
  413.                                         ; copy filspec to buffer decbuf
  414.         push    di                      ; save current destination pointer
  415.         lea     di,decbuf               ; where filespec part goes
  416.         mov     word ptr es:[di],0      ; plant safety terminator
  417. gcmdl6: lodsb                           ; get filespec char
  418.         dec     cx                      ; one less available
  419.         cmp     cx,0                    ; any chars left?
  420.         jle     gcmdl7                  ; le = no
  421.         cmp     al,' '                  ; in printables?
  422.         jbe     gcmdl7                  ; be = no, all done
  423.         cmp     al,','                  ; comma command separator?
  424.         je      gcmdl7                  ; e = yes, all done
  425.         stosb                           ; store filespec char
  426.         mov     byte ptr es:[di],0      ; end filespec on a null
  427.         jmp     short gcmdl6
  428. gcmdl7: pop     di                      ; recover macro register
  429.         dec     si                      ; compensate for last read above
  430.         inc     cx
  431. gcmdl8: cmp     cx,0                    ; strip trailing whitespace
  432.         jbe     gcmdl10                 ; be = nothing left
  433.         lodsb
  434.         dec     cx
  435.         cmp     al,' '                  ; white space?
  436.         jbe     gcmdl8                  ; be = yes, strip it
  437.         cmp     al,','                  ; at next command?
  438.         je      gcmdl10                 ; e = yes, skip our own comma
  439.         dec si                          ; back up to reread the char
  440.         inc cx
  441.         jmp     gcmdl3                  ; read more command text
  442.                                         ; end of flag analysis
  443. gcmdl9: stosb                           ; deposit most recent char
  444. gcmdl10:cmp     cx,0                    ; anything left to read?
  445.         jg      gcmdl3                  ; g = yes, loop
  446.                                         ;
  447.         mov     ax,datas                ; restore segment registers
  448.         mov     ds,ax
  449.         mov     es,ax                   ; return to ds=datas, es=datas
  450.         mov     si,[bx].takbuf          ; get address of text field
  451.         inc     si                      ; skip count byte
  452.         mov     cx,di                   ; current end pointer, (save di)
  453.         sub     cx,si                   ; current ptr minus start offset
  454.         mov     [bx].takcnt,cx
  455.         cmp     cx,0
  456.         jg      gcmdl11                 ; material at hand
  457.         call    takclos                 ; empty take file
  458.         jmp     gcmdl14                 ; finish up
  459.                                         ; scan for command "stay"
  460. gcmdl11:lodsb                           ; get a byte, cx and si are set above
  461.         dec     cx
  462.         cmp     al,' '                  ; separator?
  463.         jbe     gcmdl12                 ; be = yes, keep looking
  464.         cmp     al,','                  ; comma separator?
  465.         je      gcmdl12                 ; e = yes
  466.         mov     ah,al                   ; get first byte
  467.         lodsb                           ; second byte after separator
  468.         dec     cx
  469.         or      ax,2020h                ; convert to lower case
  470.         cmp     ax,'st'                 ; first two letters of stay
  471.         jne     gcmdl12                 ; ne = no match
  472.         lodsw                           ; next two letters (stay vs status)
  473.         sub     cx,2
  474.         or      ax,2020h                ; convert to lower case
  475.         cmp     ax,'ya'                 ; same as our pattern?
  476.         jne     gcmdl12                 ; ne = no match
  477.                                         ; check for separator or end of macro
  478.         cmp     cx,0                    ; at end of macro?
  479.         jle     gcmdl13                 ; yes, consider current match correct
  480.         cmp     byte ptr[si],' '        ; next char is a separator?
  481.         jbe     gcmdl13                 ; be = yes, found correct match
  482.         cmp     byte ptr[si],','        ; or comma separator?
  483.         je      gcmdl13                 ; e = yes
  484. gcmdl12:cmp     cx,0                    ; done yet? ("stay" not found)
  485.         jg      gcmdl11                 ; g = not yet, look some more
  486.         mov     si,offset eexit         ; append command "exit"
  487.         mov     cx,leexit               ; length of string "exit"
  488.         add     [bx].takcnt,cx
  489.         rep     movsb                   ; copy it into the macro
  490. gcmdl13:mov     ax,[bx].takbuf
  491.         inc     ax                      ; skip count byte
  492.         mov     [bx].takptr,ax          ; init buffer ptr
  493. gcmdl14:pop     es
  494.         ret
  495. gcmdlin endp
  496.  
  497. ; Enter with ax pointing to file name.  Searches path for given file,
  498. ; returns with ax pointing to whole name, or carry set if file can't be found.
  499. SPATH   proc    near
  500.         call    isfile                  ; does it exist as it is?
  501.         jc      spath0                  ; c = no, prepend path elements
  502.         test    byte ptr filtst.dta+21,10H ; subdirectory name?
  503.         jnz     spath0                  ; nz = yes, not desired file
  504.         clc
  505.         ret
  506. spath0: push    es                      ; save es around work
  507.         push    bx
  508.         push    si
  509.         push    di
  510.         mov     bx,ax                   ; save filename pointer in bx
  511.         mov     si,ax
  512.         mov     dl,0                    ; no '\' seen yet
  513.         cld
  514. spath1: lodsb
  515.         cmp     al,2fh                  ; contains fwd slash path characters?
  516.         je      spath1a
  517.         cmp     al,5ch                  ; or backslash?
  518.         jne     spath2                  ; no, keep going
  519. spath1a:mov     dl,1                    ; remember we've seen them
  520. spath2: or      al,al
  521.         jnz     spath1                  ; copy name in
  522.         or      dl,dl                   ; look at flag
  523.         jz      spath3                  ; no path, keep looking
  524.         jmp     spath9                  ; embedded path, fail
  525.  
  526. spath3: mov     si,pthadr               ; offset of PATH= string in environment
  527.         mov     es,psp
  528.         mov     di,es:word ptr[env]     ; pick up environment segment
  529.         mov     es,di
  530. spath4: cmp     byte ptr es:[si],0      ; end of PATH= string?
  531.         je      spath9                  ; e = yes, exit loop
  532.         mov     di,offset decbuf+64     ; place to put name
  533. spath5: mov     al,byte ptr es:[si]     ; get a byte from environment string
  534.         inc     si
  535.         cmp     al,';'                  ; end of this part?
  536.         je      spath7                  ; yes, break loop
  537.         cmp     al,0                    ; maybe end of string?
  538.         jne     spath6                  ; no, keep going
  539.         dec     si                      ; back up to null for later rereading
  540.         jmp     short spath7            ; and break loop
  541. spath6: mov     byte ptr [di],al        ; else stick in dest string
  542.         inc     di
  543.         jmp     spath5                  ; and continue
  544. spath7: push    si                      ; save this ptr
  545.         mov     si,bx                   ; this is user's file name
  546.         cmp     byte ptr [di-1],2fh     ; does path end with switch char?
  547.         je      spath8                  ; yes, don't put one in
  548.         cmp     byte ptr [di-1],5ch     ; how about this one?
  549.         je      spath8                  ; yes, don't put it in
  550.         mov     byte ptr [di],5ch       ; else add one
  551.         inc     di
  552. spath8: lodsb                           ; get filename character
  553.         mov     byte ptr [di],al        ; copy filename char to output buffer
  554.         inc     di
  555.         or      al,al                   ; end of string?
  556.         jnz     spath8                  ; nz = no, copy rest of name
  557.         pop     si                      ; restore postion in path string
  558.         mov     ax,offset decbuf+64
  559.         call    isfile                  ; is it a file?
  560.         jc      spath4                  ; c = no, keep looking
  561.         test    byte ptr filtst.dta+21,10H ; subdirectory name?
  562.         jnz     spath4                  ; nz = yes
  563.         pop     di
  564.         pop     si
  565.         pop     bx
  566.         pop     es
  567.         clc
  568.         ret                             ; return success (carry clear)
  569. spath9: mov     ax,bx                   ; restore original filename pointer
  570.         pop     di                      ; restore regs
  571.         pop     si
  572.         pop     bx
  573.         pop     es
  574.         stc                             ; no file found
  575.         ret
  576. spath   endp
  577.  
  578. ; Put offset of PATH= string in pthadr
  579. getpath proc    near
  580.         push    bx
  581.         push    cx
  582.         push    dx
  583.         mov     bx,offset pthnam        ; thing to find
  584.         mov     cx,pthlen               ; length of it
  585.         mov     pthadr,0                ; init offset to zero
  586.         call    getenv                  ; get environment value
  587.         mov     pthadr,dx
  588.         pop     dx
  589.         pop     cx
  590.         pop     bx
  591.         ret                             ; and return
  592. getpath endp
  593.  
  594. ; copy COMSPEC= environment string into cmspbuf
  595. getcsp  proc    near
  596.         push    bx
  597.         push    cx
  598.         push    dx
  599.         push    es
  600.         mov     bx,offset cmspnam       ; find COMSPEC=
  601.         mov     cx,cmsplen              ; it's length
  602.         call    getenv                  ; get environment offset in dx
  603.         mov     di,offset cmspbuf       ; where to store string
  604.         mov     si,dx                   ; address of COMSPEC= string
  605.         mov     es,psp
  606.         mov     bx,es:word ptr[env]     ; pick up environment address
  607.         mov     es,bx
  608.         push    ds                      ; save ds
  609.         push    ds                      ; make ds point to environment seg
  610.         push    es                      ; make es point to datas segment
  611.         pop     ds
  612.         pop     es
  613.         cld
  614. getcs1: lodsb                           ; get a byte from environment
  615.         cmp     al,' '                  ; space or less?
  616.         jg      getcs2                  ; g = no, keep copying
  617.         mov     al,0                    ; terminate string on spaces etc
  618. getcs2: stosb                           ; store it in cmspbuf
  619.         or      al,al                   ; at end of string yet?
  620.         jne     getcs1                  ; ne = no, keep copying
  621.         pop     ds                      ; recover ds
  622.         pop     es
  623.         pop     dx
  624.         pop     cx
  625.         pop     bx
  626.         ret                             ; and return
  627. getcsp  endp
  628.  
  629. ; Locate string variable in Environment
  630. ; bx/ variable to find (incl =), cx/ length of variable name,
  631. ; dx/ address to store value at
  632. getenv  proc    near
  633.         push    ax
  634.         push    cx
  635.         push    si
  636.         push    di
  637.         push    es
  638.         mov     es,psp
  639.         mov     ax,es:word ptr[env]     ; pick up environment address
  640.         mov     es,ax
  641.         mov     di,0                    ; start at this offset in segment
  642. geten1: cmp     es:byte ptr [di],0      ; end of environment?
  643.         je      geten4                  ; yes, forget it
  644.         push    cx                      ; save counter
  645.         push    di                      ; and offset
  646.         mov     si,bx
  647.         cld
  648.         repe    cmpsb                   ; search for name
  649.         pop     di
  650.         pop     cx                      ; restore these
  651.         je      geten2                  ; found it, break loop
  652.         push    cx                      ; preserve again
  653.         mov     cx,0ffffh               ; bogus length
  654.         mov     al,0                    ; marker to look for
  655.         repne   scasb                   ; search for it
  656.         pop     cx                      ; restore length
  657.         jmp     geten1                  ; loop thru rest of environment
  658. geten2: add     di,cx                   ; skip to definition
  659. geten4: mov     dx,di                   ; store offset of string
  660.         pop     es
  661.         pop     di
  662.         pop     si
  663.         pop     cx
  664.         pop     ax
  665.         ret                             ; and return
  666. getenv  endp
  667.  
  668. COMNT   PROC    NEAR                    ; COMMENT command
  669.         mov     ah,cmtxt
  670.         mov     bx,offset tmpbuf
  671.         mov     dx,0
  672.         call    comnd
  673.          jmp    r
  674.          nop
  675.         jmp     rskp
  676. COMNT   ENDP
  677.  
  678. ; change working directory
  679. cwdir   proc    near
  680.         mov     kstatus,0               ; global status
  681.         mov     ah,cmfile
  682.         mov     dx,offset tmpbuf
  683. ;        mov     bx,offset pthmsg
  684.         mcmsgb  pthmsg, cpthmsg
  685.  
  686.         call    comnd
  687.          jmp    r
  688.         mov     ah,cmcfm
  689.         call    comnd
  690.          jmp    r
  691.         cmp     tmpbuf,0                ; anything given?
  692.         jne     cwd1                    ; ne = yes
  693.         mov     ah,prstr
  694.        ; mov     dx,offset ermes1        ; say need more
  695.         mcmsg   ermes1,cermes1
  696.         int     dos
  697.         jmp     rskp
  698. cwd1:   mov     dl,curdsk               ; remember present disk
  699.         mov     byte ptr temp,dl
  700.         mov     bx,offset tmpbuf        ; change of drives, if req'd
  701.         cmp     byte ptr [bx+1],':'     ; was a drive specified?
  702.         jne     cwd2                    ; ne = no
  703.         mov     dl,[bx]                 ; get the drive letter
  704.         add     bx,2                    ; skip drive colon
  705.         and     dl,5FH                  ; make upper case
  706.         sub     dl,'A'                  ; convert to A = 0, etc
  707.         mov     ah,seldsk
  708.         int     dos                     ; change disks
  709.         jc      cwd3                    ; c = failure
  710.         inc     dl                      ; count A = 1 internally
  711.         mov     curdsk,dl               ; and store it
  712. cwd2:   cmp     byte ptr [bx],0         ; anything left?
  713.         je      cwd4                    ; e = no
  714.         mov     dx,bx                   ; get path string
  715.         mov     ah,chdir                ; DOS change directory
  716.         int     dos
  717.         jnc     cwd4                    ; nc = success
  718. ;cwd3:   mov     dx,offset ermes4        ; failure
  719. cwd3:   mcmsg   ermes4,cermes4
  720.         mov     ah,prstr
  721.         int     dos
  722.         mov     dl,byte ptr temp        ; get current disk
  723.         dec     dl                      ; A = 0 for DOS
  724.         mov     ah,seldsk               ; restore it
  725.         int     dos
  726.         mov     kstatus,8               ; global status
  727. cwd4:   jmp     rskp
  728. cwdir   endp
  729.  
  730.  
  731. ; Erase specified file(s). Add protection of ignore hidden, subdir, volume
  732. ; label and system files. 9 Jan 86 [jrd]
  733. DELETE  PROC    NEAR            ; revised for DOS 2.0, incl paths & ?* [jrd]
  734.         mov     kstatus,0               ; global status
  735.         mov     si,offset delcmd        ; del command
  736.         mov     di,offset tmpbuf
  737.         call    strcpy
  738.         mov     dx,offset tmpbuf
  739.         call    strlen                  ; get its length
  740.         add     di,cx                   ; point at terminator
  741.         mov     ah,cmfile               ; filespec
  742.         mov     dx,di                   ; where to place the file specs
  743. ;        mov     bx,offset filmsg        ; In case user wants help.
  744.         mcmsgb  filmsg,cfilmsg
  745.         call    comnd
  746.          jmp    r
  747.          nop
  748.         mov     temp,ax                 ; save byte count
  749.         mov     ah,cmcfm
  750.         call    comnd
  751.          jmp    r
  752.          nop
  753.         cmp     byte ptr temp+1,0       ; anything given?
  754.         jne     delet1                  ; ne = yes
  755.         mov     ah,prstr
  756.        ; mov     dx,offset ermes1        ; say need something
  757.         mcmsg   ermes1,cermes1
  758.         int     dos
  759.         jmp     rskp
  760.  
  761. delet1: mov     dx,offset delcmd        ; get length of prefix (del )
  762.         call    strlen
  763.         mov     ax,offset tmpbuf        ; command line so far
  764.         add     ax,cx                   ; bump address to filename field
  765.         call    isfile          ; and ask if file exists & what kind it is
  766.         jc      delet2                  ; c = no such file, complain
  767.         test    byte ptr filtst.dta+21,1EH; attribute bits: is file protected?
  768.         jz      delet3                  ; z = no, go ahead
  769. delet2: mov     ah,prstr
  770. ;        mov     dx,offset badnam        ; give error message
  771.         mcmsg   badnam, cbadnam
  772.         int     dos
  773.         mov     kstatus,8               ; global status
  774.         jmp     rskp                    ; and ignore this command
  775. delet3: mov     si,offset tmpbuf        ; del cmd
  776.         jmp     crun                    ; join run cmd from there
  777. DELETE  ENDP
  778.  
  779. CHKDSK  PROC    NEAR                    ; Space command
  780.         mov     kstatus,0               ; global status
  781.         mov     ah,cmcfm
  782.         call    comnd
  783.          jmp    r
  784.         mov     ah,prstr
  785.         mov     dx,offset crlf          ; start of message
  786.         int     dos
  787.         mov     dl,0                    ; use current drive
  788.         mov     ah,36h                  ; get disk free space
  789.         int     dos
  790.         cmp     ax,0ffffh               ; error response?
  791.         je      chkdsk1                 ; e = yes
  792.         mul     bx                      ; sectors/cluster * clusters = sectors
  793.         mov     bx,dx                   ; save high word of sectors (> 64K)
  794.         mul     cx                      ; bytes = sectors * bytes/sector
  795.         push    ax                      ; save low word of bytes
  796.         mov     ax,bx                   ; recall sectors high word
  797.         mov     bx,dx                   ; save current bytes high word
  798.         mul     cx                      ; high word sectors * bytes/sector
  799.         add     ax,bx                   ; new high bytes + old high bytes
  800.         mov     dx,ax
  801.         pop     ax
  802.         mov     di,offset tmpbuf        ; work space for lnout
  803.         mov     word ptr[di],'  '       ; start with two spaces
  804.         add     di,2
  805.         call    lnout
  806.  
  807.         mov     si,offset spcmsg
  808.         cmp     isccdos,0               ; if in CCDOS ?
  809.         jz      chkdsk0                 ; z = No
  810.         mov     si,offset cspcmsg
  811.  
  812. chkdsk0:call    strcat                  ; add text to end of message
  813.         mov     dx,offset tmpbuf
  814.         call    prtasz                  ; print asciiz string
  815.         jmp     rskp
  816. chkdsk1:mov     ah,prstr
  817. ;        mov     dx,offset spcmsg2       ; say drive not ready
  818.         mcmsg   spcmsg2, cspcmsg2
  819.         int     dos
  820.         mov     kstatus,8               ; global status
  821.         jmp     rskp
  822. CHKDSK  ENDP
  823.  
  824. ; Get directory listing
  825. DIRECT  PROC    NEAR
  826.         mov     kstatus,0               ; global status
  827.         mov     si,offset dircmd        ; dir command
  828.         mov     di,offset tmpbuf
  829.         call    strcpy
  830.         mov     dx,offset tmpbuf
  831.         call    strlen                  ; get its length
  832.         add     di,cx                   ; point at terminator
  833.         mov     ah,cmtxt                ; parse with cmtxt so we can have paths
  834.         mov     bx,di                   ; next available byte
  835. ;        mov     dx,offset filmsg        ; In case user wants help.
  836.         mcmsg   filmsg, cfilmsg
  837.         call    comnd
  838.          jmp    r
  839.         mov     byte ptr [bx],0         ; plant terminator
  840.         mov     si,offset tmpbuf
  841.         jmp     crun                    ; join run cmd from there
  842. DIRECT  ENDP
  843.  
  844. ; This is the 'HELP' command.  It gives a list of the commands
  845.  
  846. HELP    PROC    NEAR
  847.         mov     kstatus,0               ; global status
  848.         mov     ah,cmcfm
  849.         call    comnd                   ; Get a confirm
  850.          jmp    r
  851.         mov     ah,prstr                ; show Quick help summary screen
  852. ;        mov     dx,offset qckhlp
  853.         mcmsg   qckhlp,cqckhlp
  854.         int     dos
  855.         mov     ah,conout
  856.         mov     dl,trans.escchr         ; get Kermit escape character
  857.         add     dl,40h                  ; convert to printable
  858.         push    dx                      ; save it for repeats below
  859.         int     dos
  860.         mov     ah,prstr
  861. ;        mov     dx,offset qckhlp1       ; more help text
  862.         mcmsg   qckhlp1,cqckhlp1
  863.         int     dos
  864.         mov     ah,conout
  865.         pop     dx
  866.         push    dx
  867.         int     dos
  868.         mov     ah,prstr
  869. ;        mov     dx,offset qckhlp2       ; more help text
  870.         mcmsg   qckhlp2,cqckhlp2
  871.         int     dos
  872.         pop     dx                      ; recover current escape char
  873.         mov     ah,conout
  874.         int     dos
  875.         mov     ah,prstr
  876. ;        mov     dx,offset qckhlp3       ; end of help message
  877.         mcmsg   qckhlp3,cqckhlp3
  878.         int     dos
  879.         mov     ah,coninq               ; get a keystroke, quietly
  880.         int     dos
  881.         cmp     al,'?'                  ; query mark?
  882.         jne     helpx                   ; ne = no, skip second screen
  883.         mov     ah,prstr                ; show help summary screen
  884.         mov     dx,offset crlf          ; a few blank lines
  885.         int     dos
  886.         int     dos
  887.         int     dos
  888. ;        mov     dx,offset tophlp        ; show usual cryptic help
  889.         mcmsg   tophlp,ctophlp
  890.         int     dos
  891. helpx:  jmp     rskp
  892. HELP    ENDP
  893.  
  894. ; the version command - print our version number
  895. prvers  proc    near
  896.         mov     kstatus,0               ; global status
  897.         mov     ah,cmcfm
  898.         call    comnd
  899.          jmp    r
  900.         mov     ah,prstr
  901.         mov     dx,offset crlf
  902.         int     dos
  903.         mov     ah,prstr
  904.         mov     dx,offset machnam       ; print machine name
  905.         int     dos
  906.         mov     ah,prstr                ; Print the version header
  907.       ;  mov     dx,offset versio
  908.         mcmsg   versio, cversio
  909.         int     dos
  910.         jmp     rskp
  911. prvers  endp
  912.  
  913. ; the show command
  914. showcmd proc    near
  915.         mov     kstatus,0               ; global status
  916.         mov     ah,cmkey
  917.         mov     dx,offset shotab
  918.         xor     bx,bx                   ; no canned help
  919.         call    comnd
  920.          jmp    r
  921.         jmp     bx                      ; execute the handler
  922. showcmd endp
  923.  
  924. ; the type command - type out a file
  925. typec   proc    near
  926.         mov     kstatus,0               ; global status
  927.         mov     si,offset typcmd        ; type command
  928.         mov     di,offset tmpbuf
  929.         call    strcpy
  930.         mov     dx,offset tmpbuf
  931.         call    strlen                  ; get its length
  932.         add     di,cx                   ; point at terminator
  933.         mov     ah,cmtxt                ; parse with cmtxt so we can have paths
  934.         mov     bx,di                   ; next available byte
  935. ;        mov     dx,offset filmsg        ; In case user wants help.
  936.         mcmsg   filmsg,  cfilmsg
  937.         call    comnd
  938.          jmp    r
  939.         cmp     ah,0                    ; any text given?
  940.         jne     typec1                  ; ne = yes
  941.         mov     ah,prstr
  942. ;        mov     dx,offset ermes1        ; say need more info
  943.         mcmsg   ermes1, cermes1
  944.         int     dos
  945.         jmp     rskp
  946. typec1: mov     byte ptr [bx],0         ; plant terminator
  947.         mov     si,offset tmpbuf
  948.         jmp     crun                    ; join run cmd from there
  949. typec   endp
  950.  
  951. ; PUSH to DOS (run another copy of Command.com or equiv)
  952. ; entry fpush (fast push...) pushes without waiting for a confirm
  953. ; returns rskp
  954. dopush  proc    near
  955. dopus1: mov     ah,cmcfm
  956.         call    comnd
  957.          jmp    r
  958.          nop
  959. fpush:  mov     si,offset tmpbuf        ; a dummy buffer
  960.         mov     byte ptr [si],0         ; plant terminator
  961.         jmp     short crun4             ; go run it
  962. dopush  endp
  963.  
  964. ; Run a program from within Kermit
  965. RUN     PROC    NEAR
  966.         mov     ah,cmtxt                ; Get program name and any arguments
  967.         mov     bx,offset tmpbuf        ; place for user's text
  968. ;        mov     dx,offset runmsg        ; In case user wants help
  969.         mcmsg   runmsg, crunmsg
  970.         call    comnd
  971.          jmp    r
  972.          nop
  973.         cmp     ah,0                    ; byte count
  974.         jne     run2                    ; ne = have program name
  975.         mov     ah,prstr                ; else complain
  976. ;        mov     dx,offset ermes1        ; need more info
  977.         mcmsg   ermes1,cermes1
  978.         int     dos
  979.         jmp     rskp
  980. run2:   mov     si,offset tmpbuf        ; source of text
  981.         jmp     crun
  982. RUN     ENDP
  983.  
  984. ; crun - run an arbitrary program.      Rewritten by [jrd]
  985. ; Enter with ordinary asciiz command in si (such as Dir *.asm)
  986. ; Append a c/r and a null terminator and then ask command.com to do it
  987. CRUN    proc    near
  988.         mov     ah,prstr           ; output crlf before executing comnd. [lba]
  989.         mov     dx,offset crlf          ; [lba]
  990.         int     dos                     ; display it. [lba]
  991.         mov     di,offset tmpbuf        ; where to put full command line text
  992.         cmp     si,di                   ; same place?
  993.         je      crun1                   ; e = yes, don't copy ourself
  994.         call    strcpy                  ; si holds source text
  995. crun1:  mov     si,offset slashc        ; DOS command begins with slashc area
  996.         mov     dx,offset slashc+1      ; si points to /c part of command line
  997.         call    strlen                  ; get its length into cx
  998.         push    bx
  999.         mov     bx,dx
  1000.         add     bx,cx
  1001.         mov     byte ptr [bx],cr        ; end string with a c/r for dos
  1002.         inc     cx                      ; count the c/r
  1003.         mov     byte ptr [bx+1],0       ; and terminate
  1004.         pop     bx
  1005.         mov     [si],cl                 ; put length of argument here
  1006. crun4:  mov     exearg+2,si             ; pointer to argument string
  1007.         mov     exearg+4,ds             ; segment of same
  1008.         cmp     lclsusp,0               ; sys dependent routine to call
  1009.         je      crun5                   ; e = none
  1010.         mov     bx,lclsusp              ; address to call
  1011.         call    bx                      ; call sys dependent suspend routine
  1012. crun5:  call    serrst                  ; reset serial port (if active)
  1013.         mov     es,psp                  ; point to psp again
  1014.         mov     exearg+8,es             ; segment of psp, use our def fcb's
  1015.         mov     exearg+12,es            ; segment of psp, ditto, for fcb 2
  1016.         mov     ax,es:word ptr [env]    ; get environment ptr
  1017.         mov     exearg,ax               ; put into argument block
  1018.         mov     ax,ds
  1019.         mov     es,ax                   ; put es segment back
  1020.         mov     bx,offset exearg        ; es:bx points to exec parameter block
  1021.         mov     dx,offset cmspbuf       ; always use command.com
  1022.         mov     al,0                    ; load and execute..
  1023.         mov     ah,exec
  1024.         mov     ssave,sp                ; save stack ptr
  1025.         int     dos                     ; go run the program
  1026.         mov     ax,datas
  1027.         mov     ds,ax                   ; reset data segment
  1028.         mov     es,ax                   ; and extra segment
  1029.         mov     ax,cstack
  1030.         mov     ss,ax                   ; and stack segment
  1031.         mov     sp,ssave                ; restore stack ptr
  1032.         pushf                           ; save  flags
  1033.         mov     ah,setdma
  1034.         mov     dx,offset buff
  1035.         int     dos                     ; restore dma address!!
  1036.         popf                            ; recover flags
  1037.         jc      crun8                   ; c = error, handle
  1038.         cmp     lclrest,0               ; sys dependent routine to call
  1039.         je      crun9                   ; e = none
  1040.         mov     bx,lclrest              ; get routine's address
  1041.         call    bx                      ; call sys dependent restore routine
  1042. crun9:  jmp     rskp                    ; ok, return
  1043. crun8:  mov     ah,prstr
  1044. ;        mov     dx,offset erms37
  1045.         mcmsg   erms37,cerms37
  1046.         int     dos
  1047.         mov     kstatus,8               ; global status
  1048.         jmp     rskp
  1049. CRUN    ENDP
  1050.  
  1051. ; Replace Int 23h and Int 24h with our own handlers
  1052. ; Revised to ask DOS for original interrupt vector contents, as suggested by
  1053. ; Jack Bryans. 9 Jan 1986 jrd
  1054. ; Modified again 30 August 1986 [jrd]
  1055. SETINT  PROC    NEAR
  1056.         push    es                      ; save registers
  1057.         push    bx
  1058.         mov     al,23H                  ; desired interrupt vector (^C)
  1059.         mov     ah,35H                  ; Int 21H, function 35H = Get Vector
  1060.         int     dos                     ; get vector in es:bx
  1061.         mov     in3ad,bx              ; save offset address of original vector
  1062.         mov     in3ad+2,es              ;   and its segment
  1063.         mov     al,24h                  ; DOS critical error, Int 24h
  1064.         mov     ah,35h
  1065.         int     dos
  1066.         mov     word ptr ceadr,bx       ; DOS's Critical Error handler, offset
  1067.         mov     word ptr ceadr+2,es     ;  and segment address
  1068.         push    ds                      ; save ds around next DOS call
  1069.         mov     ax,cs                   ; compose full address of ^C routine
  1070.         mov     ds,ax                   ; Offset is the code segment
  1071.         mov     dx,offset intbrk        ;   and main address is intbrk
  1072.         mov     al,23H                  ; On ^C, goto intbrk
  1073.         mov     ah,25H                  ; set interrupt address from ds:dx
  1074.         int     dos
  1075.         mov     dx,offset dosce         ; replacement Critical Error handler
  1076.         mov     al,24h                  ; interrupt 24h
  1077.         mov     ah,25h                  ; replace it
  1078.         int     dos
  1079.         pop     ds
  1080.         pop     bx
  1081.         pop     es
  1082.         ret
  1083. SETINT  ENDP
  1084.  
  1085. ; Control Break, Interrupt 23h replacement
  1086. ; Always return with a Continue (vs Abort) condition since Kermit will cope
  1087. ; with failures. [jrd]
  1088. intbrk: push ax
  1089.         push    ds
  1090.         mov     ax,datas                ; get Kermit's data segment
  1091.         mov     ds,ax
  1092.         mov     flags.cxzflg,'C'        ; Say we saw a ^C
  1093.         mov     pack.state,'A'          ; Set the state to abort
  1094.         pop     ds
  1095.         pop     ax
  1096.         iret                       ; return to caller in a Continue condition
  1097.  
  1098. ; Kermit's DOS Critical Error Handler, Int 24h. [jrd]
  1099. ; Needed to avoid aborting Kermit with the serial port interrupt active and
  1100. ; the Control Break interrupt redirected. See the DOS Tech Ref Manual for
  1101. ; a start on this material; it is neither complete nor entirely accurate
  1102. ; The stack is the Kermit's stack, the data segment is unknown, interrupts
  1103. ; are off, and the code segment is Kermit's. Note: some implementations of
  1104. ; MS DOS may leave us in DOS's stack. Called by a DOS Int 21h function
  1105. dosce:  test    ah,80h          ; block device (disk drive)?
  1106.         jnz     dosce1          ; nz = no; serial device, memory, etc
  1107.         mov     al,3            ; tell DOS to Fail the Int 21h call
  1108.         iret                    ; return to DOS
  1109. dosce1: add     sp,6            ; pop IP, CS, Flags regs, from DOS's Int 24h
  1110.         pop     ax              ; restore original callers regs existing
  1111.         pop     bx              ;  just before doing Int 21h call
  1112.         pop     cx
  1113.         pop     dx
  1114.         pop     si
  1115.         pop     di
  1116.         pop     bp
  1117.         pop     ds
  1118.         pop     es
  1119.         mov     al,0ffh         ; signal failure (usually) the DOS 1.x way
  1120.         push    ax              ; Kermit's IP, CS, and Flags are on the stack
  1121.         push    bp              ;  all ready for an iret, but first a word ..
  1122.         mov     bp,sp
  1123.         mov     ax,ss:[bp+8]    ; get Kermit's flags word
  1124.         or      ax,1            ; set the carry bit, signal failure DOS 2+ way
  1125.         mov     ss:[bp+8],ax    ; store new flags back in the stack
  1126.         pop     bp              ; this avoids seeing the Interrupt flag bit
  1127.         pop     ax
  1128.         iret                    ; return to user, simulate return from Int 21h
  1129.  
  1130. ISFILE  PROC    NEAR
  1131. ; Enter with ds:ax pointing at asciiz filename string
  1132. ; Returns carry set if the file pointed to by ax does not exist, else reset
  1133. ; Returns status byte, fstat, with DOS status and high bit set if major error
  1134. ; Does a search-for-first to permit paths and wild cards
  1135. ; Examines All kinds of files (ordinary, subdirs, vol labels, system,
  1136. ;  and hidden). Upgraded to All kinds on 27 Dec 1985. Revised 30 Aug 86 [jrd]
  1137. ; All registers are preserved
  1138.  
  1139.         push    dx                      ; save regs
  1140.         push    cx
  1141.         push    ax
  1142.         mov     byte ptr filtst.dta+21,0 ; clear old attribute bits
  1143.         mov     byte ptr filtst.fname,0 ; clear any old filenames
  1144.         mov     filtst.fstat,0          ; clear status byte
  1145.         mov     cx,3fH                  ; look at all kinds of files
  1146.         mov     dx,offset filtst.dta    ; own own temporary dta
  1147.         mov     ah,setdma               ; set to new dta
  1148.         int     dos
  1149.         pop     dx                      ; get ax (filename string ptr)
  1150.         push    dx                      ; save it again
  1151.         mov     ah,first2               ; search for first
  1152.         int     dos
  1153.         pushf                           ; save flags
  1154.         mov     dx,offset buff          ; reset dma
  1155.         mov     ah,setdma
  1156.         int     dos
  1157.         popf                            ; recover flags
  1158.         jnc     isfil1                  ; nc = file found
  1159.         mov     filtst.fstat,al         ; record DOS status
  1160.         cmp     al,2                    ; just "File Not Found"?
  1161.         je      isfil2                  ; e = yes
  1162.         cmp     al,3                    ; "Path not found"?
  1163.         je      isfil2                  ; e = yes
  1164.         cmp     al,18                   ; "No more files"?
  1165.         je      isfil2                  ; e = yes
  1166.         or      filtst.fstat,80h        ; set high bit for more serious error
  1167.         jmp     isfil2
  1168. isfil1: cmp     byte ptr filtst.fname,0 ; did DOS fill in a name?
  1169.         jne     isfil3                  ; nz = yes
  1170. isfil2: stc                             ; else set carry flag bit
  1171. isfil3: pop     ax
  1172.         pop     cx
  1173.         pop     dx
  1174.         ret                             ; DOS sets carry if file not found
  1175. ISFILE  ENDP
  1176.  
  1177. ; initialize memory usage by returning to DOS anything past the end of kermit
  1178. memini  proc    near
  1179.         push    es
  1180.         mov     es,psp                  ; address psp segment again
  1181.         mov     bx,offset msfinal + 15  ; end of pgm + roundup
  1182.         mov     cl,4
  1183.         shr     bx,cl                   ; compute # of paragraphs in last seg
  1184.         mov     ax,datas                ; last segment
  1185.         sub     ax,psp                  ; minus beginning
  1186.         add     bx,ax                   ; # of paragraphs occupied
  1187.         mov     ah,setblk
  1188.         int     dos
  1189.          jc     memin1
  1190.         pop     es
  1191.         ret
  1192. memin1: pop     es
  1193. ;        mov     dx,offset ermes2
  1194.         mcmsg   ermes2,cermes2
  1195.         mov     ah,prstr
  1196.         int     dos                     ; complain
  1197.         jmp     krmend                  ; and just exit..
  1198. memini  endp
  1199.  
  1200. ; Allocate memory.  Passed a memory size in ax, allocates that many
  1201. ; bytes (actually rounds up to a paragraph) and returns its SEGMENT in ax
  1202. ; The memory is NOT initialized.  Written by [jrd] to allow memory to
  1203. ; be allocated anywhere in the 1MB address space
  1204. sbrk    proc    near                    ; K & R, please forgive us
  1205.         mov     bx,ax                   ; bytes wanted
  1206.         add     bx,15                   ; round up
  1207.         mov     cl,4
  1208.         shr     bx,cl                   ; convert to # of paragraphs
  1209.         mov     ah,alloc                ; DOS memory allocator
  1210.         int     dos
  1211.         jc      sbrkx                   ; c = fatal
  1212.         ret                             ; and return segment in ax
  1213. ;sbrkx:  mov     dx,offset mfmsg         ; assume not enough memory (ax = 8)
  1214. sbrkx:  mcmsg     mfmsg, cmfmsg
  1215.         cmp     ax,7                    ; corrupted memory (ax = 7)?
  1216.         jne     sbrkx1                  ; ne = no
  1217. ;        mov     dx,offset mf7msg        ; corrupted memory found
  1218.         mcmsg   mf7msg, cmf7msg
  1219. sbrkx1: mov     ah,prstr
  1220.         int     dos
  1221.         jmp     krmend                  ; exit Kermit now
  1222. sbrk    endp
  1223.  
  1224.  
  1225. ; Jumping to this location is like retskp.  It assumes the instruction
  1226. ;   after the call is a jmp addr
  1227.  
  1228. RSKP    PROC    NEAR
  1229.         pop     bp
  1230.         add     bp,3
  1231.         push    bp
  1232.         ret
  1233. RSKP    ENDP
  1234.  
  1235. ; Jumping here is the same as a ret
  1236.  
  1237. R       PROC    NEAR
  1238.         ret
  1239. R       ENDP
  1240.  
  1241. code    ends                    ; End of code section
  1242.         end     start
  1243.