home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msk316src.zip / MSSSER.ASM < prev    next >
Assembly Source File  |  2001-04-22  |  90KB  |  2,879 lines

  1.     NAME    mssser
  2. ; File MSSSER.ASM
  3.     include mssdef.h
  4. ;    Copyright (C) 1982, 1999, Trustees of Columbia University in the 
  5. ;    City of New York.  The MS-DOS Kermit software may not be, in whole 
  6. ;    or in part, licensed or sold for profit as a software product itself,
  7. ;    nor may it be included in or distributed with commercial products
  8. ;    or otherwise distributed by commercial concerns to their clients 
  9. ;    or customers without written permission of the Office of Kermit 
  10. ;    Development and Distribution, Columbia University.  This copyright 
  11. ;    notice must not be removed, altered, or obscured.
  12. ;
  13. ; Edit history
  14. ; 12 Jan 1995 version 3.14
  15. ; Last edit
  16. ; 12 Jan 1995
  17.  
  18.     public    bye, finish, remote, get, server, denyflg, srvtmo
  19.     public    luser, lpass, queryseg, termserver, retrieve, reget
  20.  
  21. data    segment
  22.     extrn    flags:byte, trans:byte, curdsk:byte, diskio:byte, auxfile:byte
  23.     extrn    comand:byte, filtst:byte, maxtry:byte, dtrans:byte
  24.     extrn    fmtdsp:byte, errlev:byte, fsta:word, kstatus:word
  25.     extrn    rpacket:byte, encbuf:byte, decbuf:byte, sstate:byte
  26.     extrn    rstate:byte, pktnum:byte, windlow:byte, takadr:word
  27.     extrn    prmptr:word, chkparflg:byte, rdbuf:byte, mcctab:byte
  28.     extrn    valtab:byte, echrcnt:word, dostemp:byte, k_rto:word
  29.     extern    delfile_flag:byte, resend_flag:byte, vfile:byte
  30.     extern    crcword:word, lastfsize:dword, sendkind:byte
  31.  
  32. scrser    equ    0209H        ; place for server state display line
  33. scrmsg    equ    0e16H        ; place for Last message
  34.  
  35. remcmd    db    0        ; Remote command to be executed
  36. rempac    db    0        ; Packet type: C (host) or G (generic)
  37. remlen    db    0        ; length of following text field
  38.  
  39. ermes6    db    'Filename too long for packet',0
  40. erms37    db    ' REGET requires SET FILE TYPE BINARY to be given$'
  41. erms38    db    ' REGET requires SET ATTRIBUTES ON to be given$'
  42. cemsg    db    'User intervention',0
  43. infms1    db    'Server mode: type C or Control-C to exit',cr,lf,'$'
  44. infms2    db    cr,lf,'?More parameters are needed$'
  45. infms3    db    'REMOTE command reply',0    ; for transaction logging
  46. infms4    db    'Help text',0            ; filename for REM Help reply
  47. infms5    db    'kermit.tmp',0            ; filename for REM QUERY
  48. remms1    db    ' Unknown server command',0
  49. remms2    db    ' Invalid login information',0
  50. remms3    db    ' Kermit-MS Server ready',0
  51. remms5    db    ' File not found',0
  52. remms6    db    ' Command failed',0
  53. remms7    db    ' REMOTE LOGIN is required',0
  54. remms8    db    ' Command succeeded',0
  55. remms9    db    ' Command is Disabled',0
  56. remms10    db    ' Could not create work file',0
  57. remms11    db    ' Command too long for server',0
  58. byemsg    db    ' Goodbye!',0
  59. whomsg    db    ' Just this Server',0
  60. spcmsg    db    ' bytes available on drive '    ; remote space responses
  61. spcmsg1    db    ' ',0
  62. spcmsg2    db    ' Drive '
  63. spcmsg3    db    ' : is not ready',0
  64. user    db    ' Username: ',0        ; for Remote Login, asciiz
  65. password db    ' Password: ',0        ; for Remote Login and Remote CD
  66. account    db    ' Account: ',0        ; for Remote Login
  67. slogin    db    0            ; non-zero if successful local login
  68. remlog    db    0            ; rem login (1) vs rem logout (0)
  69. luser    db    17 dup (0)        ; local Username, case insenstitive
  70. lpass    db    17 dup (0)        ; local Password, case sensitive
  71. delstr    db    'del ',0
  72. dirstr    db    'dir ',0
  73. queryseg dw    0            ; seg of query response (0=none)
  74. getkind    db    0            ; 4 for recursive GET, else 0
  75.  
  76. crlf    db    cr,lf,'$'
  77. emptymsg db    0            ; empty asciiz msg
  78. skertmp    dw    0            ; REMOTE KERMIT work word
  79. denyflg    dw    0+retflg        ; bit field of denied commands
  80. temp    dw    0
  81. temp2    dw    0
  82. cnt    dw    0
  83. bufptr    dw    0
  84. dsptmp    db    0            ; temp to hold fmtdsp during serving
  85. srvtmo    db    0            ; idle NAK time, default is no NAKs
  86. srvtime    db    0            ; non-zero if timing Server residence
  87. remfnm    db    ' Remote Source File: ',0    ; asciiz
  88. lclfnm    db    ' Local Destination File: ',0    ; asciiz
  89. tmpbuf    db    20 dup (0)
  90. srvbuf    db    128 dup (0)        ; place After tmpbuf, for status
  91. termserver db    0            ; 1 if Connect mode -> server
  92.                     ; >1 if now servicing that invokation
  93. savflg    flginfo    <>            ; save area for flags.*
  94. savflgl    equ    $-savflg        ; length
  95. savdtr    trinfo <>            ; save area for dtrans.*
  96. savdtrl equ    $-savdtr        ; length
  97. savtr    trinfo    <>            ; save area for trans.*
  98. savmaxtry db    0            ; save area for maxtry
  99.  
  100. srvchr    db    'SRGIECKHJV'        ; server cmd characters, use w/srvfun
  101. srvfln    equ    $-srvchr        ; length of table
  102.  
  103. srvfun    dw    srvsnd,srvrcv,srvgen,srvini,srverr,srvhos,srvker ; for srvchr
  104.     dw    srvret,srvrget,srvrcvr
  105.  
  106. srvch2    db    'ACDEFHLMSTUVW'        ; server commands, use with srvdsp
  107. srvfl2    equ    $-srvch2
  108.  
  109. srvdsp    dw    srvpwd,srvcwd,srvdir,srvdel,srvfin,srvhlp,srvlog,srvmsg
  110.     dw    srvset,srvtyp,srvspc,srvvcmd,srvwho
  111.  
  112.  
  113.                     ; Answer from Server to REMOTE HELP
  114. hlprem    db    cr,lf,'Kermit-MS Server commands:',lf
  115.     db    cr,lf,'GET  filespec              '
  116.     db    'REMOTE DIRECTORY filespec REMOTE PWD'
  117.     db    cr,lf,'SEND filespec              '
  118.     db    'REMOTE HELP  this text    REMOTE QUERY'
  119.     db    cr,lf,'BYE, FINISH, REMOTE LOGOUT'
  120.     db    'REMOTE HOST command       REMOTE SET command'
  121.     db    cr,lf,'REMOTE ASSIGN/ASG variable '
  122.     db    'REMOTE LOGIN name passwrd REMOTE SPACE drive-letter'
  123.     db    cr,lf,'REMOTE CD/CWD directory    '
  124.     db    'REMOTE MESSAGE 1-line msg REMOTE TYPE filespec'
  125.     db    cr,lf,'REMOTE DELETE filespec     '
  126.     db    'REMOTE PRINT filespec     REMOTE WHO'
  127.     db    cr,lf
  128.     db    0
  129.  
  130. remtab    db    19            ; 19 entries
  131.     mkeyw    'Assign',remasg
  132.     mkeyw    'Asg',remasg
  133.     mkeyw    'CD',remcwd
  134.     mkeyw    'CWD',remcwd
  135.     mkeyw    'Delete',remdel
  136.     mkeyw    'Directory',remdir
  137.     mkeyw    'Help',remhel
  138.     mkeyw    'Host',remhos
  139.     mkeyw    'Kermit',remker
  140.     mkeyw    'Login',remlogin
  141.     mkeyw    'Logout',remlogout
  142.     mkeyw    'Message',remmsg
  143.     mkeyw    'Print',remprn        ; top of SEND procedure in msssen
  144.     mkeyw    'PWD',rempwd
  145.     mkeyw    'Query',remqry
  146.     mkeyw    'Set',remset
  147.     mkeyw    'Space',remdis
  148.     mkeyw    'Type',remtyp
  149.     mkeyw    'Who',remwho
  150.  
  151. qrytab    db    3                ; REMOTE QUERY kind
  152.     mkeyw    'User','G!'
  153.     mkeyw    'Kermit','K!'
  154.     mkeyw    'System','S!'
  155.  
  156. setval    dw    300,302,310            ; answer REMOTE SET workers
  157.     dw    400,401,402,403,404,405,406
  158. setvlen    equ    ($-setval)/2            ; number of entries
  159. setvec    dw    sftype,sfcoll,sfinc        ; routines paralleling setval
  160.     dw    sblkck,srpkt,srtmo,sretry,sstmo,sxfrch,swind
  161.  
  162. remstt1    db    9            ; REMOTE SET top level table
  163.     mkeyw    'Attributes',1
  164.     mkeyw    'File',2
  165.     mkeyw    'Incomplete',310
  166.     mkeyw    'Block-check',400
  167.     mkeyw    'Receive',3
  168.     mkeyw    'Retry',403
  169.     mkeyw    'Server',404
  170.     mkeyw    'Transfer',405
  171.     mkeyw    'Window-slots',406
  172.  
  173. remsat1    db    2            ; REMOTE SET ATTRIBUTES
  174.     mkeyw    'IN',0
  175.     mkeyw    'OUT',100
  176.  
  177. remsat2    db    17            ; REMOTE ATTRIBUTES {IN} item
  178.                     ; REM ATT {OUT} item is 100 greater
  179.     mkeyw    'All',132
  180.     mkeyw    'Length',133
  181.     mkeyw    'Type',134
  182.     mkeyw    'Date',135
  183.     mkeyw    'Creator',136
  184.     mkeyw    'Account',137
  185.     mkeyw    'Area',138
  186.     mkeyw    'Block-size',139
  187.     mkeyw    'Access',140
  188.     mkeyw    'Encoding',141
  189.     mkeyw    'Disposition',142
  190.     mkeyw    'Protection',143
  191.     mkeyw    'Gprotection',144
  192.     mkeyw    'System-ID',145
  193.     mkeyw    'Format',146
  194.     mkeyw    'Sys-Info',147
  195.     mkeyw    'Byte-count',148
  196.  
  197. remsfit    db    5            ; REMOTE SET FILE
  198.     mkeyw    'Type',300
  199.     mkeyw    'Names',301
  200.     mkeyw    'Collision',302
  201.     mkeyw    'Replace',303
  202.     mkeyw    'Incomplete',310
  203.  
  204. remsfty    db    2            ; REMOTE SET FILE TYPE
  205.     mkeyw    'Text',0
  206.     mkeyw    'Binary',1
  207.  
  208. remsfna    db    2            ; REMOTE SET FILE NAME
  209.     mkeyw    'Converted',0
  210.     mkeyw    'Literal',1
  211.  
  212. remsfco    db    7            ; REMOTE SET FILE COLLISION
  213.     mkeyw    'Append',3
  214.     mkeyw    'Ask',5
  215.     mkeyw    'Backup',2
  216.     mkeyw    'Discard',4
  217.     mkeyw    'Rename',0
  218.     mkeyw    'Replace',1
  219.     mkeyw    'Update',6
  220.  
  221. remsfre    db    2            ; REMOTE SET FILE REPLACE
  222.     mkeyw    'Preserve',0
  223.     mkeyw    'Default',1
  224.  
  225. remsfin    db    2            ; REMOTE SET FILE INCOMPLETE
  226.     mkeyw    'Discard',0
  227.     mkeyw    'Keep',1
  228.  
  229. remsrcv    db    2            ; REMOTE SET RECEIVE
  230.     mkeyw    'Packet-length',401
  231.     mkeyw    'Timeout',402
  232.  
  233. remsxfr    db    2            ; REMOTE SET TRANSFER
  234.     mkeyw    'Character-set',405
  235.     mkeyw    'Mode',410
  236.  
  237. sndswtab db    2            ; Get /switches
  238.     mkeyw    '/recursive',4
  239.     mkeyw    '/nonrecursive',0
  240.  
  241. onoff    db    2            ; ON, OFF table
  242.     mkeyw    'off',0
  243.     mkeyw    'on',1
  244.  
  245. modetab    db    2            ; REMOTE SET TRANSFER MODE
  246.     mkeyw    'Automatic',0
  247.     mkeyw    'Manual',1
  248.  
  249. data    ends
  250.  
  251. data1    segment
  252. inthlp    db    cr,lf,' Time-limit to remain in Server mode, seconds or'
  253.     db    ' specific hh:mm:ss (24h clock).'
  254.     db    cr,lf,' SET TIMER ON to time.  Return for no time limit.$'
  255. filmsg    db    ' Remote filename, or press ENTER for prompts$'
  256. filhlp    db    ' File name to use locally$'
  257. frem    db    ' Name of file on remote system $'
  258. genmsg    db    ' Enter text to be sent to remote server $'
  259. numhlp    db    ' number$'
  260. xfrhlp    db    ' character set identifier string$'
  261. rasghlp1 db    ' name of variable on remote Kermit$'
  262. rasghlp2 db    ' value of variable on remote Kermit$'
  263. remhlp    db    cr,lf,' Command    Action performed by the server Kermit'
  264.     db    cr,lf,' -------    -------------------------------------'
  265.     db    cr,lf,' Assign     variable-name   definition'
  266.     db    cr,lf,' CD/CWD     change working directory'    ; Answer to
  267.     db    cr,lf,' Delete     a file'            ; local
  268.     db    cr,lf,' Directory  filespec'            ; REM HELP
  269.     db    cr,lf,' Help       show server''s remote help screen'
  270.     db    cr,lf,' Host       command  (to remote operating system)'
  271.     db    cr,lf,' Kermit     command  (to Kermit server)'
  272.     db    cr,lf,' Login      name password  to a Kermit server'
  273.     db    cr,lf,' Logout     exit remote Kermit (but keep remote host)'
  274.     db    cr,lf,' Message    short one line message'
  275.     db    cr,lf,' Print      local file  (on server''s printer)'
  276.     db    cr,lf,' PWD        print working directory'
  277.     db    cr,lf,' Query      ask User, Kermit, System variables'
  278.     db    cr,lf,' Set        command  (modify server)'
  279.     db    cr,lf,' Space      drive/directory'
  280.     db    cr,lf,' Type       a file on this screen'
  281.     db    cr,lf,' Who        user parameters$'
  282. data1    ends
  283.  
  284. code1    segment
  285.     extrn bufclr:far, pakptr:far, bufrel:far, makebuf:far, chkwind:far
  286.     extrn firstfree:far, getbuf:far, pakdup:far, rpack:far, fcsrtype:far
  287.     extrn fqryenv:far, fparse:far, strlen:far, strcpy:far,  prtscr:far
  288.     extrn strcat:far, prtasz:far, dec2di:far, malloc:far,isfile:far
  289.     extrn inptim:far, chktmo:far, cdsr:far, dskspace:far, sparmax:far
  290.     extrn rpar:far
  291. code1    ends
  292.  
  293. code    segment
  294.     extrn comnd:near, init:near, serini:near, rrinit:near
  295.     extrn read2:near, spar:near, intmsg:near
  296.     extrn serhng:near, clrbuf:near, clearl:near
  297.     extrn dodec: near, doenc:near, packlen:near, send10:near, errpack:near
  298.     extrn pktsize:near, poscur:near, lnout:near, clrmod:near, ermsg:near
  299.     extrn rprpos:near, crun:near, prompt:near, ihostr:near
  300.     extrn pcwait:far, nvaltoa:near
  301.     extrn nakpak:near, sndpak:near, response:near, dodecom:near
  302.     extrn msgmsg:near, ackpak:near
  303.     extrn takopen_macro:far, takclos:far, setcom:near
  304.     extrn remprn:near
  305.  
  306.     assume    cs:code, ds:data, es:nothing
  307.  
  308. ; Server command
  309.  
  310. SERVER    PROC    NEAR
  311.     mov    ah,cmword        ; get a word 
  312.     mov    bx,offset srvbuf    ; place to put text
  313.     mov    dx,offset inthlp    ; help message
  314.     call    comnd            ; get the pattern text
  315.     jnc    serv1a            ; nc = success
  316.     ret                ; failure
  317. serv1a:    mov    ah,cmeol
  318.     call    comnd
  319.     jnc    serv1b            ; nc = success
  320.     ret
  321. serv1b:    mov    srvtime,0        ; assume not doing timed residence
  322.     mov    si,offset srvbuf
  323.     mov    al,[si]
  324.     or    al,al            ; any time given?
  325.     jz    serv4            ; z = no
  326.     cmp    al,'0'            ; numeric or colon?
  327.     jb    serv2            ; b = not proper time value
  328.     cmp    al,':'            ; this covers the desired range
  329.     ja    serv2            ; a = no proper time value
  330.     call    inptim            ; convert text to timeout tod
  331.     jnc    serv3            ; c = syntax errors in time
  332. serv2:    stc                ; failure
  333.     ret
  334.  
  335. serv3:    mov    srvtime,1        ; say doing timed residence
  336. serv4:    or    flags.remflg,dserver    ; signify we are a server now
  337.     call    clrbuf            ; clear serial port buffer of junk
  338.     test    denyflg,pasflg        ; Login required?
  339.     jnz    serv4a            ; nz = no
  340.     or    denyflg,pasflg        ; assume no login info required
  341.     mov    al,luser        ; check for user/password required
  342.     or    al,lpass        ; if both null then no checks
  343.     jz    serv4a            ; z = null, no name/pass required
  344.     and    denyflg,not pasflg    ; say need name/password
  345. serv4a:    mov    dsptmp,0        ; assume no formatted server display
  346.     mov    al,dtrans.xchset    ; reset Transmission char set
  347.     mov    trans.xchset,al        ;  to the current user default
  348.     mov    al,dtrans.xtype        ; ditto for File Type
  349.     mov    trans.xtype,al
  350.     mov    si,offset flags        ; main flags structure
  351.     mov    di,offset savflg    ; save area
  352.     mov    cx,savflgl        ; length in bytes
  353.     push    es
  354.     push    ds
  355.     pop    es
  356.     cld
  357.     rep    movsb            ; save all of them
  358.     mov    si,offset dtrans    ; default transmission parameters
  359.     mov    di,offset savdtr    ; save area
  360.     mov    cx,savdtrl        ; length
  361.     rep    movsb            ; save all of them
  362.     mov    si,offset trans        ; active transmission paramters
  363.     mov    di,offset savtr        ; save area
  364.     mov    cx,savdtrl        ; same length
  365.     rep    movsb
  366.     mov    al,maxtry
  367.     mov    savmaxtry,al
  368.     pop    es
  369.     mov    si,offset rpacket    ; dummy packet
  370.     mov    rpacket.datlen,0    ; declare to be empty
  371.     call    spar            ; setup minimum operating conditions
  372.     cmp    termserver,0        ; invoked by terminal emulator?
  373.     je    serv4b            ; e = no
  374.     mov    rpacket.seqnum,0
  375.     call    nakpak            ; NAK the packet, uses rpacket
  376.     inc    termserver        ; say reacting to request
  377. serv4b:    test    flags.remflg,dquiet    ; quiet display?
  378.     jnz    serv9            ; nz = yes
  379.     mov    ah,prstr
  380.     mov    dx,offset crlf
  381.     int    dos
  382.     test    flags.remflg,dserial     ; serial display?
  383.     jnz    serv5            ; nz = yes
  384.     call    init            ; init formatted display
  385.     call    clrmod            ; but no modeline yet
  386.     mov    dl,fmtdsp
  387.     mov    dsptmp,dl        ; remember state of fmtdsp
  388.     jmp    short serv9
  389.  
  390. serv5:    mov    ah,prstr
  391.     mov    dx,offset infms1    ; say now in server mode
  392.     int    dos
  393.  
  394.                     ; TOP OF SERVER IDLE LOOP
  395. serv9:    test    flags.remflg,dquiet+dserial ; quiet or serial display?
  396.     jnz    serv10            ; nz = yes, do not change screen
  397.     mov    dx,scrmsg        ; move cursor to Last message area
  398.     add    dx,0100H    ; look at line below (DOS does CR/LF first)
  399.     call    poscur
  400.     call    clearl            ; and clear the line
  401.     mov    dl,cr            ; set cursor to left margin
  402.     mov    ah,conout
  403.     int    dos
  404. serv10:    xor    ax,ax
  405.     mov    flags.cxzflg,al        ; clear ^X, ^Z, ^C seen flag
  406.     mov    flags.xflg,al        ; reset X packet flag
  407.     mov    auxfile,al        ; say no override filename
  408.     mov    srvbuf,al        ; work buffer, clear
  409.     mov    al,dsptmp        ; get our fmtdsp state
  410.     mov    fmtdsp,al        ; and restore it
  411.     mov    trans.windo,1        ; but only 1 window slot here
  412.     mov    cx,drpsiz        ; default receive pkt length (94)
  413.     call    makebuf            ; remake all buffers for new windowing
  414.     call    packlen            ; determine max packet length
  415.     mov    dtrans.windo,31        ; set max windowing abilities
  416.     mov    trans.windo,31
  417.     mov    trans.chklen,1        ; checksum len = 1
  418.     mov    pktnum,0        ; pack number resets to 0
  419.     mov    al,srvtmo        ; use server mode timeout
  420.     or    al,al            ; is it zero?
  421.     jz    serv10b            ; z = yes, use regular timeout
  422.     mov    trans.stime,al        ; use this interval in the idle loop
  423. serv10b:call    serini            ; init serial line, just in case
  424.     jnc    serv11            ; nc = success
  425.     jmp    serv20            ; c = failure
  426. serv11:    cmp    srvtime,0        ; doing timed residence?
  427.     je    serv12            ; e = no
  428.     call    chktmo            ; check for time to exit Server mode
  429.     jnc    serv12            ; nc = ok
  430.     jmp    serv20            ; c = timeout, exit server mode
  431.  
  432. serv12:    mov    windlow,0        ; reset windowing
  433.     mov    pktnum,0        ; packet number to be used
  434.     call    getbuf            ; get a buffer
  435.     mov    chkparflg,1        ; check for unexpected parity
  436.     call    rpack            ; receive a packet, si has buffer ptr
  437.     mov    al,dtrans.stime        ; get default timeout interval
  438.     mov    trans.stime,al        ; restore active timeout interval
  439.     jc    serv13            ; c = timeout, bad pkt, intervention
  440.     mov    al,[si].seqnum        ; sequence number received
  441.     mov    rpacket.seqnum,al    ; for our reply
  442.     or    al,al            ; must be sequence number of zero
  443.     jnz    serv13            ; nz = bad packet
  444.     mov    ah,[si].pktype
  445.     cmp    ah,'I'            ; never "decode" S, I, and A packets
  446.     je    serv17            ; e = I packet
  447.     cmp    ah,'S'
  448.     je    serv17
  449.     cmp    ah,'A'
  450.     je    serv17
  451.     call     dodec            ; decode packet to decbuf
  452.     call    bufrel            ; release the packet buffer
  453.     cmp    termserver,0        ; invoked from Connect mode?
  454.     je    serv12a            ; e = no
  455.      mov    termserver,-1        ; signal exit after this command
  456. serv12a:jmp    short serv17        ; dispatch on packet type in ah
  457.  
  458. serv13:    cmp    flags.cxzflg,'C'     ; Control-C?
  459.     je    serv20            ; e = yes, exit server mode
  460.  
  461. serv14:    cmp    flags.cxzflg,'E'    ; ^E protocol abort?
  462.     jne    serv15            ; ne = no
  463.     call    bufclr            ; clear all buffers
  464.     mov    dx,offset cemsg    ; user intervention message for error packet
  465.     call    ermsg
  466.     mov    bx,dx
  467.     call    errpack            ; send error message
  468.     call    intmsg            ; show interrupt msg for Control-C-E
  469.     jmp    serv9
  470.  
  471. serv15:    cmp    [si].pktype,'T'        ; packet type of time-out?
  472.     jne    serv16            ; ne = no
  473.     cmp    termserver,0        ; invoked from Connect mode?
  474.     jne    serv20            ; ne = yes, exit
  475.     cmp    srvtime,0        ; doing timed residence?
  476.     je    serv15a            ; e = no
  477.     call    chktmo            ; check for time to exit Server mode
  478.     jc    serv20            ; c = timeout, exit server mode
  479. serv15a:cmp    srvtmo,0        ; zero server pkt timeout?
  480.     je    serv16            ; e = yes, no NAKing
  481.     mov    rpacket.seqnum,0
  482.     call    nakpak            ; NAK the packet, uses rpacket
  483. serv16:    call    bufrel            ; release the buffer
  484.     jmp    serv9            ; to top of idle loop
  485.  
  486. serv17:    cmp    [si].pktype,'N'        ; received a NAK?
  487.     je    serv18            ; e = yes, ignore it
  488.     push    es
  489.     push    ds
  490.     pop    es            ; set es to data segment
  491.     mov    di,offset srvchr    ; server characters
  492.     mov    cx,srvfln        ; length of command set
  493.     mov    al,ah            ; packet type
  494.     cld
  495.     repne    scasb            ; hunt for it
  496.     pop    es
  497.     je    serv19            ; e = found that kind
  498.     mov    dx,offset remms1    ; say unknown server command
  499.     call    ermsg
  500.     mov    bx,dx
  501.     call    errpack            ; tell the other kermit
  502. serv18:    jmp    serv9            ; get another server command
  503.  
  504. serv19:    sub    di,offset srvchr+1    ; find offset, +1 for pre-increment
  505.     shl    di,1            ; convert to word index
  506.     call    srvfun[di]        ; call the appropriate handler
  507.     jc    serv20            ; c = someone wanted to exit
  508.     cmp    termserver,-1        ; exit after Connect mode command?
  509.     je    serv20            ; e = yes
  510.     jmp    serv9            ; get another server command
  511.  
  512. serv20:    mov    di,offset flags        ; main flags structure
  513.     mov    si,offset savflg    ; save area
  514.     mov    cx,savflgl        ; length in bytes
  515.     push    es
  516.     push    ds
  517.     pop    es
  518.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  519.     mov    ah,flags.cxzflg        ; interruption flag
  520.     cld
  521.     rep    movsb            ; restore all of them
  522.     mov    di,offset dtrans    ; default transmission parameters
  523.     mov    si,offset savdtr    ; save area
  524.     mov    cx,savdtrl        ; length
  525.     rep    movsb            ; restore all of them
  526.     mov    di,offset trans        ; active transmission paramters
  527.     mov    si,offset savtr        ; save area
  528.     mov    cx,savdtrl        ; same length
  529.     rep    movsb
  530.     mov    flags.extflg,al        ; set flag as current
  531.     mov    al,savmaxtry
  532.     mov    maxtry,al
  533.     pop    es
  534.     mov    al,1            ; underline cursor
  535.     call    fcsrtype        ; set IBM-PC cursor to underline
  536.     call    rprpos            ; put prompt here
  537.     and    flags.remflg,not dserver ; say not a server anymore
  538.     mov    termserver,0        ; clear invokation from Terminal
  539.     clc
  540.     ret
  541. SERVER    ENDP
  542.  
  543. ; commands executable while acting as a server
  544.  
  545. ; Validate LOGIN status. Return carry set if login is ok, else
  546. ; send Error Packet saying Login is required (but has not been done) and
  547. ; return carry clear. Carry bit is this way because returning to the server
  548. ; idle loop with carry set exits the server mode.
  549. logchk    proc    near
  550.     test    denyflg,pasflg        ; login required?
  551.     jnz    logchk1            ; nz = no (disabled)
  552.     cmp    slogin,0        ; logged in yet?
  553.     jne    logchk1            ; ne = yes
  554.     mov    dx,offset remms7    ; reply REMOTE LOGIN is required
  555.     call    ermsg
  556.     mov    bx,dx            ; errpack works from bx
  557.     mov    trans.chklen,1        ; reply with 1 char checksum
  558.     call    errpack
  559.     clc                ; say cannot proceed with command
  560.     ret
  561. logchk1:stc                ; say can proceed with command
  562.     ret
  563. logchk    endp
  564.  
  565. ; srvsnd - receives a file that a remote kermit is sending
  566. srvsnd    proc    near
  567.     call    logchk            ; check login status
  568.     jc    srvsnd1            ; c = ok
  569.     ret                ; else have sent error packet
  570. srvsnd1:call    init            ; setup display form
  571.     xor    ax,ax
  572.     test    denyflg,sndflg        ; command disabled?
  573.     jz    srvsnd2            ; z = no
  574.     mov    al,'.'            ; dot+nul forces use of current dir
  575. srvsnd2:mov    word ptr auxfile,ax    ; override name
  576.     mov    rstate,'R'        ; receive initiate state
  577.     jmp    read2            ; packet pointer is SI, still valid
  578. srvsnd    endp
  579.  
  580. ; srvrcv - send a file to a distant kermit and delete source (Retrieve)
  581.  
  582. srvret    proc    near
  583.     test    denyflg,retflg        ; Retrieve disallowed?
  584.     jz    srvret1            ; z = no, perform it
  585.     mov    dx,offset remms9    ; Command is Disabled
  586.     call    ermsg
  587.     mov    bx,dx            ; errpack works from bx
  588.     mov    trans.chklen,1        ; reply with 1 char checksum
  589.     call    errpack
  590.     clc
  591.     ret
  592. srvret1:mov    delfile_flag,1        ; delete files after sending
  593.     jmp    srvrcv            ; send file to remote client
  594. srvret    endp
  595.  
  596. ; srvrcv - send a file to a distant kermit
  597.  
  598. srvrcv    proc    near
  599.     mov    temp,0            ; signal send a file
  600.     call    logchk            ; check login status
  601.     jc    srrcv1            ; c = ok
  602.     mov    delfile_flag,0        ; failed, clear file deletion flag
  603.     ret                ; else have sent error packet
  604. srrcv1:    mov    si,offset decbuf    ; received filename, asciiz from dodec
  605.     test    denyflg,getsflg        ; command enabled?
  606.     jz    srrcv2            ; z = yes
  607.     mov    dx,si            ; source string, from other side
  608.     mov    di,offset srvbuf    ; local path
  609.     mov    si,offset tmpbuf    ; local filename
  610.     call    fparse            ; split string
  611. srrcv2:    mov    di,offset diskio.string    ; destination
  612.     call    strcpy            ; copy filename to diskio.string
  613.     mov    auxfile,0        ; no alias name
  614.     mov    sstate,'S'        ; set sending state
  615.     mov    ax,temp
  616.     mov    resend_flag,al        ; send = 0, reget != 0
  617.     mov    al,trans.xtype
  618.     mov    trans.xtype,0        ; text mode transfer
  619.     push    ax
  620.     push    crcword            ; preserve CRC-16 word
  621.     push    word ptr lastfsize    ; and last sent file size
  622.     push    word ptr lastfsize+2
  623.     call    send10            ; this should send it
  624.     pop    word ptr lastfsize+2
  625.     pop    word ptr lastfsize
  626.     pop    crcword            ; restore CRC-16 word
  627.     pop    ax
  628.     mov    trans.xtype,al
  629.     ret
  630. srvrcv    endp
  631.  
  632. ; Respond to remote request of GET /RECURSIVE
  633. srvrcvr    proc    near
  634.     mov    sendkind,4        ; say recursive send requested
  635.     jmp    srvrcv            ; do rest as regular GET
  636. srvrcvr endp
  637.  
  638. srverr    proc    near            ; incoming Error packet
  639.     clc                ; absorb and ignore
  640.     ret
  641. srverr    endp
  642.  
  643. ; srvrget - send file to remote kermit in response to its reget command
  644. srvrget proc    near
  645.     mov    temp,1            ; signal reget a file
  646.     call    logchk            ; check login status
  647.     jc    srrcv1            ; c = ok
  648.     mov    delfile_flag,0        ; failed, clear file deletion flag
  649.     ret                ; else have sent error packet
  650. srvrget endp
  651.  
  652. ; srvgen - G generic server command dispatcher
  653. ;
  654. srvgen    proc    near
  655.     call    bufrel            ; release buffer
  656.     mov    al,decbuf        ; get first data character from pkt
  657.     cmp    al,'I'            ; LOGIN?
  658.     jne    srvge1            ; ne = no
  659.     jmp    srvlogin        ; yes
  660. srvge1:    call    logchk            ; check login status
  661.     jc    srvge2            ; c = ok
  662.     ret                ; else have sent error packet
  663. srvge2:    push    es
  664.     push    ds
  665.     pop    es            ; set es to data segment
  666.     mov    di,offset srvch2    ; command character list
  667.     mov    cx,srvfl2        ; length of command set
  668.     cld
  669.     repne    scasb            ; hunt for it
  670.     pop    es
  671.     jne    srvgex            ; ne = not found, complain
  672.     sub    di,offset srvch2+1    ; find offset, +1 for pre-increment
  673.     shl    di,1            ; convert to word index
  674.     jmp    srvdsp[di]        ; do the appropriate handler
  675.  
  676. srvgex:    mov    dx,offset remms1    ; reply Unknown server command
  677.     call    ermsg
  678.     mov    bx,dx
  679.     mov    trans.chklen,1        ; reply with 1 char checksum
  680.     call    errpack
  681.     clc
  682.     ret
  683. srvgen    endp
  684.  
  685. ; srvlog - respond to host's BYE and LOGOUT
  686. srvlog    proc    near
  687.     test    denyflg,byeflg        ; BYE/LOGOUT enabled?
  688.     jz    srvlog1            ; z = yes
  689.     call    srvfin            ; do FIN part
  690.     clc                ; c clear = do not exit server
  691.     ret
  692. srvlog1:call    srvfin            ; do FIN part
  693.     mov    flags.extflg,1        ; leave server mode and Kermit
  694.     call    serhng            ; hangup the phone and return
  695.     mov    di,offset flags        ; main flags structure
  696.     mov    si,offset savflg    ; save area
  697.     mov    cx,savflgl        ; length in bytes
  698.     push    es
  699.     push    ds
  700.     pop    es
  701.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  702.     cld
  703.     rep    movsb            ; restore all of them
  704.     mov    di,offset dtrans    ; default transmission parameters
  705.     mov    si,offset savdtr    ; save area
  706.     mov    cx,savdtrl        ; length
  707.     rep    movsb            ; restore all of them
  708.     mov    di,offset trans        ; active transmission paramters
  709.     mov    si,offset savtr        ; save area
  710.     mov    cx,savdtrl        ; same length
  711.     rep    movsb
  712.     mov    flags.extflg,al        ; make flag current
  713.     mov    al,savmaxtry
  714.     mov    maxtry,al
  715.     pop    es
  716.     stc                ; carry set = exit server mode
  717.     ret
  718. srvlog    endp
  719.  
  720. ; srvfin - respond to remote host's Fin command
  721. srvfin    proc    near
  722.     mov    slogin,0        ; say not logged in anymore
  723.     mov    si,offset byemsg    ; add brief msg of goodbye
  724.     mov    di,offset encbuf    ; packet's data field
  725.     call    strcpy            ; copy msg to pkt
  726.     mov    dx,si            ; strlen works on dx
  727.     call    strlen
  728.     push    si
  729.     mov    si,offset rpacket    ; get a reply buffer
  730.     call    doenc            ; encode the reply in encbuf
  731.     pop    si
  732.     mov    trans.chklen,1        ; reply with 1 char checksum
  733.     call    ackpak
  734.     mov    ax,100            ; wait 0.1 sec for client to settle
  735.     call    pcwait
  736.     mov    si,offset rpacket    ; dummy packet
  737.     mov    rpacket.datlen,0    ; declare to be empty
  738.     call    spar            ; setup minimum operating conditions
  739.     test    denyflg,finflg        ; command enabled?
  740.     jz    srfin2            ; z = yes
  741.     clc                ; stay in server mode
  742.     ret
  743. srfin2:    stc                ; stc exits server mode
  744.     ret
  745. srvfin    endp
  746.  
  747. ; srvcwd - handle other side's Remote CWD dirspec
  748. srvcwd    proc    near
  749.     mov    trans.chklen,1        ; reply with 1 char checksum
  750.     test    denyflg,cwdflg        ; is command enabled?
  751.     jz    srcwd1            ; z = yes
  752.     mov    dx,offset remms9    ; say command is disabled
  753.     call    ermsg            ;  to us and
  754.     mov    bx,dx
  755.     call    errpack            ;  to the other Kermit
  756.     clc
  757.     ret
  758. srcwd1:    mov    si,offset decbuf+1    ; point to byte count
  759.     xor    bh,bh
  760.     mov    bl,[si]
  761.     sub    bl,' '            ; remove ascii bias from byte count
  762.     inc    si
  763.     mov    word ptr[si+bx],0    ; make ASCIIZ w/one extra null
  764.     call    cdsr            ; CD common sub-routine
  765.     mov    si,dx            ; returns msg in dx
  766.     mov    di,offset encbuf    ; put in encode buffer
  767.     call    strcpy
  768.     mov    dx,di
  769.     call    strlen            ; get its length to cx
  770.     mov    si,offset rpacket    ; use this packet for the reply
  771.     call    doenc            ; encode reply
  772.     call    ackpak            ; send ACK with data
  773.     clc
  774.     ret
  775. srvcwd    endp
  776.  
  777. ; srvpwd - handle other side's Remote PWD
  778. srvpwd    proc    near
  779.     mov    trans.chklen,1        ; reply with 1 char checksum
  780.     mov    si,offset decbuf    ; result buffer
  781.     mov    word ptr[si],0        ; make ASCIIZ w/one extra null
  782.     call    cdsr            ; CD common sub-routine
  783.     mov    si,dx            ; returns msg in dx
  784.     mov    di,offset encbuf    ; put in encode buffer
  785.     call    strcpy
  786.     mov    dx,di
  787.     call    strlen            ; get its length to cx
  788.     mov    si,offset rpacket    ; use this packet for the reply
  789.     call    doenc            ; encode reply
  790.     call    ackpak            ; send ACK with data
  791.     clc
  792.     ret
  793. srvpwd    endp
  794.  
  795. ; srvtyp - handle other side's Remote Type filename request
  796. ; expects "data" to hold  Tcfilename   where c = # bytes in filename
  797. srvtyp    proc    near
  798.     cmp    decbuf+1,0        ; any data in packet
  799.     je    srtyp2            ; e = no
  800.     mov    cl,decbuf+1        ; get the filename byte count
  801.     sub    cl,' '            ; ascii to numeric
  802.     jle    srtyp2            ; le = no filename or error in length
  803.     xor    ch,ch            ; set up counter
  804.     mov    si,offset decbuf+2    ; received filename, asciiz from rpack
  805.     mov    di,si
  806.     add    di,cx
  807.     mov    byte ptr [di],0        ; make string asciiz
  808.     test    denyflg,typflg        ; paths permitted?
  809.     jz    srtyp1            ; z = yes, else use just filename part
  810.     mov    di,offset srvbuf    ; local path
  811.     mov    si,offset tmpbuf    ; local filename
  812.     mov    dx,offset decbuf+2    ; local string
  813.     call    fparse            ; split string
  814. srtyp1:    mov    di,offset diskio.string    ; copy local filename to destination
  815.     mov    ax,di            ; pointer to filename, for isfile
  816.     call    strcpy            ; do the copy
  817.     call    isfile            ; does it exist?
  818.     jnc    srtyp3            ; nc = yes
  819. srtyp2:    mov    si,offset remms5    ; "File not found"
  820.     mov    di,offset encbuf    ; destination for message
  821.     call    strcpy            ; move the message
  822.     mov    dx,di
  823.     call    strlen            ; length to cx
  824.     mov    si,offset rpacket    ; use this packet for reply
  825.     call    doenc            ; encode
  826.     mov    trans.chklen,1        ; reply with 1 char checksum
  827.     call    ackpak            ; send ACK with message
  828.     clc
  829.     ret
  830.  
  831. srtyp3:    mov    flags.xflg,1        ; say use X packet rather than F pkt
  832.     mov    auxfile,0        ; no alias name
  833.     mov    sstate,'S'        ; remember state
  834.     mov    resend_flag,al        ; send = 0, reget != 0
  835.     mov    al,trans.xtype
  836.     mov    trans.xtype,0        ; text mode transfer
  837.     push    ax
  838.     push    crcword            ; preserve CRC-16 word
  839.     push    word ptr lastfsize    ; and last sent file size
  840.     push    word ptr lastfsize+2
  841.     call    send10            ; this should send it
  842.     pop    word ptr lastfsize+2
  843.     pop    word ptr lastfsize
  844.     pop    crcword            ; restore CRC-16 word
  845.     pop    ax
  846.     mov    trans.xtype,al
  847.     ret
  848. srvtyp    endp
  849.  
  850. ; srvdir - handle other side's Remote Dir filespec(optional) request
  851. srvdir    proc    near
  852.     mov    di,offset decbuf+2      ; received filespec, asciiz from rpack
  853.     xor    cx,cx            ; assume no data in packet
  854.     mov    cl,decbuf+1        ; get the filename byte count
  855.     cmp    cl,' '            ; byte count present and > 0?
  856.     jg    srdir1            ; g = yes
  857.     mov    word ptr [di],0        ; clear data field
  858.     jmp    short srdir2        ; 0 = no info in pkt
  859. srdir1:    sub    cl,' '            ; ascii to numeric
  860.     add    di,cx            ; step to end of filename, terminate
  861.     mov    word ptr [di],0        ; ensure string is asciiz
  862.     mov    di,offset srvbuf    ; local path
  863.     mov    si,offset tmpbuf    ; local filename
  864.     mov    dx,offset decbuf+2    ; local string
  865.     call    fparse            ; split string
  866.     test    denyflg,dirflg        ; paths permitted?
  867.     jz    srdir2            ; z = yes, else use just filename part
  868.     mov    si,offset tmpbuf    ; copy local filename to
  869.     mov    di,offset decbuf+2    ; final filename
  870.     call    strcpy            ; copy just filename to buffer
  871. srdir2:    mov    cl,curdsk        ; current drive number
  872.     add    cl,'A'-1        ; to letter
  873.     cmp    decbuf+3,':'        ; drive specified?
  874.     jne    srdir3            ; ne = no
  875.     cmp    decbuf+2,0        ; drive letter specified?
  876.     je    srdir3            ; e = no
  877.     mov    cl,decbuf+2        ; get drive letter
  878.     and    cl,5fh            ; convert to upper case
  879. srdir3:    call    dskspace        ; check if drive ready (drive => CL)
  880.     jnc    srdir5            ; nc = success (drive is ready)
  881.     mov    spcmsg3,cl        ; insert drive letter
  882.     mov    si,offset spcmsg2    ; say drive not ready
  883.     mov    di,offset encbuf    ; destination for message
  884.     call    strcpy            ; move the message
  885.     mov    dx,di
  886.     call    strlen            ; length to cx
  887.     mov    si,offset rpacket    ; use this packet for reply
  888.     call    doenc            ; encode
  889.     mov    trans.chklen,1        ; reply with 1 char checksum
  890.     call    ackpak            ; send ACK with message
  891.     clc
  892.     ret
  893.  
  894. srdir5:    mov    di,offset srvbuf    ; work area
  895.     mov    si,offset dirstr    ; prepend "dir "
  896.     call    strcpy
  897.     mov    si,offset decbuf+2    ; directory spec, asciiz
  898.     mov    di,offset srvbuf
  899.     call    strcat
  900.  
  901. ; srdir6 does common processing for both REM DIR & REM HOST
  902. SRDIR6:    mov    si,di            ; srvbuf
  903.     mov    di,offset auxfile    ; send-as name is command line
  904.     call    strcpy
  905.     mov    si,offset dostemp    ; add redirection tag " > $kermit$.tmp"
  906.     mov    di,offset srvbuf
  907.     call    strcat
  908.     mov    si,offset srvbuf    ; command pointer for crun
  909.     call    crun
  910. ; fall thru!    jmp    srvtail            ; send contents of temp file
  911. srvdir    endp
  912.  
  913. ; Send contents of dostemp+3 temporary file, or error packet if it does not
  914. ; exist.
  915. srvtail    proc    near
  916.     mov    si,offset dostemp+3    ; get name of temp file
  917.     mov    di,offset diskio.string    ; destination
  918.     call    strcpy            ; copy it there
  919.     mov    ax,di            ; filename pointer for isfile
  920.     call    isfile            ; did we make the temp file?
  921.     jnc    srvtai1            ; nc = yes
  922.     mov    dx,offset remms10    ; "Could not create work file"
  923.     mov    trans.chklen,1        ; reply with 1 char checksum
  924.     call    ermsg
  925.     mov    bx,dx
  926.     call    errpack            ; send the error message
  927.     clc
  928.     ret
  929. srvtai1:mov    flags.xflg,1        ; say use X rather than F packet
  930.     mov    sstate,'S'        ; remember state
  931.     push    crcword            ; preserve CRC-16 word
  932.     push    word ptr lastfsize    ; and last sent file size
  933.     push    word ptr lastfsize+2
  934.     call    SEND10            ; this should send it
  935.     pop    word ptr lastfsize+2
  936.     pop    word ptr lastfsize
  937.     pop    crcword            ; restore CRC-16 word
  938.     mov    flags.xflg,0        ; clear flag
  939.     mov    dx,offset dostemp+3    ; name of temp file
  940.     mov    ah,del2            ; delete the file
  941.     int    dos
  942.     clc
  943.     ret                ; return in any case
  944. srvtail    endp
  945.  
  946. ; srvdel - handle other side's request of Remote Del filespec
  947. srvdel    proc    near
  948.     test    denyflg,delflg        ; command enabled?
  949.     jz    srvdel4            ; z = yes
  950.     mov    dx,offset remms9    ; else give a message
  951.     mov    trans.chklen,1        ; reply with 1 char checksum
  952.     call    ermsg
  953.     mov    bx,dx
  954.     call    errpack            ; back to local kermit
  955.     clc
  956.     ret
  957.  
  958. srvdel4:cmp    decbuf+1,0        ; any data?
  959.     je    srdel1            ; e = no
  960.     xor    bh,bh
  961.     mov    bl,decbuf+1        ; get the filename byte count
  962.     sub    bl,' '            ; ascii to numeric
  963.     jle    srdel3            ; le = nothing there
  964.     mov    decbuf [bx+2],0        ; plant terminator
  965.     mov    ax,offset decbuf+2    ; point to filespec
  966.     call     isfile            ; is/are there any to delete?
  967.     jc    srdel1            ; c = there is none
  968.     test    byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
  969.     jz    srdel2            ; z = not protected
  970. srdel1:    mov    si,offset remms5    ; "File not found"
  971.     mov    di,offset encbuf    ; destination for message
  972.     call    strcpy            ; move the message
  973.     mov    dx,di
  974.     call    strlen            ; length to cx
  975.     mov    si,offset rpacket    ; use this packet for reply
  976.     call    doenc            ; encode
  977.     mov    trans.chklen,1        ; reply with 1 char checksum
  978.     call    ackpak            ; send ACK with message
  979.     clc
  980.     ret
  981.  
  982. srdel2:    mov    di,offset encbuf    ; work area
  983.     mov    si,offset delstr    ; prepend "del "
  984.     call    strcpy
  985.     mov    si,offset decbuf+2    ; append incoming filespec
  986.     call    strcat            ; append to "del "
  987.     mov    si,di            ; set pointer for crun
  988.     call    crun
  989. srdel3:    mov    dx,offset encbuf    ; where command lies
  990.     call    strlen            ; length to cx
  991.     push    si
  992.     mov    si,offset rpacket    ; packet to use for reply
  993.     call    doenc            ; encode reply
  994.     pop    si
  995.     mov    trans.chklen,1        ; reply with 1 char checksum
  996.     call    ackpak
  997.     clc
  998.     ret
  999. srvdel    endp
  1000.  
  1001. ; srvlogin - handle other side's request of REMOTE LOGIN, USERNAME, PASSWORD
  1002.  
  1003. srvlogin proc    near
  1004.     mov    slogin,0        ; say not logged in yet
  1005.     cmp    luser,0            ; local username specified?
  1006.     je    srvlog9            ; e = no, do no checking
  1007.     mov    cl,decbuf+1        ; ascii byte count of username
  1008.     sub    cl,' '            ; to binary
  1009.     jle    srvlog8a        ; le = nothing there, do logout
  1010.     xor    ch,ch
  1011.     mov    si,offset decbuf+2    ; source, username field
  1012.     mov    di,offset luser        ; local username template
  1013.     push    cx
  1014.     mov    ax,cx            ; external username length
  1015.     mov    dx,di
  1016.     call    strlen            ; get length of local username
  1017.     cmp    ax,cx            ; same lengths?
  1018.     pop    cx
  1019.     jne    srvlog8            ; ne = not same length
  1020.     cld
  1021. srvlog2:lodsb                ; remote char
  1022.     mov    ah,[di]            ; local char
  1023.     inc    di
  1024.     or    ax,2020h        ; lower case both
  1025.     cmp    ah,al            ; same?
  1026.     jne    srvlog8            ; ne = no, fail
  1027.     loop    srvlog2            ; continue match
  1028.     cmp    lpass,0            ; local password specified?
  1029.     je    srclog6            ; e = no, don't check incoming p/w
  1030.     mov    cl,decbuf+1        ; username length
  1031.     sub    cl,' '
  1032.     xor    ch,ch            ; clear high byte
  1033.     mov    si,offset decbuf+2    ; skip over username field
  1034.     add    si,cx            ; password length byte
  1035.     mov    cl,[si]            ; ascii count of password bytes
  1036.     sub    cl,' '            ; to binary
  1037.     jc    srvlog8            ; carry means no field
  1038.     inc    si            ; start of password text
  1039.     mov    di,offset lpass        ; local password text, case sensitive
  1040.     push    cx
  1041.     mov    ax,cx            ; external password length
  1042.     mov    dx,di
  1043.     call    strlen            ; length of local password
  1044.     cmp    ax,cx            ; same?
  1045.     pop    cx
  1046.     je    srvlog5            ; e = yes
  1047.     mov    byte ptr [si],20h    ; corrupt external password
  1048.     jmp    short srvlog8        ; fail
  1049. srvlog5:lodsb                ; remote char
  1050.     mov    ah,[di]            ; local char
  1051.     inc    di
  1052.     cmp    ah,al            ; same?
  1053.     jne    srvlog8            ; ne = no, fail
  1054.     loop    srvlog5            ; do all chars
  1055. srclog6:mov    slogin,1        ; declare user logged-in
  1056.     jmp    short srvlog9        ; ACK with brief message
  1057.  
  1058. srvlog8:mov    si,offset remms2    ; say invalid login information
  1059.     jmp    short srvlog10
  1060.  
  1061. srvlog8a:mov    si,offset byemsg    ; say logging out (empty username)
  1062.     jmp    short srvlog10
  1063.  
  1064. srvlog9:mov    si,offset remms3    ; welcome aboard message
  1065.     mov    slogin,1        ; say logged in successfully
  1066. srvlog10:mov    di,offset encbuf    ; copy to here
  1067.     call    strcpy
  1068.     mov    dx,di            ; where command lies
  1069.     call    strlen            ; length to cx
  1070.     push    si
  1071.     mov    si,offset rpacket    ; packet to use for reply
  1072.     call    doenc            ; encode reply
  1073.     pop    si
  1074.     mov    trans.chklen,1        ; reply with 1 char checksum
  1075.     call    ackpak
  1076.     clc
  1077.     ret
  1078. srvlogin endp
  1079.  
  1080. ; srvvcmd dispatch remote V generic commands from client
  1081. srvvcmd    proc    near
  1082.     cmp    word ptr decbuf+1,'Q!'    ; Query?
  1083.     jne    srvvcmd1        ; ne = no
  1084.     test    denyflg,qryflg        ; command enabled?
  1085.     jz    srvqry            ; z = yes
  1086.     mov    dx,offset remms9    ; else give a message
  1087.     jmp    srvvcmd5
  1088.  
  1089. srvvcmd1:cmp    word ptr decbuf+1,'S!'    ; Set/define?
  1090.     jne    srvvcmd2        ; ne = no
  1091.     test    denyflg,defflg        ; command enabled?
  1092.     jz    srvvcmd2        ; z = yes
  1093.     mov    bx,offset remms9    ; else give a message
  1094.     jmp    short srvvcmd5
  1095. srvvcmd2:jmp    srvdef            ; do the set/define
  1096.  
  1097. srvvcmd3:mov    bx,offset remms1    ; "Unknown server command"
  1098. srvvcmd5:mov    trans.chklen,1        ; reply with 1 char checksum
  1099.     call    errpack            ; send error message in ptr bx
  1100.     clc
  1101.     ret
  1102. srvvcmd    endp
  1103.  
  1104. ; srvqry - query from remote client
  1105. ; expect packet (decbuf) to hold  V<len 1>Q<len 1>{G,K,S}<len><name>
  1106. srvqry    proc    near
  1107.     push    es
  1108.     mov    si,seg encbuf
  1109.     mov    es,si
  1110.     cld
  1111.     mov    si,offset decbuf+3    ; source buffer, skip V!Q
  1112.     lodsb
  1113.     cmp    al,'!'            ; check syntax, one letter
  1114.     jne    srvqry10        ; ne = fail
  1115.     lodsb                ; letter
  1116.     mov    dl,al            ; save letter around this work
  1117.     lodsb                ; length
  1118.     sub    al,' '            ; remove ASCII bias
  1119.     xor    ah,ah
  1120.     mov    cx,ax            ; get length for copy
  1121.     cmp    dl,'G'            ; User?
  1122.     jne    srvqry1            ; ne = no
  1123.     call    srvqmac            ; call worker for sub variables
  1124.     jmp    short srvqry3        ; package the ACK
  1125.  
  1126. srvqry1:cmp    dl,'S'            ; System?
  1127.     jne    srvqry2            ; ne = no
  1128.     call    fqryenv            ; query environment, in msscmd
  1129.     jmp    short srvqry3
  1130.  
  1131. srvqry2:cmp    dl,'K'            ; Kermit?
  1132.     jne    srvqry10        ; ne = no, fail
  1133.     call    srvqvar
  1134.  
  1135. srvqry3:mov    si,offset rpacket    ; use this packet for reply
  1136.     mov    temp,cx            ; preserve original length
  1137.     call    doenc            ; encode, cx has length
  1138.     cmp    echrcnt,0        ; did all fit within one packet?
  1139.     jne    srvqry4            ; no, send as file
  1140.     mov    trans.chklen,1        ; reply with 1 char checksum
  1141.     call    ackpak            ; send ACK with message
  1142.     pop    es
  1143.     clc
  1144.     ret
  1145. srvqry4:mov    dx,offset dostemp+3    ; use filename of $kermit$.tmp
  1146.     mov    ah,creat2        ; create the file
  1147.     xor    cx,cx            ; attributes r/w
  1148.     int    dos
  1149.     jc    srvqry5            ; c = could not open
  1150.     mov    dx,offset encbuf    ; source
  1151.     mov    cx,temp            ; length
  1152.     mov    bx,ax            ; handle
  1153.     mov    ah,write2        ; write to file
  1154.     int    dos            ; write the info
  1155.     mov    ah,close2    ; close the file so we can reread it below
  1156.     int    dos
  1157. srvqry5:mov    si,offset infms5    ; pseudo filename
  1158.     mov    di,offset auxfile    ; send-as name
  1159.     call    strcpy            ; copy it there
  1160.     jmp    srvtail            ; send temporary file to remote screen
  1161.  
  1162. srvqry10:mov    bx,offset remms6    ; "Command failed"
  1163.     mov    trans.chklen,1        ; reply with 1 char checksum
  1164.     call    errpack            ; send error message in ptr bx
  1165.     pop    es
  1166.     clc
  1167.     ret
  1168. srvqry    endp
  1169.  
  1170. ; Worker for srvqry. Enter with macro name in decbuf+6
  1171. ; and length in byte decbuf+5 (has ' ' bias).
  1172. ; Return carry clear and macro definition in encbuf, length in CX,
  1173. ; or fail with carry set.
  1174.  
  1175. srvqmac    proc    near
  1176.     mov    si,offset mcctab    ; table of macro names
  1177.     cld
  1178.     lodsb
  1179.     mov    cl,al            ; number of macro entries
  1180.     xor    ch,ch
  1181.     jcxz    srvmac9            ; z = none
  1182. srvmac4:push    cx            ; save loop counter
  1183.     lodsw                ; length of macro name
  1184.     mov    cl,decbuf+5        ; length of desired name
  1185.     sub    cl,' '            ; remove ASCII bias
  1186.     xor    ch,ch
  1187.     cmp    ax,cx            ; mac name shorter that user spec?
  1188.     jb    srvmac6            ; b = yes, no match
  1189.     push    ax
  1190.     push    si            ; save these around match test
  1191.     mov    di,offset decbuf+6    ; user's string
  1192. srvmac5:mov    ah,[di]
  1193.     inc    di
  1194.     lodsb                ; al = mac name char, ah = user char
  1195.     and    ax,not 2020h        ; clear bits (uppercase chars)
  1196.     cmp    ah,al            ; same?
  1197.     loope    srvmac5            ; while equal, do more
  1198.     pop    si            ; restore regs
  1199.     pop    ax
  1200.     je    srvmac7            ; e = match
  1201. srvmac6:add    si,ax            ; point to next name, add name length
  1202.     add    si,2            ;  and string pointer
  1203.     pop    cx            ; recover loop counter
  1204.     loop    srvmac4            ; one less macro to examine
  1205.     jmp    short srvmac9        ; send empty ACK
  1206.  
  1207. srvmac7:pop    cx            ; interior loop counter
  1208.     cmp    byte ptr [si],0        ; name starts with null char?
  1209.     jne    srvmac8            ; ne = no
  1210.     xor    cx,cx            ; length of result to zero
  1211.     jmp    srvmac9            ; yes, TAKE file, ignore
  1212. srvmac8:mov    ax,seg encbuf        ; buffer where encoder will operate
  1213.     mov    es,ax
  1214.     mov    di,offset encbuf
  1215.     mov    ax,[si-2]        ; length of macro name
  1216.     add    si,ax            ; skip over name
  1217.     push    DS
  1218.     mov    ds,[si]            ; segment of string structure
  1219.     xor    si,si            ; ds:si = address of count + string
  1220.     mov    cx,ds:[si]        ; length of string
  1221.     mov    bx,cx            ; save length over copy
  1222.     add    si,2            ; si = offset of string text proper
  1223.     rep    movsb            ; copy to encbuf
  1224.     pop    DS
  1225.     mov    cx,bx            ; get length again
  1226.     clc
  1227.     ret
  1228. srvmac9:xor    cx,cx            ; fail
  1229.     stc
  1230.     ret
  1231. srvqmac    endp
  1232.  
  1233.  
  1234. ; Worker for srvqry. Enter with variable (\v(..)) name in decbuf+6
  1235. ; and length in byte decbuf+5 (has ' ' bias).
  1236. ; Return carry clear and macro definition in encbuf, length in CX,
  1237. ; or fail with carry set.
  1238.  
  1239. srvqvar    proc    near
  1240.     mov    cl,decbuf+5        ; length of user spec
  1241.     sub    cl,' '
  1242.     xor    ch,ch
  1243.     jcxz    srvqvar4        ; z = empty user spec, fail
  1244.     mov    si,offset valtab    ; table of variable names
  1245.     mov    di,offset encbuf    ; output buffer
  1246.     cld
  1247.     lodsb
  1248.     mov    cl,al            ; number of variable entries
  1249.     xor    ch,ch
  1250.     jcxz    srvqvar4        ; z = none
  1251. srvqvar1:push    cx            ; save loop counter
  1252.     mov    cl,decbuf+5        ; length of user spec
  1253.     sub    cl,' '
  1254.     xor    ch,ch
  1255.     lodsw                ; length of var name, incl ')'
  1256.     push    ax            ; save length
  1257.     dec    ax            ; omit ')'
  1258.     cmp    ax,cx            ; var name shorter that user spec?
  1259.     pop    ax            ; recover full length
  1260.     jb    srvqvar2a        ; b = yes, no match
  1261.     push    ax
  1262.     push    si            ; save these around match test
  1263.     mov    di,offset decbuf+6    ; user's string
  1264. srvqvar2:mov    ah,[di]
  1265.     inc    di
  1266.     lodsb                ; al = var name char, ah = user char
  1267.     and    ax,not 2020h        ; clear bits (uppercase chars)
  1268.     cmp    ah,al            ; same?
  1269.     loope    srvqvar2        ; while equal, do more
  1270.     pop    si            ; restore regs
  1271.     pop    ax
  1272.     je    srvqvar3        ; e = found a match
  1273. srvqvar2a:add    si,ax            ; point to next name, add name length
  1274.     add    si,2            ; and string pointer
  1275.     pop    cx            ; recover loop counter
  1276.     loop    srvqvar1        ; one less macro to examine
  1277.     jmp    short srvqvar4        ; no match, fail
  1278.  
  1279. srvqvar3:pop    cx            ; interior loop counter
  1280.     mov    ax,[si-2]        ; length of variable name
  1281.     add    si,ax            ; skip over name
  1282.     mov    bx,[si]            ; get result code to bx
  1283.     xor    dx,dx            ; trim off trailing spaces
  1284.     push    es
  1285.     mov    di,seg encbuf
  1286.     mov    es,di
  1287.     mov    di,offset encbuf
  1288.     call    nvaltoa            ; fill es:di with string
  1289.     pop    es
  1290.     jc    srvqvar4        ; c = failure
  1291.     mov    cx,di            ; di is string length
  1292.     clc
  1293.     ret
  1294.  
  1295. srvqvar4:xor    cx,cx            ; say no match
  1296.     stc                ; fail
  1297.     ret
  1298. srvqvar    endp
  1299.  
  1300. ; srvdef - define local variable from remote client
  1301. ; expect packet (decbuf) to hold  V<len 1>S<len><name><len><value>
  1302. ; final <len> may be a space to say measure long length from pkt contents
  1303. srvdef    proc    near
  1304.     push    es
  1305.     mov    di,seg rdbuf
  1306.     mov    es,di
  1307.     cld
  1308.     mov    di,offset rdbuf+2    ; work buffer
  1309.     mov    si,offset decbuf+3    ; source buffer, skip over V!S
  1310.     lodsb                ; length of name
  1311.     sub    al,' '            ; remove ASCII bias
  1312.     xor    ah,ah
  1313.     mov    cx,ax            ; get length for copy
  1314.     rep    movsb            ; copy name
  1315.     mov    al,' '            ; space separator on output
  1316.     stosb
  1317.     lodsb                ; length of value
  1318.     sub    al,' '            ; remove ASCII bias
  1319.     xor    ah,ah
  1320.     mov    cx,ax            ; get length for copy
  1321.     or    ax,ax            ; given as null (' ')?
  1322.     jnz    srvdef1            ; nz = no, have length
  1323.     mov    dx,si            ; compute length from packet
  1324.     call    strlen            ; yields cx
  1325. srvdef1:rep    movsb            ; copy value string
  1326.     mov    byte ptr es:[di],0    ; null terminator
  1327.     sub    di,offset rdbuf+2    ; length of destination material+2
  1328.     mov    cx,di            ; length for dodecom, uses rdbuf
  1329.     call    dodecom            ; define the macro
  1330.     jc    srvdef5            ; c = failed
  1331.     xor    cx,cx            ; length of ACK data, zero
  1332.     mov    si,offset rpacket    ; use this packet for reply
  1333.     call    doenc            ; encode
  1334.     mov    trans.chklen,1        ; reply with 1 char checksum
  1335.     call    ackpak            ; send ACK with message
  1336.     pop    es
  1337.     clc
  1338.     ret
  1339.  
  1340. srvdef5:mov    bx,offset remms6    ; "Command failed"
  1341.     mov    trans.chklen,1        ; reply with 1 char checksum
  1342.     call    errpack            ; send error message in ptr bx
  1343.     pop    es
  1344.     clc
  1345.     ret
  1346. srvdef    endp
  1347.  
  1348. ; srvspc - handle other side's request of Remote Space
  1349. ; Enable/Disable portion has become obsolete, command is always enabled
  1350. srvspc    proc    near
  1351. ;    test    denyflg,spcflg        ; is command enabled?
  1352. ;    jz    srspc1            ; z = yes
  1353. ;    mov    dx,offset remms9    ; else give a message
  1354. ;    mov    trans.chklen,1        ; reply with 1 char checksum
  1355. ;    call    ermsg
  1356. ;    mov    bx,dx
  1357. ;    call    errpack            ; back to local kermit
  1358. ;    clc
  1359. ;    ret
  1360. srspc1:    xor    cl,cl            ; use current drive
  1361.     cmp    decbuf+1,0        ; any data?
  1362.     je    srspc2            ; e = no
  1363.     mov    cl,decbuf+2        ; get the drive letter
  1364. srspc2:    call    dskspace        ; calculate space, get letter into CL
  1365.     jnc    srspc3            ; nc = success
  1366.     mov    spcmsg3,cl        ; insert drive letter
  1367.     mov    di,offset encbuf    ; encoder buffer
  1368.     mov    si,offset spcmsg2    ; give Drive not ready message
  1369.     call    strcpy
  1370.     jmp    short srspc4        ; send it
  1371. srspc3:    mov    spcmsg1,cl        ; insert drive letter
  1372.     mov    di,offset encbuf    ; destination
  1373.     mov    word ptr[di],'  '    ; space space
  1374.     add    di,2            ; start number here
  1375.     call    lnout            ; convert number to asciiz in [di]
  1376.     mov    si,offset spcmsg    ; trailer of message
  1377.     call    strcat            ; tack onto end of number part
  1378. srspc4:    mov    trans.chklen,1        ; reply with 1 char checksum
  1379.     mov    dx,offset encbuf
  1380.     call    strlen            ; get data size into cx for doenc
  1381.     mov    si,offset rpacket
  1382.     call    doenc            ; encode
  1383.     call    pktsize            ; report packet size
  1384.     call    ackpak
  1385.     clc
  1386.     ret
  1387. srvspc    endp
  1388.  
  1389. ; srvwho - respond to remote host's WHO command.
  1390. srvwho    proc    near
  1391.     mov    si,offset whomsg    ; add brief msg of just us chickens
  1392.     mov    di,offset encbuf    ; encoder source field
  1393.     call    strcpy            ; copy msg to pkt
  1394.     mov    dx,si            ; strlen works on dx
  1395.     call    strlen
  1396.     mov    si,offset rpacket
  1397.     call    doenc            ; encode reply, size is in cx
  1398.     mov    trans.chklen,1        ; reply with 1 char checksum
  1399.     call    ackpak
  1400.     clc
  1401.     ret
  1402. srvwho    endp
  1403.  
  1404. ; srvmsg - respond to remote host's Message (Send) command
  1405. ;  show message on our screen.
  1406. srvmsg    proc    near
  1407.     cmp    decbuf,0        ; any data in the packet?
  1408.     jbe    srvmsg2            ; e = no, just ack the message 
  1409.     cmp    decbuf,'M'        ; Message packet?
  1410.     jne    srvmsg2            ; ne = no, ack and forget
  1411.     test    flags.remflg,dquiet+dserial ; quiet or serial display?
  1412.     jnz    srvmsg1            ; nz = yes
  1413.     mov    dx,scrmsg        ; move cursor to Last message area
  1414.     call    poscur
  1415.     call    clearl            ; and clear the line
  1416. srvmsg1:xor    ch,ch
  1417.     mov    cl,decbuf+1        ; data length
  1418.     sub    cl,' '            ; remove ascii bias
  1419.     jle    srvmsg2            ; le = nothing
  1420.     mov    di,offset decbuf+2    ; main part of message
  1421.     call    prtscr            ; display cx chars on the screen
  1422. srvmsg2:mov    rpacket.datlen,0    ; length
  1423.     mov    trans.chklen,1        ; reply with 1 char checksum
  1424.     call    ackpak
  1425.     clc
  1426.     ret
  1427. srvmsg    endp
  1428.  
  1429.  
  1430. ; srvhos - handle other side's request of REM Host command-line. [jrd]
  1431. ; We execute the command with STDOUT redirected to $kermit$.tmp and then
  1432. ; read and transmit that file to the other end. No such file results in
  1433. ; returning just an error msg ACK packet
  1434. srvhos    proc    near
  1435.     call    logchk            ; check login status
  1436.     jc    srvhos1            ; c = ok
  1437.     ret                ; else have sent error packet
  1438. srvhos1:test    denyflg,hostflg        ; command enabled?
  1439.     jz    srvhos2            ; z = yes
  1440.     mov    trans.chklen,1        ; reply with 1 char checksum
  1441.     mov    dx,offset remms9    ; else give a message
  1442.     call    ermsg
  1443.     mov    bx,dx
  1444.     call    errpack            ; back to local kermit
  1445.     clc
  1446.     ret
  1447.  
  1448. srvhos2:mov    si,offset decbuf    ; received filename, asciiz from dodec
  1449.     mov    di,offset srvbuf    ; destination
  1450.     call    strcpy            ; copy data to srvbuf
  1451.     jmp    SRDIR6            ; do common completion code
  1452. srvhos    endp
  1453.  
  1454. ; Respond to other side's request of Remote Help. Write & read $kermit$.tmp
  1455. srvhlp    proc    near
  1456.     mov    dx,offset dostemp+3    ; use filename of $kermit$.tmp
  1457.     mov    ah,creat2        ; create the file
  1458.     xor    cx,cx            ; attributes r/w
  1459.     int    dos
  1460.     jc    srvhlp1            ; c = could not open
  1461.     mov    dx,offset hlprem    ; data to be sent, strlen uses dx
  1462.     call    strlen            ; put string length in cx
  1463.     mov    bx,ax            ; handle
  1464.     mov    ah,write2        ; write to file
  1465.     int    dos            ; write the info
  1466.     mov    ah,close2    ; close the file so we can reread it below
  1467.     int    dos
  1468. srvhlp1:mov    si,offset infms4    ; pseudo filename
  1469.     mov    di,offset auxfile    ; send-as name
  1470.     call    strcpy            ; copy it there
  1471.     jmp    srvtail            ; send temporary file to remote screen
  1472. srvhlp    endp
  1473.  
  1474. ; srvker - handle other side's request of REM Kermit command-line.
  1475. srvker    proc    near
  1476.     call    logchk            ; check login status
  1477.     jc    srvker8            ; c = ok
  1478.     ret                ; else have sent error packet
  1479. srvker8:test    denyflg,kerflg        ; command enabled?
  1480.     jz    srvker1            ; z = yes
  1481.     mov    trans.chklen,1        ; reply with 1 char checksum
  1482.     mov    dx,offset remms9    ; else give a message
  1483.     call    ermsg
  1484.     mov    bx,dx
  1485.     call    errpack            ; back to local kermit
  1486.     clc
  1487.     ret
  1488.  
  1489. srvker1:call    takopen_macro        ; open a Take macro
  1490.     jc    srvker3            ; c = failed to obtain Take space
  1491.     mov    dx,prmptr        ; get prompt
  1492.     call    prompt              ; prompt user, set reparse address
  1493.     mov    bx,takadr        ; pointer to Take structure
  1494.     mov    skertmp,bx        ; remember it here for cleanup
  1495.     mov    dx,offset decbuf    ; received command, asciiz
  1496.     call    strlen            ; get length into cx
  1497.     mov    si,dx
  1498. srvker6:cmp    byte ptr [si],' '    ; strip leading white space
  1499.     ja    srvker7            ; a = non-white
  1500.     loop    srvker6            ; continue
  1501. srvker7:cmp    cx,8            ; need at least 8 chars "SET xx y"
  1502.     jb    srvker2            ; b = too few, bad command
  1503.     mov    ax,[si]            ; get first two characters
  1504.     or    ax,2020h        ; lower case them
  1505.     cmp    ax,'es'            ; start of "SET"?
  1506.     jne    srvker2            ; ne = no, bad command
  1507.     mov    ax,[si+2]        ; next two
  1508.     or    ax,2020h
  1509.     cmp    ax,' t'            ; rest of "SET "?
  1510.     jne    srvker2            ; ne = no, bad command
  1511.     add    si,4            ; move to end of "SET "
  1512.     sub    cx,4
  1513.     mov    [bx].takcnt,cx        ; number of bytes in command
  1514.     push    es
  1515.     mov    ax,[bx].takbuf        ; segment of Take buffer
  1516.     mov    es,ax
  1517.     mov    di,2            ; place here (skip buf length word)
  1518.     cld
  1519.     rep    movsb
  1520.     mov    al,CR
  1521.     stosb
  1522.     pop    es
  1523.     inc    [bx].takcnt        ; number of bytes in command
  1524.  
  1525.     call    setcom
  1526.     jnc    srvker3            ; nc = success
  1527. srvker2:mov    si,offset remms6    ; "Command failed"
  1528.     jmp    short srvker4
  1529. srvker3:mov    si,offset remms8    ; "Command succeeded"
  1530. srvker4:mov    di,offset encbuf    ; destination for message
  1531.     call    strcpy            ; move the message
  1532.     mov    dx,di
  1533.     call    strlen            ; length to cx
  1534.     mov    si,offset rpacket    ; use this packet for reply
  1535.     call    doenc            ; encode
  1536.     mov    trans.chklen,1        ; reply with 1 char checksum
  1537.     call    ackpak            ; send ACK with message
  1538.     mov    ax,skertmp        ; get old take address
  1539.     cmp    ax,takadr        ; same (still in current Take)?
  1540.     jne    srvker5            ; ne = no
  1541.     call    takclos            ; close the Take file
  1542. srvker5:clc
  1543.     ret
  1544. srvker    endp
  1545.  
  1546. ;  Command                                Code   Values
  1547. ;  REMOTE SET ATTRIBUTES IN ALL            132   0 = OFF, 1 = ON
  1548. ;  REMOTE SET ATTRIBUTES IN LENGTH         133   0 = OFF, 1 = ON
  1549. ;  REMOTE SET ATTRIBUTES IN TYPE           134   0 = OFF, 1 = ON
  1550. ;  REMOTE SET ATTRIBUTES IN DATE           135   0 = OFF, 1 = ON
  1551. ;X  REMOTE SET ATTRIBUTES IN CREATOR        136   0 = OFF, 1 = ON
  1552. ;X  REMOTE SET ATTRIBUTES IN ACCOUNT        137   0 = OFF, 1 = ON
  1553. ;X  REMOTE SET ATTRIBUTES IN AREA           138   0 = OFF, 1 = ON
  1554. ;X  REMOTE SET ATTRIBUTES IN BLOCK-SIZE     139   0 = OFF, 1 = ON
  1555. ;X  REMOTE SET ATTRIBUTES IN ACCESS         140   0 = OFF, 1 = ON
  1556. ;X  REMOTE SET ATTRIBUTES IN ENCODING       141   0 = OFF, 1 = ON
  1557. ;X  REMOTE SET ATTRIBUTES IN DISPOSITION    142   0 = OFF, 1 = ON
  1558. ;X  REMOTE SET ATTRIBUTES IN PROTECTION     143   0 = OFF, 1 = ON
  1559. ;X  REMOTE SET ATTRIBUTES IN GPROTECTION    144   0 = OFF, 1 = ON
  1560. ;X  REMOTE SET ATTRIBUTES IN SYSTEM-ID      145   0 = OFF, 1 = ON
  1561. ;X  REMOTE SET ATTRIBUTES IN FORMAT         146   0 = OFF, 1 = ON
  1562. ;X  REMOTE SET ATTRIBUTES IN SYS-INFO       147   0 = OFF, 1 = ON
  1563. ;X  REMOTE SET ATTRIBUTES IN BYTE-COUNT     148   0 = OFF, 1 = ON
  1564. ;
  1565. ;  REMOTE SET ATTRIBUTES OUT ALL           232   0 = OFF, 1 = ON
  1566. ;  REMOTE SET ATTRIBUTES OUT LENGTH        233   0 = OFF, 1 = ON
  1567. ;  REMOTE SET ATTRIBUTES OUT TYPE          234   0 = OFF, 1 = ON
  1568. ;  REMOTE SET ATTRIBUTES OUT DATE          235   0 = OFF, 1 = ON
  1569. ;X  REMOTE SET ATTRIBUTES OUT CREATOR       236   0 = OFF, 1 = ON
  1570. ;X  REMOTE SET ATTRIBUTES OUT ACCOUNT       237   0 = OFF, 1 = ON
  1571. ;X  REMOTE SET ATTRIBUTES OUT AREA          238   0 = OFF, 1 = ON
  1572. ;X  REMOTE SET ATTRIBUTES OUT BLOCK-SIZE    239   0 = OFF, 1 = ON
  1573. ;X  REMOTE SET ATTRIBUTES OUT ACCESS        240   0 = OFF, 1 = ON
  1574. ;X  REMOTE SET ATTRIBUTES OUT ENCODING      241   0 = OFF, 1 = ON
  1575. ;X  REMOTE SET ATTRIBUTES OUT DISPOSITION   242   0 = OFF, 1 = ON
  1576. ;X  REMOTE SET ATTRIBUTES OUT PROTECTION    243   0 = OFF, 1 = ON
  1577. ;X  REMOTE SET ATTRIBUTES OUT GPROTECTION   244   0 = OFF, 1 = ON
  1578. ;X  REMOTE SET ATTRIBUTES OUT SYSTEM-ID     245   0 = OFF, 1 = ON
  1579. ;X  REMOTE SET ATTRIBUTES OUT FORMAT        246   0 = OFF, 1 = ON
  1580. ;X  REMOTE SET ATTRIBUTES OUT SYS-INFO      247   0 = OFF, 1 = ON
  1581. ;X  REMOTE SET ATTRIBUTES OUT BYTE-COUNT    248   0 = OFF, 1 = ON
  1582. ;
  1583. ;  REMOTE SET FILE TYPE                    300   0 = TEXT, 1 = BINARY
  1584. ;X  REMOTE SET FILE NAMES                   301   0 = CONVERTED, 1 = LITERAL
  1585. ;  REMOTE SET FILE COLLISION               302   0 = RENAME,  1 = REPLACE,
  1586. ;                                                X 2 = BACKUP,  X 3 = APPEND,
  1587. ;                                                4 = DISCARD, X  5 = ASK
  1588. ;X  REMOTE SET FILE REPLACE                 303   0 = PRESERVE, 1 = DEFAULT
  1589. ;  REMOTE SET INCOMPLETE                   310   0 = DISCARD, 1 = KEEP
  1590. ;
  1591. ;  REMOTE SET BLOCK-CHECK                  400   number (1, 2, or 3)
  1592. ;  REMOTE SET RECEIVE PACKET-LENGTH        401   number (10-9024)
  1593. ;  REMOTE SET RECEIVE TIMEOUT              402   number (any, 0 = no timeout)
  1594. ;  REMOTE SET RETRY                        403   number (any, 0 = no limit)
  1595. ;  REMOTE SET SERVER TIMEOUT               404   number (any, 0 = no timeout)
  1596. ;  REMOTE SET TRANSFER CHARACTER-SET       405   Character Set Designator
  1597. ;  REMOTE SET WINDOW-SLOTS                 406   number (1-31)
  1598. ;
  1599. ; Items marked with "X" are ignored by this server
  1600.  
  1601. ; srvset - manage incoming REMOTE SET commands
  1602. ; decode buffer looks like S<len1><value1><len2><value2>
  1603. srvset    proc    near
  1604.     mov    bufptr,offset decbuf+1    ; received command data, asciiz
  1605.     call    srvswk            ; worker to convert first value to ax
  1606.     jc    srvset3            ; c = failure
  1607.     mov    temp,ax            ; save first value here
  1608.     cmp    ax,132            ; before known set?
  1609.     jb    srvset3            ; b = yes, bad
  1610.     mov    di,offset sattr        ; assume SET ATTRIBUTES
  1611.     cmp    ax,148            ; still in range?
  1612.     jbe    srvset2            ; be = yes
  1613.     cmp    ax,232            ; before next range?
  1614.     jb    srvset1            ; b = yes
  1615.     cmp    ax,248            ; still in range?
  1616.     jbe    srvset2            ; be = yes, get final value
  1617. srvset1:push    es            ; do table lookup on other values
  1618.     push    ds
  1619.     pop    es
  1620.     mov    di,offset setval    ; look up other codes in table
  1621.     mov    cx,setvlen
  1622.     cld
  1623.     repne    scasw
  1624.     pop    es
  1625.     mov    bx,offset remms1    ; "Unknown server command", if needed
  1626.     jne    srvset3            ; ne = no match, unknown command
  1627.     sub    di,offset setval+2    ; get displacement
  1628.     mov    di,setvec[di]
  1629. srvset2:call    di            ; call the action routine
  1630.     mov    bx,offset remms6    ; "Command failed", if needed
  1631.     jc    srvset3            ; c = failure
  1632.     mov    si,offset remms8    ; "Command succeeded"
  1633.     mov    di,offset encbuf    ; destination for message
  1634.     call    strcpy            ; move the message
  1635.     mov    dx,di
  1636.     call    strlen            ; length to cx
  1637.     mov    si,offset rpacket    ; use this packet for reply
  1638.     call    doenc            ; encode
  1639.     mov    trans.chklen,1        ; reply with 1 char checksum
  1640.     call    ackpak            ; send ACK with message
  1641.     clc
  1642.     ret
  1643. srvset3:mov    trans.chklen,1        ; reply with 1 char checksum
  1644.     call    errpack            ; send error message in ptr bx
  1645.     clc
  1646.     ret
  1647. srvset    endp
  1648.  
  1649. sattr    proc    near            ; SET ATTRIBUTES IN/OUT ITEM ON/OFF
  1650.     mov    ax,temp            ; get kind of attribute
  1651.     cmp    ax,200            ; the OUT kind?
  1652.     jb    sattr1            ; b = no, IN kind
  1653.     sub    ax,100            ; merge to same thing
  1654. sattr1:    cmp    ax,132            ; ALL?
  1655.     jne    sattr2            ; be = ok
  1656.     mov    bl,0ffh            ; all bits
  1657.     jmp    short sattr6
  1658. sattr2:    cmp    al,133            ; Length?
  1659.     jne    sattr3            ; ne = no
  1660.     mov    bl,attlen
  1661.     jmp    short sattr6
  1662. sattr3:    cmp    al,134            ; Type
  1663.     jne    sattr4            ; ne = no
  1664.     mov    bl,atttype
  1665.     jmp    short sattr6
  1666. sattr4:    cmp    bl,135            ; Date?
  1667.     jne    sattr5            ; ne = no, fail
  1668.     mov    bl,attdate
  1669.     jmp    short sattr6
  1670. sattr5:    stc                ; fail
  1671.     ret
  1672. sattr6:    call    srvswk            ; get second value to ax, 1 = on
  1673.     jc    sattr5            ; c = failure
  1674.     or    ax,ax            ; off?
  1675.     jnz    sattr7            ; nz = no, on
  1676.     mov    al,flags.attflg        ; current flags
  1677.     not    bl            ; invert selected items
  1678.     and    al,bl            ; turn off selected items
  1679.     mov    flags.attflg,al        ; store the flags
  1680.     clc
  1681.     ret
  1682. sattr7:    cmp    ax,1            ; on?
  1683.     jne    sattr5            ; ne = no, fail
  1684.     or    flags.attflg,bl        ; insert ON selected bits
  1685.     clc    
  1686.     ret
  1687. sattr    endp
  1688.  
  1689. sftype    proc    near            ; SET FILE TYPE
  1690.     call    srvswk            ; get second value to ax
  1691.     jc    sftypb            ; c = failure
  1692.     cmp    al,1
  1693.     ja    sftypb            ; a = bad
  1694.     mov    trans.xtype,al        ; store transfer type
  1695.     mov    dtrans.xtype,al        ; store transfer type
  1696.     clc
  1697.     ret
  1698. sftypb:    stc                ; bad command
  1699.     ret
  1700. sftype    endp
  1701.  
  1702. sfcoll    proc    near            ; SET FILE COLLISION
  1703.     call    srvswk            ; get second value to ax
  1704.     jc    sfcollb            ; c = failure
  1705.     cmp    ax,filecol_update    ; 6, highest value
  1706.     ja    sfcollb            ; a = bad
  1707.     cmp    ax,filecol_backup    ; backup?
  1708.     je    sfcollb            ; e = yes, bad command
  1709. ;;;;;;    cmp    ax,filecol_append    ; append?
  1710. ;;;;;;    je    sfcollb            ; e = yes, bad command
  1711.     mov    flags.flwflg,al        ; set file collison state
  1712.     clc
  1713.     ret
  1714. sfcollb:stc                ; bad command
  1715.     ret
  1716. sfcoll    endp
  1717.  
  1718. sfinc    proc    near             ; SET INCOMPLETE, SET FILE INCOMPLETE
  1719.     call    srvswk            ; get second value to ax
  1720.     jc    sfincb            ; c = failure
  1721.     cmp    ax,1
  1722.     ja    sfincb            ; a = bad
  1723.     xor    al,1            ; invert from wire (wire discard = 0)
  1724.     mov    flags.abfflg,al        ; discard incomplete files if al = 1
  1725.     clc
  1726.     ret
  1727. sfincb:    stc                ; bad command
  1728.     ret
  1729. sfinc    endp
  1730.  
  1731. srtmo    proc    near            ; SET RECEIVE TIMEOUT
  1732.     call    srvswk            ; get second value to ax
  1733.     jnc    srtmo1            ; nc = success
  1734.     ret
  1735. srtmo1:    cmp    ax,94            ; above limit?
  1736.     jbe    srtmo2            ; be = no
  1737.     mov    al,94
  1738. srtmo2:    mov    trans.rtime,al
  1739.     clc
  1740.     ret
  1741. srtmo    endp
  1742.  
  1743. sblkck    proc    near            ; SET BLOCK-CHECK
  1744.     call    srvswk            ; get second value to ax
  1745.     jnc    sblkck1            ; nc = success
  1746.     ret                ; fail
  1747. sblkck1:cmp    ax,3            ; our limit
  1748.     jbe    sblkck2            ; be = safe
  1749.     mov    ax,3            ; set to max
  1750. sblkck2:or    ax,ax            ; too small?
  1751.     jnz    sblkck3            ; z = no
  1752.     inc    ax
  1753. sblkck3:mov    dtrans.chklen,al    ; use this char as initial checksum
  1754.     clc
  1755.     ret
  1756. sblkck    endp
  1757.  
  1758. srpkt    proc    near             ; SET RECEIVE PACKET-LENGTH
  1759.     call    srvswk            ; get second value to ax
  1760.     jnc    srpkt1            ; nc = success
  1761.     ret
  1762. srpkt1:    cmp    ax,9024            ; above limit?
  1763.     jbe    srpkt2            ; be = no
  1764.     mov    ax,9024
  1765. srpkt2:    cmp    ax,20            ; too small?
  1766.     jae    srpkt3            ; ae = no
  1767.     mov    ax,20            ; set minimum
  1768. srpkt3:    mov    dtrans.rlong,ax        ; set long packet size
  1769.     mov    bl,dtrans.rpsiz        ; regular packet size
  1770.     xor    bh,bh
  1771.     cmp    ax,bx            ; is long packet shorter
  1772.     jae    srpkt4            ; ae = no
  1773.     mov    dtrans.rpsiz,al        ; set regular pkt length too
  1774. srpkt4:    clc
  1775.     ret
  1776. srpkt    endp
  1777.  
  1778. sretry    proc    near            ; REMOTE SET RETRY
  1779.     call    srvswk            ; get second value to ax
  1780.     jnc    sretry1            ; nc = success
  1781.     ret                ; fail
  1782. sretry1:cmp    ax,63            ; our limit
  1783.     jbe    sretry2            ; be = safe
  1784.     mov    ax,63            ; set to max
  1785. sretry2:mov    maxtry,al        ; set packet retry limit
  1786.     clc
  1787.     ret
  1788. sretry    endp
  1789.  
  1790. sstmo    proc    near            ; SET SERVER TIMEOUT
  1791.     call    srvswk            ; get second value to ax
  1792.     jnc    sstmo1            ; nc = success
  1793.     ret
  1794. sstmo1:    cmp    ax,255
  1795.     jbe    sstmo2            ; be = in range
  1796.     mov    al,255            ; limit to max
  1797. sstmo2:    mov    srvtmo,al        ; store timeout value
  1798.     clc
  1799.     ret
  1800. sstmo    endp
  1801.  
  1802. sxfrch    proc    near            ; SET TRANSFER CHARACTER-SET string
  1803.     mov    bx,bufptr
  1804.     xor    ch,ch
  1805.     mov    cl,[bx]            ; byte count of next field, if any
  1806.     sub    cl,' '            ; remove ascii bias
  1807.     jnc    sxfrch1            ; nc = is ok
  1808.     ret
  1809. sxfrch1:inc    bx            ; look at character string
  1810.     cmp    byte ptr[bx],'A'    ; A for Transparent?
  1811.     jne    sxfrch2
  1812.     cmp    cx,1            ; just that char?
  1813.     jne    sxfrchb            ; ne = no, fail
  1814.     mov    trans.xchset,0        ; set transfer char set to Transparent
  1815.     clc
  1816.     ret
  1817. sxfrch2:cmp    cx,6            ; "I2/100"?
  1818.     jne    sxfrchb            ; ne = no, fail
  1819.     cmp    word ptr [bx],'2I'    ; length is ok, check spelling
  1820.     jne    sxfrchb            ; ne = failure
  1821.     cmp    word ptr [bx+2],'1/'
  1822.     jne    sxfrchb
  1823.     cmp    word ptr [bx+4],'00'
  1824.     jne    sxfrchb
  1825.     mov    trans.xchset,1        ; set transfer char set to Latin1
  1826.     clc
  1827.     ret
  1828. sxfrchb:stc                ; fail
  1829.     ret
  1830. sxfrch    endp
  1831.  
  1832. swind    proc    near            ; SET WINDOW-SLOTS
  1833.     call    srvswk            ; get second value to ax
  1834.     jnc    swind1            ; nc = success
  1835.     ret
  1836. swind1:    cmp    ax,31            ; max legal
  1837.     jbe    swind2            ; be = in range
  1838.     mov    al,31            ; limit to max
  1839. swind2:    or    ax,ax            ; no windowing?
  1840.     jnz    swind3            ; nz = no, not that way
  1841.     mov    ax,1            ; local min size for no windowing
  1842. swind3:    mov    dtrans.windo,al        ; store default window size
  1843.     clc
  1844.     ret
  1845. swind    endp
  1846.  
  1847. ; Worker for srvset. Reads buffer pointed at by bufptr looking for 
  1848. ; construction <length><numbers>. Returns carry clear and binary number
  1849. ; in AX, else carry set and AX = -1. Bufptr is always updated.
  1850. srvswk    proc    near
  1851.     push    bx
  1852.     push    cx
  1853.     push    dx
  1854.     push    si
  1855.     mov    bx,bufptr
  1856.     xor    ch,ch
  1857.     mov    cl,[bx]            ; byte count of next field, if any
  1858.     sub    cl,' '            ; remove ascii bias
  1859.     jnc    srvswk1            ; nc = is ok
  1860.     mov    ax,-1            ; else say value is -1
  1861.     jmp    short srvswkx
  1862. srvswk1:inc    bx
  1863.     xor    si,si            ; accumulated value
  1864.     mov    dl,10
  1865. srvswk2:mov    ax,si            ; accumulated value
  1866.     mul    dl            ; times 10
  1867.     mov    si,ax            ; store
  1868.     xor    ah,ah
  1869.     mov    al,[bx]            ; get a digit
  1870.     inc    bx
  1871.     sub    al,'0'            ; remove ascii bias
  1872.     jnc    srvswk3            ; nc = no
  1873.     mov    ax,-1            ; say bad value
  1874.     jmp    short srvswkx        ; and quit
  1875. srvswk3:add    si,ax            ; accumulate new digit
  1876.     loop    srvswk2            ; do all digits
  1877.     mov    ax,si            ; return results in ax
  1878.     clc
  1879. srvswkx:mov    bufptr,bx        ; remember where we read from decbuf
  1880.     pop    si
  1881.     pop    dx
  1882.     pop    cx
  1883.     pop    bx
  1884.     ret
  1885. srvswk    endp
  1886.  
  1887. ; srvini - init parms based on 'I' init packet
  1888. srvini    proc    near
  1889.     call    spar            ; parse info
  1890.     call    packlen
  1891.     mov    cx,trans.rlong        ; max receiving pkt length to report
  1892.     call    makebuf            ; remake buffers for new windowing
  1893.     push    si
  1894.     mov    si,offset rpacket
  1895.     call    rpar            ; setup info about our reception
  1896.     pop    si
  1897.     mov    al,trans.chklen        ; checksum length negotiated
  1898.     push    ax            ; save around reply
  1899.     mov    trans.chklen,1        ; reply with 1 char checksum
  1900.     call    ackpak
  1901.     pop    ax            ; restore checksum length
  1902.     mov    dtrans.chklen,al    ;  to negotiation value
  1903.     clc                ; success
  1904.     ret
  1905. srvini    endp
  1906.  
  1907.  
  1908. ; BYE command - tell remote KERSRV to logout & exit to DOS  
  1909.  
  1910. BYE    PROC    NEAR
  1911.     mov    ah,cmeol        ; get a confirm
  1912.     call    comnd
  1913.     jnc    bye1            ; nc = success
  1914.     ret                ; failure
  1915. bye1:    mov    remcmd,'L'        ; Logout command letter
  1916.     call    logo            ; tell the host Kermit to logout
  1917.      jc    bye2            ; c = failed, do not exit
  1918. ;;;    mov    flags.extflg,1        ; set this Kermit's exit flag
  1919.     call    serhng            ; hangup the phone
  1920. bye2:    clc
  1921.     ret
  1922. BYE    ENDP
  1923.  
  1924. ; FINISH - tell    remote KERSRV to exit
  1925.  
  1926. FINISH    PROC    NEAR
  1927.     mov    ah,cmeol        ; get a confirm
  1928.     call    comnd
  1929.     jnc    finish1            ; nc = success
  1930.     ret                ; failure
  1931. finish1:mov    remcmd,'F'        ; Finish command letter
  1932.     call    logo
  1933.     clc
  1934.     ret
  1935. FINISH    ENDP
  1936.  
  1937. ; Common routine for BYE, FINISH, REMOTE LOGOUT. Avoids sending I packet.
  1938. ; Return carry clear for success, else carry set
  1939. LOGO    PROC    NEAR
  1940.     call    serini            ; Initialize port
  1941.     jnc    logo1            ; nc = success
  1942.     ret                ; c = failure
  1943. logo1:    call    clrbuf            ; clear serial port buffer
  1944.     call    ihostr            ; initialize the host
  1945.     mov    trans.windo,1        ; one window slot before negotiations
  1946.     mov    cx,dspsiz        ; default send pkt length (94)
  1947.     call    makebuf            ; set up packet buffers
  1948.     xor    ax,ax
  1949.     mov    diskio.string,al    ; clear local filename for stats
  1950.     mov    pktnum,al        ; packet number to be used
  1951.     mov    windlow,al        ; reset windowing
  1952.     call    packlen            ; get max packet length
  1953.     call    getbuf            ; get buffer for sending
  1954.     mov    trans.chklen,1        ; use one char for server functions
  1955.     mov    ah,remcmd        ; get command letter ('L' or 'F')
  1956.     mov    encbuf,ah        ; encode the command
  1957.     mov    cx,1            ; one piece of data
  1958.     call    doenc            ; do encoding
  1959.     mov    [si].pktype,'G'        ; Generic command packet type
  1960.     mov    flags.xflg,1        ; say receiving to screen
  1961.     call    sndpak            ;  to suppress # pkts msg
  1962.     jc    logo3            ; c = failure
  1963.     mov    al,[si].seqnum        ; get response for this sequence num
  1964.     mov    ah,maxtry        ; retry threshold
  1965.     call    response        ; get response
  1966.     pushf
  1967.     mov    si,offset rpacket    ; packet to look at
  1968.     cmp    [si].pktype,'E'        ; Error packet?
  1969.     je    logo2            ; e = yes, contents displayed already
  1970.     call    msgmsg            ; show any message
  1971. logo2:    popf
  1972. logo3:    mov    flags.cxzflg,0        ; clear these flags
  1973.     mov    flags.xflg,0
  1974.     ret                ; exit with carry flag from response
  1975. LOGO    ENDP
  1976.  
  1977. ; Get files from server, ask for them to be deleted at source afterward.
  1978. RETRIEVE PROC    NEAR
  1979.     mov    delfile_flag,1
  1980.     mov    temp,0
  1981.     mov    getkind,0        ; non-recursive
  1982.     jmp    GET0
  1983. RETRIEVE ENDP
  1984.  
  1985. REGET    PROC    NEAR
  1986.     mov    dx,offset erms37    ; say use Binary mode
  1987.     cmp    dtrans.xtype,1        ; in Binary mode?
  1988.     jne    reget1            ; ne = no, a requirement
  1989.     mov    dx,offset erms38    ; say must use attributes
  1990.     cmp    flags.attflg,0        ; allowed to do file attributes?
  1991.     je    reget1            ; e = no
  1992.     mov    temp,1            ; flag for internal RESEND state (1)
  1993.     mov    getkind,0        ; non-recursive
  1994.     jmp    GET0
  1995. reget1:    mov    ah,prstr
  1996.     int    dos
  1997.     or    fsta.xstatus,kssend+ksgen ; set status, failed + cmd failure
  1998.     mov    kstatus,kssend+ksgen    ; global status
  1999.     stc
  2000.     ret
  2001. REGET    ENDP
  2002.  
  2003. ; GET command. Ask remote server to send the specified file(s)
  2004. ; Queries for remote filename and optional local override path/filename
  2005. GET    PROC    NEAR
  2006.     mov    delfile_flag,0
  2007.     mov    temp,0
  2008.     mov    getkind,0        ; assume non-recursive
  2009.     mov    comand.cmswitch,1    ; parse for optional /switch
  2010.     mov    comand.cmcr,1        ; empty line is ok
  2011.     mov    ah,cmkey
  2012.     mov    dx,offset sndswtab    ; switch table
  2013.     xor    bx,bx            ; no help text
  2014.     call    comnd
  2015.     jc    GET0            ; c = no switch
  2016.     mov    getkind,bl        ; remember switch value
  2017.             ; GET0 is also used by REGET and RETRIEVE above
  2018. GET0:    mov    auxfile,0        ; local name, clear for safety
  2019.     mov    flags.cxzflg,0        ; no Control-C typed yet
  2020.     mov    bx,offset encbuf    ; where to put text
  2021.     mov    dx,offset filmsg    ; help
  2022.     mov    ah,cmword        ; filename w/out embedded whitespace
  2023.     call    comnd
  2024.     jnc    get1            ; nc = success
  2025.     ret                ; failure 
  2026. get1:    mov    cnt,ax            ; remember number of chars we read
  2027.     or    ax,ax            ; read any chars?
  2028.     jnz    get4            ; nz = yes, get optional local name
  2029.                     ; empty line, ask for file names
  2030. get2:    mov    dx,offset remfnm    ; ask for remote name first
  2031.     call    prompt
  2032.     mov    bx,offset encbuf    ; place for remote filename
  2033.         mov    dx,offset frem        ; help message
  2034.     mov    ah,cmline        ; use this for embedded spaces
  2035.     call    comnd            ; get a filename
  2036.     jnc    get3            ; nc = success
  2037.     ret                ; failure
  2038. get3:    mov    cnt,ax            ; remember number of chars read
  2039.     or    ax,ax            ; count of entered chars
  2040.     jz    get2            ; z = none, try again
  2041.     mov    dx,offset lclfnm    ; prompt for local filename
  2042.     call    prompt
  2043. get4:    mov    dx,offset filhlp
  2044.     mov    bx,offset auxfile    ; complete local filename
  2045.     mov    ah,cmword        ; get a word
  2046.     call    comnd
  2047.     jnc    get5            ; nc = success
  2048.     ret                ; failure
  2049. get5:    mov    ah,cmeol        ; get confirmation
  2050.     call    comnd
  2051.     jnc    get6            ; nc = success
  2052.     ret                ; failure
  2053. get6:    cmp    auxfile,'#'        ; is first char a replacement for '?'
  2054.     jne    get7            ; ne = no
  2055.     mov    auxfile,'?'        ; replace '#' by '?'
  2056. get7:    cmp    encbuf,'#'        ; is first char a replacement for '?' ?
  2057.     jne    get8            ; ne = no
  2058.     mov    encbuf,'?'        ; replace '#' by '?'
  2059.  
  2060. get8:    call    rrinit            ; get & clear buffers and counters
  2061.     mov    flags.xflg,1        ; assume writing to screen
  2062.     cmp    flags.destflg,dest_screen ; receiving to screen?
  2063.     je    get8a            ; e = yes, skip screen stuff
  2064.     mov    flags.xflg,0        ; not writing to screen, yet
  2065.     call    init            ; init (formatted) screen
  2066. get8a:    mov    kstatus,kssuc        ; global status, success
  2067.     call    ipack            ; Send Initialize, 'I', packet
  2068.     jnc    get8b            ; nc = success, ok to fail 'I' pkt
  2069.     jmp    short get10        ; failure
  2070.  
  2071. get8b:    mov    si,offset encbuf    ; copy from here
  2072.     mov    di,offset fsta.xname    ; to statistics remote name field
  2073.     call    strcpy
  2074.     mov    di,offset vfile
  2075.     call    strcpy            ; for vfile in mssrcv
  2076.     mov    si,offset rpacket    ; packet for response
  2077.     mov    cx,cnt            ; get back remote filename size
  2078.     call    doenc            ; encode data already in encbuf
  2079.     jnc    get9            ; nc = success
  2080.     mov    dx,offset ermes6        ; filename is too long for pkt
  2081.     call    ermsg
  2082.     mov    bx,dx            ; point to message, for errpack
  2083.     call    errpack            ; tell the host we are quiting
  2084.     jmp    short get10        ; data could not all fit into packet
  2085.  
  2086. get9:    mov    trans.chklen,1        ; use one char for server functions
  2087.     mov    rpacket.pktype,'R'    ; Receive init packet
  2088.     cmp    temp,0            ; not a REGET?
  2089.     je    get9b            ; e = correct
  2090.     mov    rpacket.pktype,'J'    ; make this a REGET
  2091. get9b:    cmp    delfile_flag,0        ; normal GET?
  2092.     je    get9a            ; e = yes
  2093.     mov    rpacket.pktype,'H'    ; Retrieve initiate
  2094. get9a:    cmp    getkind,4        ; recursive?
  2095.     jne    get9c            ; ne = no
  2096.     mov    rpacket.pktype,'V'    ; recursive receive
  2097. get9c:    mov    si,offset rpacket
  2098.     call    sndpak            ; send the packet, no ACK expected
  2099.     jc    get10            ; c = failure to send packet
  2100.     mov    rstate,'R'        ; Set the state to receive initiate
  2101.     jmp    READ2            ; go join read code
  2102.  
  2103. get10:    call    bufclr            ; total failures come here
  2104.     call    rprpos            ; reset cursor for prompt
  2105.     or    errlev,ksrecv        ; set DOS error level to cannot rcv
  2106.     or    fsta.xstatus,ksrecv    ; set status
  2107.     mov    kstatus,ksrecv        ; global status
  2108.     mov    flags.cxzflg,0        ; clear flag for next command
  2109.     mov    auxfile,0        ; clear send-as filename buffer
  2110.     mov    flags.xflg,0        ; clear to-screen flag
  2111.     mov    al,1            ; underline cursor
  2112.     call    fcsrtype        ; set IBM-PC cursor to underline
  2113.     clc
  2114.     ret
  2115. GET    ENDP
  2116.  
  2117. ;    This is the REMOTE command
  2118.  
  2119. REMOTE    PROC    NEAR
  2120.     mov    dx,offset remtab    ; Parse keyword from the REMOTE table
  2121.     mov    bx,offset remhlp
  2122.     mov    ah,cmkey
  2123.     call    comnd
  2124.     jnc    remote1            ; nc = success
  2125.     ret                ; failure
  2126. remote1:push    crcword            ; preserve CRC-16 around remotes
  2127.     push    word ptr lastfsize    ; and last sent file size
  2128.     push    word ptr lastfsize+2
  2129.     call    bx            ; do the appropriate routine
  2130.     pop    word ptr lastfsize+2
  2131.     pop    word ptr lastfsize
  2132.     pop    crcword            ; restore CRC-16
  2133.     ret
  2134. REMOTE    ENDP
  2135.  
  2136. ; REMSET - Execute a REMOTE SET command
  2137.  
  2138. REMSET    PROC    NEAR
  2139.     mov    rempac,'G'        ; Packet type = generic
  2140.     mov    encbuf,'S'        ; command type = Set
  2141.     mov    bufptr,offset encbuf+1    ; place more pkt material here
  2142.     mov    ah,cmkey        ; get keyword
  2143.     mov    dx,offset remstt1    ; table of keywords
  2144.     xor    bx,bx            ; help
  2145.     call    comnd
  2146.     jnc    remset1            ; nc = success
  2147.     ret
  2148. remset1:cmp    bx,1            ; Attributes?
  2149.     jne    remset5            ; ne = no
  2150.     mov    dx,offset remsat1    ; Attributes IN, OUT table
  2151.     xor    bx,bx            ; help
  2152.     mov    ah,cmkey
  2153.     call    comnd
  2154.     jnc    remset2
  2155.     ret
  2156. remset2:mov    temp,bx            ; save in out
  2157.     mov    dx,offset remsat2    ; next attributes keyword table
  2158.     xor    bx,bx            ; help
  2159.     mov    ah,cmkey
  2160.     call    comnd
  2161.     jnc    remset3
  2162.     ret
  2163. remset3:add    bx,temp            ; save final value
  2164.     call    remwork
  2165.     mov    dx,offset onoff        ; ON, OFF table
  2166.     xor    bx,bx            ; help
  2167.     mov    ah,cmkey        ; get on,off
  2168.     call    comnd
  2169.     jnc    remset4
  2170.     ret
  2171. remset4:jmp    remset17
  2172.  
  2173. remset5:cmp    bx,2            ; REMOTE SET FILE?
  2174.     jne    remset14        ; ne = no
  2175.     mov    dx,offset remsfit    ; REM SET FILE table
  2176.     xor    bx,bx            ; help
  2177.     mov    ah,cmkey
  2178.     call    comnd
  2179.     jnc    remset6
  2180.     ret
  2181. remset6:push    bx
  2182.     call    remwork            ; write kind to buffer
  2183.     pop    bx
  2184.     cmp    bx,300            ; TYPE?
  2185.     jne    remset8
  2186.     mov    dx,offset remsfty    ; TYPE table
  2187.     xor    bx,bx
  2188.     mov    ah,cmkey
  2189.     call    comnd
  2190.     jnc    remset6a        ; nc = success
  2191.     ret
  2192. remset6a:push    bx
  2193.     mov    ah,cmeol        ; get a confirmation
  2194.     call    comnd
  2195.     pop    bx
  2196.     jnc    remset6b
  2197.     ret
  2198. remset6b:mov    dtrans.xtype,bl        ; store transfer type
  2199.     mov    trans.xtype,bl        ; store transfer type
  2200.     call    remwork            ; write to buffer
  2201.     jmp    remset23
  2202.  
  2203. remset8:cmp    bx,301            ; NAME?
  2204.     jne    remset10        ; ne = no
  2205.     mov    dx,offset remsfna    ; NAME table
  2206.     xor    bx,bx
  2207.     mov    ah,cmkey
  2208.     call    comnd
  2209.     jnc    remset17
  2210.     ret
  2211.  
  2212. remset10:cmp    bx,302            ; COLLISION?
  2213.     jne    remset12        ; ne = no
  2214.     mov    dx,offset remsfco    ; COLLISION table
  2215.     xor    bx,bx
  2216.     mov    ah,cmkey
  2217.     call    comnd
  2218.     jnc    remset17
  2219.     ret
  2220.  
  2221. remset12:cmp    bx,303            ; REPLACE?
  2222.     jne    remset13        ; ne = no
  2223.     mov    dx,offset remsfre    ; REPLACE table
  2224.     xor    bx,bx
  2225.     mov    ah,cmkey
  2226.     call    comnd
  2227.     jnc    remset17
  2228.     ret
  2229.  
  2230. remset13:cmp    bx,310            ; INCOMPLETE?
  2231.     jne    remset13a        ; ne = no
  2232.     mov    dx,offset remsfin    ; INCOMPLETE table
  2233.     xor    bx,bx
  2234.     mov    ah,cmkey
  2235.     call    comnd
  2236.     jnc    remset17
  2237. remset13a:stc
  2238.     ret
  2239.  
  2240. remset14:cmp    bx,310            ; REMOTE SET INCOMPLETE?
  2241.     jne    remset15        ; ne = no
  2242.     push    bx
  2243.     call    remwork            ; write main command
  2244.     pop    bx
  2245.     jmp    short remset13        ; use above to complete the command
  2246.  
  2247. remset15:cmp    bx,3            ; REMOTE SET RECEIVE?
  2248.     jne    remset18        ; ne = no
  2249.     mov    dx,offset remsrcv    ; RECEIVE table
  2250.     xor    bx,bx
  2251.     mov    ah,cmkey
  2252.     call    comnd
  2253.     jnc    remset19        ; get value as text
  2254. remset16:stc
  2255.     ret
  2256.  
  2257. remset17:call    remwork            ; write to buffer
  2258.     jmp    short remset22
  2259.                     ; text as last item commands
  2260. remset18:mov    temp,bx
  2261.     cmp    bx,405            ; Transfer?
  2262.     jne    remset19        ; ne = no, do common code
  2263.     mov    dx,offset remsxfr    ; TRANSFER table
  2264.     xor    bx,bx
  2265.     mov    ah,cmkey
  2266.     call    comnd
  2267.     jnc    remset18a
  2268.     ret
  2269. remset18a:cmp    bx,410            ; REMOTE SET TRANSFER MODE?
  2270.     jne    remset19        ; ne = no
  2271.     mov    dx,offset modetab    ; Mode table
  2272.     xor    bx,bx
  2273.     mov    ah,cmkey
  2274.     call    comnd
  2275.     jnc    remset17        ; nc = ok, write value to buffer
  2276.     ret
  2277.  
  2278. remset19:call    remwork            ; store command type
  2279.     mov    bx,bufptr        ; store response as text
  2280.     inc    bx            ; skip count byte
  2281.     mov    dx,offset numhlp
  2282.     cmp    temp,405        ; Transfer character set needs string
  2283.     jne    remset20        ; ne = not string
  2284.     mov    dx,offset xfrhlp    ; use this help
  2285. remset20:mov    ah,cmword
  2286.     call    comnd
  2287.     jnc    remset21
  2288.     ret
  2289. remset21:mov    dx,bufptr        ; field pointer
  2290.     inc    dx            ; look at text
  2291.     call    strlen            ; length to cx
  2292.     add    cx,' '            ; compute byte count field
  2293.     mov    bx,bufptr
  2294.     mov    [bx],cl            ; store byte count
  2295.  
  2296. remset22:mov    ah,cmeol        ; get a confirmation
  2297.     call    comnd
  2298.     jnc    remset23
  2299.     ret
  2300. remset23:mov    dx,offset encbuf
  2301.     call    strlen            ; get length
  2302.     mov    cnt,cx            ; length for generic
  2303.     mov    flags.xflg,1        ; response coming to screen
  2304.     jmp    genr9            ; do the operation
  2305. REMSET    ENDP
  2306.  
  2307. ; Remote Set worker. Enter with new numerical value in BX. Writes length
  2308. ; and asciiz value to encbuf and increments buffer pointer bufptr.
  2309. remwork    proc    near
  2310.     mov    di,offset tmpbuf    ; temp buffer
  2311.     mov    byte ptr [di],0        ; clear it
  2312.     mov    ax,bx
  2313.     call    dec2di            ; convert value to asciiz
  2314.     mov    dx,offset tmpbuf    ; get length to cx
  2315.     mov    si,dx            ; asciiz data source
  2316.     call    strlen
  2317.     push    cx            ; save length
  2318.     mov    di,bufptr        ; byte count field
  2319.     add    cl,' '            ; to ascii
  2320.     mov    [di],cl            ; store count byte
  2321.     inc    di
  2322.     pop    cx
  2323.     push    es
  2324.     push    ds
  2325.     pop    es
  2326.     cld
  2327.     rep    movsb            ; copy asciiz data value
  2328.     pop    es
  2329.     mov    byte ptr [di],0        ; insert null terminator
  2330.     mov    bufptr,di
  2331.     ret
  2332. remwork    endp
  2333.  
  2334. ; In REM commands below, al = remcmd, ah = rempac, cl = remlen
  2335.  
  2336. ; REMOTE ASSIGN name value
  2337. ; Packet is GV<count of 1>S<count>name<count>value
  2338. REMASG    PROC    NEAR
  2339.     mov    encbuf,'V'        ; V is set 
  2340.     mov    word ptr encbuf+1,'S!'    ; S for system variable, len 1 (!)
  2341.     mov    encbuf+3,' '        ; count of name string
  2342.     mov    bx,offset encbuf+4    ; buffer for remote variable name
  2343.     mov    dx,offset rasghlp1    ; add help later
  2344.     mov    comand.cmper,1        ; do not react to '\%' in macro name
  2345.     mov    comand.cmblen,94    ; max length encoded in one byte 
  2346.     mov    ah,cmword
  2347.     call    comnd
  2348.     jnc    remasg1            ; nc = success
  2349.     ret                ; failure
  2350. remasg1:add    encbuf+3,al        ; length of variable
  2351.     mov    bx,offset encbuf+4    ; buffer for 'value'
  2352.     add    bx,ax            ; length of variable string
  2353.     mov    byte ptr [bx],' '    ; empty second byte count
  2354.     push    bx
  2355.     inc    bx            ; skip second byte count
  2356.     mov    ax,offset encbuf+512    ; last byte + 1 in encbuf
  2357.     sub    ax,bx            ; minus part already used
  2358.     mov    comand.cmblen,ax    ; length of encbuf available
  2359.     mov    ah,cmline        ; read definition string
  2360.     mov    dx,offset rasghlp2
  2361.     call    comnd
  2362.     pop    bx
  2363.     jnc    remasg2            ; nc = success
  2364.     ret                ; failure
  2365. remasg2:cmp    ax,94            ; longer than fits in one byte?
  2366.     ja    remasg3            ; ae = yes, use <count> of space
  2367.     add    [bx],al            ; length of 'value'
  2368. remasg3:add    bx,ax            ; step to end of string
  2369.     mov    byte ptr [bx+1],0    ; null terminator
  2370.     mov    flags.xflg,1        ; response coming to screen
  2371.     mov    rempac,'G'        ; Generic Kermit command
  2372.     jmp    genr9            ; send the packet after I exchange
  2373. REMASG    ENDP
  2374.  
  2375. ; REMCWD - Change remote working directory
  2376.  
  2377. REMCWD    PROC    NEAR
  2378.     mov    ax,'GC'            ; Packet type = generic
  2379.     xor    cl,cl            ; no text required
  2380.     jmp    genric
  2381. REMCWD    ENDP
  2382.  
  2383. ; REMDEL - Delete a remote file
  2384.  
  2385. REMDEL    PROC    NEAR
  2386.     mov    ax,'GE'            ; Packet type = generic
  2387.     mov    cl,1            ; text required
  2388.     jmp    genric
  2389. REMDEL    ENDP
  2390.  
  2391. ; REMDIR - Do a directory
  2392.  
  2393. REMDIR    PROC    NEAR
  2394.     mov    ax,'GD'            ; Packet type = generic
  2395.     xor    cl,cl            ; no text required
  2396.     jmp    genric
  2397. REMDIR    ENDP
  2398.  
  2399. ; REMDIS - Get disk usage on remote system
  2400.  
  2401. REMDIS    PROC    NEAR
  2402.     mov    ax,'GU'            ; Packet type = generic, disk usage
  2403.     xor    cl,cl            ; optional text permitted
  2404.     jmp    genric            ; Execute generic Kermit command
  2405. REMDIS    ENDP
  2406.  
  2407.  
  2408. ; REMHEL - Get help about remote commands
  2409.  
  2410. REMHEL    PROC    NEAR
  2411.     mov    ax,'GH'            ; Packet type = generic, Help
  2412.     xor    cl,cl            ; no text required
  2413.     jmp    genric            ; Execute generic Kermit command
  2414. REMHEL    ENDP
  2415.  
  2416. ; REMHOS - Execute a remote host command
  2417.  
  2418. REMHOS    PROC    NEAR
  2419.     mov    ax,'C '            ; Packet type = remote command
  2420.     mov    cl,1            ; text required
  2421.     jmp    genric
  2422. REMHOS    ENDP
  2423.  
  2424. ; REMKER - Execute a remote Kermit command
  2425.  
  2426. REMKER    PROC    NEAR
  2427.     mov    ax,'K '            ; Packet type = remote Kermit command
  2428.     mov    cl,1            ; text required
  2429.     jmp    genric
  2430. REMKER    ENDP
  2431.  
  2432. ; REMLOGIN - LOGIN [username [password [account]]]
  2433.  
  2434. REMLOGIN PROC    NEAR
  2435.     mov    ax,'GI'            ; Packet type = generic
  2436.     xor    cl,cl            ; no text required
  2437.     mov    remlog,1        ; do prompts
  2438.     jmp    genric
  2439. REMLOGIN ENDP
  2440.  
  2441. ; REMOTE LOGOUT - Logout of remote server and host, stay in this Kermit
  2442. REMLOGOUT PROC    NEAR
  2443.     mov    ax,'GI'            ; Packet type = generic
  2444.     xor    cl,cl            ; no text required
  2445.     mov    remlog,0        ; skip prompts
  2446.     jmp    genric
  2447.     
  2448.     mov    remcmd,'L'        ; Logout command letter
  2449.     call    logo            ; perform without I packet
  2450.     clc
  2451.     ret
  2452. REMLOGOUT ENDP
  2453.  
  2454. ; REMMSG - Send one line short message to remote screen.
  2455.  
  2456. REMMSG    proc    near
  2457.     mov    ax,'GM'
  2458.     mov    cl,1            ; text required
  2459.     jmp    genric
  2460. REMMSG    endp
  2461.  
  2462. ; REMPWD - print remote's working directory
  2463.  
  2464. REMPWD    PROC    NEAR
  2465.     mov    ah,cmeol
  2466.     call    comnd
  2467.     jnc    rempwd1
  2468.     ret
  2469. rempwd1:mov    ax,'GA'            ; Packet type = generic
  2470.     xor    cl,cl            ; no text required
  2471.     jmp    genric
  2472. REMPWD    ENDP
  2473.  
  2474. ; REMQRY - Remote Query {Kermit | System | User} name
  2475. REMQRY    PROC    NEAR
  2476.     mov    dx,offset qrytab    ; table of query types (K, S, G)
  2477.     xor    bx,bx            ; help is table
  2478.     mov    ah,cmkey        ; get key word
  2479.     call    comnd            ; get pointer to keyword structure
  2480.     jnc    remqry1            ; nc = success, bx = 16 bit data
  2481.     ret                ; failure
  2482. remqry1:mov    encbuf,'V'        ; V is set 
  2483.     mov    word ptr encbuf+1,'Q!'    ; Q for query, len 1 (!)
  2484.     mov    word ptr encbuf+3,bx    ; query count and letter
  2485.     mov    encbuf+5,0        ; count of name string
  2486.     mov    bx,offset encbuf+6    ; buffer for remote variable name
  2487.     mov    dx,offset rasghlp1    ; help msg
  2488.     mov    ah,cmword
  2489.     call    comnd
  2490.     jnc    remqry2            ; nc = success
  2491.     ret                ; failure
  2492. remqry2:add    al,' '            ; add ASCII bias
  2493.     mov    encbuf+5,al        ; length of variable
  2494.     mov    ah,cmeol        ; get c/r confirmation
  2495.     call    comnd
  2496.     jnc    remqry3
  2497.     ret
  2498. remqry3:mov    rempac,'G'        ; Generic Kermit command
  2499.     mov    flags.xflg,1        ; response coming to screen
  2500.     mov    kstatus,kssuc
  2501.     CALL    genr9            ; send the packet after I exchange
  2502.     cmp    kstatus,kssuc        ; success?
  2503.     je    remqry4            ; e = yes
  2504.     mov    decbuf,0        ; empty the definition
  2505. remqry4:push    es
  2506.     mov    ax,queryseg        ; malloc'd memory yet?
  2507.     or    ax,ax
  2508.     jz    remqry5            ; z = no
  2509.     mov    es,ax
  2510.     mov    ah,freemem        ; free it
  2511.     int    dos
  2512.     mov    queryseg,0        ; no segment
  2513.  
  2514. remqry5:mov    si,offset decbuf    ; decoded response, we hope
  2515.     mov    dx,si            ; get length
  2516.     call    strlen
  2517.     mov    ax,cx            ; bytes in string
  2518.     add    ax,2            ; plus count word
  2519.     call    malloc            ; malloc space (ax bytes)
  2520.     jnc    remqry6            ; nc = got the memory
  2521.     xor    cx,cx            ; return cx = 0
  2522.     mov    queryseg,cx
  2523.     pop    es
  2524.     stc                ; fail right now
  2525.     ret
  2526. remqry6:mov    queryseg,ax        ; seg to store into
  2527.     mov    es,ax
  2528.     xor    di,di            ; offset of zero
  2529.     cld
  2530.     mov    ax,cx            ; store length word first
  2531.     stosw
  2532.     rep    movsb            ; copy to output buffer
  2533.     pop    es
  2534.     clc
  2535.     ret
  2536. REMQRY    ENDP
  2537.  
  2538. ; REMTYP - Type a remote file
  2539.  
  2540. REMTYP    PROC    NEAR
  2541.     mov    ax,'GT'            ; Packet type = generic, Type file
  2542.     mov    cl,1            ; text required
  2543.     jmp    short genric
  2544. REMTYP    ENDP
  2545.  
  2546. ; REMWHO - ask for list of remote logged on users
  2547.  
  2548. REMWHO    proc    near
  2549.     mov    ax,'GW'
  2550.     xor    cl,cl            ; optional text permitted
  2551.     jmp    short genric
  2552. REMWHO    endp
  2553.  
  2554. ; GENRIC - Send a generic command to a remote Kermit server
  2555. ; remlen = 0: no additional text, or additional text is optional
  2556. ; remlen = 1: additional text is required
  2557. GENRIC    PROC    NEAR
  2558.     mov    remcmd,al        ; stash cmd info in real memory
  2559.     mov    rempac,ah        ; packet type
  2560.     mov    remlen,cl        ; text required flag
  2561.     mov    si,offset infms3    ; dummy filename for transaction log
  2562.     mov    di,offset diskio.string    ; where such names go
  2563.     call    strcpy            ; move the name
  2564.     mov    bx,offset encbuf    ; where to put text
  2565.     mov    temp,bx            ; where field starts
  2566.     cmp    rempac,'C'        ; Remote Host command? 
  2567.     je    genr2            ; e = yes, no counted string(s)
  2568.     cmp    rempac,'K'        ; Remote Kermit command?
  2569.     je    genr2            ; e = yes, no counted string(s)
  2570. genr1:    mov    ah,remcmd        ; get command letter
  2571.     mov    [bx],ah            ; store in buffer
  2572.     add    bx,2            ; leave room for count byte
  2573.     mov    temp,bx            ; point at data field
  2574. genr2:    mov    ah,cmword        ; get trailing optional password
  2575.     mov    dx,offset genmsg    ; help message
  2576.     cmp    remcmd,'C'        ; Remote Change Working Directory?
  2577.     je    genr2a            ; e = yes, get optional password
  2578.     mov    ah,cmline        ; get a line text
  2579. genr2a:    call    comnd
  2580.     jnc    genr3            ; nc = success
  2581.     ret                ; failure
  2582. genr3:    mov    cnt,ax            ; size
  2583.     call    genredir        ; act on any ">filespec" redirection
  2584.     add    temp,ax            ; point to next field
  2585.     cmp    rempac,'C'        ; Remote Host command?
  2586.     je    genr4            ; e = yes, no counted string(s)
  2587.     cmp    rempac,'K'        ; Remote Kermit command?
  2588.     je    genr4            ; e = yes, no counted string(s)
  2589.     mov    encbuf+1,al        ; size of first field
  2590.     add    encbuf+1,32        ; do tochar function
  2591.     inc    temp            ; include count byte
  2592. genr4:    cmp    al,remlen        ; got necessary command text?
  2593.     jae    genr5            ; ae = yes
  2594.     cmp    remlen,0        ; is text optional?
  2595.     je    genr5            ; e = yes, continue without it
  2596. genr4a:    mov    dx,offset infms2    ; say need more info
  2597.     mov    ah,prstr
  2598.     int    dos
  2599.     or    errlev,ksgen        ; say cannot receive
  2600.     or    fsta.xstatus,ksgen    ; set status failed
  2601.     mov    kstatus,ksgen        ; global status
  2602.     clc
  2603.     ret
  2604.  
  2605. genr5:    mov    flags.xflg,1        ; output coming to screen
  2606.     cmp    remcmd,'I'        ; Remote Login command?
  2607.     je    genr6            ; e = yes
  2608.     cmp    remcmd,'C'        ; Remote Change Working Directory?
  2609.     je    genr7a            ; e = yes, get optional password
  2610.     jmp    short genr8        ; neither so no extra prompts here
  2611.  
  2612. genr6:    cmp    remlog,0        ; skip prompts (REM LOGOUT)?
  2613.     je    genr8            ; e = yes
  2614.     cmp    cnt,0            ; have username etc already?
  2615.     je    genr6a            ; e = no
  2616.     call    genupwd            ; parse username etc
  2617.     jmp    short genr8        ; send formatted contents
  2618. genr6a:    mov    dx,offset user        ; prompt for username
  2619.      call    prompt
  2620.     mov    bx,offset encbuf+1    ; skip command letter
  2621.     mov    temp,bx            ; start of field
  2622.     call    input            ; read text
  2623.     jc    genr8            ; c = none
  2624.     mov    temp,bx            ; point to next data field
  2625.  
  2626. genr7:    mov    dx,offset password    ; get optional password
  2627.     call    prompt
  2628. genr7a:    mov    bx,temp            ; where to put the password
  2629.     cmp    byte ptr [bx-1],0    ; extra null?
  2630.     jne    genr7b            ; ne = no
  2631.     dec    bx            ; backup to overwrite it
  2632.     dec    temp
  2633. genr7b:    mov    comand.cmquiet,1    ; turn on quiet mode
  2634.     call    input            ; read in the password
  2635.     mov    comand.cmquiet,0    ; turn off quiet mode
  2636.     jc    genr8            ; c = no text, do not add field
  2637.     mov    temp,bx            ; point to next data field
  2638.                     ;
  2639.     cmp    remcmd,'I'        ; Remote Login command?
  2640.     jne    genr8            ; ne = no
  2641.     cmp    remlog,0        ; skip prompts (REM LOGOUT)?
  2642.     je    genr8            ; e = yes
  2643.     mov    dx,offset account    ; get optional account ident
  2644.     call    prompt
  2645.     mov    bx,temp            ; where this field starts
  2646.     call    input            ; read text
  2647. genr8:    mov    remlog,0        ; clear rem login/out distinguisher
  2648.     cmp    flags.cxzflg,'C'    ; Control-C entered?
  2649.     jne    genr9            ; ne = no
  2650.     stc
  2651.     ret                ; return failure
  2652.  
  2653. GENR9:    mov    kstatus,kssuc        ; global status
  2654.     call    ipack            ; Send Init parameters
  2655.     jc    genr11            ; c = failure
  2656.     mov    trans.chklen,1        ; use 1 char for server functions
  2657.     mov    fsta.pretry,0        ; no retries yet
  2658.     mov    pktnum,0
  2659.     cmp    flags.cxzflg,'C'    ; did the user type a ^C?
  2660.     jne    genr10            ; ne = no
  2661.     stc
  2662.     ret                ; return in error state
  2663.  
  2664. genr10:    push    si
  2665.     mov    dx,offset encbuf    ; source buffer
  2666.     call    strlen            ; length of data
  2667.     call    getbuf            ; get a buffer address into si
  2668.     mov    ah,rempac        ; packet type
  2669.     mov    [si].pktype,ah
  2670.     call    doenc            ; encode data
  2671.     mov    trans.chklen,1        ; use block check 1 to server
  2672.     cmp    echrcnt,0        ; did all the data fit?
  2673.     je    genr10a            ; e = yes
  2674.     pop    si            ; fail, send E pkt, post local msg
  2675.     mov    dx,offset remms11    ; say command is too long
  2676.     call    ermsg            ;  to us and
  2677.     mov    bx,dx
  2678.     call    errpack            ;  to the other Kermit
  2679.     jmp    short genr11        ; fail out
  2680.  
  2681. genr10a:call    sndpak            ; send the Generic command packet
  2682.     pop    si
  2683.     jc    genr11            ; c = failure
  2684.     mov    rstate,'R'        ; next state is Receive Initiate
  2685.     push    crcword            ; preserve CRC-16 word
  2686.     push    word ptr lastfsize    ; and last sent file size
  2687.     push    word ptr lastfsize+2
  2688.     call    READ2            ; file receiver does the rest
  2689.     pop    word ptr lastfsize+2
  2690.     pop    word ptr lastfsize
  2691.     pop    crcword
  2692.     ret
  2693. genr11:    mov    flags.xflg,0        ; reset screen output flag
  2694.     xor    ax,ax            ; tell statistics this was a read
  2695.     or    errlev,ksrem         ; DOS error level, failure of REMote cmd
  2696.     mov    fsta.xstatus,ksrem    ; set status
  2697.     mov    kstatus,ksrem        ; global status
  2698.     clc
  2699.     ret
  2700. GENRIC    ENDP
  2701.  
  2702. ; Extract ">filespec" redirection at end of command line. If found put
  2703. ; filespec in auxfile as new output name.
  2704. genredir proc    near
  2705.     mov    cx,cnt            ; chars on command line
  2706.     jcxz    genred3            ; z = none
  2707.     mov    di,temp            ; buffer, after prologue
  2708.     add    di,cx            ; end of buffer+1
  2709.     dec    di            ; last byte of string
  2710.     push    ax
  2711.     push    es
  2712.     mov    ax,ds
  2713.     mov    es,ax
  2714.     mov    al,'>'            ; redirection symbol
  2715.     std                ; scan backward
  2716.     repne    scasb            ; found '>'?
  2717.     cld
  2718.     pop    es
  2719.     pop    ax
  2720.     jne    genred3            ; ne = no
  2721.     inc    di            ; look at '>'
  2722.     mov    byte ptr[di],0        ; insert terminator
  2723.     mov    ax,cx            ; new count length
  2724.     mov    cnt,cx            ; remember here too
  2725. genred1:inc    di            ; look at optional filename
  2726.     or    di,di            ; terminator?
  2727.     jz    genred2            ; z = yes
  2728.     cmp    byte ptr [di],' '    ; remove lead-in puncutation
  2729.     jbe    genred1            ; be = punctuation, go until text
  2730. genred2:mov    si,di
  2731.     mov    di,offset auxfile    ; new output name goes here
  2732.     call    strcpy
  2733. genred3:ret
  2734. genredir endp
  2735.  
  2736. ; Parse a single command line into username, password, account in counted
  2737. ; string style, for REM LOGIN. Enter with BX pointing at the next new
  2738. ; byte to store a command character and CNT holding the current line length.
  2739. ; Returns a completely formatted line, asciiz. Use {..} to surround items
  2740. ; with embedded spaces.
  2741. genupwd    proc    near
  2742.     push    ax
  2743.     push    bx
  2744.     push    es
  2745.     mov    ax,ds
  2746.     mov    es,ax
  2747.     sub    bx,cnt            ; next item minus count of items
  2748.     mov    si,bx            ; where text starts
  2749.     dec    bx            ; point at count byte
  2750.     mov    cx,3            ; three fields possible
  2751. genupw1:push    cx
  2752.     mov    cx,cnt            ; number of text chars to examine
  2753.     call    genup10            ; get first field
  2754.     mov    cnt,cx            ; update remaining count
  2755.     or    cx,cx            ; get remaining count
  2756.     pop    cx            ; recover loop counter
  2757.     jz    genupw2            ; z means empty remainder
  2758.     loop    genupw1            ; try to do three fields
  2759. genupw2:pop    es
  2760.     pop    bx
  2761.     pop    ax
  2762.     ret
  2763.  
  2764. ; Worker. Enter with bx=offset of count byte, si=offset of start of text,
  2765. ;  cx=chars remaining in input string.
  2766. ; Exit with bx=offset of next count byte, si=offset of where new text is
  2767. ; to be read, cx=chars remaining in input string.
  2768. genup10:mov    byte ptr [bx],' '    ; clear count byte to zero + space
  2769.     mov    di,si            ; work on text part
  2770.     mov    al,' '            ; skip whitespace
  2771.     cld
  2772.     repe    scasb
  2773.     je    genup12            ; e = nothing present
  2774.     dec    di            ; back up to non-white char
  2775.     inc    cx            ; correct count
  2776.     mov    si,di            ; si = where non-white text starts
  2777.     mov    di,bx            ; count byte
  2778.     inc    di            ; where text goes
  2779.     mov    ah,' '            ; assume this is the break char
  2780.     cmp    byte ptr [si],'{'    ; field starts with brace?
  2781.     jne    genup11            ; ne = no
  2782.     mov    ah,'}'            ; use this break char
  2783.     inc    si            ; skip over leading brace
  2784.     dec    cx            ; one less char to consider
  2785. genup11:lodsb                ; get a char
  2786.     cmp    al,ah            ; break char yet?
  2787.     je    genup12            ; e = yes
  2788.     or    al,al            ; end of text?
  2789.     jz    genup12            ; z = yes
  2790.     stosb                ; store char without leading padding
  2791.     inc    byte ptr [bx]        ; count chars stored in this field
  2792.     loop    genup11            ; continue
  2793. genup12:mov    bx,di            ; where to store next count byte
  2794.     mov    byte ptr [di],0        ; null terminator
  2795.     ret
  2796. genupwd    endp
  2797.     
  2798. ; Send    "I" packet with transmission parameters
  2799.  
  2800. IPACK    PROC    NEAR
  2801.     call    serini            ; initialize serial port
  2802.     jnc    ipack1
  2803.     ret                ; c = failure
  2804. ipack1:    call    ihostr            ; initialize the host
  2805.     call    clrbuf            ; clear serial port buffer
  2806.     call    sparmax            ; set up our maximum capabilites
  2807.     mov    trans.windo,1        ; no windows yet
  2808.     mov    cx,dspsiz        ; default send pkt length (94)
  2809.     call    makebuf            ; remake buffers
  2810.     xor    ax,ax
  2811.     mov    rpacket.numtry,al    ; number of receive retries
  2812.     mov    fsta.pretry,ax        ; no retries
  2813.     mov    pktnum,al        ; packet number 0
  2814.     mov    windlow,al        ; reset windowing
  2815.     call    packlen            ; compute packet length
  2816.     call    getbuf            ; get buffer for sending
  2817.     call    rpar            ; store them in the packet
  2818.     mov    trans.chklen,1        ; one char for server function
  2819.     mov    ax,18            ; 18.2 Bios ticks per second
  2820.     mul    trans.stime        ; byte, seconds
  2821.     mov    k_rto,ax        ; round trip timeout, Bios ticks
  2822.     mov    [si].pktype,'I'        ; "I" packet
  2823.     call    sndpak            ; send the packet
  2824.     jnc    ipack2            ; nc = success
  2825.     ret                ; return failure
  2826. ipack2:    mov    al,[si].seqnum
  2827.     mov    ah,maxtry        ; retry threshold
  2828.     add    ah,ah
  2829.     add    ah,maxtry        ; triple the normal retries
  2830.     mov    chkparflg,1        ; check for unexpected parity
  2831.     call    response        ; get response
  2832.     jnc    ipack3            ; nc = success
  2833.     call    bufclr            ; clear all
  2834.     cmp    rpacket.pktype,'E'    ; was it an Error pkt response?
  2835.     je    ipack4            ; e = yes, this is forgivable
  2836.     stc                ; carry set for failure
  2837.     ret                ; return failure
  2838.  
  2839. ipack3:    cmp    rpacket.pktype,'Y'    ; ACK response?
  2840.     jne    ipack4            ; ne = no
  2841.     push    si
  2842.     mov    si,offset rpacket    ; packet address
  2843.     call    spar            ; read in the data
  2844.     pop    si
  2845.     call    packlen            ; get max send packet size
  2846.     mov    cx,trans.rlong        ; max receiving pkt length to report
  2847.     call    makebuf            ; remake buffers for new windowing
  2848. ipack4:    cmp    rpacket.pktype,'E'    ; was it an Error pkt response?
  2849.     jne    ipack5            ; ne = no
  2850.     mov    dx,offset emptymsg    ; clear last error line
  2851.     call    ermsg            ; do it
  2852. ipack5:    clc
  2853.     ret                ; return success
  2854. IPACK    ENDP
  2855.  
  2856. ; Returns BX the updated pointer to the input buffer
  2857. ;      input buffer = <ascii data length count byte>textstring
  2858. ; return carry clear if have text, else carry set for none
  2859. INPUT    PROC    NEAR
  2860.     mov    temp2,bx        ; where to put byte count
  2861.     inc    bx            ; start text after count byte
  2862.     xor    dx,dx            ; help, none
  2863.     mov    ah,cmline        ; get text with embedded whitespace
  2864.     call    comnd
  2865.     jnc    input1            ; nc = success
  2866.     mov    bx,temp2        ; empty field, restore pointer
  2867.     ret                ; failure
  2868. input1:    push    bx
  2869.     mov    bx,temp2
  2870.     add    al,' '            ; convert byte count to ascii
  2871.     mov    [bx],al            ; store count byte
  2872.     pop    bx            ; return pointer to next free byte
  2873.     clc                ; say have bytes
  2874.     ret
  2875. INPUT    ENDP
  2876.  
  2877. code    ends
  2878.     end
  2879.