home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msvp98b1.lzh / MSNTNI.ORG < prev    next >
Text File  |  1993-05-14  |  19KB  |  721 lines

  1.     NAME    MSNTNI
  2. ; File MSNTNI.ASM
  3. ; Telnet interface to MS-DOS Kermit
  4. ;
  5. ;  Copyright (C) 1985, 1992, Trustees of Columbia University in the 
  6. ;  City of New York.  Permission is granted to any individual or institution
  7. ;  to use this software as long as it is not sold for profit.  This copyright
  8. ;  notice must be retained.  This software may not be included in commercial
  9. ;  products without written permission of Columbia University.
  10. ; Written by Joe R. Doupnik, Utah State University, 
  11. ;  jrd@cc.usu.edu, jrd@usu.Bitnet.
  12. ;
  13. ; Edit history
  14. ; 6 Sept 1991 version 3.11
  15. ; Last edit 28 Jan 1992
  16.     include    mssdef.h
  17.  
  18. getintv    equ    35h        ; DOS get interrupt vector to es:bx
  19. bapicon    equ    0a0h        ; 3Com BAPI, connect to port
  20. bapidisc equ    0a1h        ; 3Com BAPI, disconnect
  21. bapiwrit equ    0a4h        ; 3Com BAPI, write block
  22. bapiread equ    0a5h        ; 3Com BAPI, read block
  23. bapibrk    equ    0a6h        ; 3Com BAPI, send short break
  24. bapistat equ    0a7h        ; 3Com BAPI, read status (# chars to be read)
  25. bapihere equ    0afh        ; 3Com BAPI, presence check
  26. bapieecm equ    0b0h        ; 3Com BAPI, enable/disable ECM char
  27. bapiecm    equ    0b1h        ; 3Com BAPI, trap Enter Command Mode char
  28.  
  29. data    segment public 'kdata'
  30.     extrn    tcptos:word    ; top of stack for TCP code
  31.     extrn    flags:byte, yflags:byte, portval:word, ttyact:byte
  32.     extrn    ftogmod:dword, crt_lins:byte, crt_cols:byte
  33. data    ends
  34.  
  35. _TEXT    SEGMENT  WORD PUBLIC 'CODE'
  36. _TEXT    ENDS
  37. _DATA    SEGMENT  WORD PUBLIC 'DATA'
  38. _DATA    ENDS
  39. CONST    SEGMENT  WORD PUBLIC 'CONST'
  40. CONST    ENDS
  41. _BSS    SEGMENT  WORD PUBLIC 'BSS'
  42. _BSS    ENDS
  43. DGROUP    GROUP    CONST, _BSS, _DATA
  44.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  45.  
  46. _DATA      SEGMENT
  47.     public _kmyip, _knetmask, _kdomain, _kgateway, _kns1, _kns2, _khost
  48.     public _kbcast, _bapibuf, _bapireq, _bapiret, _msgcnt, _msgbuf
  49.     public    _display_mode, _kport, _kpdint, _kserver, _kdebug, _kterm
  50.     public    _ktttype, _kterm_lines, _kterm_cols
  51.  
  52.     extrn    _my_ip_addr:dword, _sin_mask:dword
  53.  
  54.         db 'DUMMY',0           ; null pointer guard
  55. _kmyip        db 33 dup (0)        ; our IP number
  56. _knetmask    db 33 dup (0)        ; our netmask
  57. _kdomain    db 33 dup (0)        ; our domain
  58. _kgateway     db 33 dup (0)        ; our gateway
  59. _kns1        db 33 dup (0)        ; our nameserver #1
  60. _kns2        db 33 dup (0)        ; our nameserver #2
  61. _khost        db 61 dup (0)        ; remote host name/IP #
  62. _kbcast        db 33 dup (0)        ; broadcast IP
  63. _ktttype    db 33 dup (0)        ; terminal-type override string
  64. _kserver    dw    0        ; non-zero for Kermit server
  65. _kport        dw    23        ; TCP port (Telnet = 23)
  66. _kpdint        dw    0        ; Packet Driver Int, 0 = search
  67. _kdebug        dw    0        ; if SET DEBUG ON is effective
  68. _kterm        dw    0        ; terminal type index, see mssdef.h
  69. _kterm_lines    db    0        ; terminal screen height (24)
  70. _kterm_cols    db    0        ; terminal screen width (80)
  71. oldint8    dd    0            ; original Int 8 owner
  72. tcpstack dd    0            ; TCP code stack
  73. stack8    dd    0            ; stack at Int 8 invokation
  74. kstack    dw    0            ; Kermit mainline stack pointer
  75. tempax    dw    0            ; a temp
  76. tcpflag    db    0        ; who is running TCP code: 1=Kermit, 2=Int 8
  77. tcpdata    dw    0            ; Kermit offset of "tcpdata" block
  78. int8cnt    db    0            ; Int 8 times called counter
  79. _display_mode db 0            ; msg, none if == 0
  80. opcode    db    0            ; BAPI op code
  81. userbuf    dd    0            ; BAPI user's comms buffer address
  82. _bapireq dw    0            ; BAPI count of chars requested
  83. _bapiret dw    0            ; BAPI count of chars processed
  84. buflen    equ    512
  85. _bapibuf db    buflen dup (0)        ; BAPI buffer in TCP address space
  86. _msgcnt    dw    0            ; count of bytes in msg buffer
  87. _msgbuf    db    256 dup (0)        ; interrupt level msg buffer
  88. _DATA      ENDS
  89.  
  90.  
  91. _TEXT    segment
  92.     ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
  93.     extrn    _serial_handler:near, _main:near, _exit:near 
  94.     extrn    _pkt_release:near, _tcp_tick:near, _bcopy:near, _itoa:near
  95.     extrn    _strlen:near, _strcpy:near
  96.  
  97. public    _enable
  98. enable    proc    near
  99. _enable    equ    this byte
  100.     sti
  101.     ret
  102. enable    endp
  103.  
  104. public    _disable
  105. disable    proc    near
  106. _disable equ    this byte
  107.     cli
  108.     ret
  109. disable    endp
  110.  
  111. ; Hook Interrupts 8h. Return AX = 1 if successful else 0.
  112.     public    _hookvect
  113. hookvect proc    near
  114. _hookvect equ    this byte
  115.     push    bp
  116.     mov    bp,sp
  117.     mov    ax,bp
  118.     add    ax,2+2            ; C sp just before this call
  119.     mov    word ptr tcpstack,ax    ; save as main prog stack level
  120.     push    es
  121.     mov    ah,getintv        ; get interrupt vector
  122.     mov    al,8            ; vector number
  123.     int    dos
  124.     mov    ax,es
  125.     mov    cx,cs
  126.     cmp    ax,cx            ; points to us now?
  127.     je    hook2            ; e = yes, do not touch
  128.     mov    word ptr DGROUP:oldint8+2,ax    ; save segment
  129.     mov    word ptr DGROUP:oldint8,bx    ; save offset
  130.     mov    dx,offset ourtimer     ; new handler
  131.     push    ds
  132.     mov    ax,cs            ; segment
  133.     mov    ds,ax
  134.     mov    al,8            ; for Int 8
  135.     mov    ah,25H            ; set interrupt address from ds:dx
  136.     int    dos
  137.     pop    ds
  138. hook2:    mov    tcpflag,1     ; say Kermit but not Int 8 is running TCP
  139.     mov    ax,1            ; return 1 for success
  140.     pop    es
  141.     pop    bp
  142.     ret
  143. hook3:    call    unhookvect        ; put any back
  144.     xor    ax,ax            ; return 0 for failure
  145.     pop    es
  146.     pop    bp
  147.     ret
  148. hookvect endp
  149.  
  150.     public    _unhookvect
  151. unhookvect proc    near
  152. _unhookvect equ    this byte
  153.     push    bp
  154.     mov    bp,sp
  155.     push    es
  156.     push    bx
  157.     push    cx
  158.     clc
  159.     mov    tempax,0        ; assume failure status
  160.     mov    ah,getintv        ; get interrupt vector
  161.     clc
  162.     mov    al,8            ; vector number
  163.     int    dos
  164.     jc    unhook2            ; c = failed
  165.     mov    ax,es            ; es:bx is current owner, us?
  166.     mov    cx,cs
  167.     cmp    ax,cx            ; seg should be right here
  168.     jne    unhook2            ; ne = is not
  169.     cmp    bx,offset ourtimer    ; should be the same too
  170.     jne    unhook2            ; ne = is not, let them have the int
  171.     mov    ax,word ptr DGROUP:oldint8+2    ; segment
  172.     mov    dx,word ptr DGROUP:oldint8    ; offset
  173.     mov    cx,dx
  174.     or    cx,ax            ; was it used by us?
  175.     jz    unhook2            ; z = no, leave alone
  176.     push    ds
  177.     mov    ds,ax
  178.     mov    al,8            ; for Int 8
  179.     mov    ah,25H            ; set interrupt address from ds:dx
  180.     int    dos
  181.     pop    ds
  182.     and    tcpflag,not 2        ; Int 8 no longer touches TCP
  183.     mov    word ptr DGROUP:oldint8,0
  184.     mov    word ptr DGROUP:oldint8+2,0
  185.     mov    tempax,1        ; success status
  186.     jmp    short unhook3
  187. unhook2:mov    tempax,0        ; failure
  188. unhook3:mov    ax,tempax        ; return status (1=success, 0=fail)
  189.     pop    cx
  190.     pop    bx
  191.     pop    es
  192.     pop    bp
  193.     ret
  194. unhookvect endp
  195.  
  196. ; Int 8 routine to call the TCP code if Kermit main body does not.
  197. ourtimer proc near
  198.     push    ds
  199.     push    ax
  200.     mov    ax,dgroup        ; set addressibility to our dgroup
  201.     mov    ds,ax
  202.     pushf                ; simulate interrupt invokation
  203.     call    dword ptr DGROUP:oldint8 ; call previous owner of Int 8
  204.  
  205.     mov    ax,DGROUP        ; set addressibility to our dgroup
  206.     mov    ds,ax
  207.     test    tcpflag,1+2        ; is TCP code running now?
  208.     jnz    ourtim2            ; nz = yes, so we don't run now
  209.     mov    al,int8cnt        ; get our times-called counter
  210.     inc    al            ; up once again
  211.     and    al,7            ; keep 3 bits, about .5 sec @18.2tic/s
  212.     mov    int8cnt,al        ; store
  213.     or    al,al            ; is it zero?
  214.     jnz    ourtim2            ; nz = no, go away for awhile
  215.     or    tcpflag,2        ; say we are running the TCP code
  216.     push    bp
  217.     push    bx
  218.     push    cx
  219.     push    dx
  220.     push    si
  221.     push    di
  222.     push    es
  223.     cli
  224.     mov    ax,ss
  225.     mov    word ptr stack8+2,ax    ; save current stack
  226.     mov    word ptr stack8,sp
  227.     mov    ax,word ptr tcpstack+2    ; get TCP stack seg
  228.     mov    ss,ax            ; set to TCP stack
  229.     mov    sp,word ptr tcpstack
  230.     sti                ; restart interrupts
  231.     xor    ax,ax            ; socket pointer, null
  232.     push    ax            ; set call frame for tcp_tick(NULL)
  233.     call    _tcp_tick        ; process some incoming packets
  234.     pop    ax            ; clean call frame
  235.     mov    ax,word ptr stack8+2    ; get original stack seg
  236.     cli
  237.     mov    ss,ax
  238.     mov    sp,word ptr stack8
  239.     sti
  240.     pop    es
  241.     pop    di
  242.     pop    si
  243.     pop    dx
  244.     pop    cx
  245.     pop    bx
  246.     pop    bp
  247.     and    tcpflag,not 2        ; finished our running of TCP code
  248. ourtim2:pop    ax
  249.     pop    ds
  250.     iret
  251. ourtimer endp
  252.  
  253. ; This routine is invoked from outside by a Far call. Enter with the caller's
  254. ; registers but our CS. Switch stacks and data segments.
  255. ; This version supports 3Com BAPI calls and does the near/far stuff via
  256. ; a local buffer.
  257.     public    ktcpcom
  258. ktcpcom     proc    FAR            ; i/o service routine
  259.     assume    ds:DGROUP
  260.     push    ds
  261.     push    ax
  262.     mov    ax,dgroup        ; set addressibility to our dgroup
  263.     mov    ds,ax
  264.     pop    ax
  265.     test    tcpflag,2        ; is Int 8 running TCP?
  266.     jz    ourser8            ; z = no, should never be yes, but...
  267.     mov    ah,1            ; say no char written
  268.     xor    cx,cx            ; chars written
  269.     pop    ds
  270.     ret
  271.  
  272. ourser8:or    tcpflag,1        ; say we are running TCP
  273.     push    es            ; save regs on the user's stack
  274.     push    di
  275.     push    si
  276.     push    dx
  277.     push    bx
  278.     push    bp
  279.     push    ax
  280.     mov    ax,dgroup        ; set addressibility to our dgroup
  281.     mov    ds,ax
  282.     pop    ax
  283.     mov    kstack,sp        ; remember caller's stack now
  284.     mov    sp,word ptr tcpstack    ; move to our TCP stack
  285.     mov    word ptr userbuf,bx    ; remember caller's es:bx
  286.     mov    word ptr userbuf+2,es
  287.     mov    _bapireq,cx        ; requested char count to TCP code
  288.     mov    _bapiret,0        ; init returned CX char count
  289.     mov    opcode,ah        ; remember operation for return proc
  290.     cmp    ah,bapihere        ; presence check?
  291.     jne    ourser6            ; ne = no
  292.     mov    ax,0af01h        ; return this value
  293.     jmp    ourser4            ; done
  294.  
  295. ourser6:
  296.     cmp    ah,bapiwrit        ; BAPI write?
  297.     jne    ourser2            ; ne = no
  298.     push    ax
  299.     push    cx
  300.     push    es
  301.     push    ds
  302.     mov    di,offset DGROUP:_bapibuf ; where it goes
  303.     mov    si,bx            ; es:bx, whence it comes
  304.     mov    bx,es
  305.     mov    ax,ds
  306.     mov    es,ax
  307.     mov    ds,bx
  308.     cld
  309.     cmp    cx,buflen        ; largest block i/o we allow here
  310.     jbe    ourser1            ; be = ok
  311.     mov    cx,buflen        ; truncate the request
  312. ourser1:shr    cx,1
  313.     jnc    ourser1a
  314.     movsb
  315. ourser1a:rep    movsw            ; copy their buffer to ours
  316.     pop    ds
  317.     pop    es
  318.     pop    cx
  319.     pop    ax
  320. ourser2:cmp    ah,bapiread        ; read?
  321.     jne    ourser3            ; ne = no
  322.     cmp    _msgcnt,0        ; any outstanding msgs from TCP?
  323.     je    ourser3            ; e = no msgs
  324.     call    oursmsg            ; send back the msgs instead
  325.     jmp    short ourser4        ; ax has status of ok
  326. ourser3:sti                ; let other ints happen
  327.     mov    bx,dgroup        ; set up es to dgroup too
  328.     mov    es,bx            ; bx is not needed at this time
  329.     xchg    ah,al            ; put function code in al
  330.     xor    ah,ah
  331.     push    ax            ; setup call frame
  332.  
  333.     call    _serial_handler        ; a near call, _serial_handler(ax)
  334.  
  335.     cli                ; reg ax has return status
  336.     add    sp,2            ; clean stack
  337.     mov    cx,dgroup        ; safety check, not really needed
  338.     mov    ds,cx
  339.     mov    cx,_bapiret        ; count of chars returned
  340.     cmp    opcode,bapiread        ; BAPI read?
  341.     jne    ourser4            ; ne = no
  342.     jcxz    ourser4            ; z = nothing to copy
  343.     push    ax
  344.     push    cx
  345.     mov    si,offset DGROUP:_bapibuf ; whence it comes
  346.     mov    di,word ptr userbuf    ; where it goes
  347.     mov    ax,word ptr userbuf+2    ; segment
  348.     mov    es,ax
  349.     cld
  350.     shr    cx,1
  351.     jnc    ourser3a
  352.     movsb
  353. ourser3a:rep    movsw            ; copy our buffer to theirs
  354.     pop    cx            ; return count in cx
  355.     pop    ax            ; return result code in ah, cnt in cx
  356. ourser4:clc                ; assume success
  357.     xchg    ah,al            ; put return status in ah
  358.     xor    al,al
  359.     cmp    ah,3            ; serious error status?
  360.     jb    ourserx            ; b = no, zero is success
  361.     stc                ; set carry too
  362. ourserx:mov    sp,kstack         ; move to caller's stack
  363.     and    tcpflag,not 1        ; say we are not running TCP
  364.     pop    bp
  365.     pop    bx
  366.     pop    dx
  367.     pop    si
  368.     pop    di
  369.     pop    es
  370.     pop    ds
  371.     ret                ; AX and CX are changed as returns
  372. ktcpcom endp
  373.  
  374. ; Copy contents of msgbuf (local Telnet msg collector buffer) to main body.
  375. oursmsg    proc    near
  376.     mov    cx,_msgcnt
  377.     jcxz    ourser3            ; z = no msgs
  378.     cmp    cx,_bapireq        ; longer than request?
  379.     jbe    oursmsg1        ; be = no
  380.     mov    cx,_bapireq        ; do this much now
  381. oursmsg1:push    cx
  382.     mov    si,offset DGROUP:_msgbuf ; whence it comes
  383.     mov    di,word ptr userbuf    ; where it goes
  384.     mov    ax,word ptr userbuf+2    ; segment
  385.     mov    es,ax
  386.     cld
  387.     rep    movsb            ; copy our buffer to theirs
  388.     pop    cx            ; return count in cx
  389.     mov    _bapiret,cx        ; return count to user
  390.     sub    _msgcnt,cx        ; deduct chars relayed
  391.     cmp    _msgcnt,0        ; examine remainder
  392.     je    oursmsg3        ; e = none
  393.     mov    ax,_msgcnt        ; count
  394.     push    ax
  395.     mov    ax,offset DGROUP:_msgbuf
  396.     push    ax            ; destination
  397.     add    ax,_msgcnt        ; source
  398.     push    ax
  399.     call    _bcopy            ; copy to beginning of buffer
  400.     add    sp,6            ; clean stack
  401. oursmsg3:mov    ax,0            ; return status of success
  402.     ret
  403. oursmsg    endp
  404.  
  405.  
  406. ; tcpaddress db    'unknown',(32-($-tcpaddress)) dup (0),0
  407. ; tcpsubnet  db    '255.255.255.0',(32-($-tcpsubnet)) dup (0),0
  408. ; tcpdomain  db    'unknown',(32-($-tcpdomain)) dup (0),0
  409. ; tcpgateway db    'unknown',(32-($-tcpgateway)) dup (0),0
  410. ; tcpprimens db    'unknown',(32-($-tcpprimens)) dup (0),0
  411. ; tcpsecondns db 'unknown',(32-($-tcpsecondns)) dup (0),0
  412. ; tcphost db    (60 -($-tcphost)) dup (0),0
  413. ; tcpbcast db    '255.255.255.255',(32-($-tcpbcast)) dup (0),0
  414. ; tcpport dw    23
  415. ; tcppdint dw    60h
  416. ; tcpdata dw    offset tcpaddress ; externally visible far pointers
  417. ;     dw    offset tcpsubnet
  418. ;     dw    offset tcpdomain
  419. ;     dw    offset tcpgateway
  420. ;     dw    offset tcpprimens
  421. ;     dw    offset tcpsecondns
  422. ;    dw    offset tcphost
  423. ;    dw    offset tcpbcast
  424. ;    dw    offset tcpport
  425. ;    dw    offset tcppdint
  426. ;    dw    offset tcpttbuf
  427.  
  428.     public    ktcpstart
  429. ktcpstart proc    far
  430.     ASSUME    DS:DATA, ES:DGROUP
  431.     push    es            ; save regs on main Kermit stack
  432.     push    ds
  433.     push    di
  434.     push    si
  435.     push    dx
  436.     push    cx
  437.     push    bx
  438.     push    bp
  439.     mov    ax,DGROUP
  440.     mov    es,ax            ; destination is the TCP module
  441.     cld
  442.     mov    tcpdata,bx        ; store offset of Kermit data block
  443.     mov    si,[bx]            ; get offset of our IP address
  444.     mov    di,offset DGROUP:_kmyip    ; our storage slot
  445.     mov    cx,16            ; max bytes
  446. start5:    lodsb
  447.     stosb
  448.     or    al,al
  449.     loopne    start5            ; copy IP address string, asciiz
  450.     xor    al,al            ; extra terminator
  451.     stosb
  452.     mov    si,[bx+2]        ; get offset in Kermit
  453.     mov    di,offset DGROUP:_knetmask
  454.     mov    cx,16
  455. start6:    lodsb
  456.     stosb
  457.     or    al,al
  458.     loopne    start6
  459.     xor    al,al
  460.     stosb
  461.     mov    si,[bx+4]            ; get offset in Kermit
  462.     mov    di,offset DGROUP:_kdomain
  463.     mov    cx,32
  464. start7:    lodsb
  465.     stosb
  466.     or    al,al
  467.     loopne    start7
  468.     xor    al,al
  469.     stosb
  470.     mov    si,[bx+6]            ; get offset in Kermit
  471.     mov    di,offset DGROUP:_kgateway
  472.     mov    cx,32
  473. start8:    lodsb
  474.     stosb
  475.     or    al,al
  476.     loopne    start8
  477.     xor    al,al
  478.     stosb
  479.     mov    si,[bx+8]            ; get offset in Kermit
  480.     mov    di,offset DGROUP:_kns1
  481.     mov    cx,32
  482. start9:    lodsb
  483.     stosb
  484.     or    al,al
  485.     loopne    start9
  486.     xor    al,al
  487.     stosb
  488.     mov    si,[bx+10]            ; get offset in Kermit
  489.     mov    di,offset DGROUP:_kns2
  490.     mov    cx,32
  491. start10:lodsb
  492.     stosb
  493.     or    al,al
  494.     loopne    start10
  495.     xor    al,al
  496.     stosb
  497.     mov    si,[bx+12]            ; get offset in Kermit
  498.     mov    di,offset DGROUP:_khost
  499.     mov    cx,60
  500. start11:lodsb
  501.     stosb
  502.     or    al,al
  503.     loopne    start11
  504.     xor    al,al
  505.     stosb
  506.     mov    si,[bx+14]            ; broadcast address
  507.     mov    di,offset DGROUP:_kbcast
  508.     mov    cx,32
  509. start12:lodsb
  510.     stosb
  511.     or    al,al
  512.     loopne    start12
  513.     xor    al,al
  514.     stosb
  515.     mov    si,[bx+16]        ; TCP port
  516.     mov    ax,[si]
  517.     mov    es:_kport,ax
  518.     mov    si,[bx+18]        ; Packet Driver Interrupt
  519.     mov    ax,[si]
  520.     mov    es:_kpdint,ax        ; 0 means scan
  521.     mov    si,[bx+20]        ; offset of term-type string
  522.     mov    di,offset DGROUP:_ktttype ; local storage of the string
  523.     mov    cx,32
  524. start13:lodsb
  525.     stosb
  526.     or    al,al
  527.     loopne    start13
  528.     xor    al,al
  529.     stosb
  530.  
  531.     mov    es:_display_mode,0    ; presume quiet screen
  532.     test    flags.remflg,dquiet    ; quiet display mode?
  533.     jnz    start14            ; nz = yes. Don't write to screen
  534.     inc    es:_display_mode    ; say can write to screen
  535. start14:mov    es:_kserver,0        ; assume not a server
  536.     test    flags.remflg,dserver    ; Server mode?
  537.     jz    start15            ; z = no
  538.     mov    es:_kserver,1        ; say being a server (do Listen)
  539. start15:mov    es:_kdebug,0        ; assume no debug mode
  540.     test    flags.debug,0ffh    ; debugging active?
  541.     jz    start16            ; z = no
  542.     inc    es:_kdebug        ; turn on debugging here
  543. start16:mov    ax,flags.vtflg        ; get terminal type index
  544.     mov    es:_kterm,ax
  545.     mov    al,crt_lins        ; get display height
  546.     mov    es:_kterm_lines,al
  547.     mov    al,crt_cols        ; get display width
  548.     mov    es:_kterm_cols,al
  549.  
  550. start20:mov    bx,tcptos        ; top of stack for tcp code
  551.  
  552.     assume    ds:DGROUP, ES:NOTHING
  553.     
  554.     mov    ax,dgroup        ; set addressibility to our dgroup
  555.     mov    ds,ax
  556.     mov    es,ax
  557.     mov    word ptr tcpstack+2,ax    ; set TCP stack seg
  558.     mov    word ptr kstack,sp    ; store Kermit's stack ptr
  559.     mov    sp,bx            ; new TCP stack pointer, DGROUP based
  560.     mov    bp,sp            ; preset this as insurance
  561.     or    tcpflag,1        ; say this is running TCP code
  562.     call    _main            ; call the C code
  563.     and    tcpflag,not 1        ; finished running tcp code
  564.     mov    sp,word ptr kstack    ; restore for Kermit's main stack
  565.     mov    bx,data            ; main Kermit data segment
  566.     mov    es,bx
  567.     mov    bx,tcpdata        ; pointer to storage word
  568.     mov    cx,_kpdint        ; report back Packet Driver Int
  569.     mov    bx,es:[bx+18]        ; get address of storage slot
  570.     mov    es:[bx],cx        ; store value in main data seg
  571.     pop    bp            ; restore regs, Kermit's main stack
  572.     pop    bx
  573.     pop    cx
  574.     pop    dx
  575.     pop    si
  576.     pop    di
  577.     pop    ds
  578.     pop    es
  579.     ret                ; return to caller
  580. ktcpstart endp
  581.  
  582.     public    ktcpstop
  583. ktcpstop proc    far
  584.     assume    ds:dgroup, es:nothing
  585.     push    es            ; save regs on the user's stack
  586.     push    ds
  587.     push    di
  588.     push    si
  589.     push    dx
  590.     push    cx
  591.     push    bx
  592.     push    bp
  593.     mov    ax,dgroup        ; set addressibility to our dgroup
  594.     mov    ds,ax
  595.     mov    kstack,sp        ; remember Kermit's main sp
  596.     or    tcpflag,1        ; say we are running TCP code
  597.     mov    ax,word ptr tcpstack    ; set sp to TCP sp
  598.     mov    sp,ax
  599.     mov    bp,sp            ; preset this as insurance
  600.     push    ds
  601.     pop    es
  602.     xor    ax,ax
  603.     push    ax            ; exit(0) setup
  604.     call    _exit
  605.     add    sp,2            ; returns status in AX
  606.     mov    tempax,ax
  607.     mov    ax,word ptr tcpstack    ; set sp to TCP sp again
  608.     mov    sp,ax
  609.     mov    bp,sp            ; preset this as insurance
  610.     call    _pkt_release        ; do this as insurance
  611.     mov    ax,tempax        ; regain status
  612.     push    ax
  613.     call    unhookvect        ; ditto
  614.     pop    ax
  615.     mov    tcpflag,0        ; no one is running the TCP code
  616.     mov    sp,kstack
  617.     pop    bp            ; restore regs, Kermit's main stack
  618.     pop    bx
  619.     pop    cx
  620.     pop    dx
  621.     pop    si
  622.     pop    di
  623.     pop    ds
  624.     pop    es
  625.     ret                ; return to caller
  626. ktcpstop endp
  627.  
  628.     public    _readback
  629. _readback proc    near
  630.     assume    ds:dgroup, es:dgroup
  631.     push    bp
  632.     mov    bp,sp
  633.     push    si
  634.     push    di
  635.     push    es
  636.     mov    ax,data
  637.     mov    es,ax
  638.     mov    si,offset dgroup:_kmyip
  639.     push    si
  640.     push    si
  641.     call    _strlen                ; get length of string
  642.     add    sp,2
  643.     pop    si
  644.     mov    di,tcpdata            ; copy to Kermit main body
  645.     mov    di,es:[di]            ; offset of the string
  646.     mov    cx,ax
  647.     cld
  648.     rep    movsb
  649.     xor    al,al
  650.     stosb                    ; terminator
  651.     mov    si,offset dgroup:_knetmask
  652.     mov    di,tcpdata
  653.     mov    di,es:[di+2]
  654.     mov    cx,17
  655.     rep    movsb
  656.     stosb                    ; terminator
  657.     mov    si,offset dgroup:_kgateway
  658.     mov    di,tcpdata
  659.     mov    di,es:[di+6]
  660.     mov    cx,17
  661.     rep    movsb
  662.     stosb                    ; terminator
  663.     mov    si,offset dgroup:_kns1
  664.     mov    di,tcpdata
  665.     mov    di,es:[di+8]
  666.     mov    cx,17
  667.     rep    movsb
  668.     stosb                    ; terminator
  669.     mov    si,offset dgroup:_kns2
  670.     mov    di,tcpdata
  671.     mov    di,es:[di+10]
  672.     mov    cx,17
  673.     rep    movsb
  674.     stosb                    ; terminator
  675.     pop    es
  676.     pop    si
  677.     pop    di
  678.     pop    bp
  679.     ret
  680. _readback endp
  681.  
  682. ; Track Telnet echo variable (0 do not do local echo) into terminal emulator
  683. ; and Kermit main body. Call this each time Telnet options change echo.
  684.     public    _kecho
  685. _kecho    proc    near
  686.     assume    ds:data, es:dgroup
  687.     push    bp
  688.     mov    bp,sp
  689.     push    ds
  690.     push    es
  691.     push    si
  692.     push    ax
  693.     mov    ax,data            ; Kermit main data segment
  694.     mov    ds,ax
  695.     mov    ax,dgroup
  696.     mov    es,ax
  697.     mov    ax,[bp+4+0]        ; get Telnet _echo variable
  698.     and    yflags,not lclecho    ; assume no local echo in emulator
  699.     or    al,al            ; Telnet local echo is off?
  700.     jz    kecho1            ; z = yes
  701.     mov    al,lclecho        ; lclecho flag for emulator
  702. kecho1:    or    yflags,al        ; set terminal emulator
  703.     mov    si,portval
  704.     mov    [si].ecoflg,al        ; set mainline SET echo flag
  705.     cmp    ttyact,0        ; acting as a Terminal?
  706.     je    kecho2            ; e = no
  707.     call    dword ptr ftogmod    ; toggle mode line
  708.     call    dword ptr ftogmod    ; and again
  709. kecho2:    pop    ax
  710.     pop    si
  711.     pop    es
  712.     pop    ds
  713.     pop    bp
  714.     ret
  715. _kecho    endp
  716. _TEXT    ends
  717.         end
  718.  
  719.