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

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