home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / extra / nyenhuis3.arc / MSSSER.ASM < prev    next >
Assembly Source File  |  1990-01-16  |  65KB  |  2,136 lines

  1.     NAME    mssser
  2. ; File MSSSER.ASM
  3.     include mssdef.h
  4. ; Edit history:
  5. ; Last edit 16 Jan 1990
  6.  
  7.     public    logout, bye, finish, remote, get, server, denyflg, srvtmo
  8.     public    luser, lpass
  9.  
  10. data    segment    public 'data'
  11.     extrn    flags:byte, trans:byte, curdsk:byte, diskio:byte, auxfile:byte
  12.     extrn    comand:byte, filtst:byte, maxtry:byte, dtrans:byte
  13.     extrn    fmtdsp:byte, errlev:byte, fsta:word, kstatus:word
  14.     extrn    rpacket:byte, encbuf:byte, decbuf:byte, sstate:byte
  15.     extrn    rstate:byte, pktnum:byte, windlow:byte, takadr:word
  16.     extrn    taklev:byte, prmptr:word
  17.  
  18. scrser    equ    0209H        ; place for server state display line
  19. scrmsg    equ    0C16H        ; place for Last message
  20.  
  21. remcmd    db    0        ; Remote command to be executed
  22. rempac    db    0        ; Packet type: C (host) or G (generic)
  23. remlen    db    0        ; length of following text field
  24.  
  25. ermes6    db    'Filename too long for packet',0
  26. cemsg    db    'User intervention',0
  27. infms1    db    'Server mode: type Control-C to exit',cr,lf,'$'
  28. infms2    db    cr,lf,'?More parameters are needed$'
  29. infms3    db    'REMOTE command reply',0    ; for transaction logging
  30. infms4    db    'Help text',0            ; filename for REM Help reply
  31. inthlp    db    cr,lf,' Time-limit to remain in Server mode, seconds or'
  32.     db    ' specific hh:mm:ss (24h clock).'
  33.     db    cr,lf,' SET TIMER ON to time.  Return for no time limit.$'
  34. remms1    db    ' Unknown server command',0
  35. remms2    db    ' Invalid login information',0
  36. remms3    db    ' Kermit-MS Server ready',0
  37. remms5    db    ' File not found',0
  38. remms6    db    ' Command failed',0
  39. remms7    db    ' REMOTE LOGIN is required',0
  40. remms8    db    ' Command succeeded',0
  41. remms9    db    ' Command is Disabled',0
  42. remms10    db    ' Could not create work file',0
  43. byemsg    db    ' Goodbye!',0
  44. whomsg    db    ' Just this Server',0
  45. spcmsg    db    ' bytes available on drive '    ; remote space responses
  46. spcmsg1    db    ' ',0
  47. spcmsg2    db    ' Drive '
  48. spcmsg3    db    ' : is not ready',0
  49. user    db    ' Username: ',0        ; for Remote Login, asciiz
  50. password db    ' Password: ',0        ; for Remote Login and Remote CD
  51. account    db    ' Account: ',0        ; for Remote Login
  52. slogin    db    0            ; non-zero if successful local login
  53. luser    db    17 dup (0)        ; local Username, case insenstitive
  54. lpass    db    17 dup (0)        ; local Password, case sensitive
  55. srvtmp    db    ' > :$kermit$.tmp',0    ; asciiz, kermit's temp output file
  56. delstr    db    'del ',0
  57. dirstr    db    'dir ',0
  58. crlf    db    cr,lf,'$'
  59. skertmp    dw    0            ; REMOTE KERMIT work word
  60. denyflg    dw    0            ; bit field of denied commands
  61. temp    dw    0
  62. temp2    dw    0
  63. cnt    dw    0
  64. bufptr    dw    0
  65. dsptmp    db    0            ; temp to hold fmtdsp during serving
  66. srvtmo    db    0            ; idle NAK time, default is no NAKs
  67. srvtime    db    0            ; non-zero if timing Server residence
  68. remfnm    db    ' Remote Source File: ',0    ; asciiz
  69. lclfnm    db    ' Local Destination File: ',0    ; asciiz
  70. filhlp    db    ' File name to use locally$'
  71. filmsg    db    ' Remote filename, or press ENTER for prompts$'
  72. frem    db    ' Name of file on remote system $'
  73. genmsg    db    ' Enter text to be sent to remote server $'
  74. numhlp    db    ' number$'
  75. xfrhlp    db    ' character set identifier string$'
  76. rdbuf    db    20 dup (0)
  77. srvbuf    db    80 dup (0)        ; place After rdbuf, for status
  78.  
  79. savflg    flginfo    <>            ; save area for flags.*
  80. savflgl    equ    $-savflg        ; length
  81. savdtr    trinfo <>            ; save area for dtrans.*
  82. savdtrl equ    $-savdtr        ; length
  83. savtr    trinfo    <>            ; save area for trans.*
  84. savmaxtry db    0            ; save area for maxtry
  85.  
  86. srvchr    db    'SRGIECK'        ; server cmd characters, use w/srvfun
  87. srvfln    equ    $-srvchr        ; length of table
  88.  
  89. srvfun    dw    srvsnd,srvrcv,srvgen,srvini,srverr,srvhos,srvker ; for srvchr
  90.  
  91. remhlp    db    cr,lf,'CD/CWD     change working directory'    ; Answer to
  92.     db    cr,lf,'Delete     a file'            ; local
  93.     db    cr,lf,'Directory  filespec'            ; REM HELP
  94.     db    cr,lf,'Help'
  95.     db    cr,lf,'Host       command'
  96.     db    cr,lf,'Kermit     command'
  97.     db    cr,lf,'Login      name password  to a Kermit server'
  98.     db    cr,lf,'Message    short one line message'
  99.     db    cr,lf,'Set        command'
  100.     db    cr,lf,'Space      drive/directory'
  101.     db    cr,lf,'Type       a file'
  102.     db    cr,lf,'Who        user spec$'
  103.  
  104.                     ; Answer from Server to REMOTE HELP
  105. hlprem    db    cr,lf,'Kermit-MS Server commands:',lf
  106.     db    cr,lf,'GET  filespec            '
  107.     db    'REMOTE DIRECTORY filespec  '
  108.     db    'REMOTE MESSAGE 1-line msg'
  109.     db    cr,lf,'SEND filespec            '
  110.     db    'REMOTE HELP  this text     '
  111.     db    'REMOTE SET command'
  112.     db    cr,lf,'FINISH, LOGOUT, BYE      '
  113.     db    'REMOTE HOST command        '
  114.     db    'REMOTE SPACE drive-letter'
  115.     db    cr,lf,'REMOTE CD/CWD directory  '
  116.     db    'REMOTE KERMIT SET command  '
  117.     db    'REMOTE TYPE filespec'
  118.     db    cr,lf,'REMOTE DELETE filespec   '
  119.     db    'REMOTE LOGIN name password '
  120.     db    'REMOTE WHO'
  121.     db    0
  122.  
  123. remtab    db    13            ; 13 entries
  124.     mkeyw    'CD',remcwd
  125.     mkeyw    'CWD',remcwd
  126.     mkeyw    'Delete',remdel
  127.     mkeyw    'Directory',remdir
  128.     mkeyw    'Help',remhel
  129.     mkeyw    'Host',remhos
  130.     mkeyw    'Kermit',remker
  131.     mkeyw    'Login',remlogin
  132.     mkeyw    'Message',remmsg
  133.     mkeyw    'Set',remset
  134.     mkeyw    'Space',remdis
  135.     mkeyw    'Type',remtyp
  136.     mkeyw    'Who',remwho
  137.  
  138. setval    dw    300,302,310            ; answer REMOTE SET workers
  139.     dw    400,401,402,403,404,405,406
  140. setvlen    equ    ($-setval)/2            ; number of entries
  141. setvec    dw    sftype,sfcoll,sfinc        ; routines paralleling setval
  142.     dw    sblkck,srpkt,srtmo,sretry,sstmo,sxfrch,swind
  143.  
  144. remstt1    db    9            ; REMOTE SET top level table
  145.     mkeyw    'Attributes',1
  146.     mkeyw    'File',2
  147.     mkeyw    'Incomplete',310
  148.     mkeyw    'Block-check',400
  149.     mkeyw    'Receive',3
  150.     mkeyw    'Retry',403
  151.     mkeyw    'Server',404
  152.     mkeyw    'Transfer',405
  153.     mkeyw    'Window-slots',406
  154.  
  155. remsat1    db    2            ; REMOTE SET ATTRIBUTES
  156.     mkeyw    'IN',0
  157.     mkeyw    'OUT',100
  158.  
  159. remsat2    db    17            ; REMOTE ATTRIBUTES {IN} item
  160.                     ; REM ATT {OUT} item is 100 greater
  161.     mkeyw    'All',132
  162.     mkeyw    'Length',133
  163.     mkeyw    'Type',134
  164.     mkeyw    'Date',135
  165.     mkeyw    'Creator',136
  166.     mkeyw    'Account',137
  167.     mkeyw    'Area',138
  168.     mkeyw    'Block-size',139
  169.     mkeyw    'Access',140
  170.     mkeyw    'Encoding',141
  171.     mkeyw    'Disposition',142
  172.     mkeyw    'Protection',143
  173.     mkeyw    'Gprotection',144
  174.     mkeyw    'System-ID',145
  175.     mkeyw    'Format',146
  176.     mkeyw    'Sys-Info',147
  177.     mkeyw    'Byte-count',148
  178.  
  179. remsfit    db    5            ; REMOTE SET FILE
  180.     mkeyw    'Type',300
  181.     mkeyw    'Names',301
  182.     mkeyw    'Collision',302
  183.     mkeyw    'Replace',303
  184.     mkeyw    'Incomplete',310
  185.  
  186. remsfty    db    2            ; REMOTE SET FILE TYPE
  187.     mkeyw    'Text',0
  188.     mkeyw    'Binary',1
  189.  
  190. remsfna    db    2            ; REMOTE SET FILE NAME
  191.     mkeyw    'Converted',0
  192.     mkeyw    'Literal',1
  193.  
  194. remsfco    db    6            ; REMOTE SET FILE COLLISION
  195.     mkeyw    'Rename',0
  196.     mkeyw    'Replace',1
  197.     mkeyw    'Backup',2
  198.     mkeyw    'Append',3
  199.     mkeyw    'Discard',4
  200.     mkeyw    'Ask',5
  201.  
  202. remsfre    db    2            ; REMOTE SET FILE REPLACE
  203.     mkeyw    'Preserve',0
  204.     mkeyw    'Default',1
  205.  
  206. remsfin    db    2            ; REMOTE SET FILE INCOMPLETE
  207.     mkeyw    'Discard',0
  208.     mkeyw    'Keep',1
  209.  
  210. remsrcv    db    2            ; REMOTE SET RECEIVE
  211.     mkeyw    'Packet-length',401
  212.     mkeyw    'Timeout',402
  213.  
  214. remsxfr    db    1            ; REMOTE SET TRANSFER
  215.     mkeyw    'Character-set',405
  216.  
  217.  
  218. onoff    db    2            ; ON, OFF table
  219.     mkeyw    'off',0
  220.     mkeyw    'on',1
  221.  
  222. data    ends
  223.  
  224. code    segment    public 'code'
  225.     extrn comnd:near,  rpack:near, init:near, serini:near, rrinit:near
  226.     extrn read2:near, rpar:near, spar:near, intmsg:near, sparmax:near
  227.     extrn serhng:near, bufclr:near, bufrel:near, clrbuf:near, clearl:near
  228.     extrn dodec: near, doenc:near, packlen:near, send10:near, errpack:near
  229.     extrn pktsize:near, poscur:near, lnout:near, clrmod:near, ermsg:near
  230.     extrn rprpos:near, crun:near, prompt:near,  prtscr:near, strcat:near
  231.     extrn strlen:near, strcpy:near, fparse:near, isfile:near, ihostr:near
  232.     extrn begtim:near, inptim:near, chktmo:near, pcwait:near, makebuf:near
  233.     extrn getbuf:near, nakpak:near, sndpak:near, response:near
  234.     extrn msgmsg:near, ackpak:near, dskspace:near, cdsr:near, dec2di:near
  235.     extrn takopen:near, takclos:near, setcom:near
  236.  
  237.     assume    cs:code, ds:data, es:nothing
  238.  
  239. ; Server command
  240.  
  241. SERVER    PROC    NEAR
  242.     mov    ah,cmword        ; get a word 
  243.     mov    dx,offset srvbuf    ; place to put text
  244.     mov    bx,offset inthlp    ; help message
  245.     call    comnd            ; get the pattern text
  246.     jnc    serv1a            ; nc = success
  247.     ret                ; failure
  248. serv1a:    mov    ah,cmeol
  249.     call    comnd
  250.     jnc    serv1b            ; nc = success
  251.     ret
  252. serv1b:    mov    srvtime,0        ; assume not doing timed residence
  253.     mov    si,offset srvbuf
  254.     cmp    byte ptr [si],0        ; any time given?
  255.     je    serv4            ; e = no
  256.     cmp    byte ptr [si],'0'    ; numeric or colon?
  257.     jb    serv2            ; b = not proper time value
  258.     cmp    byte ptr [si],':'    ; this covers the desired range
  259.     ja    serv2            ; a = no proper time value
  260.     call    inptim            ; convert text to timeout tod
  261.     jnc    serv3            ; c = syntax errors in time
  262. serv2:    stc                ; failure
  263.     ret
  264.  
  265. serv3:    mov    srvtime,1        ; say doing timed residence
  266. serv4:    or    flags.remflg,dserver    ; signify we are a server now
  267.     call    clrbuf            ; clear serial port buffer of junk
  268.     test    denyflg,pasflg        ; Login required?
  269.     jnz    serv4a            ; nz = no
  270.     or    denyflg,pasflg        ; assume no login info required
  271.     mov    al,luser        ; check for user/password required
  272.     or    al,lpass        ; if both null then no checks
  273.     jz    serv4a            ; z = null, no name/pass required
  274.     and    denyflg,not pasflg    ; say need name/password
  275. serv4a:    mov    dsptmp,0        ; assume no formatted server display
  276.     mov    si,offset flags        ; main flags structure
  277.     mov    di,offset savflg    ; save area
  278.     mov    cx,savflgl        ; length in bytes
  279.     push    es
  280.     push    ds
  281.     pop    es
  282.     cld
  283.     rep    movsb            ; save all of them
  284.     mov    si,offset dtrans    ; default transmission parameters
  285.     mov    di,offset savdtr    ; save area
  286.     mov    cx,savdtrl        ; length
  287.     rep    movsb            ; save all of them
  288.     mov    si,offset trans        ; active transmission paramters
  289.     mov    di,offset savtr        ; save area
  290.     mov    cx,savdtrl        ; same length
  291.     rep    movsb
  292.     mov    al,maxtry
  293.     mov    savmaxtry,al
  294.     pop    es
  295.     test    flags.remflg,dquiet    ; quiet display?
  296.     jnz    serv9            ; nz = yes
  297.     mov    ah,prstr
  298.     mov    dx,offset crlf
  299.     int    dos
  300.     test    flags.remflg,dserial     ; serial display?
  301.     jnz    serv5            ; nz = yes
  302.     call    init            ; init formatted display
  303.     call    clrmod            ; but no modeline yet
  304.     mov    dl,fmtdsp
  305.     mov    dsptmp,dl        ; remember state of fmtdsp
  306.     mov    dx,scrser        ; move cursor near top of screen
  307.     call    poscur
  308. serv5:    mov    ah,prstr
  309.     mov    dx,offset infms1    ; say now in server mode
  310.     int    dos
  311.  
  312.                     ; TOP OF SERVER IDLE LOOP
  313. serv9:    test    flags.remflg,dquiet+dserial ; quiet or serial display?
  314.     jnz    serv10            ; nz = yes, do not change screen
  315.     mov    dx,scrmsg        ; move cursor to Last message area
  316.     add    dx,0100H    ; look at line below (DOS does CR/LF first)
  317.     call    poscur
  318.     call    clearl            ; and clear the line
  319.     mov    dl,cr            ; set cursor to left margin
  320.     mov    ah,conout
  321.     int    dos
  322. serv10:    mov    flags.cxzflg,0        ; clear ^X, ^Z, ^C seen flag
  323.     mov    flags.xflg,0        ; reset X packet flag
  324.     mov    auxfile,0        ; say no override filename
  325.     mov    srvbuf,0        ; work buffer, clear
  326.     mov    al,dsptmp        ; get our fmtdsp state
  327.     mov    fmtdsp,al        ; and restore it
  328.     call    sparmax            ; set our maximum capabilities
  329.     mov    trans.windo,1        ; but only 1 window slot here
  330.     call    makebuf            ; remake all buffers for new windowing
  331.     call    packlen            ; determine max packet length
  332.     mov    trans.chklen,1        ; checksum len = 1
  333.     mov    pktnum,0        ; pack number resets to 0
  334.     mov    al,dtrans.xchset    ; reset Transmission char set
  335.     mov    trans.xchset,al        ;  to the current user default
  336.     mov    al,dtrans.xtype        ; ditto for File Type
  337.     mov    trans.xtype,al
  338.     mov    al,srvtmo        ; use server mode timeout
  339.     mov    trans.stime,al        ; use this interval in the idle loop
  340.     call    serini            ; init serial line, just in case
  341.     jnc    serv11            ; nc = success
  342.     jmp    serv20            ; c = failure
  343. serv11:    cmp    srvtime,0        ; doing timed residence?
  344.     je    serv12            ; e = no
  345.     call    chktmo            ; check for time to exit Server mode
  346.     jnc    serv12            ; nc = ok
  347.     jmp    serv20            ; c = timeout, exit server mode
  348.  
  349. serv12:    mov    windlow,0        ; reset windowing
  350.     mov    pktnum,0        ; packet number to be used
  351.     call    getbuf            ; get a buffer
  352.     call    rpack            ; receive a packet, si has buffer ptr
  353.     mov    al,dtrans.stime        ; get default timeout interval
  354.     mov    trans.stime,al        ; restore active timeout interval
  355.     jc    serv13            ; c = timeout, bad pkt, intervention
  356.     mov    al,[si].seqnum        ; sequence number received
  357.     mov    rpacket.seqnum,al    ; for our reply
  358.     or    al,al            ; must be sequence number of zero
  359.     jnz    serv13            ; nz = bad packet
  360.     mov    ah,[si].pktype
  361.     cmp    ah,'I'            ; never "decode" S, I, and A packets
  362.     je    serv17            ; e = I packet
  363.     cmp    ah,'S'
  364.     je    serv17
  365.     cmp    ah,'A'
  366.     je    serv17
  367.     call     dodec            ; decode packet to decbuf
  368.     call    bufrel            ; release the packet buffer
  369.     jmp    short serv17        ; dispatch on packet type in ah
  370.  
  371. serv13:    cmp    flags.cxzflg,'C'     ; Control-C?
  372.     jne    serv14            ; ne = no
  373.     mov    flags.cxzflg,0        ; clear flag for later uses
  374.     jmp    short serv20        ; and exit server mode
  375.  
  376. serv14:    cmp    flags.cxzflg,'E'    ; ^E protocol abort?
  377.     jne    serv15            ; ne = no
  378.     call    bufclr            ; clear all buffers
  379.     mov    dx,offset cemsg    ; user intervention message for error packet
  380.     call    ermsg
  381.     mov    bx,dx
  382.     call    errpack            ; send error message
  383.     call    intmsg            ; show interrupt msg for Control-C-E
  384.     jmp    serv9
  385.  
  386. serv15:    cmp    [si].pktype,'T'        ; packet type of time-out?
  387.     jne    serv16            ; ne = no
  388.     mov    rpacket.seqnum,0
  389.     call    nakpak            ; nak the packet, uses rpacket
  390. serv16:    call    bufrel            ; release the buffer
  391.     jmp    serv9            ; return to top of server idle loop
  392.  
  393. serv17:    cmp    [si].pktype,'N'        ; received a Nak?
  394.     je    serv18            ; e = yes, ignore it
  395.     push    es
  396.     push    ds
  397.     pop    es            ; set es to data segment
  398.     mov    di,offset srvchr    ; server characters
  399.     mov    cx,srvfln        ; length of command set
  400.     mov    al,ah            ; packet type
  401.     cld
  402.     repne    scasb            ; hunt for it
  403.     pop    es
  404.     je    serv19            ; e = found that kind
  405.     mov    dx,offset remms1    ; say unknown server command
  406.     call    ermsg
  407.     mov    bx,dx
  408.     call    errpack            ; tell the other kermit
  409. serv18:    jmp    serv9            ; get another server command
  410. serv19:    sub    di,offset srvchr+1    ; find offset, +1 for pre-increment
  411.     shl    di,1            ; convert to word index
  412.     call    srvfun[di]        ; call the appropriate handler
  413.     jc    serv20            ; c = someone wanted to exit
  414.     jmp    serv9            ; get another server command
  415.  
  416. serv20:    mov    di,offset flags        ; main flags structure
  417.     mov    si,offset savflg    ; save area
  418.     mov    cx,savflgl        ; length in bytes
  419.     push    es
  420.     push    ds
  421.     pop    es
  422.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  423.     cld
  424.     rep    movsb            ; restore all of them
  425.     mov    di,offset dtrans    ; default transmission parameters
  426.     mov    si,offset savdtr    ; save area
  427.     mov    cx,savdtrl        ; length
  428.     rep    movsb            ; restore all of them
  429.     mov    di,offset trans        ; active transmission paramters
  430.     mov    si,offset savtr        ; save area
  431.     mov    cx,savdtrl        ; same length
  432.     rep    movsb
  433.     mov    flags.extflg,al        ; set flag as current
  434.     mov    al,savmaxtry
  435.     mov    maxtry,al
  436.     pop    es
  437.     call    rprpos            ; put prompt here
  438.     and    flags.remflg,not dserver ; say not a server anymore
  439.     mov    flags.cxzflg,0
  440.     clc
  441.     ret
  442. SERVER    ENDP
  443.  
  444. ; commands executable while acting as a server
  445.  
  446. ; Validate LOGIN status. Return carry set if login is ok, else
  447. ; send Error Packet saying Login is required (but has not been done) and
  448. ; return carry clear. Carry bit is this way because returning to the server
  449. ; idle loop with carry set exits the server mode.
  450. logchk    proc    near
  451.     test    denyflg,pasflg        ; login required?
  452.     jnz    logchk1            ; nz = no (disabled)
  453.     cmp    slogin,0        ; logged in yet?
  454.     jne    logchk1            ; ne = yes
  455.     mov    dx,offset remms7    ; reply REMOTE LOGIN is required
  456.     call    ermsg
  457.     mov    bx,dx            ; errpack works from bx
  458.     mov    trans.chklen,1        ; reply with 1 char checksum
  459.     call    errpack
  460.     clc                ; say cannot proceed with command
  461.     ret
  462. logchk1:stc                ; say can proceed with command
  463.     ret
  464. logchk    endp
  465.  
  466. ; srvsnd - receives a file that a remote kermit is sending
  467. srvsnd    proc    near
  468.     call    logchk            ; check login status
  469.     jc    srvsnd1            ; c = ok
  470.     ret                ; else have sent error packet
  471. srvsnd1:call    init            ; setup display form
  472.     xor    ax,ax
  473.     test    denyflg,sndflg        ; command disabled?
  474.     jz    srvsnd2            ; z = no
  475.     mov    al,'.'            ; dot+nul forces use of current dir
  476. srvsnd2:mov    word ptr auxfile,ax    ; override name
  477.     mov    rstate,'R'        ; receive initiate state
  478.     jmp    read2            ; packet pointer is SI, still valid
  479. srvsnd    endp
  480.  
  481. ; srvrcv - send a file to a distant kermit
  482.  
  483. srvrcv    proc    near
  484.     call    logchk            ; check login status
  485.     jc    srrcv1            ; c = ok
  486.     ret                ; else have sent error packet
  487. srrcv1:    mov    si,offset decbuf    ; received filename, asciiz from dodec
  488.     test    denyflg,getsflg        ; command enabled?
  489.     jz    srrcv2            ; z = yes
  490.     mov    dx,si            ; source string, from other side
  491.     mov    di,offset srvbuf    ; local path
  492.     mov    si,offset rdbuf        ; local filename
  493.     call    fparse            ; split string
  494. srrcv2:    mov    di,offset diskio.string    ; destination
  495.     call    strcpy            ; copy filename to diskio.string
  496.     mov    auxfile,0        ; no alias name
  497.     mov    sstate,'S'        ; set sending state
  498.     jmp    send10            ; this should send it
  499. srvrcv    endp
  500.  
  501. srverr    proc    near            ; incoming Error packet
  502.     clc                ; absorb and ignore
  503.     ret
  504. srverr    endp
  505.  
  506. ; srvgen - G generic server command dispatcher
  507. ;
  508. srvgen    proc    near
  509.     call    bufrel            ; release buffer
  510.     mov    al,decbuf        ; get first data character from pkt
  511.     cmp    al,'I'            ; LOGIN?
  512.     jne    srvge1            ; ne = no
  513.     jmp    srvlogin        ; yes
  514. srvge1:    call    logchk            ; check login status
  515.     jc    srvge2            ; c = ok
  516.     ret                ; else have sent error packet
  517. srvge2:cmp    al,'T'            ; Type a file?
  518.     jne    srvge3            ; ne = no
  519.     jmp    srvtyp            ; do the typing
  520. srvge3:    cmp    al,'D'            ; do a directory?
  521.     jne    srvge4
  522.     jmp    srvdir            ; do the directory command
  523. srvge4:    cmp    al,'E'            ; do a file erase (delete)?
  524.     jne    srvge5
  525.     jmp    srvdel            ; do the delete command
  526. srvge5:    cmp    al,'C'            ; change working dir?
  527.     jne    srvge6            ; ne = no
  528.     jmp    srvcwd            ; do it
  529. srvge6:    cmp    al,'U'            ; do a space command?
  530.     jne    srvge7
  531.     jmp    srvspc            ; do the space command
  532. srvge7:    cmp    al,'F'            ; FIN?
  533.     jne    srvge8            ; ne = no
  534.     jmp    short srvfin
  535. srvge8:    cmp    al,'L'            ; LOGO or BYE?
  536.     jne    srvge9            ; ne = no
  537.     call    srvfin
  538.     pushf                ; carry set means leave Server mode
  539.     call    serhng            ; hangup the phone and return
  540.     popf
  541.     jnc    srvge8a            ; nc = stay active (command denied)
  542.     mov    flags.extflg,1        ; leave server mode and Kermit
  543. srvge8a:mov    di,offset flags        ; main flags structure
  544.     mov    si,offset savflg    ; save area
  545.     mov    cx,savflgl        ; length in bytes
  546.     push    es
  547.     push    ds
  548.     pop    es
  549.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  550.     cld
  551.     rep    movsb            ; restore all of them
  552.     mov    di,offset dtrans    ; default transmission parameters
  553.     mov    si,offset savdtr    ; save area
  554.     mov    cx,savdtrl        ; length
  555.     rep    movsb            ; restore all of them
  556.     mov    di,offset trans        ; active transmission paramters
  557.     mov    si,offset savtr        ; save area
  558.     mov    cx,savdtrl        ; same length
  559.     rep    movsb
  560.     mov    flags.extflg,al        ; make flag current
  561.     mov    al,savmaxtry
  562.     mov    maxtry,al
  563.     pop    es
  564.     clc
  565.     ret
  566.             
  567. srvge9:    cmp    al,'M'            ; one line Message?
  568.     jne    srvge10            ; ne = no
  569.     jmp    srvmsg
  570. srvge10:cmp    al,'W'            ; WHO?
  571.     jne    srvge11            ; ne = no
  572.     jmp    srvwho
  573. srvge11:cmp    al,'H'            ; Help?
  574.     jne    srvge12            ; ne = no
  575.     jmp    srvhlp
  576. srvge12:cmp    al,'S'            ; SET?
  577.     jne    srvgex            ; ne = no
  578.     jmp    srvset
  579. srvgex:    mov    dx,offset remms1    ; reply Unknown server command
  580.     call    ermsg
  581.     mov    bx,dx
  582.     mov    trans.chklen,1        ; reply with 1 char checksum
  583.     call    errpack
  584.     clc
  585.     ret
  586. srvgen    endp
  587.  
  588. ; srvfin - respond to remote host's Fin command
  589. srvfin    proc    near
  590.     mov    slogin,0        ; say not logged in anymore
  591.     mov    si,offset byemsg    ; add brief msg of goodbye
  592.     mov    di,offset encbuf    ; packet's data field
  593.     call    strcpy            ; copy msg to pkt
  594.     mov    dx,si            ; strlen works on dx
  595.     call    strlen
  596.     push    si
  597.     mov    si,offset rpacket    ; get a reply buffer
  598.     call    doenc            ; encode the reply in encbuf
  599.     pop    si
  600.     mov    trans.chklen,1        ; reply with 1 char checksum
  601.     call    ackpak
  602.     mov    ax,100            ; wait 0.1 sec for client to settle
  603.     call    pcwait
  604.     test    denyflg,finflg        ; command enabled?
  605.     jz    srfin2            ; z = yes
  606.     clc                ; stay in server mode
  607.     ret
  608. srfin2:    stc                ; stc exits server mode
  609.     ret
  610. srvfin    endp
  611.  
  612. ; srvcwd - handle other side's Remote CWD dirspec
  613. srvcwd    proc    near
  614.     mov    trans.chklen,1        ; reply with 1 char checksum
  615.     test    denyflg,cwdflg        ; is command enabled?
  616.     jz    srcwd1            ; z = yes
  617.     mov    dx,offset remms9    ; say command is disabled
  618.     call    ermsg            ;  to us and
  619.     mov    bx,dx
  620.     call    errpack            ;  to the other Kermit
  621.     clc
  622.     ret
  623. srcwd1:    mov    si,offset decbuf+1    ; point to byte count
  624.     xor    bh,bh
  625.     mov    bl,[si]
  626.     sub    bl,' '            ; remove ascii bias from byte count
  627.     inc    si
  628.     mov    word ptr[si+bx],0    ; make ASCIIZ w/one extra null
  629.     call    cdsr            ; CD common sub-routine
  630.     mov    si,dx            ; returns msg in dx
  631.     mov    di,offset encbuf    ; put in encode buffer
  632.     call    strcpy
  633.     mov    dx,di
  634.     call    strlen            ; get its length to cx
  635.     mov    si,offset rpacket    ; use this packet for the reply
  636.     call    doenc            ; encode reply
  637.     call    ackpak            ; send ACK with data
  638.     clc
  639.     ret
  640. srvcwd    endp
  641.  
  642. ; srvtyp - handle other side's Remote Type filename request
  643. ; expects "data" to hold  Tcfilename   where c = # bytes in filename
  644. srvtyp    proc    near
  645.     cmp    decbuf+1,0        ; any data in packet
  646.     je    srtyp2            ; e = no
  647.     mov    cl,decbuf+1        ; get the filename byte count
  648.     sub    cl,' '            ; ascii to numeric
  649.     xor    ch,ch            ; set up counter
  650.     mov    si,offset decbuf+2    ; received filename, asciiz from rpack
  651.     mov    di,si
  652.     add    di,cx
  653.     mov    byte ptr [di],0        ; make string asciiz
  654.     test    denyflg,typflg        ; paths permitted?
  655.     jz    srtyp1            ; z = yes, else use just filename part
  656.     mov    di,offset srvbuf    ; local path
  657.     mov    si,offset rdbuf        ; local filename
  658.     mov    dx,offset decbuf+2    ; local string
  659.     call    fparse            ; split string
  660. srtyp1:    mov    di,offset diskio.string    ; copy local filename to destination
  661.     mov    ax,di            ; pointer to filename, for isfile
  662.     call    strcpy            ; do the copy
  663.     call    isfile            ; does it exist?
  664.     jnc    srtyp3            ; nc = yes
  665. srtyp2:    mov    si,offset remms5    ; "File not found"
  666.     mov    di,offset encbuf    ; destination for message
  667.     call    strcpy            ; move the message
  668.     mov    dx,di
  669.     call    strlen            ; length to cx
  670.     mov    si,offset rpacket    ; use this packet for reply
  671.     call    doenc            ; encode
  672.     mov    trans.chklen,1        ; reply with 1 char checksum
  673.     call    ackpak            ; send ACK with message
  674.     clc
  675.     ret
  676.  
  677. srtyp3:    mov    flags.xflg,1        ; say use X packet rather than F pkt
  678.     mov    auxfile,0        ; no alias name
  679.     mov    sstate,'S'        ; remember state
  680.     jmp    send10            ; this should send it
  681. srvtyp    endp
  682.  
  683. ; srvdir - handle other side's Remote Dir filespec(optional) request
  684. srvdir    proc    near
  685.     mov    di,offset decbuf+2      ; received filespec, asciiz from rpack
  686.     xor    cx,cx            ; assume no data in packet
  687.     mov    cl,decbuf+1        ; get the filename byte count
  688.     cmp    cl,' '            ; byte count present and > 0?
  689.     jg    srdir1            ; g = yes
  690.     mov    word ptr [di],0        ; clear data field
  691.     jmp    short srdir2        ; 0 = no info in pkt
  692. srdir1:    sub    cl,' '            ; ascii to numeric
  693.     add    di,cx            ; step to end of filename, terminate
  694.     mov    word ptr [di],0        ; ensure string is asciiz
  695.     mov    di,offset srvbuf    ; local path
  696.     mov    si,offset rdbuf        ; local filename
  697.     mov    dx,offset decbuf+2    ; local string
  698.     call    fparse            ; split string
  699.     test    denyflg,dirflg        ; paths permitted?
  700.     jz    srdir2            ; z = yes, else use just filename part
  701.     mov    si,offset rdbuf        ; copy local filename to
  702.     mov    di,offset decbuf+2    ; final filename
  703.     call    strcpy            ; copy just filename to buffer
  704. srdir2:    mov    cl,curdsk        ; current drive number
  705.     add    cl,'A'-1        ; to letter
  706.     cmp    decbuf+3,':'        ; drive specified?
  707.     jne    srdir3            ; ne = no
  708.     cmp    decbuf+2,0        ; drive letter specified?
  709.     je    srdir3            ; e = no
  710.     mov    cl,decbuf+2        ; get drive letter
  711.     and    cl,5fh            ; convert to upper case
  712. srdir3:    call    dskspace        ; check if drive ready (drive => CL)
  713.     jnc    srdir5            ; nc = success (drive is ready)
  714.     mov    spcmsg3,cl        ; insert drive letter
  715.     mov    si,offset spcmsg2    ; say drive not ready
  716.     mov    di,offset encbuf    ; destination for message
  717.     call    strcpy            ; move the message
  718.     mov    dx,di
  719.     call    strlen            ; length to cx
  720.     mov    si,offset rpacket    ; use this packet for reply
  721.     call    doenc            ; encode
  722.     mov    trans.chklen,1        ; reply with 1 char checksum
  723.     call    ackpak            ; send ACK with message
  724.     clc
  725.     ret
  726.  
  727. srdir5:    mov    di,offset srvbuf    ; work area
  728.     mov    si,offset dirstr    ; prepend "dir "
  729.     call    strcpy
  730.     mov    si,offset decbuf+2    ; directory spec, asciiz
  731.     mov    di,offset srvbuf
  732.     call    strcat
  733.  
  734. ; srdir6 does common processing for both REM DIR & REM HOST
  735. SRDIR6:    mov    si,di            ; srvbuf
  736.     mov    di,offset auxfile    ; send-as name is command line
  737.     call    strcpy
  738.     mov    dl,curdsk
  739.     add    dl,'A'-1        ; change to letter
  740.     mov    srvtmp+2,dl        ; insert current disk drive
  741.     mov    si,offset srvtmp    ; add redirection tag " >d:$kermit$.tmp"
  742.     mov    di,offset srvbuf
  743.     call    strcat
  744.     mov    si,offset srvbuf    ; command pointer for crun
  745.     call    crun
  746. ; fall thru!    jmp    srvtail            ; send contents of temp file
  747. srvdir    endp
  748.  
  749. ; Send contents of srvtmp+2 temporary file, or error packet if it does not
  750. ; exist.
  751. srvtail    proc    near
  752.     mov    si,offset srvtmp+2    ; get name of temp file
  753.     mov    di,offset diskio.string    ; destination
  754.     call    strcpy            ; copy it there
  755.     mov    ax,di            ; filename pointer for isfile
  756.     call    isfile            ; did we make the temp file?
  757.     jnc    srvtai1            ; nc = yes
  758.     mov    dx,offset remms10    ; "Could not create work file"
  759.     mov    trans.chklen,1        ; reply with 1 char checksum
  760.     call    ermsg
  761.     mov    bx,dx
  762.     call    errpack            ; send the error message
  763.     clc
  764.     ret
  765. srvtai1:mov    flags.xflg,1        ; say use X rather than F packet
  766.     mov    sstate,'S'        ; remember state
  767.     call    send10            ; this should send it
  768.     mov    flags.xflg,0        ; clear flag
  769.     mov    dx,offset srvtmp+2    ; name of temp file
  770.     mov    ah,del2            ; delete the file
  771.     int    dos
  772.     clc
  773.     ret                ; return in any case
  774. srvtail    endp
  775.  
  776. ; srvdel - handle other side's request of Remote Del filespec
  777. srvdel    proc    near
  778.     test    denyflg,delflg        ; command enabled?
  779.     jz    srvdel4            ; z = yes
  780.     mov    dx,offset remms9    ; else give a message
  781.     mov    trans.chklen,1        ; reply with 1 char checksum
  782.     call    ermsg
  783.     mov    bx,dx
  784.     call    errpack            ; back to local kermit
  785.     clc
  786.     ret
  787.  
  788. srvdel4:cmp    decbuf+1,0        ; any data?
  789.     je    srdel1            ; e = no
  790.     mov    bl,decbuf+1        ; get the filename byte count
  791.     sub    bl,' '            ; ascii to numeric
  792.     xor    bh,bh
  793.     cmp    bl,0            ; anything there?
  794.     jle    srdel3            ; le = no
  795.     mov    decbuf [bx+2],0        ; plant terminator
  796.     mov    ax,offset decbuf+2    ; point to filespec
  797.     call     isfile            ; is/are there any to delete?
  798.     jc    srdel1            ; c = there is none
  799.     test    byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
  800.     jz    srdel2            ; z = not protected
  801. srdel1:    mov    si,offset remms5    ; "File not found"
  802.     mov    di,offset encbuf    ; destination for message
  803.     call    strcpy            ; move the message
  804.     mov    dx,di
  805.     call    strlen            ; length to cx
  806.     mov    si,offset rpacket    ; use this packet for reply
  807.     call    doenc            ; encode
  808.     mov    trans.chklen,1        ; reply with 1 char checksum
  809.     call    ackpak            ; send ACK with message
  810.     clc
  811.     ret
  812.  
  813. srdel2:    mov    di,offset encbuf    ; work area
  814.     mov    si,offset delstr    ; prepend "del "
  815.     call    strcpy
  816.     mov    si,offset decbuf+2    ; append incoming filespec
  817.     call    strcat            ; append to "del "
  818.     mov    si,di            ; set pointer for crun
  819.     call    crun
  820. srdel3:    mov    dx,offset encbuf    ; where command lies
  821.     call    strlen            ; length to cx
  822.     push    si
  823.     mov    si,offset rpacket    ; packet to use for reply
  824.     call    doenc            ; encode reply
  825.     pop    si
  826.     mov    trans.chklen,1        ; reply with 1 char checksum
  827.     call    ackpak
  828.     clc
  829.     ret
  830. srvdel    endp
  831.  
  832. ; srvlogin - handle other side's request of REMOTE LOGIN, USERNAME, PASSWORD
  833.  
  834. srvlogin proc    near
  835.     mov    slogin,0        ; say not logged in yet
  836.     cmp    luser,0            ; local username specified?
  837.     je    srvlog9            ; e = no, do no checking
  838.     mov    cl,decbuf+1        ; ascii byte count of username
  839.     sub    cl,' '            ; to binary
  840.     cmp    cl,0            ; anything there?
  841.     jle    srvlog8            ; le = no
  842.     xor    ch,ch
  843.     mov    si,offset decbuf+2    ; source, username field
  844.     mov    di,offset luser        ; local username template
  845.     cld
  846. srvlog2:lodsb                ; remote char
  847.     mov    ah,[di]            ; local char
  848.     inc    di
  849.     or    ax,2020h        ; lower case both
  850.     cmp    ah,al            ; same?
  851.     jne    srvlog8            ; ne = no, fail
  852.     loop    srvlog2            ; continue match
  853.     cmp    lpass,0            ; local password specified?
  854.     je    srclog6            ; e = no, don't check incoming p/w
  855.     mov    cl,decbuf+1        ; username length
  856.     sub    cl,' '
  857.     xor    ch,ch            ; clear high byte
  858.     mov    si,offset decbuf+2    ; skip over username field
  859.     add    si,cx            ; password length byte
  860.     mov    cl,[si]            ; ascii count of password bytes
  861.     sub    cl,' '            ; to binary
  862.     jc    srvlog8            ; carry means no field
  863.     inc    si            ; start of password text
  864.     mov    di,offset lpass        ; local password text, case sensitive
  865. srvlog5:lodsb                ; remote char
  866.     mov    ah,[di]            ; local char
  867.     inc    di
  868.     cmp    ah,al            ; same?
  869.     jne    srvlog8            ; ne = no, fail
  870.     loop    srvlog5            ; do all chars
  871. srclog6:mov    slogin,1        ; declare user logged-in
  872.     jmp    short srvlog9        ; ACK with brief message
  873.  
  874. srvlog8:mov    si,offset remms2    ; say invalid login information
  875.     jmp    short srvlog10
  876.  
  877. srvlog9:mov    si,offset remms3    ; welcome aboard message
  878.     mov    slogin,1        ; say logged in successfully
  879. srvlog10:mov    di,offset encbuf    ; copy to here
  880.     call    strcpy
  881.     mov    dx,di            ; where command lies
  882.     call    strlen            ; length to cx
  883.     push    si
  884.     mov    si,offset rpacket    ; packet to use for reply
  885.     call    doenc            ; encode reply
  886.     pop    si
  887.     mov    trans.chklen,1        ; reply with 1 char checksum
  888.     call    ackpak
  889.     clc
  890.     ret
  891. srvlogin endp
  892.  
  893. ; srvspc - handle other side's request of Remote Space
  894. srvspc    proc    near
  895.     test    denyflg,spcflg        ; is command enabled?
  896.     jz    srspc1            ; z = yes
  897.     mov    dx,offset remms9    ; else give a message
  898.     mov    trans.chklen,1        ; reply with 1 char checksum
  899.     call    ermsg
  900.     mov    bx,dx
  901.     call    errpack            ; back to local kermit
  902.     clc
  903.     ret
  904. srspc1:    xor    cl,cl            ; use current drive
  905.     cmp    decbuf+1,0        ; any data?
  906.     je    srspc2            ; e = no
  907.     mov    cl,decbuf+2        ; get the drive letter
  908. srspc2:    call    dskspace        ; calculate space, get letter into CL
  909.     jnc    srspc3            ; nc = success
  910.     mov    spcmsg3,cl        ; insert drive letter
  911.     mov    di,offset encbuf    ; encoder buffer
  912.     mov    si,offset spcmsg2    ; give Drive not ready message
  913.     call    strcpy
  914.     jmp    short srspc4        ; send it
  915. srspc3:    mov    spcmsg1,cl        ; insert drive letter
  916.     mov    di,offset encbuf    ; destination
  917.     mov    word ptr[di],'  '    ; space space
  918.     add    di,2            ; start number here
  919.     call    lnout            ; convert number to asciiz in [di]
  920.     mov    si,offset spcmsg    ; trailer of message
  921.     call    strcat            ; tack onto end of number part
  922. srspc4:    mov    trans.chklen,1        ; reply with 1 char checksum
  923.     mov    dx,offset encbuf
  924.     call    strlen            ; get data size into cx for doenc
  925.     mov    si,offset rpacket
  926.     call    doenc            ; encode
  927.     call    pktsize            ; report packet size
  928.     call    ackpak
  929.     clc
  930.     ret
  931. srvspc    endp
  932.  
  933. ; srvwho - respond to remote host's WHO command.
  934. srvwho    proc    near
  935.     mov    si,offset whomsg    ; add brief msg of just us chickens
  936.     mov    di,offset encbuf    ; encoder source field
  937.     call    strcpy            ; copy msg to pkt
  938.     mov    dx,si            ; strlen works on dx
  939.     call    strlen
  940.     mov    si,offset rpacket
  941.     call    doenc            ; encode reply, size is in cx
  942.     mov    trans.chklen,1        ; reply with 1 char checksum
  943.     call    ackpak
  944.     clc
  945.     ret
  946. srvwho    endp
  947.  
  948. ; srvmsg - respond to remote host's Message (Send) command
  949. ;  show message on our screen.
  950. srvmsg    proc    near
  951.     cmp    decbuf,0        ; any data in the packet?
  952.     jbe    srvmsg2            ; e = no, just ack the message 
  953.     cmp    decbuf,'M'        ; Message packet?
  954.     jne    srvmsg2            ; ne = no, ack and forget
  955.     test    flags.remflg,dquiet+dserial ; quiet or serial display?
  956.     jnz    srvmsg1            ; nz = yes
  957.     mov    dx,scrmsg        ; move cursor to Last message area
  958.     call    poscur
  959.     call    clearl            ; and clear the line
  960. srvmsg1:xor    ch,ch
  961.     mov    cl,decbuf+1        ; data length
  962.     sub    cl,' '            ; remove ascii bias
  963.     jle    srvmsg2            ; le = nothing
  964.     mov    di,offset decbuf+2    ; main part of message
  965.     call    prtscr            ; display cx chars on the screen
  966. srvmsg2:mov    rpacket.datlen,0    ; length
  967.     mov    trans.chklen,1        ; reply with 1 char checksum
  968.     call    ackpak
  969.     clc
  970.     ret
  971. srvmsg    endp
  972.  
  973.  
  974. ; srvhos - handle other side's request of REM Host command-line. [jrd]
  975. ; We execute the command with STDOUT redirected to $kermit$.tmp and then
  976. ; read and transmit that file to the other end. No such file results in
  977. ; returning just an error msg ACK packet
  978. srvhos    proc    near
  979.     test    denyflg,hostflg        ; command enabled?
  980.     jz    srvhos2            ; z = yes
  981.     mov    trans.chklen,1        ; reply with 1 char checksum
  982.     mov    dx,offset remms9    ; else give a message
  983.     call    ermsg
  984.     mov    bx,dx
  985.     call    errpack            ; back to local kermit
  986.     clc
  987.     ret
  988.  
  989. srvhos2:mov    si,offset decbuf    ; received filename, asciiz from dodec
  990.     mov    di,offset srvbuf    ; destination
  991.     call    strcpy            ; copy data to srvbuf
  992.     jmp    SRDIR6            ; do common completion code
  993. srvhos    endp
  994.  
  995. ; Respond to other side's request of Remote Help. Write & read $kermit$.tmp
  996. srvhlp    proc    near
  997.     mov    dl,curdsk
  998.     add    dl,'A'-1        ; change to letter
  999.     mov    srvtmp+2,dl        ; insert current disk drive
  1000.     mov    dx,offset srvtmp+2    ; use filename of d:$kermit$.tmp
  1001.     mov    ah,creat2        ; create the file
  1002.     xor    cx,cx            ; attributes r/w
  1003.     int    dos
  1004.     jc    srvhlp1            ; c = could not open
  1005.     mov    dx,offset hlprem    ; data to be sent, strlen uses dx
  1006.     call    strlen            ; put string length in cx
  1007.     mov    bx,ax            ; handle
  1008.     mov    ah,write2        ; write to file
  1009.     int    dos            ; write the info
  1010.     mov    ah,close2    ; close the file so we can reread it below
  1011.     int    dos
  1012. srvhlp1:mov    si,offset infms4    ; pseudo filename
  1013.     mov    di,offset auxfile    ; send-as name
  1014.     call    strcpy            ; copy it there
  1015.     jmp    srvtail            ; send temporary file to remote screen
  1016. srvhlp    endp
  1017.  
  1018. ; srvker - handle other side's request of REM Kermit command-line. [jrd]
  1019. srvker    proc    near
  1020.     test    denyflg,kerflg        ; command enabled?
  1021.     jz    srvker1            ; z = yes
  1022.     mov    trans.chklen,1        ; reply with 1 char checksum
  1023.     mov    dx,offset remms9    ; else give a message
  1024.     call    ermsg
  1025.     mov    bx,dx
  1026.     call    errpack            ; back to local kermit
  1027.     clc
  1028.     ret
  1029.  
  1030. srvker1:call    takopen            ; open a Take file
  1031.     jc    srvker3            ; c = failed to obtain Take space
  1032.     mov    dx,prmptr        ; get prompt
  1033.     call    prompt              ; prompt user, set reparse address
  1034.     mov    bx,takadr        ; pointer to Take structure
  1035.     mov    skertmp,bx        ; remember it here for cleanup
  1036.     mov    [bx].taktyp,0ffh    ; mark as a macro
  1037.     mov    dx,offset decbuf    ; received command, asciiz
  1038.     call    strlen            ; get length into cx
  1039.     mov    si,dx
  1040. srvker6:cmp    byte ptr [si],' '    ; strip leading white space
  1041.     ja    srvker7            ; a = non-white
  1042.     loop    srvker6            ; continue
  1043. srvker7:cmp    cx,8            ; need at least 8 chars "SET xx y"
  1044.     jb    srvker2            ; b = too few, bad command
  1045.     mov    ax,[si]            ; get first two characters
  1046.     or    ax,2020h        ; lower case them
  1047.     cmp    ax,'es'            ; start of "SET"?
  1048.     jne    srvker2            ; ne = no, bad command
  1049.     mov    ax,[si+2]        ; next two
  1050.     or    ax,2020h
  1051.     cmp    ax,' t'            ; rest of "SET "?
  1052.     jne    srvker2            ; ne = no, bad command
  1053.     add    si,4            ; move to end of "SET "
  1054.     sub    cx,4
  1055.     mov    [bx].takcnt,cx        ; number of bytes in command
  1056.     push    es
  1057.     mov    ax,[bx].takbuf        ; segment of Take buffer
  1058.     mov    es,ax
  1059.     mov    di,1            ; place here (skip buf length byte)
  1060.     cld
  1061.     rep    movsb
  1062.     pop    es
  1063.     call    setcom
  1064.     jnc    srvker3            ; nc = success
  1065. srvker2:mov    si,offset remms6    ; "Command failed"
  1066.     jmp    short srvker4
  1067. srvker3:mov    si,offset remms8    ; "Command succeeded"
  1068. srvker4:mov    di,offset encbuf    ; destination for message
  1069.     call    strcpy            ; move the message
  1070.     mov    dx,di
  1071.     call    strlen            ; length to cx
  1072.     mov    si,offset rpacket    ; use this packet for reply
  1073.     call    doenc            ; encode
  1074.     mov    trans.chklen,1        ; reply with 1 char checksum
  1075.     call    ackpak            ; send ACK with message
  1076.     mov    ax,skertmp        ; get old take address
  1077.     cmp    ax,takadr        ; same (still in current Take)?
  1078.     jne    srvker5            ; ne = no
  1079.     call    takclos            ; close the Take file
  1080. srvker5:clc
  1081.     ret
  1082. srvker    endp
  1083.  
  1084. ;  Command                                Code   Values
  1085. ;  REMOTE SET ATTRIBUTES IN ALL            132   0 = OFF, 1 = ON
  1086. ;  REMOTE SET ATTRIBUTES IN LENGTH         133   0 = OFF, 1 = ON
  1087. ;  REMOTE SET ATTRIBUTES IN TYPE           134   0 = OFF, 1 = ON
  1088. ;  REMOTE SET ATTRIBUTES IN DATE           135   0 = OFF, 1 = ON
  1089. ;X  REMOTE SET ATTRIBUTES IN CREATOR        136   0 = OFF, 1 = ON
  1090. ;X  REMOTE SET ATTRIBUTES IN ACCOUNT        137   0 = OFF, 1 = ON
  1091. ;X  REMOTE SET ATTRIBUTES IN AREA           138   0 = OFF, 1 = ON
  1092. ;X  REMOTE SET ATTRIBUTES IN BLOCK-SIZE     139   0 = OFF, 1 = ON
  1093. ;X  REMOTE SET ATTRIBUTES IN ACCESS         140   0 = OFF, 1 = ON
  1094. ;X  REMOTE SET ATTRIBUTES IN ENCODING       141   0 = OFF, 1 = ON
  1095. ;X  REMOTE SET ATTRIBUTES IN DISPOSITION    142   0 = OFF, 1 = ON
  1096. ;X  REMOTE SET ATTRIBUTES IN PROTECTION     143   0 = OFF, 1 = ON
  1097. ;X  REMOTE SET ATTRIBUTES IN GPROTECTION    144   0 = OFF, 1 = ON
  1098. ;X  REMOTE SET ATTRIBUTES IN SYSTEM-ID      145   0 = OFF, 1 = ON
  1099. ;X  REMOTE SET ATTRIBUTES IN FORMAT         146   0 = OFF, 1 = ON
  1100. ;X  REMOTE SET ATTRIBUTES IN SYS-INFO       147   0 = OFF, 1 = ON
  1101. ;X  REMOTE SET ATTRIBUTES IN BYTE-COUNT     148   0 = OFF, 1 = ON
  1102. ;
  1103. ;  REMOTE SET ATTRIBUTES OUT ALL           232   0 = OFF, 1 = ON
  1104. ;  REMOTE SET ATTRIBUTES OUT LENGTH        233   0 = OFF, 1 = ON
  1105. ;  REMOTE SET ATTRIBUTES OUT TYPE          234   0 = OFF, 1 = ON
  1106. ;  REMOTE SET ATTRIBUTES OUT DATE          235   0 = OFF, 1 = ON
  1107. ;X  REMOTE SET ATTRIBUTES OUT CREATOR       236   0 = OFF, 1 = ON
  1108. ;X  REMOTE SET ATTRIBUTES OUT ACCOUNT       237   0 = OFF, 1 = ON
  1109. ;X  REMOTE SET ATTRIBUTES OUT AREA          238   0 = OFF, 1 = ON
  1110. ;X  REMOTE SET ATTRIBUTES OUT BLOCK-SIZE    239   0 = OFF, 1 = ON
  1111. ;X  REMOTE SET ATTRIBUTES OUT ACCESS        240   0 = OFF, 1 = ON
  1112. ;X  REMOTE SET ATTRIBUTES OUT ENCODING      241   0 = OFF, 1 = ON
  1113. ;X  REMOTE SET ATTRIBUTES OUT DISPOSITION   242   0 = OFF, 1 = ON
  1114. ;X  REMOTE SET ATTRIBUTES OUT PROTECTION    243   0 = OFF, 1 = ON
  1115. ;X  REMOTE SET ATTRIBUTES OUT GPROTECTION   244   0 = OFF, 1 = ON
  1116. ;X  REMOTE SET ATTRIBUTES OUT SYSTEM-ID     245   0 = OFF, 1 = ON
  1117. ;X  REMOTE SET ATTRIBUTES OUT FORMAT        246   0 = OFF, 1 = ON
  1118. ;X  REMOTE SET ATTRIBUTES OUT SYS-INFO      247   0 = OFF, 1 = ON
  1119. ;X  REMOTE SET ATTRIBUTES OUT BYTE-COUNT    248   0 = OFF, 1 = ON
  1120. ;
  1121. ;  REMOTE SET FILE TYPE                    300   0 = TEXT, 1 = BINARY
  1122. ;X  REMOTE SET FILE NAMES                   301   0 = CONVERTED, 1 = LITERAL
  1123. ;  REMOTE SET FILE COLLISION               302   0 = RENAME,  1 = REPLACE,
  1124. ;                                                X 2 = BACKUP,  X 3 = APPEND,
  1125. ;                                                4 = DISCARD, X  5 = ASK
  1126. ;X  REMOTE SET FILE REPLACE                 303   0 = PRESERVE, 1 = DEFAULT
  1127. ;  REMOTE SET INCOMPLETE                   310   0 = DISCARD, 1 = KEEP
  1128. ;
  1129. ;  REMOTE SET BLOCK-CHECK                  400   number (1, 2, or 3)
  1130. ;  REMOTE SET RECEIVE PACKET-LENGTH        401   number (10-9024)
  1131. ;  REMOTE SET RECEIVE TIMEOUT              402   number (any, 0 = no timeout)
  1132. ;  REMOTE SET RETRY                        403   number (any, 0 = no limit)
  1133. ;  REMOTE SET SERVER TIMEOUT               404   number (any, 0 = no timeout)
  1134. ;  REMOTE SET TRANSFER CHARACTER-SET       405   Character Set Designator
  1135. ;  REMOTE SET WINDOW-SLOTS                 406   number (1-31)
  1136. ;
  1137. ; Items marked with "X" are ignored by this server
  1138.  
  1139. ; srvset - manage incoming REMOTE SET commands
  1140. ; decode buffer looks like S<len1><value1><len2><value2>
  1141. srvset    proc    near
  1142.     mov    bufptr,offset decbuf+1    ; received command data, asciiz
  1143.     call    srvswk            ; worker to convert first value to ax
  1144.     jc    srvset3            ; c = failure
  1145.     mov    temp,ax            ; save first value here
  1146.     cmp    ax,132            ; before known set?
  1147.     jb    srvset3            ; b = yes, bad
  1148.     mov    di,offset sattr        ; assume SET ATTRIBUTES
  1149.     cmp    ax,148            ; still in range?
  1150.     jbe    srvset2            ; be = yes
  1151.     cmp    ax,232            ; before next range?
  1152.     jb    srvset1            ; b = yes
  1153.     cmp    ax,248            ; still in range?
  1154.     jbe    srvset2            ; be = yes, get final value
  1155. srvset1:push    es            ; do table lookup on other values
  1156.     push    ds
  1157.     pop    es
  1158.     mov    di,offset setval    ; look up other codes in table
  1159.     mov    cx,setvlen
  1160.     cld
  1161.     repne    scasw
  1162.     pop    es
  1163.     mov    bx,offset remms1    ; "Unknown server command", if needed
  1164.     jne    srvset3            ; ne = no match, unknown command
  1165.     sub    di,offset setval+2    ; get displacement
  1166.     mov    di,setvec[di]
  1167. srvset2:call    di            ; call the action routine
  1168.     mov    bx,offset remms6    ; "Command failed", if needed
  1169.     jc    srvset3            ; c = failure
  1170.     mov    si,offset remms8    ; "Command succeeded"
  1171.     mov    di,offset encbuf    ; destination for message
  1172.     call    strcpy            ; move the message
  1173.     mov    dx,di
  1174.     call    strlen            ; length to cx
  1175.     mov    si,offset rpacket    ; use this packet for reply
  1176.     call    doenc            ; encode
  1177.     mov    trans.chklen,1        ; reply with 1 char checksum
  1178.     call    ackpak            ; send ACK with message
  1179.     clc
  1180.     ret
  1181. srvset3:mov    trans.chklen,1        ; reply with 1 char checksum
  1182.     call    errpack            ; send error message in ptr bx
  1183.     clc
  1184.     ret
  1185. srvset    endp
  1186.  
  1187. sattr    proc    near            ; SET ATTRIBUTES IN/OUT ITEM ON/OFF
  1188.     mov    ax,temp            ; get kind of attribute
  1189.     cmp    ax,200            ; the OUT kind?
  1190.     jb    sattr1            ; b = no, IN kind
  1191.     sub    ax,100            ; merge to same thing
  1192. sattr1:    cmp    ax,132            ; ALL?
  1193.     jne    sattr2            ; be = ok
  1194.     mov    bl,0ffh            ; all bits
  1195.     jmp    short sattr6
  1196. sattr2:    cmp    al,133            ; Length?
  1197.     jne    sattr3            ; ne = no
  1198.     mov    bl,attlen
  1199.     jmp    short sattr6
  1200. sattr3:    cmp    al,134            ; Type
  1201.     jne    sattr4            ; ne = no
  1202.     mov    bl,atttype
  1203.     jmp    short sattr6
  1204. sattr4:    cmp    bl,135            ; Date?
  1205.     jne    sattr5            ; ne = no, fail
  1206.     mov    bl,attdate
  1207.     jmp    short sattr6
  1208. sattr5:    stc                ; fail
  1209.     ret
  1210. sattr6:    call    srvswk            ; get second value to ax, 1 = on
  1211.     jc    sattr5            ; c = failure
  1212.     cmp    ax,0            ; off?
  1213.     jne    sattr7            ; ne = no, on
  1214.     mov    al,flags.attflg        ; current flags
  1215.     not    bl            ; invert selected items
  1216.     and    al,bl            ; turn off selected items
  1217.     mov    flags.attflg,al        ; store the flags
  1218.     clc
  1219.     ret
  1220. sattr7:    cmp    ax,1            ; on?
  1221.     jne    sattr5            ; ne = no, fail
  1222.     or    flags.attflg,bl        ; insert ON selected bits
  1223.     clc    
  1224.     ret
  1225. sattr    endp
  1226.  
  1227. sftype    proc    near            ; SET FILE TYPE
  1228.     call    srvswk            ; get second value to ax
  1229.     jc    sftypb            ; c = failure
  1230.     cmp    al,1
  1231.     ja    sftypb            ; a = bad
  1232.     mov    trans.xtype,al        ; store transfer type
  1233.     clc
  1234.     ret
  1235. sftypb:    stc                ; bad command
  1236.     ret
  1237. sftype    endp
  1238.  
  1239. sfcoll    proc    near            ; SET FILE COLLISION
  1240.     call    srvswk            ; get second value to ax
  1241.     jc    sfcollb            ; c = failure
  1242.     cmp    ax,4
  1243.     ja    sfcollb            ; a = bad
  1244.     cmp    ax,2            ; backup?
  1245.     je    sfcollb            ; e = yes, bad command
  1246.     cmp    ax,3            ; append?
  1247.     je    sfcollb            ; e = yes, bad command
  1248.     mov    flags.flwflg,al        ; set file collison state
  1249.     clc
  1250.     ret
  1251. sfcollb:stc                ; bad command
  1252.     ret
  1253. sfcoll    endp
  1254.  
  1255. sfinc    proc    near             ; SET INCOMPLETE, SET FILE INCOMPLETE
  1256.     call    srvswk            ; get second value to ax
  1257.     jc    sfincb            ; c = failure
  1258.     cmp    ax,1
  1259.     ja    sfincb            ; a = bad
  1260.     mov    flags.abfflg,al        ; discard incomplete files if al = 1
  1261.     clc
  1262.     ret
  1263. sfincb:    stc                ; bad command
  1264.     ret
  1265. sfinc    endp
  1266.  
  1267. srtmo    proc    near            ; SET RECEIVE TIMEOUT
  1268.     call    srvswk            ; get second value to ax
  1269.     jnc    srtmo1            ; nc = success
  1270.     ret
  1271. srtmo1:    cmp    ax,94            ; above limit?
  1272.     jbe    srtmo2            ; be = no
  1273.     mov    al,94
  1274. srtmo2:    mov    trans.rtime,al
  1275.     clc
  1276.     ret
  1277. srtmo    endp
  1278.  
  1279. sblkck    proc    near            ; SET BLOCK-CHECK
  1280.     call    srvswk            ; get second value to ax
  1281.     jnc    sblkck1            ; nc = success
  1282.     ret                ; fail
  1283. sblkck1:cmp    ax,3            ; our limit
  1284.     jbe    sblkck2            ; be = safe
  1285.     mov    ax,3            ; set to max
  1286. sblkck2:or    ax,ax            ; too small?
  1287.     jnz    sblkck3            ; z = no
  1288.     inc    ax
  1289. sblkck3:mov    dtrans.chklen,al    ; use this char as initial checksum
  1290.     clc
  1291.     ret
  1292. sblkck    endp
  1293.  
  1294. srpkt    proc    near             ; SET RECEIVE PACKET-LENGTH
  1295.     call    srvswk            ; get second value to ax
  1296.     jnc    srpkt1            ; nc = success
  1297.     ret
  1298. srpkt1:    cmp    ax,maxpack        ; above limit?
  1299.     jbe    srpkt2            ; be = no
  1300.     mov    ax,maxpack
  1301. srpkt2:    cmp    ax,20            ; too small?
  1302.     jae    srpkt3            ; ae = no
  1303.     mov    ax,20            ; set minimum
  1304. srpkt3:    mov    dtrans.rlong,ax        ; set long packet size
  1305.     mov    bl,dtrans.rpsiz        ; regular packet size
  1306.     xor    bh,bh
  1307.     cmp    ax,bx            ; is long packet shorter
  1308.     jae    srpkt4            ; ae = no
  1309.     mov    dtrans.rpsiz,al        ; set regular pkt length too
  1310. srpkt4:    clc
  1311.     ret
  1312. srpkt    endp
  1313.  
  1314. sretry    proc    near            ; REMOTE SET RETRY
  1315.     call    srvswk            ; get second value to ax
  1316.     jnc    sretry1            ; nc = success
  1317.     ret                ; fail
  1318. sretry1:cmp    ax,63            ; our limit
  1319.     jbe    sretry2            ; be = safe
  1320.     mov    ax,63            ; set to max
  1321. sretry2:mov    maxtry,al        ; set packet retry limit
  1322.     clc
  1323.     ret
  1324. sretry    endp
  1325.  
  1326. sstmo    proc    near            ; SET SERVER TIMEOUT
  1327.     call    srvswk            ; get second value to ax
  1328.     jnc    sstmo1            ; nc = success
  1329.     ret
  1330. sstmo1:    cmp    ax,255
  1331.     jbe    sstmo2            ; be = in range
  1332.     mov    al,255            ; limit to max
  1333. sstmo2:    mov    srvtmo,al        ; store timeout value
  1334.     clc
  1335.     ret
  1336. sstmo    endp
  1337.  
  1338. sxfrch    proc    near            ; SET TRANSFER CHARACTER-SET string
  1339.     mov    bx,bufptr
  1340.     xor    ch,ch
  1341.     mov    cl,[bx]            ; byte count of next field, if any
  1342.     sub    cl,' '            ; remove ascii bias
  1343.     jnc    sxfrch1            ; nc = is ok
  1344.     ret
  1345. sxfrch1:inc    bx            ; look at character string
  1346.     cmp    byte ptr[bx],'A'    ; A for Transparent?
  1347.     jne    sxfrch2
  1348.     cmp    cx,1            ; just that char?
  1349.     jne    sxfrchb            ; ne = no, fail
  1350.     mov    trans.xchset,0        ; set transfer char set to Transparent
  1351.     clc
  1352.     ret
  1353. sxfrch2:cmp    cx,6            ; "I2/100"?
  1354.     jne    sxfrchb            ; ne = no, fail
  1355.     cmp    word ptr [bx],'2I'    ; length is ok, check spelling
  1356.     jne    sxfrchb            ; ne = failure
  1357.     cmp    word ptr [bx+2],'1/'
  1358.     jne    sxfrchb
  1359.     cmp    word ptr [bx+4],'00'
  1360.     jne    sxfrchb
  1361.     mov    trans.xchset,1        ; set transfer char set to Latin1
  1362.     clc
  1363.     ret
  1364. sxfrchb:stc                ; fail
  1365.     ret
  1366. sxfrch    endp
  1367.  
  1368. swind    proc    near            ; SET WINDOW-SLOTS
  1369.     call    srvswk            ; get second value to ax
  1370.     jnc    swind1            ; nc = success
  1371.     ret
  1372. swind1:    cmp    ax,31            ; max legal
  1373.     jbe    swind2            ; be = in range
  1374.     mov    al,31            ; limit to max
  1375. swind2:    or    ax,ax            ; no windowing?
  1376.     jnz    swind3            ; nz = no, not that way
  1377.     mov    ax,1            ; local min size for no windowing
  1378. swind3:    mov    dtrans.windo,al        ; store default window size
  1379.     clc
  1380.     ret
  1381. swind    endp
  1382.  
  1383. ; Worker for srvset. Reads buffer pointed at by bufptr looking for 
  1384. ; construction <length><numbers>. Returns carry clear and binary number
  1385. ; in AX, else carry set and AX = -1. Bufptr is always updated.
  1386. srvswk    proc    near
  1387.     push    bx
  1388.     push    cx
  1389.     push    dx
  1390.     push    si
  1391.     mov    bx,bufptr
  1392.     xor    ch,ch
  1393.     mov    cl,[bx]            ; byte count of next field, if any
  1394.     sub    cl,' '            ; remove ascii bias
  1395.     jnc    srvswk1            ; nc = is ok
  1396.     mov    ax,-1            ; else say value is -1
  1397.     jmp    short srvswkx
  1398. srvswk1:inc    bx
  1399.     xor    si,si            ; accumulated value
  1400.     mov    dl,10
  1401. srvswk2:mov    ax,si            ; accumulated value
  1402.     mul    dl            ; times 10
  1403.     mov    si,ax            ; store
  1404.     xor    ah,ah
  1405.     mov    al,[bx]            ; get a digit
  1406.     inc    bx
  1407.     sub    al,'0'            ; remove ascii bias
  1408.     jnc    srvswk3            ; nc = no
  1409.     mov    ax,-1            ; say bad value
  1410.     jmp    short srvswkx        ; and quit
  1411. srvswk3:add    si,ax            ; accumulate new digit
  1412.     loop    srvswk2            ; do all digits
  1413.     mov    ax,si            ; return results in ax
  1414.     clc
  1415. srvswkx:mov    bufptr,bx        ; remember where we read from decbuf
  1416.     pop    si
  1417.     pop    dx
  1418.     pop    cx
  1419.     pop    bx
  1420.     ret
  1421. srvswk    endp
  1422.  
  1423. ; srvini - init parms based on 'I' init packet
  1424. srvini    proc    near
  1425.     call    spar            ; parse info
  1426.     call    packlen
  1427.     call    makebuf            ; remake buffers for new windowing
  1428.     push    si
  1429.     mov    si,offset rpacket
  1430.     call    rpar            ; setup info about our reception
  1431.     pop    si
  1432.     mov    al,trans.chklen        ; checksum length negotiated
  1433.     push    ax            ; save around reply
  1434.     mov    trans.chklen,1        ; reply with 1 char checksum
  1435.     call    ackpak
  1436.     pop    ax            ; restore checksum length
  1437.     mov    trans.chklen,al
  1438.     clc                ; success
  1439.     ret
  1440. srvini    endp
  1441.  
  1442.  
  1443. ; BYE command - tell remote KERSRV to logout & exit to DOS  
  1444.  
  1445. BYE    PROC    NEAR
  1446.     mov    ah,cmeol        ; get a confirm
  1447.     call    comnd
  1448.     jnc    bye1            ; nc = success
  1449.     ret                ; failure
  1450. bye1:    mov    remcmd,'L'        ; Logout command letter
  1451.     call    logo            ; tell the host Kermit to logout
  1452.      jc    bye2            ; c = failed, do not exit
  1453.     mov    flags.extflg,1        ; set this Kermit's exit flag
  1454.     call    serhng            ; hangup the phone
  1455. bye2:    clc
  1456.     ret
  1457. BYE    ENDP
  1458.  
  1459. ; FINISH - tell    remote KERSRV to exit
  1460.  
  1461. FINISH    PROC    NEAR
  1462.     mov    ah,cmeol        ; get a confirm
  1463.     call    comnd
  1464.     jnc    finish1            ; nc = success
  1465.     ret                ; failure
  1466. finish1:mov    remcmd,'F'        ; Finish command letter
  1467.     call    logo
  1468.     clc
  1469.     ret
  1470. FINISH    ENDP
  1471.  
  1472. ; LOGOUT - tell remote KERSRV to logout
  1473.  
  1474. LOGOUT    PROC    NEAR
  1475.     mov    ah,cmeol
  1476.     call    comnd            ; get a confirm
  1477.     jnc    logout1            ; nc = success
  1478.     ret                ; failure
  1479. logout1:mov    remcmd,'L'        ; Logout command letter
  1480.     call    logo
  1481.     clc
  1482.     ret
  1483. LOGOUT    ENDP
  1484.  
  1485. ; Common routine for FINISH, LOGOUT, BYE
  1486. ; Return carry clear for success, else carry set
  1487. LOGO    PROC    NEAR
  1488.     call    serini            ; Initialize port
  1489.     jnc    logo1            ; nc = success
  1490.     ret                ; c = failure
  1491. logo1:    call    clrbuf            ; clear serial port buffer
  1492.     call    ihostr            ; initialize the host
  1493.     mov    diskio.string,0        ; clear local filename for stats
  1494.     call    makebuf            ; set up packet buffers
  1495.     mov    pktnum,0        ; packet number to be used
  1496.     mov    windlow,0        ; reset windowing
  1497.     call    packlen            ; get max packet length
  1498.     call    getbuf            ; get buffer for sending
  1499.     mov    trans.chklen,1        ; use one char for server functions
  1500.     mov    ah,remcmd        ; get command letter ('L' or 'F')
  1501.     mov    encbuf,ah        ; encode the command
  1502.     mov    cx,1            ; one piece of data
  1503.     call    doenc            ; do encoding
  1504.     mov    [si].pktype,'G'        ; Generic command packet type
  1505.     mov    flags.xflg,1        ; say receiving to screen
  1506.     call    sndpak            ;  to suppress # pkts msg
  1507.     jc    logo3            ; c = failure
  1508.     mov    al,[si].seqnum        ; get response for this sequence num
  1509.     mov    ah,maxtry        ; retry threshold
  1510.     call    response        ; get response
  1511.     mov    si,offset rpacket    ; packet to look at
  1512.     call    msgmsg            ; show any message
  1513. logo3:    mov    flags.cxzflg,0        ; clear these flags
  1514.     mov    flags.xflg,0
  1515.     ret                ; exit with carry flag from response
  1516. LOGO    ENDP
  1517.  
  1518. ; GET command. Ask remote server to send the specified file(s)
  1519. ; Queries for remote filename and optional local override path/filename
  1520. GET    PROC    NEAR
  1521.     mov    auxfile,0        ; clear, for safety
  1522.     mov    encbuf,0        ; ditto
  1523.     mov    flags.cxzflg,0        ; no Control-C typed yet
  1524.     mov    bx,offset encbuf    ; where to put text
  1525.     mov    dx,offset filmsg    ; help
  1526.     mov    ah,cmline        ; filenames with embedded whitespace
  1527.     call    comnd            ; get text or confirm
  1528.     jnc    get1            ; nc = success
  1529.     ret                ; failure 
  1530. get1:    mov    al,ah
  1531.     xor    ah,ah
  1532.     mov    cnt,ax            ; remember number of chars we read
  1533.     or    al,al            ; read in any chars?
  1534.     jnz    get7            ; nz = yes, analyze
  1535.                     ; if empty line, ask for file names
  1536. get2:    mov    dx,offset remfnm    ; ask for remote name first
  1537.     call    prompt
  1538.     mov    bx,offset encbuf    ; place for remote filename
  1539.         mov    dx,offset frem        ; help message
  1540.     mov    ah,cmline        ; use this for embedded spaces
  1541.     call    comnd            ; get a filename
  1542.     jnc    get3            ; nc = success
  1543.     ret                ; failure
  1544. get3:    mov    al,ah
  1545.     xor    ah,ah
  1546.     mov    cnt,ax            ; remember number of chars read
  1547.     or    al,al            ; count of entered chars
  1548.     jz    get2            ; z = none, try again
  1549.     mov    dx,offset lclfnm    ; prompt for local filename
  1550.     call    prompt
  1551.     mov    bx,offset filhlp
  1552.     mov    dx,offset auxfile    ; complete local filename
  1553.     mov    auxfile,0        ; clear, for safety
  1554.     mov    ah,cmword        ; get a word
  1555.     call    comnd
  1556.     jnc    get5            ; nc = success
  1557.     ret                ; failure
  1558. get5:    mov    ah,cmeol        ; get confirmation
  1559.     call    comnd
  1560.     jnc    get6            ; nc = success
  1561.     ret                ; failure
  1562. get6:    cmp    auxfile,'#'        ; is first char a replacement for '?'
  1563.     jne    get7            ; ne = no
  1564.     mov    auxfile,'?'        ; replace '#' by '?'
  1565. get7:    cmp    encbuf,'#'        ; is first char a replacement for '?' ?
  1566.     jne    get8            ; ne = no
  1567.     mov    encbuf,'?'        ; replace '#' by '?'
  1568.  
  1569. get8:    call    rrinit            ; clear buffers and counters
  1570.     mov    flags.xflg,1        ; assume writing to screen
  1571.     cmp    flags.destflg,2        ; receiving to screen?
  1572.     je    get8a            ; e = yes, skip screen stuff
  1573.     mov    flags.xflg,0        ; not writing to screen, yet
  1574.     call    init            ; init (formatted) screen
  1575. get8a:    call    begtim            ; start statistics
  1576.     mov    kstatus,0        ; global status, success
  1577.     call    makebuf            ; setup packet buffers
  1578.     call    ipack            ; Send Initialize, 'I', packet
  1579.     jnc    get8b            ; nc = success
  1580.     jmp    short get10        ; failure
  1581.  
  1582. get8b:    mov    si,offset encbuf    ; copy from here
  1583.     mov    di,offset fsta.xname    ; to statistics remote name field
  1584.     call    strcpy
  1585.     mov    si,offset rpacket    ; packet for response
  1586.     mov    cx,cnt            ; get back remote filename size
  1587.     call    doenc            ; encode data already in encbuf
  1588.     jnc    get9            ; nc = success
  1589.     mov    dx,offset ermes6        ; filename is too long for pkt
  1590.     call    ermsg
  1591.     mov    bx,dx            ; point to message, for errpack
  1592.     call    errpack            ; tell the host we are quiting
  1593.     jmp    short get10        ; data could not all fit into packet
  1594.  
  1595. get9:    mov    trans.chklen,1        ; use one char for server functions
  1596.     mov    rpacket.pktype,'R'    ; Receive init packet
  1597.     mov    si,offset rpacket
  1598.     call    sndpak            ; send the packet, no ACK expected
  1599.     jc    get10            ; c = failure to send packet
  1600.     mov    rstate,'R'        ; Set the state to receive initiate
  1601.     jmp    READ2            ; go join read code
  1602.  
  1603. get10:    call    bufclr            ; total failures come here
  1604.     call    rprpos            ; reset cursor for prompt
  1605.     or    errlev,2        ; set DOS error level to cannot rcv
  1606.     or    fsta.xstatus,2        ; set status
  1607.     mov    kstatus,2        ; global status
  1608.     mov    flags.cxzflg,0        ; clear flag for next command
  1609.     mov    auxfile,0        ; clear send-as filename buffer
  1610.     mov    flags.xflg,0        ; clear to-screen flag
  1611.     clc
  1612.     ret
  1613. GET    ENDP
  1614.  
  1615. ;    This is the REMOTE command
  1616.  
  1617. REMOTE    PROC    NEAR
  1618.     mov    dx,offset remtab    ; Parse keyword from the REMOTE table
  1619.     mov    bx,offset remhlp
  1620.     mov    ah,cmkey
  1621.     call    comnd
  1622.     jnc    remote1            ; nc = success
  1623.     ret                ; failure
  1624. remote1:jmp    bx            ; do the appropriate routine
  1625. REMOTE    ENDP
  1626.  
  1627. ; REMSET - Execute a REMOTE SET command
  1628.  
  1629. REMSET    PROC    NEAR
  1630.     mov    rempac,'G'        ; Packet type = generic
  1631.     mov    encbuf,'S'        ; command type = Set
  1632.     mov    bufptr,offset encbuf+1    ; place more pkt material here
  1633.     mov    ah,cmkey        ; get keyword
  1634.     mov    dx,offset remstt1    ; table of keywords
  1635.     xor    bx,bx            ; help
  1636.     call    comnd
  1637.     jnc    remset1            ; nc = success
  1638.     ret
  1639. remset1:cmp    bx,1            ; Attributes?
  1640.     jne    remset5            ; ne = no
  1641.     mov    dx,offset remsat1    ; Attributes IN, OUT table
  1642.     xor    bx,bx            ; help
  1643.     mov    ah,cmkey
  1644.     call    comnd
  1645.     jnc    remset2
  1646.     ret
  1647. remset2:mov    temp,bx            ; save in out
  1648.     mov    dx,offset remsat2    ; next attributes keyword table
  1649.     xor    bx,bx            ; help
  1650.     mov    ah,cmkey
  1651.     call    comnd
  1652.     jnc    remset3
  1653.     ret
  1654. remset3:add    bx,temp            ; save final value
  1655.     call    remwork
  1656.     mov    dx,offset onoff        ; ON, OFF table
  1657.     xor    bx,bx            ; help
  1658.     mov    ah,cmkey        ; get on,off
  1659.     call    comnd
  1660.     jnc    remset4
  1661.     ret
  1662. remset4:jmp    remset17
  1663.  
  1664. remset5:cmp    bx,2            ; REMOTE SET FILE?
  1665.     jne    remset14        ; ne = no
  1666.     mov    dx,offset remsfit    ; REM SET FILE table
  1667.     xor    bx,bx            ; help
  1668.     mov    ah,cmkey
  1669.     call    comnd
  1670.     jnc    remset6
  1671.     ret
  1672. remset6:push    bx
  1673.     call    remwork            ; write kind to buffer
  1674.     pop    bx
  1675.     cmp    bx,300            ; TYPE?
  1676.     jne    remset8
  1677.     mov    dx,offset remsfty    ; TYPE table
  1678.     xor    bx,bx
  1679.     mov    ah,cmkey
  1680.     call    comnd
  1681.     jnc    remset17
  1682.     ret
  1683.  
  1684. remset8:cmp    bx,301            ; NAME?
  1685.     jne    remset10        ; ne = no
  1686.     mov    dx,offset remsfna    ; NAME table
  1687.     xor    bx,bx
  1688.     mov    ah,cmkey
  1689.     call    comnd
  1690.     jnc    remset17
  1691.     ret
  1692.  
  1693. remset10:cmp    bx,302            ; COLLISION?
  1694.     jne    remset12        ; ne = no
  1695.     mov    dx,offset remsfco    ; COLLISION table
  1696.     xor    bx,bx
  1697.     mov    ah,cmkey
  1698.     call    comnd
  1699.     jnc    remset17
  1700.     ret
  1701.  
  1702. remset12:cmp    bx,303            ; REPLACE?
  1703.     jne    remset13        ; ne = no
  1704.     mov    dx,offset remsfre    ; REPLACE table
  1705.     xor    bx,bx
  1706.     mov    ah,cmkey
  1707.     call    comnd
  1708.     jnc    remset17
  1709.     ret
  1710.  
  1711. remset13:cmp    bx,310            ; INCOMPLETE?
  1712.     jne    remset13a        ; ne = no
  1713.     mov    dx,offset remsfin    ; INCOMPLETE table
  1714.     xor    bx,bx
  1715.     mov    ah,cmkey
  1716.     call    comnd
  1717.     jnc    remset17
  1718. remset13a:stc
  1719.     ret
  1720.  
  1721. remset14:cmp    bx,310            ; REMOTE SET INCOMPLETE?
  1722.     jne    remset15        ; ne = no
  1723.     push    bx
  1724.     call    remwork            ; write main command
  1725.     pop    bx
  1726.     jmp    short remset13        ; use above to complete the command
  1727.  
  1728. remset15:cmp    bx,3            ; REMOTE SET RECEIVE?
  1729.     jne    remset18        ; ne = no
  1730.     mov    dx,offset remsrcv    ; RECEIVE table
  1731.     xor    bx,bx
  1732.     mov    ah,cmkey
  1733.     call    comnd
  1734.     jnc    remset19        ; get value as text
  1735. remset16:stc
  1736.     ret
  1737.  
  1738. remset17:call    remwork            ; write to buffer
  1739.     jmp    remset22
  1740.                     ; text as last item commands
  1741. remset18:mov    temp,bx
  1742.     cmp    bx,405            ; Transfer?
  1743.     jne    remset19        ; ne = no
  1744.     mov    dx,offset remsxfr    ; TRANSFER table
  1745.     xor    bx,bx
  1746.     mov    ah,cmkey
  1747.     call    comnd
  1748.     jnc    remset19
  1749.     ret
  1750. remset19:call    remwork            ; store command type
  1751.     mov    dx,bufptr        ; store response as text
  1752.     inc    dx            ; skip count byte
  1753.     mov    bx,offset numhlp
  1754.     cmp    temp,405        ; Transfer character set needs string
  1755.     jne    remset20        ; ne = not string
  1756.     mov    bx,offset xfrhlp    ; use this help
  1757. remset20:mov    ah,cmword
  1758.     call    comnd
  1759.     jnc    remset21
  1760.     ret
  1761. remset21:mov    dx,bufptr        ; field pointer
  1762.     inc    dx            ; look at text
  1763.     call    strlen            ; length to cx
  1764.     add    cx,' '            ; compute byte count field
  1765.     mov    bx,bufptr
  1766.     mov    [bx],cl            ; store byte count
  1767.  
  1768. remset22:mov    ah,cmeol        ; get a confirmation
  1769.     call    comnd
  1770.     jnc    remset23
  1771.     ret
  1772. remset23:mov    dx,offset encbuf
  1773.     call    strlen            ; get length
  1774.     mov    cnt,cx            ; length for generic
  1775.     mov    flags.xflg,1        ; response coming to screen
  1776.     jmp    genr9            ; do the operation
  1777.  
  1778.  
  1779. REMSET    ENDP
  1780.  
  1781. ; Remote Set worker. Enter with new numerical value in BX. Writes length
  1782. ; and asciiz value to encbuf and increments buffer pointer bufptr.
  1783. remwork    proc    near
  1784.     mov    di,offset rdbuf        ; temp buffer
  1785.     mov    byte ptr [di],0        ; clear it
  1786.     mov    ax,bx
  1787.     call    dec2di            ; convert value to asciiz
  1788.     mov    dx,offset rdbuf        ; get length to cx
  1789.     call    strlen
  1790.     push    cx            ; save length
  1791.     mov    di,bufptr        ; byte count field
  1792.     add    cl,' '            ; to ascii
  1793.     mov    [di],cl            ; store count byte
  1794.     inc    di
  1795.     pop    cx
  1796.     mov    si,offset rdbuf        ; asciiz data source
  1797.     push    es
  1798.     push    ds
  1799.     pop    es
  1800.     cld
  1801.     rep    movsb            ; copy asciiz data value
  1802.     pop    es
  1803.     mov    byte ptr [di],0        ; insert null terminator
  1804.     mov    bufptr,di
  1805.     ret
  1806. remwork    endp
  1807.  
  1808. ; REMDIS - Get disk usage on remote system
  1809.  
  1810. REMDIS    PROC    NEAR
  1811.     mov    remcmd,'U'        ; Disk usage command
  1812.     mov    rempac,'G'        ; Packet type = generic
  1813.     mov    remlen,1        ; optional text permitted
  1814.     jmp    genric            ; Execute generic Kermit command
  1815. REMDIS    ENDP
  1816.  
  1817.  
  1818. ; REMHEL - Get help about remote commands
  1819.  
  1820. REMHEL    PROC    NEAR
  1821.     mov    remcmd,'H'        ; Help
  1822.     mov    rempac,'G'        ; Packet type = generic
  1823.     mov    remlen,0        ; no text required
  1824.     jmp    genric            ; Execute generic Kermit command
  1825. REMHEL    ENDP
  1826.  
  1827. ; REMTYP - Type a remote file
  1828.  
  1829. REMTYP    PROC    NEAR
  1830.     mov    remcmd,'T'        ; Type the file
  1831.     mov    rempac,'G'        ; Packet type = generic
  1832.     mov    remlen,2        ; text required
  1833.     jmp    genric
  1834. REMTYP    ENDP
  1835.  
  1836. ; REMHOS - Execute a remote host command
  1837.  
  1838. REMHOS    PROC    NEAR
  1839.     mov    remcmd,' '        ; Don't need one
  1840.     mov    rempac,'C'        ; Packet type = remote command
  1841.     mov    remlen,2        ; text required
  1842.     jmp    genric
  1843. REMHOS    ENDP
  1844.  
  1845. ; REMKER - Execute a remote Kermit command
  1846.  
  1847. REMKER    PROC    NEAR
  1848.     mov    remcmd,' '        ; Don't need one
  1849.     mov    rempac,'K'        ; Packet type = remote Kermit command
  1850.     mov    remlen,2        ; text required
  1851.     jmp    short genric
  1852. REMKER    ENDP
  1853.  
  1854. ; REMDIR - Do a directory
  1855.  
  1856. REMDIR    PROC    NEAR
  1857.     mov    remcmd,'D'
  1858.     mov    rempac,'G'        ; Packet type = generic
  1859.     mov    remlen,0        ; no text required
  1860.     jmp    short genric
  1861. REMDIR    ENDP
  1862.  
  1863. ; REMDEL - Delete a remote file
  1864.  
  1865. REMDEL    PROC    NEAR
  1866.      mov    remcmd,'E'
  1867.     mov    rempac,'G'        ; Packet type = generic
  1868.     mov    remlen,2        ; text required
  1869.     jmp    short genric
  1870. REMDEL    ENDP
  1871.  
  1872. ; REMCWD - Change remote working directory
  1873.  
  1874. REMCWD    PROC    NEAR
  1875.     mov    remcmd,'C'
  1876.     mov    rempac,'G'        ; Packet type = generic
  1877.     mov    remlen,0        ; no text required
  1878.     jmp    short genric
  1879. REMCWD    ENDP
  1880.  
  1881. ; REMLOGIN - LOGIN [username [password [account]]]
  1882.  
  1883. REMLOGIN PROC    NEAR
  1884.     mov    remcmd,'I'
  1885.     mov    rempac,'G'        ; Packet type = generic
  1886.     mov    remlen,0        ; no text required
  1887.     jmp    short genric
  1888. REMLOGIN ENDP
  1889.  
  1890. ; REMMSG - Send one line short message to remote screen.
  1891.  
  1892. REMMSG    proc    near
  1893.     mov    remcmd,'M'
  1894.     mov    rempac,'G'
  1895.     mov    remlen,2        ; text required
  1896.     jmp    short genric
  1897. REMMSG    endp
  1898.  
  1899.  
  1900. ; REMWHO - ask for list of remote logged on users
  1901.  
  1902. REMWHO    proc    near
  1903.     mov    remcmd,'W'
  1904.     mov    rempac,'G'
  1905.     mov    remlen,1        ; optional text permitted
  1906.     jmp    short genric
  1907. REMWHO    endp
  1908.  
  1909. ; GENRIC - Send a generic command to a remote Kermit server
  1910. ; remlen = 0: no additional text
  1911. ; remlen = 1: additional text is optional
  1912. ; remlen = 2: additional text is required
  1913. GENRIC    PROC    NEAR
  1914.     mov    si,offset infms3    ; dummy filename for transaction log
  1915.     mov    di,offset diskio.string    ; where such names go
  1916.     call    strcpy            ; move the name
  1917.     mov    bx,offset encbuf    ; where to put text
  1918.     mov    temp,bx            ; where field starts
  1919.     cmp    rempac,'C'        ; Remote Host command? 
  1920.     je    genr2            ; e = yes, no counted string(s)
  1921.     cmp    rempac,'K'        ; Remote Kermit command?
  1922.     je    genr2            ; e = yes, no counted string(s)
  1923. genr1:    mov    ah,remcmd        ; get command letter
  1924.     mov    [bx],ah            ; store in buffer
  1925.     inc    temp            ; inc to data field
  1926.     add    bx,2            ; leave room for type and size
  1927. genr2:    mov    ah,cmline        ; get a line text
  1928.     mov    dx,offset genmsg    ; help message
  1929.     call    comnd
  1930.     jnc    genr3            ; nc = success
  1931.     ret                ; failure
  1932. genr3:    mov    al,ah            ; size
  1933.     xor    ah,ah
  1934.     mov    cnt,ax            ; save it here
  1935.     call    genredir        ; act on any ">filespec" redirection
  1936.     add    temp,ax            ; point to next field
  1937.     cmp    rempac,'C'        ; Remote Host command? 
  1938.     je    genr4            ; e = yes, no counted string(s)
  1939.     cmp    rempac,'K'        ; Remote Kermit command?
  1940.     je    genr4            ; e = yes, no counted string(s)
  1941.     mov    encbuf+1,al        ; size of first field
  1942.     add    encbuf+1,32        ; do tochar function
  1943.     inc    temp            ; include count byte
  1944. genr4:    cmp    al,remlen        ; got necessary command text?
  1945.     jae    genr5            ; ae = yes
  1946.     cmp    remlen,1        ; is text optional?
  1947.     je    genr5            ; e = yes, continue without it
  1948.     mov    dx,offset infms2    ; say need more info
  1949.     mov    ah,prstr
  1950.     int    dos
  1951.     or    errlev,2        ; say cannot receive
  1952.     or    fsta.xstatus,2        ; set status failed
  1953.     mov    kstatus,2        ; global status
  1954.     clc
  1955.     ret
  1956.  
  1957. genr5:    mov    flags.xflg,1        ; output coming to screen
  1958.     cmp    rempac,'K'        ; Remote Kermit command?
  1959.     je    genr8            ; e = yes
  1960.     cmp    rempac,'C'        ; Remote host command? 
  1961.     je    genr8            ; e = no, skip this part
  1962.     cmp    remcmd,'C'        ; change working directory?
  1963.     je    genr7a            ; e = yes, get optional password
  1964.     cmp    remcmd,'I'        ; remote login command?
  1965.     je    genr6            ; e = yes
  1966.     jmp    short genr8        ; neither so no extra prompts here
  1967.  
  1968. genr6:    cmp    cnt,0            ; have user name already?
  1969.     jne    genr7            ; ne = yes
  1970.     mov    dx,offset user        ; prompt for username
  1971.      call    prompt
  1972.     mov    bx,offset encbuf+1    ; skip command letter
  1973.     mov    temp,bx            ; start of field
  1974.     call    input            ; read text
  1975.     jc    genr8            ; c = none
  1976.     mov    temp,bx            ; point to next data field
  1977.  
  1978. genr7:    mov    dx,offset password    ; get optional password
  1979.     call    prompt
  1980. genr7a:    mov    bx,temp            ; where to put the password
  1981.     mov    comand.cmquiet,1    ; turn on quiet mode
  1982.     call    input            ; read in the password
  1983.     mov    comand.cmquiet,0    ; turn off quiet mode
  1984.     jc    genr8            ; c = no text, do not add field
  1985.     mov    temp,bx            ; point to next data field
  1986.                     ;
  1987.     cmp    remcmd,'I'        ; remote login command?
  1988.     jne    genr8            ; ne = no
  1989.     mov    dx,offset account    ; get optional account ident
  1990.     call    prompt
  1991.     mov    bx,temp            ; where this field starts
  1992.     call    input            ; read text
  1993.     jc    genr8            ; c = no text, do not add field
  1994.     mov    temp,bx            ; point to next data field
  1995.                     ; all fields completed
  1996. genr8:    mov    ax,temp            ; pointer to next field
  1997.     sub    ax,offset encbuf    ; minus start of buffer = data length
  1998.     mov    cnt,ax            ; remember size here
  1999.     cmp    flags.cxzflg,'C'    ; Control-C entered?
  2000.     jne    genr9            ; ne = no
  2001.     stc
  2002.     ret                ; return failure
  2003.  
  2004. GENR9:    mov    kstatus,0        ; global status
  2005.     call    ipack            ; Send Init parameters
  2006.     jc    genr11            ; c = failure
  2007.     mov    trans.chklen,1        ; use 1 char for server functions
  2008.     mov    fsta.pretry,0        ; no retries yet
  2009.     mov    pktnum,0
  2010.     cmp    flags.cxzflg,'C'    ; did the user type a ^C?
  2011.     jne    genr10            ; ne = no
  2012.     stc
  2013.     ret                ; return in error state
  2014.  
  2015. genr10:    push    si
  2016.     mov    si,offset rpacket    ; use this packet for reply
  2017.     mov    cx,cnt            ; length  of data
  2018.     call    doenc            ; encode data
  2019.     mov    trans.chklen,1        ; use block check 1 to server
  2020.     mov    ah,rempac        ; packet type
  2021.     mov    rpacket.pktype,ah
  2022.     call    sndpak            ; send the Generic command packet
  2023.     pop    si
  2024.     jc    genr11            ; c = failure
  2025.     mov    rstate,'R'        ; next state is Receive Initiate
  2026.     jmp    READ2            ; file receiver does the rest
  2027.  
  2028. genr11:    mov    flags.xflg,0        ; reset screen output flag
  2029.     xor    ax,ax            ; tell statistics this was a read
  2030.     or    errlev,4         ; DOS error level, failure of REMote cmd
  2031.     mov    fsta.xstatus,4        ; set status
  2032.     mov    kstatus,4        ; global status
  2033.     clc
  2034.     ret
  2035. GENRIC    ENDP
  2036.  
  2037. ; Extract ">filespec" redirection at end of command line. If found put
  2038. ; filespec in auxfile as new output name.
  2039. genredir proc    near
  2040.     mov    cx,cnt            ; chars on command line
  2041.     mov    di,offset encbuf+2    ; buffer, after prologue
  2042.     add    di,cx            ; end of buffer + 1
  2043.     dec    di            ; last char
  2044.     push    ax
  2045.     mov    al,'>'            ; redirection symbol
  2046.     push    es
  2047.     push    ds
  2048.     pop    es
  2049.     std                ; scan backward
  2050.     repne    scasb            ; found '>'?
  2051.     cld
  2052.     pop    es
  2053.     pop    ax
  2054.     jne    genred3            ; ne = no
  2055.     inc    di            ; look at '>'
  2056.     mov    byte ptr[di],0        ; insert terminator
  2057.     mov    ax,cx            ; new count length
  2058.     mov    cnt,cx            ; remember here too
  2059. genred1:inc    di            ; look at optional filename
  2060.     or    di,di            ; terminator?
  2061.     jz    genred2            ; z = yes
  2062.     cmp    byte ptr [di],' '    ; remove lead-in puncutation
  2063.     jbe    genred1            ; be = punctuation, go until text
  2064. genred2:mov    si,di
  2065.     mov    di,offset auxfile    ; new output name goes here
  2066.     call    strcpy
  2067. genred3:ret
  2068. genredir endp
  2069.     
  2070. ; Send    "I" packet with transmission parameters
  2071.  
  2072. IPACK    PROC    NEAR
  2073.     call    serini            ; initialize serial port
  2074.     jnc    ipack1
  2075.     ret                ; c = failure
  2076. ipack1:    call    clrbuf            ; clear serial port buffer
  2077.     call    ihostr            ; initialize the host
  2078.     call    sparmax            ; set up our maximum capabilites
  2079.     mov    trans.windo,1        ; no windows yet
  2080.     mov    rpacket.numtry,0    ; number of receive retries
  2081.     mov    fsta.pretry,0        ; no retries
  2082.     call    makebuf            ; remake buffers
  2083.     mov    pktnum,0        ; packet number 0
  2084.     mov    windlow,0        ; reset windowing
  2085.     call    packlen            ; compute packet length
  2086.     call    getbuf            ; get buffer for sending
  2087.     call    rpar            ; store them in the packet
  2088.     mov    trans.chklen,1        ; one char for server function
  2089.     mov    [si].pktype,'I'        ; "I" packet
  2090.     call    sndpak            ; send the packet
  2091.     jnc    ipack2            ; nc = success
  2092.     ret                ; return failure
  2093. ipack2:    mov    al,[si].seqnum
  2094.     mov    ah,maxtry        ; retry threshold
  2095.     add    ah,ah
  2096.     add    ah,maxtry        ; triple the normal retries
  2097.     call    response        ; get response
  2098.     jnc    ipack3            ; nc = success
  2099.     call    bufclr            ; clear all
  2100.     stc                ; carry set for failure
  2101.     ret                ; return failure
  2102.  
  2103. ipack3:    push    si
  2104.     mov    si,offset rpacket    ; packet address
  2105.     call    spar            ; read in the data
  2106.     pop    si
  2107.     call    packlen            ; get max send packet size
  2108.     call    makebuf            ; remake buffers for new windowing
  2109.     clc
  2110.     ret                ; return success
  2111. IPACK    ENDP
  2112.  
  2113. ; Returns BX the updated pointer to the input buffer
  2114. ;      input buffer = <ascii data length count byte>textstring
  2115. ; return carry clear if have text, else carry set for none
  2116. INPUT    PROC    NEAR
  2117.     mov    temp2,bx        ; where to put byte count
  2118.     inc    bx            ; start text after count byte
  2119.     xor    dx,dx            ; help, none
  2120.     mov    ah,cmline        ; get text with embedded whitespace
  2121.     call    comnd
  2122.     jnc    input1            ; nc = success
  2123.     mov    bx,temp2        ; empty field, restore pointer
  2124.     ret                ; failure
  2125. input1:    push    bx
  2126.     mov    bx,temp2
  2127.     add    ah,' '            ; convert byte count to ascii
  2128.     mov    [bx],ah            ; store count byte
  2129.     pop    bx            ; return pointer to next free byte
  2130.     clc                ; say have bytes
  2131.     ret
  2132. INPUT    ENDP
  2133.  
  2134. code    ends
  2135.     end
  2136.