home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 15 / CDACTUAL15.iso / cdactual / program / asm / MSKERMIT.ZIP / MSKERM.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-05-17  |  34.8 KB  |  1,435 lines

  1.     public    prompt, dosnum, curdsk, swchar
  2.     include msdefs.h
  3. ;******************** Version 2.26 **********************************
  4. ; KERMIT, Celtic for "free"
  5. ;
  6. ; The name "Kermit" is a registered trade mark of Henson Associates, Inc.,
  7. ; used by permission.
  8. ;
  9. ;    Kermit-MS Program Version 2.26, July 26, 1984
  10. ;
  11. ;    Based on the Columbia University KERMIT Protocol.
  12. ;
  13. ;    Copyright (C) 1982,1983,1984 Trustees of Columbia University
  14. ;
  15. ;    Daphne Tzoar, Jeff Damens
  16. ;    Columbia University Center for Computing Activities
  17. ;    612 West 115th Street
  18. ;    New York, NY  10025
  19. ;
  20. ; Special thanks to Frank da Cruz, Bill Catchings, Steve Jensen, Herm Fischer,
  21. ; Vace Kundakci, and Bernie Eiben for their help and contributions.
  22.  
  23. makseg    equ    26H
  24. deffcb    equ    5cH
  25. setblk    equ    4AH
  26. exec    equ    4BH
  27. env    equ    2CH        ; environment address in psp
  28. terma    equ    10        ; termination address in psp
  29. cline    equ    80H        ; offset in psp of command line
  30. namsiz    equ    20        ; Bytes for file name and size.
  31. maxnam    equ    10
  32. chmod    equ    43H        ; chmod call (used to test for file existence)
  33.  
  34. STACK    SEGMENT PARA STACK 'STACK'
  35.     DW    100 DUP(0)    ; Initialize stack to all zeros.
  36. STK    EQU    THIS WORD
  37. STACK    ENDS
  38.  
  39. datas    segment public 'datas'
  40.     extrn    buff:byte, comand:byte, flags:byte, pack:byte, trans:byte
  41.     extrn    fcb:byte, cpfcb:byte, prmptr:word, inichk:byte
  42.     extrn    machnam:byte
  43.     public    takadr,taklev
  44.  
  45. versio    label    byte
  46.     verdef
  47.     db    cr,lf
  48.     db    'Type ? for help',cr,lf
  49.     db    '$'
  50. tmp    db    ?,'$'
  51. crlf    db    cr,lf,'$'
  52. ermes1    db    cr,lf,'?Unrecognized command$'
  53. ermes3    db    cr,lf,'?Not confirmed$'
  54. erms30    db    cr,lf,'Passed maximum nesting level for TAKE command$'
  55. erms31    db    cr,lf,'Take file not found$'
  56. erms32    db    cr,lf,'File(s) not found$'
  57. erms33    db    cr,lf,'CHKDSK program not found on current disk$'
  58. erms34    db    cr,lf,'This command works only for DOS 2.0 and above$'
  59. erms35    db    cr,lf,'Must specify program name$'
  60. erms36    db    cr,lf,'Could not free memory$'
  61. erms37    db    cr,lf,'Unable to execute program$'
  62. infms1    db    'Really erase *.*? $'
  63. infms8    db    cr,lf,'File(s) erased$'
  64. tmsg5    db    cr,lf,'[closing log file]',cr,lf,'$' ; [jd]
  65. filhlp1 db    ' Command file specification $'
  66. filhlp2 db    ' File specification (possibly wild) $'
  67. filhlp3 db    ' File spec (possibly wild) or confirm with carriage return$'
  68. filmsg    db    ' File specification with optional path name $'
  69. filwmsg db    ' File specification (possibly wild) with optional path name $'
  70. chkfil    db    0,'CHKDSK  COM'
  71. chkflen equ    $-chkfil
  72.  
  73. tophlp    db    cr,lf
  74.     db    'BYE',tab,tab
  75.     db    'CLOSE',tab,tab
  76.     db    'CONNECT',tab,tab
  77.     db    'DEFINE',tab,tab
  78.     db    cr,lf
  79.     db    'DELETE',tab,tab
  80.     db    'DIRECTORY',tab
  81.     db    'DO',tab,tab
  82.     db    'EXIT',tab,tab
  83.     db    cr,lf
  84.     db    'FINISH',tab,tab
  85.     db    'GET',tab,tab
  86.     db    'HELP',tab,tab
  87.     db    'LOCAL',tab,tab
  88.     db    cr,lf
  89.     db    'LOG',tab,tab
  90.     db    'LOGOUT',tab,tab
  91.     db    'PUSH',tab,tab
  92.     db    'QUIT',tab,tab
  93.     db    cr,lf
  94.     db    'RECEIVE',tab,tab
  95.     db    'REMOTE',tab,tab
  96.     db    'RUN',tab,tab
  97.     db    'SEND',tab,tab
  98.     db    cr,lf
  99.     db    'SERVER',tab,tab
  100.     db    'SET',tab,tab
  101.     db    'SHOW',tab,tab
  102.     db    'SPACE',tab,tab
  103.     db    cr,lf
  104.     db    'STATUS',tab,tab
  105.     db    'TAKE'
  106.     db    '$'
  107.  
  108. lochlp    db    cr,lf,'DELETE file'
  109.     db    cr,lf,'DIRECTORY [filespec]'
  110.     db    cr,lf,'SPACE remaining on current disk'
  111.     db    cr,lf,'RUN program'
  112.     db    cr,lf,'PUSH to command interpreter'
  113.     db    '$'
  114.  
  115.     ; COMND tables
  116.  
  117. yestab    db    2
  118.     mkeyw    'NO',0
  119.     mkeyw    'YES',1
  120.  
  121. comtab    db    27
  122.     mkeyw    'BYE',bye
  123.     mkeyw    'C',telnet
  124.     mkeyw    'CLOSE',clscpt
  125.     mkeyw    'CONNECT',telnet
  126.     mkeyw    'DEFINE',dodef
  127.     mkeyw    'DELETE',delete
  128.     mkeyw    'DIRECTORY',direct
  129.     mkeyw    'DO',docom
  130.     mkeyw    'EXIT',exit
  131.     mkeyw    'FINISH',finish
  132.     mkeyw    'GET',get
  133.     mkeyw    'HELP',help
  134.     mkeyw    'LOCAL',lclcmd
  135.     mkeyw    'LOG',setcpt
  136.     mkeyw    'LOGOUT',logout
  137.     mkeyw    'PUSH',dopush
  138.     mkeyw    'QUIT',exit
  139.     mkeyw    'RECEIVE',read
  140.     mkeyw    'REMOTE',remote
  141.     mkeyw    'RUN',run
  142.     mkeyw    'SEND',send
  143.     mkeyw    'SERVER',server
  144.     mkeyw    'SET',setcom
  145.     mkeyw    'SHOW',showcmd
  146.     mkeyw    'SPACE',chkdsk
  147.     mkeyw    'STATUS',status
  148.     mkeyw    'TAKE',take
  149.  
  150. loctab    db    5
  151.     mkeyw    'DELETE',delete
  152.     mkeyw    'DIRECTORY',direct
  153.     mkeyw    'PUSH',dopush
  154.     mkeyw    'RUN',run
  155.     mkeyw    'SPACE',chkdsk
  156.  
  157. shotab    db    2
  158.     mkeyw    'KEY',shokey
  159.     mkeyw    'MACRO',shomac
  160.  
  161. ; Program storage.
  162.  
  163. oldstk    dw    ?        ; Storage for system stack.
  164. oldsts    dw    ?        ; System stack segment.
  165. ssave    dw    ?        ; Original SS when doing CHKDSK.
  166. siz    dw    ?        ; Memory size.
  167. in3ad    dd    0        ; Original break interrupt addresses. [25]
  168. curdsk    db    0        ; Current disk.
  169. origd    db    0        ; Original disk.
  170. fildat    db    0        ; Manipulate file data/time creation.
  171.     db    0
  172. taklev    db    0        ; Take levels. [25t]
  173. takadr    dw    takstr-(size takinfo) ; Pointer into structure. [25t]
  174. temp    dw    0
  175. temp1    dw    ?        ; Temporary storage.
  176. temp2    dw    ?
  177. temp3    dw    ?
  178. temp4    dw    ?
  179. psp    dw    ?
  180. divst    dw    0
  181. takstr    db    (size takinfo) * maxtak dup(?)
  182. ininam    db    0,'MSKERMITINI' ; init file name, on default disk, 12 chars
  183. ininm2    db    'MSKERMIT.INI',0 ; init file name for 2.0
  184. nambuf    db    maxnam * namsiz dup (?)
  185. cmdnam    db    namsiz dup (?)
  186. exefcb    db    fcbsiz dup (?)
  187. exefcb2 db    fcbsiz dup (?)
  188. exearg    dw    ?        ; segment addr of environment (filled in below)
  189.     dd    0        ; ptr to cmd line (filled in below)
  190.     dd    exefcb        ; default fcb
  191.     dd    exefcb2     ; second default fcb
  192. dircmd    db    ' /c dir '
  193. dirclen equ    $-dircmd
  194. dirnam    db    50h dup (?)
  195. chkdcmd db    'chkdsk.com'
  196. chkdlen equ    $-chkdcmd
  197. dosnum    db    ?        ; dos version number
  198. pthnam    db    'PATH='
  199. pthlen    equ    $-pthnam
  200. pthbuf    db    100 dup (?)    ; buffer for path definition.
  201. defpth    db    '\', 70 dup (?) ; buffer for default path
  202. cmspnam db    'COMSPEC='
  203. cmsplen equ    $-cmspnam
  204. cmspbuf db    '\command.com',0 ; default name
  205.     db    30 dup (?)    ; some additional space
  206. tfile    db    100 dup (?)    ; temp space for file names.
  207. eexit    db    cr,'exit',cr
  208. leexit    equ    $-eexit
  209. swchar    db    '\'             ; default switch character.
  210. datas    ends            ; End data segment
  211.  
  212. code    segment public
  213.     public    takrd
  214. start    proc  far
  215.     extrn    cmblnk:near, locate:near, logout:near
  216.     extrn    bye:near, telnet:near, finish:near, comnd:near
  217.     extrn    read:near, remote:near, send:near, status:near, get:near
  218.     extrn    dodisk:near, serrst:near, setcom:near
  219.     extrn    clscpi:near, clscpt:near, getbaud:near
  220.     extrn    dodef:near, setcpt:near, docom:near
  221.     extrn    server:near, lclini:near, shokey:near, shomac:near
  222.     assume    cs:code,ds:datas,ss:stack,es:nothing
  223.  
  224.     push ds         ; Save system data area.
  225.     sub ax,ax        ; Get a zero.
  226.     push ax         ; Put zero return addr on stack.
  227.  
  228.     mov ax,datas           ; Initialize DS.
  229.     mov ds,ax
  230.     sub ax,ax
  231.  
  232.     mov oldstk,sp        ; Save old stack pointer.
  233.  
  234.     mov ax,es:[2]        ; In program segment prefix
  235.     mov siz,ax        ; Pick up memory size
  236.     mov psp,es
  237.  
  238.     mov ah,prstr
  239.     mov dx,offset machnam    ; print machine name
  240.     int dos
  241.     mov ah,prstr        ; Print the version header.
  242.     mov dx,offset versio
  243.     int dos
  244.  
  245.     mov ah,setdma        ; Set disk transfer address.
  246.     mov dx,offset buff
  247.     int dos
  248.  
  249.     call getbaud        ; Get the baud rate. [25]
  250.     call dodisk        ; See how many disk drives we have. [21a]
  251.     call setint
  252.     mov ah,gcurdsk        ; Get current disk.
  253.     int dos
  254.     inc al            ; We want 1 == A (not zero).
  255.     mov curdsk,al
  256.     mov origd,al        ; Remember original disk we started on.
  257.     mov ah,dosver
  258.     int dos
  259.     mov dosnum,al        ; remember dos version
  260.     cmp al,0
  261.     je start1        ; 1.1, keep going
  262.     mov es,psp
  263.     mov ax,es:[env]     ; pick up environment address
  264.     push ax
  265.     call getpath        ; get the path from the environment
  266.     pop ax            ; get environment back
  267.     call getcsp        ; get comspec from environment as well
  268. start1: call lclini        ; do local initialization
  269.     call gcmdlin        ; read command line
  270.     call rdinit        ; read kermit init file
  271.     call packlen        ; Packet length in case do server comand.
  272. ; This is the main KERMIT loop.  It prompts for and gets the users commands.
  273.  
  274. kermit: mov ax,ds
  275.     mov es,ax        ; make sure this addresses data segment
  276.     mov dx,prmptr        ; get prompt
  277.     call prompt        ; Prompt the user.
  278.     mov pack.state,0    ; Clear the state.
  279.     mov flags.cxzflg,0    ; Reset each itme.
  280.     mov ah,inichk        ; Original or set checksum length.
  281.     mov trans.chklen,ah    ; Reset just in case.
  282.     mov dx,offset comtab
  283.     mov bx,offset tophlp
  284.     mov comand.cmcr,1    ; Allow bare CR's.
  285.     mov ah,cmkey
  286.     call comnd
  287.      jmp kermt2
  288.     mov comand.cmcr,0    ; Not anymore.
  289.     call bx         ; Call the routine returned.
  290.      jmp kermt3
  291.     cmp flags.extflg,0    ;  Check if the exit flag is set.
  292.     jne krmend        ;  If so jump to KRMEND.
  293.     jmp kermit        ; Do it again.
  294.  
  295. kermt2: mov dx,offset ermes1    ;  Give an error.
  296.     jmp short kermt4
  297.  
  298. kermt3: mov dx,offset ermes3    ;  Give an error.
  299. kermt4: cmp flags.cxzflg,'C'    ; some sort of abort?
  300.     je kermit        ; yes, don't print error message.
  301.     mov ah,prstr
  302.     int dos
  303.     mov flags.droflg,0    ; Reset drive override flag.
  304.     mov flags.nmoflg,0    ; Reset filename override flag.
  305.     mov flags.getflg,0    ; May as well do this one.
  306.     mov flags.cmrflg,0    ; This one too.
  307.     jmp kermit
  308.  
  309. krmend: call serrst        ; Just in case the port wasn't reset. [21c]
  310.     mov dl,origd        ; Original disk drive.
  311.     dec dl            ; Want A == 0.
  312.     mov ah,seldsk        ; Reset original disk just in case.
  313.     int dos
  314.     mov sp,oldstk
  315.     ret
  316.  
  317. START    ENDP
  318.  
  319. ; This is the 'exit' command.  It leaves KERMIT and returns to DOS.
  320.  
  321. EXIT    PROC    NEAR
  322.     mov ah,cmcfm
  323.     call comnd        ; Get a confirm.
  324.      jmp r
  325.     test    flags.capflg,0FFH    ; capturing?
  326.     jz    exit1            ; no, keep going
  327.     mov    dx,offset tmsg5
  328.     mov    ah,prstr
  329.     int    dos
  330.     call    clscpi
  331.      nop                ; this skip returns...
  332.      nop
  333.      nop
  334. exit1:
  335.     mov flags.extflg,1    ;  Set the exit flag.
  336.     jmp rskp        ; Then return to system.
  337. EXIT    ENDP
  338.  
  339.  
  340. ; This is the 'help' command.  It gives a list of the commands.
  341.  
  342. HELP    PROC    NEAR
  343.     mov ah,cmcfm
  344.     call comnd        ; Get a confirm.
  345.      jmp r
  346.     mov ah,prstr        ; Print a string to the console.
  347.     mov dx,offset tophlp    ; The address of the help message.
  348.     int dos
  349.     jmp rskp
  350. HELP    ENDP
  351.  
  352. lclcmd    proc    near
  353.     mov ah,cmkey
  354.     mov dx,offset loctab
  355.     mov bx,offset lochlp
  356.     call comnd
  357.      jmp r
  358.     call bx
  359.     nop
  360.     nop
  361.     nop
  362.     jmp rskp
  363. lclcmd    endp
  364.  
  365. ; Don't ignore ^C when in debug mode.
  366. SETINT    PROC    NEAR
  367.     push ds         ; Don't forget this. [25]
  368.     mov ax,ds
  369.     mov es,ax        ; So can access our data area.
  370.     mov ax,0
  371.     mov ds,ax        ; Access low core.
  372.     mov ax,ds:[23H * 4]    ; Address for interrupt 23H.
  373.     mov cx,ds:[23H * 4 +2]    ; CS value for it.
  374.     mov word ptr es:in3ad,ax ; Remember original values.
  375.     mov word ptr es:in3ad+2,cx
  376.     mov ax,cs
  377.     mov ds,ax        ; Access code are.
  378.     mov dx,offset intbrk
  379.     mov al,23H        ; On ^C, goto above address.
  380.     mov ah,25H
  381.     int dos
  382.     pop ds
  383.     ret
  384. SETINT    ENDP
  385.  
  386. ; take commands from a file, but allow a path name
  387. PTAKE    PROC    NEAR
  388.     cmp taklev,maxtak        ; Hit our limit?
  389.     jl ptake1            ; Continue if still OK.
  390.     mov ah,prstr
  391.     mov dx,offset erms30        ; Complain.
  392.     int dos
  393.     ret
  394. ptake1: mov di,takadr
  395.     add di,size takinfo
  396.     push di
  397.     mov ah,cmtxt
  398.     lea bx,[di].takbuf        ; convenient place to parse name into
  399.     mov dx,offset filmsg        ; Help in case user types "?".
  400.     call comnd
  401.      pop di
  402.      ret
  403.      nop
  404.     pop di                ; restore frame address
  405.     push di             ; keep it on stack.
  406.     lea si,[di].takbuf        ; get buffer back
  407.     mov bl,ah            ; length of thing parsed
  408.     mov bh,0
  409.     mov byte ptr [bx+si],0        ; make it asciz
  410.     mov ax,si            ; point to name again
  411.     call spath            ; is it around?
  412.     pop di                ; need this back
  413.     jc ptake2            ; no, go complain
  414.     mov dx,ax            ; point to name from spath
  415.     mov ah,open2            ; 2.0 open call
  416.     mov al,0            ; open for reading
  417.     int dos
  418.     jnc ptake3            ; open ok, keep going
  419. ptake2: mov ah,prstr
  420.     mov dx,offset erms31
  421.     int dos
  422.     ret
  423. ptake3: inc taklev
  424.     mov takadr,di
  425.     mov word ptr [di].takfcb+1,ax    ; save file descriptor
  426.     mov byte ptr [di].takfcb,0feh    ; mark as 2.0 file descriptor
  427.     mov bx,ax            ; need descriptor here
  428.     mov ah,lseek
  429.     mov al,2
  430.     mov cx,0
  431.     mov dx,cx            ; seek 0 bytes from end
  432.     int dos
  433.     mov [di].takcnt,ax
  434.     mov [di].takcnt+2,dx        ; store length
  435.     mov ah,lseek
  436.     mov al,0
  437.     mov cx,0
  438.     mov dx,cx            ; now seek back to beginning
  439.     int dos
  440.     cmp flags.takflg,0
  441.     je ptake4
  442.     mov ah,prstr
  443.     mov dx,offset crlf
  444.     int dos
  445. ptake4: call takrd        ; Get a buffer full of data.
  446.     jmp rskp
  447. PTAKE    ENDP
  448.  
  449.  
  450. ;    TAKE commands from a file.  [25t]
  451.  
  452. TAKE    PROC    NEAR
  453.     cmp dosnum,0
  454.     je take1
  455.     jmp ptake            ; use this for 2.0
  456. take1:    cmp taklev,maxtak        ; Hit our limit?
  457.     jl take2                ; Continue if still OK.
  458.     mov ah,prstr
  459.     mov dx,offset erms30        ; Complain.
  460.     int dos
  461.     ret
  462. take2:    mov bx,takadr
  463.     add bx,size takinfo
  464.     push bx
  465.     lea dx,[bx].takfcb
  466.     mov comand.cmcr,0        ; Filename must be specified.
  467.     mov ah,cmifi
  468.     mov bx,offset filhlp1
  469.     call comnd
  470.      pop bx
  471.      ret                ; Make sure this is three bytes long.
  472.      nop
  473.     pop bx
  474.     mov byte ptr [bx].takfcb+32,0    ; have to clear current record in fcb
  475.     mov ah,openf
  476.     lea dx,[bx].takfcb
  477.     int dos
  478.     cmp al,0FFH            ; File not found?
  479.     jne take3
  480.     mov ah,prstr
  481.     mov dx,offset erms31
  482.     int dos
  483. take3:    inc taklev
  484.     mov takadr,bx
  485.     mov ax,word ptr [bx+16].takfcb
  486.     mov [bx].takcnt,ax
  487.     mov ax,word ptr [bx+18].takfcb
  488.     mov [bx].takcnt+2,ax        ; copy size into takinfo
  489.     cmp flags.takflg,0
  490.     je take4
  491.     mov ah,prstr
  492.     mov dx,offset crlf
  493.     int dos
  494. take4:    call takrd            ; Get a buffer full of data.
  495.     jmp rskp
  496. TAKE    ENDP
  497.  
  498. TAKRD    PROC    NEAR
  499.     push bx
  500.     push cx
  501.     push dx
  502.     mov bx,takadr
  503.     cmp byte ptr [bx].takfcb,0feh    ; is it a 2.0 file handle?
  504.     jne takrd1            ; no, handle differently
  505.     push bx             ; save frame address
  506.     lea dx,[bx].takbuf        ; buffer to read into
  507.     mov cx,dmasiz            ; # of bytes to read
  508.     mov ah,readf2            ; 2.0 read call
  509.     mov bx,word ptr [bx].takfcb+1    ; file handle is stored here
  510.     int dos
  511.     pop bx                ; restore frame address
  512.     jmp takrd2            ; rejoin common exit
  513.  
  514. takrd1: mov ah,setdma
  515.     lea dx,[bx].takbuf
  516.     int dos
  517.     mov ah,readf
  518.     lea dx,[bx].takfcb
  519.     int dos
  520.     mov ah,setdma
  521.     lea dx,buff
  522.     int dos
  523. takrd2: mov [bx].takchl,dmasiz
  524.     lea ax,[bx].takbuf
  525.     mov [bx].takptr,ax
  526.     pop dx
  527.     pop cx
  528.     pop bx
  529.     ret
  530.  
  531. TAKRD    ENDP
  532.  
  533. ; copy the path into pthbuf
  534. ; enter with ax/ environment segment address
  535. ; works in 2.0 only.
  536. getpath proc    near
  537.     push    es
  538.     mov    bx,ds
  539.     mov    es,bx            ; address data segment
  540.     mov    bx,offset pthnam    ; thing to find
  541.     mov    cx,pthlen        ; length of it
  542.     mov    dx,offset pthbuf    ; place to put it
  543.     mov    byte ptr pthbuf,0    ; initialize to null...
  544.     call    getenv            ; get environment value
  545.     pop    es
  546.     ret                ; and return
  547. getpath endp
  548.  
  549. ; copy the comspec into cmspbuf
  550. ; enter with ax/ environment segment address
  551. ; works in 2.0 only.
  552. getcsp    proc    near
  553.     push    es
  554.     mov    bx,ds
  555.     mov    es,bx            ; address data segment
  556.     mov    bx,offset cmspnam    ; thing to find
  557.     mov    cx,cmsplen        ; length of it
  558.     mov    dx,offset cmspbuf    ; place to put it
  559.     call    getenv            ; get environment value
  560.     pop    es
  561.     ret                ; and return
  562. getcsp    endp
  563.  
  564. ; find a path variable.  Enter with ax/ environment segment,
  565. ; bx/ variable to find (incl =), cx/ length of variable name,
  566. ; dx/ address to store value at.
  567. ; The buffer given in dx is unchanged if the variable isn't found
  568. getenv    proc    near
  569.     push    ds
  570.     push    es
  571.     mov    es,ax            ; address segment
  572.     mov    di,0            ; offset in segment
  573. geten1: cmp    es:byte ptr [di],0    ; end?
  574.     je    geten4            ; yes, forget it
  575.     push    cx            ; save counter
  576.     push    di            ; and offset
  577.     mov    si,bx
  578.     repe    cmpsb            ; is it the one?
  579.     pop    di
  580.     pop    cx            ; restore these
  581.     je    geten2            ; found it, break loop
  582.     push    cx            ; preserve again
  583.     mov    cx,0ffffh        ; bogus length
  584.     mov    al,0            ; marker to look for
  585.     repne    scasb            ; search for it
  586.     pop    cx            ; restore length
  587.     jmp    geten1            ; loop thru rest of environment
  588. geten2: add    di,cx            ; skip to definition
  589.     mov    si,di            ; this is source
  590.     mov    di,dx            ; destination as given
  591.     mov    ax,ds
  592.     mov    bx,es
  593.     mov    ds,bx
  594.     mov    es,ax            ; exchange segment regs for copy
  595. geten3: lodsb                ; get a byte
  596.     stosb                ; drop it off
  597.     cmp    al,0            ; end of string
  598.     jne    geten3            ; no, go on
  599. geten4: pop    es
  600.     pop    ds            ; restore registers
  601.     ret                ; and return
  602. getenv    endp
  603.  
  604. ; put kermit.ini onto take stack if it exists.    Just like
  605. ; the take command, except it doesn't read a filename.
  606.  
  607. rdinit    proc    near        ; read kermit init file...
  608.     mov al,dosnum        ; get dos version
  609.     or al,al
  610.     jne rdini4        ; post 2.0, use file handle instead...
  611.     mov bx,takadr
  612.     add bx,size takinfo    ; bump take ptr, point to current take frame
  613.     lea di,[bx].takfcb    ; destination is fcb
  614.     mov ax,ds
  615.     mov es,ax        ; destination segment = source segment
  616.     mov si,offset ininam    ; name of init file
  617.     mov cx,12        ; 8 char name + 3 char ext + 1 char drive...
  618.     rep movsb        ; copy it in
  619.     mov byte ptr [bx].takfcb+32,0 ; have to clear current record in fcb
  620.     mov ah,openf
  621.     lea dx,[bx].takfcb
  622.     int dos
  623.     cmp al,0FFH        ; File not found?
  624.     jne rdini1        ; no, keep going
  625.     ret            ; else just return, no init file
  626. rdini1: inc taklev        ; bump take level
  627.     mov takadr,bx        ; save current take frame ptr
  628.     mov ax,word ptr [bx+16].takfcb
  629.     mov [bx].takcnt,ax
  630.     mov ax,word ptr [bx+18].takfcb
  631.     mov [bx].takcnt+2,ax    ; copy size into takinfo
  632. rdini2: cmp flags.takflg,0
  633.     je rdini3
  634.     mov ah,prstr
  635.     mov dx,offset crlf
  636.     int dos
  637. rdini3: call takrd        ; Get a buffer full of data.
  638.     ret
  639.  
  640. rdini4: mov ax,offset ininm2    ; name to try
  641.     push bx
  642.     call spath        ; can we find it?
  643.     pop di
  644.     jc rdini6        ; no, forget it, go use it
  645.     mov dx,ax        ; point to name
  646.     mov ah,open2        ; 2.0 open function
  647.     mov al,0        ; for reading...
  648.     int dos
  649.     jc rdini6        ; can't open, forget it
  650.  
  651. rdini5: inc taklev        ; bump take level
  652.     add takadr,size takinfo
  653.     mov di,takadr        ; get current frame ptr
  654.     mov word ptr [di].takfcb+1,ax    ; save file handle
  655.     mov byte ptr [di].takfcb,0feh    ; mark as a handle
  656.     mov bx,ax            ; move file ptr
  657.     mov ah,lseek
  658.     mov al,2
  659.     mov cx,0
  660.     mov dx,0            ; seek to end of file
  661.     int dos
  662.     mov [di].takcnt,ax        ; copy file size
  663.     mov [di].takcnt+2,dx        ; into structure
  664.     mov al,0
  665.     mov ah,lseek
  666.     mov cx,0
  667.     mov dx,0
  668.     int dos             ; seek back to beginning
  669.     jmp rdini2            ; go rejoin common exit
  670. rdini6: ret                ; no init file, just return
  671. rdinit    endp
  672.  
  673. ; get command line into a macro buffer.
  674.  
  675. gcmdlin proc    near
  676.     push    ds
  677.     push    es
  678.     cld
  679.     mov    es,psp            ; address psp
  680.     mov    ch,0
  681.     mov    cl,es:[cline]        ; length of cmd line
  682.     mov    di,cline+1        ; point to actual line
  683.     mov    al,' '
  684.     jcxz    gcmdl3            ; no command line, forget it.
  685.     repe    scasb            ; skip over spaces
  686.     je    gcmdl3            ; all spaces, forget it
  687.     mov    si,di            ; this is first non-space
  688.     dec    si            ; pre-incremented...
  689.     inc    cx
  690.     inc    taklev            ; bump take level
  691.     add    takadr,size takinfo    ; address new take frame
  692.     mov    bx,takadr
  693.     mov    byte ptr [bx].takfcb,0ffh ; mark as a macro
  694.     push    cx            ; save length
  695.     push    ds            ; and segment
  696.     lea    di,[bx].takbuf        ; into take buffer
  697.     mov    ax,ds
  698.     mov    ds,psp
  699.     mov    es,ax            ; switch segments for copy
  700. gcmdl1: lodsb                ; get a byte
  701.     cmp    al,','                  ; comma?
  702.     jne    gcmdl2            ; no, keep going
  703.     mov    al,cr            ; convert to cr
  704. gcmdl2: stosb                ; deposit it
  705.     loop    gcmdl1            ; copy whole cmd
  706.     pop    ds            ; restore segment
  707.     mov    si,offset eexit     ; something to tack onto end
  708.     mov    cx,leexit        ; length of it
  709.     rep    movsb            ; copy it in
  710.     pop    cx            ; restore len
  711.     add    cx,leexit        ; count wnat we added
  712.  
  713.     lea    ax,[bx].takbuf
  714.     mov    [bx].takptr,ax        ; init buffer ptr
  715.     mov    [bx].takchl,cl        ; chars remaining
  716.     mov    [bx].takcnt,cx        ; and all chars
  717.     mov    [bx].takcnt+2,0     ; clear high order
  718. gcmdl3: pop    es
  719.     pop    ds
  720.     ret
  721. gcmdlin endp
  722.  
  723. ;    This routine prints the prompt and specifies the reparse address.
  724.  
  725. PROMPT    PROC  NEAR
  726.     mov comand.cmprmp,dx    ; save the prompt
  727.     pop bx            ; Get the return address.
  728.     mov comand.cmrprs,bx    ; Save as addr to go to on reparse.
  729.     mov comand.cmostp,sp    ; Save for later restoral.
  730.     push bx         ; Put it on the stack again.
  731.     mov bx,offset comand.cmdbuf
  732.     mov comand.cmcptr,bx    ; Initialize the command pointer.
  733.     mov comand.cmdptr,bx
  734.     mov ah,0
  735.     mov comand.cmaflg,ah    ; Zero the flags.
  736.     mov comand.cmccnt,ah
  737.     mov comand.cmsflg,0FFH
  738.     cmp flags.takflg,0    ; look at take flag
  739.     jne promp1        ; supposed to echo, skip this check...
  740.     cmp taklev,0        ; inside a take file?
  741.     je promp1        ; no, keep going
  742.     ret            ; yes, return
  743. promp1: mov ah,prstr
  744.     mov dx,offset crlf
  745.     int dos
  746.     mov ah,prstr        ; Print the prompt.
  747.     mov dx,comand.cmprmp
  748.     int dos
  749.     ret
  750. PROMPT    ENDP
  751.  
  752. ; Erase specified file(s).
  753. DELETE    PROC    NEAR
  754.     mov comand.cmcr,0    ; Filename must be specified.
  755.     mov ah,cmifi        ; Parse an input filespec.
  756.     mov dx,offset fcb
  757.     mov bx,offset filhlp2    ; Text of help message.
  758.     call comnd
  759.      jmp r            ; Bad filename.
  760.     mov ah,cmcfm        ; Parse a confirm.
  761.     call comnd
  762.      jmp r
  763.     cld
  764.     mov di,offset fcb+1
  765.     mov al,'?'
  766.     mov cx,11        ; # of chars in a name
  767.     repe scasb        ; are they all ?'s?
  768.     jne del1        ; no, skip message
  769.     mov dx,offset infms1
  770.     call prompt
  771.     mov ah,cmkey
  772.     mov dx,offset yestab
  773.     mov bx,0
  774.     call comnd
  775.      jmp r
  776.     push bx
  777.     mov ah,cmcfm
  778.     call comnd
  779.      pop bx
  780.      ret
  781.      nop
  782.     pop bx
  783.     cmp bx,0
  784.     jne del1
  785.     jmp rskp
  786. del1:    mov dx,offset fcb
  787.     mov ah,sfirst        ; See if any files match this specification.
  788.     int dos
  789.     cmp al,0FFH        ; No matches?
  790.     jne del2
  791.     mov ah,prstr
  792.     mov dx,offset erms32
  793.     int dos
  794.     jmp rskp
  795. del2:    mov dx,offset fcb
  796.     mov ah,delf        ; Erase the file(s).
  797.     int dos
  798.     mov dx,offset infms8
  799.     mov ah,prstr        ; Say we did so.
  800.     int dos
  801.     jmp rskp
  802. DELETE    ENDP
  803.  
  804. CHKDSK    PROC    NEAR
  805.     mov ah,cmcfm
  806.     call comnd
  807.      jmp r
  808.     cmp dosnum,0
  809.     je chkds1            ; yes, have to do it the hard way
  810.     mov si,offset chkdcmd        ; point to cmd
  811.     mov cx,chkdlen            ; and length
  812.     jmp crun            ; and go execute it nicely
  813. chkds1: push es
  814.     mov ax,ds
  815.     mov es,ax
  816.     mov di,offset fcb
  817.     mov si,offset chkfil
  818.     mov cx,chkflen
  819.     rep movsb
  820.     mov dx,offset stk + 15        ; End of stack plus roundoff.
  821.     mov cl,4
  822.     shr dx,cl            ; Divide to get segment.
  823.     add dx,seg stack        ; Get past the stack.
  824.     mov es,dx            ; remember where segment is.
  825.     mov ah,makseg            ; Create new PSP.
  826.     int dos
  827.     mov ax,siz            ; Update machine size.
  828.     mov es:2,ax
  829.     mov es: byte ptr [deffcb],0    ; Blank default fcb.
  830.     mov di,deffcb+1
  831.     mov al,' '                      ; Blank out fcb.
  832.     mov cx,fcbsiz
  833.     rep stosb
  834.     mov word ptr es:[terma],offset term    ; Termination address.
  835.     mov es:[terma+2],cs
  836.     mov ah,openf
  837.     mov dx,offset fcb
  838.     int dos
  839.     inc al
  840.     jnz chkok
  841.     mov dx,offset erms33
  842.     mov ah,prstr
  843.     int dos
  844.     jmp chkend
  845.  
  846. chkok:    mov byte ptr fcb+32,0        ; set current record field
  847.     mov di,100h            ; offset to copy into
  848. lp:    mov dx,offset fcb
  849.     mov ah,readf
  850.     int dos
  851.     push ax             ; save status
  852.     mov si,offset buff
  853.     mov cx,dmasiz/2         ; Word size of DMA
  854.     rep movsw            ; copy into new segment...
  855.     pop ax
  856.     cmp al,1            ; End of file
  857.     je dun
  858.     cmp al,3            ; Done here too
  859.     jne lp
  860. dun:    mov ssave,sp            ; Save stack pointer.
  861.     mov ax,es
  862.     mov word ptr cs:[doit+2],ax    ; Set segment for CHKDSK.
  863.     mov ds,ax
  864.     mov ss,ax
  865.     mov ax,0
  866.     jmp cs: dword ptr [doit]    ; Call CHKDSK.
  867. term:    mov ax,seg datas        ; Reset data area.
  868.     mov ds,ax
  869.     mov sp,ssave
  870.     mov ax,seg stack
  871.     mov ss,ax
  872.     mov ah,setdma
  873.     mov dx,offset buff
  874.     int dos             ; restore dma address!!
  875. chkend: pop es
  876.     jmp rskp
  877. doit    dd 100h
  878. CHKDSK    ENDP
  879.  
  880. ; Get directory listing.
  881. DIRECT    PROC    NEAR
  882.     mov ah,dosver        ; See what level of DOS we're at.
  883.     int dos
  884.     cmp al,0        ; Level 2.0 or above?
  885.     jne dir4        ; Yes - get directory the easy way.
  886.     mov comand.cmcr,1    ; Allow plain CR (so DIR == DIR *.*).
  887.     mov ah,cmifi        ; Get input file spec.
  888.     mov dx,offset fcb    ; Give the address for the FCB.
  889.     mov bx,offset filhlp3
  890.     call comnd
  891.      jmp r
  892.     mov ah,cmcfm        ; Parse a confirm.
  893.     call comnd
  894.      jmp r
  895.     mov comand.cmcr,0    ; Reset this.
  896.     push es
  897.     mov ax,ds
  898.     mov es,ax
  899.     mov temp1,0FFH
  900.     mov di,offset nambuf
  901. dir0:    call getfn        ; Get a matching file name.
  902.     cmp al,0FFH        ; Retcode -- are we done?
  903.     je dir1         ; Yes, just leave.
  904.     call dumpit        ; Print it or dump to buffer.
  905.     jmp dir0
  906. dir1:    pop es
  907.     jmp rskp
  908.  
  909. dir4:    mov si,offset cmspbuf    ; command processor
  910.     mov di,offset dirnam
  911. dir5:    lodsb            ; get a byte
  912.     or al,al
  913.     jz dir6         ; stop on the null
  914.     stosb            ; otherwise copy it in
  915.     jmp dir5        ; and keep going
  916. dir6:    mov si,offset dircmd    ; add directory command to it
  917.     mov cx,dirclen
  918.     rep movsb
  919.     mov ah,cmtxt        ; parse with cmtxt so we can have paths...
  920.     mov bx,di        ; next available byte
  921.     mov dx,offset filwmsg    ; In case user wants help.
  922.     call comnd
  923.      jmp r
  924.     mov cl,ah
  925.     mov ch,0        ; length of name
  926.     sub di,offset dirnam    ; compute # of bytes used
  927.     add cx,di
  928.     mov si,offset dirnam    ; dir cmd
  929.     jmp crun        ; join run cmd from there.
  930. DIRECT    ENDP
  931.  
  932. getfn:    cmp temp1,0FFH
  933.     jne gtfn1
  934.     mov ah,sfirst        ; Any matches?
  935.     mov dx,offset fcb
  936.     int dos
  937.     cmp al,0FFH        ; Means no matches.
  938.     je gtfn5
  939.     call savfcb
  940.     mov temp1,0
  941.     jmp gtfn4
  942. gtfn1:    cmp flags.wldflg,0FFH    ; Wilcard seen?
  943.     je gtfn2        ; Yes, get next file.
  944.     mov al,0FFH        ; No, set retcode.
  945.     ret
  946. gtfn2:    call rstfcb
  947.     mov ah,snext
  948.     mov dx,offset fcb
  949.     int dos
  950.     cmp al,0        ; Any more matches?
  951.     je gtfn3        ; Yes keep going.
  952.     mov al,0FFH        ; OK return code.
  953.     ret
  954. gtfn3:    call savfcb
  955. gtfn4:    push di
  956.     mov si,offset buff    ; Data is here.
  957.     mov di,offset fcb    ; Copy to here.
  958.     mov cx,37
  959.     repne movsb
  960.     pop di
  961.     call nicnam        ; Make name nice for printing.
  962.     mov al,0
  963.     ret
  964. gtfn5:    mov ah,prstr        ; Don't print if a server.
  965.     mov dx,offset erms32    ; Say no matches.
  966.     int dos
  967.     mov al,0FFH        ; Failure return code.
  968.     ret
  969.  
  970. savfcb: push di
  971.     mov si,offset fcb    ; Data is here.
  972.     mov di,offset cpfcb    ; Copy to here.
  973.     mov cx,37
  974.     repne movsb
  975.     pop di
  976.     ret
  977.  
  978. rstfcb: push di
  979.     mov si,offset cpfcb    ; Data is here.
  980.     mov di,offset fcb    ; Copy to here.
  981.     mov cx,37
  982.     repne movsb
  983.     pop di
  984.     ret
  985.  
  986. nicnam: mov al,CR        ; Add CRLF before print names
  987.     stosb
  988.     mov al,LF
  989.     stosb
  990.     mov cx,8
  991.     mov si,offset fcb+1
  992.     repne movsb        ; Get the file name.
  993.     mov al,' '
  994.     stosb
  995.     mov cx,3
  996.     repne movsb
  997.     mov al,tab
  998.     stosb
  999.     mov al,' '
  1000.     stosb
  1001.     mov ah,openf
  1002.     mov dx,offset fcb
  1003.     int dos
  1004.     mov bx,offset fcb+18    ; Get hi order word of file size.
  1005.     mov ax,[bx]
  1006.     mov dx,ax
  1007.     mov bx,offset fcb+16    ; Get lo order word.
  1008.     mov ax,[bx]
  1009.     call nout2x        ; Get it in decimal.
  1010.     mov al,tab
  1011.     stosb
  1012.     mov al,' '
  1013.     stosb
  1014.     mov ah,0
  1015.     mov si,offset fcb+20
  1016.     lodsb
  1017.     mov fildat+1,al
  1018.     lodsb
  1019.     mov fildat,al        ; Date field of fcb.
  1020.     mov cl,5
  1021.     shr fildat+1,cl
  1022.     and fildat,1
  1023.     mov cl,3
  1024.     shl fildat,cl
  1025.     mov al,fildat
  1026.     or al,fildat+1        ; Get the month field.
  1027.     cmp al,9
  1028.     jg nic0
  1029.     push ax
  1030.     mov al,' '
  1031.     stosb
  1032.     pop ax
  1033. nic0:    call nout2        ; Make it decimal.
  1034.     mov al,'-'
  1035.     stosb
  1036.     mov si,offset fcb+20    ; Get date field.
  1037.     lodsb
  1038.     and al,1FH
  1039.     cmp al,10        ; Only one digit?
  1040.     jge nic0x
  1041.     push ax
  1042.     mov al,'0'              ; Make it two digits.
  1043.     stosb
  1044.     pop ax
  1045. nic0x:    call nout2        ; Make it decimal.
  1046.     mov al,'-'
  1047.     stosb
  1048.     mov si,offset fcb+21    ; Get the year field.
  1049.     lodsb
  1050.     shr al,1
  1051.     add al,80
  1052.     cmp al,100        ; At the year 2000 or above?
  1053.     js nic0y        ; No, just go on.
  1054.     sub al,100        ; Go back to two digits.
  1055. nic0y:    cmp al,10        ; Only one digit?
  1056.     jge nic0z
  1057.     push ax
  1058.     mov al,'0'              ; Make it two digits.
  1059.     stosb
  1060.     pop ax
  1061. nic0z:    call nout2        ; Make it decimal.
  1062.     mov al,tab
  1063.     stosb
  1064.     mov si,offset fcb+23    ; Get time field of fcb.
  1065.     lodsb
  1066.     mov cl,3        ; Get the hour field.
  1067.     shr al,cl
  1068.     mov tmp,'a'             ; For AM.
  1069.     cmp al,12        ; Before noon?
  1070.     jl nic1
  1071.     mov tmp,'p'             ; It's PM.
  1072.     je nic1         ; Don't change "12" to "0".
  1073.     sub al,12        ; Use a 12 hr. clock.
  1074. nic1:    cmp al,0        ; Just after midnight?
  1075.     jne nic1x
  1076.     add al,12        ; Make it "12" instead of "0".
  1077. nic1x:    cmp al,10        ; Pad with a space?
  1078.     jge nic2
  1079.     push ax
  1080.     mov al,' '
  1081.     stosb
  1082.     pop ax
  1083. nic2:    call nout2        ; Make it decimal.
  1084.     mov al,':'              ; Separate hours and minutes.
  1085.     stosb
  1086.     mov si,offset fcb+23    ; Get the minutes field.
  1087.     lodsb
  1088.     and al,07
  1089.     mov cl,3
  1090.     shl al,cl
  1091.     mov ah,al
  1092.     mov si,offset fcb+22
  1093.     lodsb
  1094.     mov cl,5
  1095.     shr al,cl
  1096.     or al,ah
  1097.     mov ah,0
  1098.     cmp al,10        ; Would there be a leading zero.
  1099.     jge nic3
  1100.     push ax
  1101.     mov al,'0'
  1102.     stosb
  1103.     pop ax
  1104. nic3:    call nout2        ; Make it decimal.
  1105.     mov al,tmp        ; Add 'a' (AM) or 'p' (PM).
  1106.     stosb
  1107.     mov ah,closf
  1108.     mov dx,offset fcb
  1109.     int dos
  1110.     ret
  1111.  
  1112. ; For now, just print it.
  1113. dumpit: mov al,'$'
  1114.     stosb
  1115.     mov ah,prstr
  1116.     mov dx,offset nambuf
  1117.     int dos
  1118.     mov di,offset nambuf
  1119.     ret
  1120.  
  1121. ; push to an inferior command parser
  1122. dopush    proc    near
  1123.     cmp    dosnum,0        ; < 2.0 ?
  1124.     jne    dopus1            ; no, go on
  1125.     mov    dx,offset erms34
  1126.     mov    ah,prstr
  1127.     int    dos
  1128.     jmp    rskp
  1129. dopus1: mov    ah,cmcfm
  1130.     call    comnd
  1131.      jmp    r
  1132.     mov    si,offset cmspbuf    ; name of parser
  1133.     push    si            ; save beginning
  1134.     sub    cx,cx            ; initial length
  1135. dopus2: lodsb
  1136.     inc    cx            ; count this
  1137.     or    al,al            ; at end?
  1138.     jnz    dopus2            ; no, keep going
  1139.     pop    si            ; restore cmd
  1140.     dec    cx            ; this is incremented one over
  1141.     jmp    short crun        ; go run it
  1142. dopush    endp
  1143.  
  1144. ; crun - run an arbitrary program.  Enter with si/address of whole
  1145. ; cmd, cx/length of cmd.
  1146. CRUN    proc    near
  1147.     push cx         ; save length of cmd
  1148.     mov ax,ds
  1149.     mov es,ax        ; address dest segment
  1150.     mov di,offset nambuf
  1151.     rep movsb        ; copy command so we can mess with it
  1152.     pop cx
  1153.     mov si,offset nambuf    ; point to command
  1154.     jmp short run3        ; and join run code
  1155. CRUN    ENDP
  1156.  
  1157. RUN    PROC    NEAR
  1158.     cmp dosnum,0
  1159.     jne run1
  1160.     mov ah,prstr
  1161.     mov dx,offset erms34    ; Complain.
  1162.     int dos
  1163.     jmp rskp
  1164. run1:    mov ah,cmtxt        ; Get program name.
  1165.     mov bx,offset nambuf    ; Convenient buffer.
  1166.     mov dx,offset filmsg    ; In case user wants help.
  1167.     call comnd
  1168.      nop
  1169.      nop
  1170.      nop
  1171.     cmp ah,0
  1172.     jne run2
  1173.     mov ah,prstr
  1174.     mov dx,offset erms35
  1175.     int dos
  1176.     jmp rskp
  1177. run2:    mov cl,ah
  1178.     mov ch,0
  1179.     mov si,offset nambuf
  1180.  
  1181. ; alternate entry if cmd is already known.  Source cmd ptr in si
  1182. ; is trashed.
  1183. run3:    mov bx,cx
  1184.     mov byte ptr [si+bx],cr ; end string with a cr for dos.
  1185.     mov di,offset cmdnam
  1186.     mov ax,ds
  1187.     mov es,ax
  1188. run4:    lodsb
  1189.     cmp al,' '
  1190.     jne run5
  1191.     dec si            ; back up over space
  1192.     jmp short run6        ; and exit loop
  1193. run5:    stosb
  1194.     loop run4
  1195. run6:    mov byte ptr [di],0    ; terminate string
  1196.     dec si            ; point back a byte into argument
  1197.     mov [si],cl        ; put length of argument here
  1198.     mov exearg+2,si     ; pointer to argument string
  1199.     mov exearg+4,ds     ; segment of same
  1200.     inc si            ; pass length over
  1201.     mov al,1        ; scan leading separators
  1202.     mov di,offset exefcb    ; parse into this fcb
  1203.     mov ah,prsfcb
  1204.     int dos         ; go parse the fcb
  1205.     mov al,1        ; scan leading separators
  1206.     mov di,offset exefcb2    ; second fcb to fill
  1207.     mov ah,prsfcb
  1208.     int dos         ; parse the fcb
  1209.     mov es,psp        ; point to psp again
  1210.     mov ax,es:[env]     ; get environment ptr
  1211.     mov exearg,ax        ; put into argument block
  1212.     mov bx,offset stk + 15    ; end of pgm
  1213.     mov cl,4
  1214.     shr bx,cl        ; compute # of paragraphs in last segment
  1215.     mov ax,seg stack    ; end of kermit
  1216.     sub ax,psp        ; minus beginning...
  1217.     add bx,ax        ; # of paragraphs occupied
  1218.     mov ah,setblk
  1219.     int dos
  1220.     jc run7         ; nope...
  1221.     mov ax,ds
  1222.     mov es,ax        ; put es segment back
  1223.     mov ax,offset cmdnam    ; point to cmd name again
  1224.     call spath        ; look for it
  1225.     jc run8         ; not found, go complain
  1226.     mov dx,ax        ; point to command name
  1227.     mov al,0        ; load and execute...
  1228.     mov ah,exec
  1229.     mov bx,offset exearg    ; and to arguments
  1230.     mov ssave,sp        ; save stack ptr
  1231.     int dos         ; go run the program
  1232.     mov ax,seg datas
  1233.     mov ds,ax        ; reset data segment
  1234.     mov ax,seg stack
  1235.     mov ss,ax        ; and stack segment
  1236.     mov sp,ssave        ; restore stack ptr
  1237.     mov ah,setdma
  1238.     mov dx,offset buff
  1239.     pushf            ; save flags
  1240.     int dos         ; restore dma address!!
  1241.     popf            ; recover flags
  1242.     jc run8         ; error, handle.
  1243.     jmp rskp        ; ok, return
  1244. run7:    mov ah,prstr
  1245.     mov dx,offset erms36
  1246.     int dos
  1247.     jmp rskp
  1248. run8:    mov ah,prstr
  1249.     mov dx,offset erms37
  1250.     int dos
  1251.     jmp rskp
  1252. RUN    ENDP
  1253.  
  1254. ; the show command
  1255. showcmd proc    near
  1256.     mov    ah,cmkey
  1257.     mov    dx,offset shotab
  1258.     xor    bx,bx            ; no canned help
  1259.     call    comnd
  1260.      jmp    r
  1261.     call    bx            ; call the handler
  1262.      jmp    r
  1263.     jmp    rskp            ; and return
  1264. showcmd endp
  1265.  
  1266. intbrk: cmp flags.debug,1    ; Debug mode?
  1267.     je intb1        ; Yes, then don't ignore the ^C.
  1268.     push ax
  1269.     push ds
  1270.     mov ax,seg datas
  1271.     mov ds,ax
  1272.     mov flags.cxzflg,'C'    ; Say we saw a ^C.
  1273.     mov pack.state,'A'      ; Set the state to abort.
  1274.     pop ds
  1275.     pop ax
  1276.     iret
  1277. intb1:    jmp in3ad        ; Original break interrupt address.
  1278.  
  1279. ; Set the maximum data packet size. [21b]
  1280.  
  1281. PACKLEN PROC    NEAR
  1282.     mov ah,trans.spsiz    ; Maximum send packet size.
  1283.     sub ah,4        ; Size minus control info.
  1284.     sub ah,trans.chklen    ; And minus checksum chars.
  1285.     sub ah,2        ; Leave room at end: 2 for possible #X.
  1286.     cmp trans.ebquot,'N'    ; Doing 8-bit quoting?
  1287.     je pack0        ; Nope so we've got our size.
  1288.     cmp trans.ebquot,'Y'
  1289.     je pack0        ; Not doing it in this case either.
  1290.     sub ah,1        ; Another 1 for 8th-bit quoting.
  1291. pack0:    mov trans.maxdat,ah    ; Save max length for data field.
  1292.     ret
  1293. PACKLEN ENDP
  1294.  
  1295. NOUT2    PROC    NEAR
  1296.     push ax
  1297.     push dx
  1298.     mov temp,10        ; Divide quotient by 10.
  1299.     cwd            ; Convert word to doubleword.
  1300.     div temp        ; AX <-- Quo, DX <-- Rem.
  1301.     cmp ax,0        ; Are we done?
  1302.     jz nout0        ; Yes.
  1303.     call nout2        ; If not, then recurse.
  1304. nout0:    add dl,'0'              ; Make it printable.
  1305.     mov temp,ax
  1306.     mov al,dl
  1307.     stosb
  1308.     mov ax,temp
  1309.     pop dx
  1310.     pop ax
  1311.     ret            ; We're done. [21c]
  1312. NOUT2    ENDP
  1313.  
  1314. NOUT2X    PROC    NEAR
  1315.     push ax
  1316.     push dx
  1317.     push cx
  1318.     mov temp,10        ; Divide quotient by 10.
  1319.     div temp        ; AX <-- Quo, DX <-- Rem.
  1320.     mov cx,dx        ; Remember the remainder.
  1321.     cmp ax,0        ; Are we done?
  1322.     jz nout0x        ; Yes.
  1323.     mov dx,0
  1324.     call nout2        ; If not, then recurse.
  1325. nout0x: add cl,'0'              ; Make it printable.
  1326.     mov temp,ax
  1327.     mov al,cl
  1328.     stosb
  1329.     mov ax,temp
  1330.     pop cx
  1331.     pop dx
  1332.     pop ax
  1333.     ret            ; We're done. [21c]
  1334. NOUT2X    ENDP
  1335.  
  1336. SPATH    proc    near
  1337. ; enter with ax/ ptr to file name.  Searches path for given file,
  1338. ; returns with ax/ ptr to whole name, or carry on if file isn't
  1339. ; to be found.
  1340.     push    es
  1341.     mov    bx,ds
  1342.     mov    es,bx            ; address data segment
  1343.     mov    bx,ax            ; convenient place to keep this
  1344.     mov    si,ax
  1345.     mov    di,offset tfile     ; place to copy to
  1346.     mov    dl,0            ; no '\' seen yet
  1347.     mov    ah,swchar        ; get switch character
  1348. spath1: lodsb
  1349.     stosb
  1350.     cmp    al,ah            ; contain path characters?
  1351.     jne    spath2            ; no, keep going
  1352.     mov    dl,1            ; remember we've seen them
  1353. spath2: or    al,al
  1354.     jnz    spath1            ; copy name in
  1355.     or    dl,dl            ; look at flag
  1356.     jz    spath3            ; no path embedded, keep going
  1357.     pop    es
  1358.     mov    ax,offset tfile     ; else...
  1359.     call    isfile
  1360.     mov    ax,offset tfile     ; point to right thing...
  1361.     ret                ; let isfile decide and return
  1362. ; no path, keep going
  1363. spath3: mov    si,offset pthbuf    ; path definition
  1364.     cmp    byte ptr [si],0     ; empty path?
  1365.     jne    spath4            ; no, keep going
  1366.     mov    ah,gcd            ; get current dir
  1367.     mov    dl,0            ; for default drive
  1368.     mov    si,offset defpth+1    ; place to put it
  1369.     int    dos
  1370.     mov    si,offset defpth    ; point to the path
  1371. spath4: cmp    byte ptr [si],0     ; null, exit loop
  1372.     je    spath9
  1373.     mov    di,offset tfile     ; place to put name
  1374. spath5: lodsb                ; get a byte
  1375.     cmp    al,';'                  ; end of this part?
  1376.     je    spath7            ; yes, break loop
  1377.     cmp    al,0            ; maybe end of string?
  1378.     jne    spath6            ; no, keep going
  1379.     dec    si            ; back up over it
  1380.     jmp    short spath7        ; and break loop
  1381. spath6: stosb                ; else stick in dest string
  1382.     jmp    spath5            ; and continue
  1383. spath7: push    si            ; save this ptr
  1384.     mov    si,bx            ; this is user's file name
  1385.     mov    al,swchar        ; get switch character.
  1386.     cmp    byte ptr [di-1],al    ; does it end with switch char?
  1387.     je    spath8            ; yes, don't put one in
  1388.     stosb                ; else add one
  1389. spath8: lodsb
  1390.     stosb
  1391.     or    al,al
  1392.     jnz    spath8            ; copy rest of name
  1393.     pop    si            ; restore pos in path def
  1394.     mov    ax,offset tfile
  1395.     call    isfile            ; is it a file?
  1396.     jc    spath4            ; no, keep looking
  1397.     mov    ax,offset tfile
  1398.     pop    es
  1399.     ret                ; return success (carry off)
  1400. spath9: pop    es            ; restore this
  1401.     mov    ax,bx            ; not found yet, get original path
  1402.     call    isfile            ; does it exist?
  1403.     ret                ; return whatever isfile says.
  1404. spath    endp
  1405.  
  1406.  
  1407. isfile    proc    near
  1408. ; returns carry off if the file pointed to by ax exists
  1409.     mov    dx,ax            ; copy ptr
  1410.     mov    al,0            ; don't change anything
  1411.     mov    ah,chmod
  1412.     int    dos
  1413.     ret                ; dos sets carry
  1414. isfile    endp
  1415.  
  1416. ; Jumping to this location is like retskp.  It assumes the instruction
  1417. ;   after the call is a jmp addr.
  1418.  
  1419. RSKP    PROC    NEAR
  1420.     pop bp
  1421.     add bp,3
  1422.     push bp
  1423.     ret
  1424.  
  1425. RSKP    ENDP
  1426.  
  1427. ; Jumping here is the same as a ret.
  1428.  
  1429. R    PROC    NEAR
  1430.     ret
  1431. R    ENDP
  1432.  
  1433. code    ends            ; End of code section.
  1434.     end    start
  1435.