	NAME	mssset
; File MSSSET.ASM
	include mssdef.h
;  Copyright (C) 1985, 1993, Trustees of Columbia University in the 
;  City of New York.  Permission is granted to any individual or institution
;  to use this software as long as it is not sold for profit.  This copyright
;  notice must be retained.  This software may not be included in commercial
;  products without written permission of Columbia University.
;
; edit history:
; 27 August 1992 version 3.13
; 6 Sept 1991 version 3.11
; Last edit 13 Feb 1992
 
	public setcom, prmptr, dodef, setcpt, docom, stkadr, rdbuf
	public setrx, rxtable, srvdsa, srvena, mcctab, takopen, takclos, ask
	public askq, assign, initibm, mccptr, setinpbuf, setrollb, npages
	public	xfchtab, xftyptab, com1port, com2port, com3port, com4port
	public	flotab, popcmd, domacptr, warntab, portirq, dodecom
	public	tcpdata, tcphost, xfertab1, xfertab2, rollwidth, setwidth
	public	getok

braceop	equ	7bh		; opening curly brace
bracecl	equ	7dh		; closing curly brace

maketab	MACRO			; Assembler Macro to make rxtable [jrd]
cnt = 0
	rept 256
	db	cnt		; initialize table to 0 .. 255
cnt = cnt + 1
	endm
	db	0		; table off (0) or on (1) indicator
ENDM

data 	segment
	extrn	comand:byte, flags:byte, trans:byte, takadr:word, taklev:byte
	extrn	portval:word, dtrans:byte, spause:word, machnam:byte
	extrn	filtst:byte, maxtry:byte, script:byte, denyflg:word
	extrn	sloghnd:word, ploghnd:word, tloghnd:word
	extrn	decbuf:byte, kstatus:word, errlev:byte, srvtmo:byte
	extrn	luser:byte, lpass:byte, partab:byte, destab:byte, blktab:byte
	extrn	seoftab:byte, dmpname:byte, lsesnam:byte, lpktnam:byte
	extrn	ltranam:byte, incstb:byte, inactb:byte, rxoffmsg:byte
	extrn	rxonmsg:byte, scpbuflen:word, oldtak:byte, setchtab:byte
	extrn	prnname:byte, prnhand:word, outpace:word, apctrap:byte
	extrn	protlist:byte

rxtable	equ THIS BYTE		; build 256 byte Translation Input table
	maketab			; table rxtable is used by Connect mode

kerm	db	'MS-Kermit>',0		; default asciiz prompt
prm	db	60 dup (0)		; buffer for new prompt
rdbuf	db	cmdblen dup (?)		; work space; room for macro def
					;  and for Status display line

stflg	db	0		; Says if setting SEND or RECEIVE parameter
defkind	db	0		; 0 for ASSIGN, 1 for DEFINE
ermes1	db	cr,lf,'?Too many macro names$'
ermes2	db	cr,lf,bell,'?No room for Take file buffer or Macro definition'
	db	cr,lf,bell,'$'
ermes4	db	cr,lf,'?Too many active Take files and Macros',cr,lf, bell,'$'
ermes5	db	cr,lf,'?Not implemented$'
ermes6	db	cr,lf,'?More parameters are needed$'
ermes7	db	cr,lf,'?Cannot use RTS/CTS on non-UART ports$'
errcap	db	cr,lf,'?Unable to open that file$'
erropn	db	cr,lf,'?Log file is already open$'
askhlp1	db	'Variable name  then  prompt string$'
askhlp2	db	'Prompt string$'
askhlp3	db	'Enter a line of text$'
getokhlp db	'Optional prompt string$'
getdef	db	'Please respond Yes or No ',0	; ASCII, used as prompt
filhlp	db	' Output filename for the log$'
dishlp	db	cr,lf,' Quiet (no screen writing), Regular (normal),'
	db	' Serial (non-formatted screen)'
	db	cr,lf,' and/or 7-BIT (default) or 8-BIT wide characters.$'
remhlp	db	cr,lf,' OFF to show file transfer display,'
	db	' ON for quiet screen$'
macmsg	db	' Specify macro name followed by body of macro, on same line$'
prmmsg	db	cr,lf
	db    ' Enter new prompt string or nothing to regain regular prompt.'
	db	cr,lf,' Use \123 notation for special chars (Escape is \27)$'

srxhlp1	db	cr,lf,' Enter   code for received byte   code for'
	db	' local byte ',cr,lf,' use ascii characters themselves or'
	db	cr,lf,' numerical equivalents of  \nnn  decimal'
	db	' or \Onnn  octal or \Xnnn  hexadecimal',cr,lf
	db	' or keywords  ON  or  OFF  (translation is initially off)'
	db	cr,lf,'$'
badrx	db	cr,lf,'?Expected ON, OFF, or \nnn$'

takchlp	db	cr,lf,'Value 0 to 65535 for COUNT in script IF COUNT command$'
takcerr	db	cr,lf,'?Note: command is valid only in Take files and Macros$'

dmpdefnam db	'Kermit.scn',0		; asciiz default screen dump filename
prndefnam db	'PRN',0			; asciiz default printer name
nummsg1 db	cr,lf,'?Use a number between $'
nummsg2	db	' and $'
srvthlp	db	'seconds, 0-255, waiting for a transaction$'
unkchhlp db	cr,lf,' Disposition of files arriving with unknown'
	db	' character sets:',cr,lf,'  Keep (default), Cancel$'
winhelp	db	cr,lf,'Number of sliding window slots 1 (no windowing) to 31$'
eophlp	db	' Decimal number between 0 and 31$'
ctlhlp	db	' Decimal number between 0 and 31, 128 and 159$'
cntlhlp db	cr,lf,' PREFIXED <0..31, 128..159> protectively quotes this'
	db	' control code',cr,lf
	db	' UNPREFIXED <0..31, 128..159> sends control code as-is'
	db	cr,lf,' Use ALL to change all codes at once.$'
badcntlmsg db	cr,lf,'?Number is not in range of 0..31, 128..159',cr,lf,'$'
sohhlp	db	' Decimal number between 0 and 31.',cr,lf,' Special case:'
	db	' up to 126, but reduces strength of the protocol.$'
dmphlp	db	' Filename to hold screen dumps$'
prnhlp	db	' Filename for printer output (default is PRN)$'
prnerr	db	cr,lf,' Cannot open that name. Using default of PRN$'
erlhlp	db	' Decimal number between 0 and 255$'
pakerr	db	cr,lf,'?Choose a decimal number '
	db	'from 20 to 94 (normal) or to 9024 (long)$'
pakhlp	db	cr,lf,'Decimal number between 20 and 94 (normal) or '
	db	'9024 (long)$'
padhlp	db	cr,lf,' Decimal number between 0 and 31 or 127$'
pauhlp	db	' Decimal number between 0 and 65383 milliseconds$'
quohlp	db	' Decimal number between 33 and 126$'
retryhlp db	' Decimal number between 1 and 63$'
rollhlp	db	' Decimal number between 0 and 8000$'
dblhlp	db	' Decimal number between 0 and 255$'
luserh	db	cr,lf,'Username Password from remote Kermit (0-16 chars each)$'
lpassh	db	cr,lf,'Password from remote Kermit (0-16 chars,'
	db	' spaces allowed)$'
timhlp	db	' Decimal number between 0 and 94$'
delyhlp	db	' Delay seconds before sending file (0-63)$'
eschlp	db	cr,lf,'Press literal control keys (ex: Control ]) or'
	db	' enter in \nnn numerical form$'
escerr	db	cr,lf,'?Not a control code$'
hnd1hlp	db	cr,lf,'XON (\17), XOFF (\19), CR (\13), LF (\10), BELL (\7),'
	DB	' ESC (\27), NONE (\0)'
	db	cr,lf,' or "CODE" followed by decimal number$' 
intoms	db	'number of seconds to wait before timeout',cr,lf,'$'
loghlp	db	cr,lf
	db    ' PACKETS - during file transfers  (to default file PACKET.LOG)'
	db	cr,lf
	db    ' SESSION - during Connect mode   (to default file SESSION.LOG)'
	db	cr,lf
	db    ' TRANSACTIONS - files transfers (to default file TRANSACT.LOG)'
	db	cr,lf,'  followed by an optional filename for the log.$'
comhlp	db	cr,lf,' Address of the COM1 - COM4 port (ex: COM3 \x02f8 or'
	db	' COM4 \x02e8)$'
irqhlp	db	cr,lf,' Enter, or IRQ of port (ex: \3)$'
debhlp	db	cr,lf,' PACKETS - during file transfers'	; Debugging
	db	cr,lf,' SESSION - during Connect mode'
	db	cr,lf,' ON - both packets and session'
	db	cr,lf,' OFF - turns off all debugging$'
dohlp	db	cr,lf,'definitions of variables (\%n), or press ENTER key$'

sdshlp	db	cr,lf,'DISABLE or ENABLE access to selected Server commands:'
	db	cr,lf
	db	' CD/CWD, DEL, DIR, FINISH (includes BYE & LOGOUT), GET,'
	db	' HOST, KERMIT, LOGIN,',cr,lf
	db	' PRINT, SEND, SPACE, TYPE, and ALL.$'

xfchhlp	db	cr,lf,' Which character set to put on the wire during file'
	db	' transfers:',cr,lf
	db	'  TRANSPARENT (regular PC codes)',cr,lf
	db	'  LATIN1   (ISO 8859-1)',cr,lf
	db	'  LATIN2   (ISO 8859-2)',cr,lf
	db	'  HEBREW   (ISO 8859-8)',cr,lf
	db	'  CYRILLIC (ISO 8859-5)',cr,lf
	db	'  JAPANESE-EUC$'
xferhlp1 db	cr,lf,' OFF: disable feature, ON: enable (default), FORCE:'
	db	' forced on$'
xfchhlp2 db	cr,lf,' READABLE: translate some/many characters to/from'
	db	' locally readable form (def).'
	db	cr,lf,' INVERTIBLE: use codes which can be copied back to the'
	db	' host in its form.$'
xfchbad	db	cr,lf,'Warning: forcing FILE CHARACTER-SET to CP866$'
xfchbad2 db	cr,lf,'Warning: forcing FILE CHARACTER-SET to Shift-JIS$'
xfchbad3 db	cr,lf,'Warning: forcing FILE CHARACTER-SET to CP862$'
setchmsg db   cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to CYRILLIC$'
setchmsg2 db  cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to'
	db	' Japanese-EUC$'
setchmsg3 db  cr,lf,'Warning: forcing TRANSFER CHARACTER-SET to HEBREW-ISO$'
xfilhlp	db	'NONE, SPACE, or filler character$'
xpmthlp db	'Host echo char acting as prompt, \1-\255$'
xpauhlp	db	'Millisec to pause between lines, 1 - 65000$'
opacehlp db	'Millisec to pause between OUTPUT bytes, 0 - 65000$'
pophlp	db	'Status value to be returned  msg, nothing if no new value$'
crlf	db	cr,lf,'$'

srvtab	db	2			; SET SERVER table
	mkeyw	'Login',1
	mkeyw	'Timeout',2

sethlp	db	cr,lf
	db	'  Alarm    sec from now or HH:MM:SS  '
	db	'  Local-echo        on/off           '
	db	cr,lf
	db	'  Attributes packets on/off          '
	db	'  Mode-line         on/off'
	db	cr,lf
	db	'  Bell    on/off    at end of xfers  '
	db	'  NetBios-name      (our local name)'
	db	cr,lf
	db	'  Block-check-type  checksum/CRC     '
	db	'  Output pacing (ms between bytes)  '
	db	cr,lf
	db	'  COM1 - COM4 port-address irq       '
	db	'  Parity    even/odd/mark/space/none'
	db	cr,lf
	db	'  Control prefixed/unprefixed  code  '
	db	'  Port (or Line)    1/2/COM1/COM2/etc'
	db	cr,lf
	db	'  Count   number    a loop counter   '
	db	'  Printer filespec   for Connect mode'
	db	cr,lf
	db	'  Debug   on/off    display packets  '
	db	'  Prompt  string   (new Kermit prompt)'
	db	cr,lf
	db	'  Default-disk                       '
	db	'  Receive parameter  many things'
	db	cr,lf
	db	'  Delay   secs  before Sending file  '
	db	'  Retry limit for packet send/receive'
	db	cr,lf
	db	'  Destination   Disk/Screen/Printer  '
	db	'  Rollback, terminal screens'
	db	cr,lf
	db	'  Display quiet/reg/serial show cnts?'
	db	'  Send parameter    many things'
	db	cr,lf
	db	'  Dump filespec     screen to disk   '
	db	'  Server parameter'
	db	cr,lf
	db	'  Duplex            half or full     '
	db      '  Speed or Baud     many speeds'	
	db	cr,lf
	db	'  EOF Ctrl-Z/NoCtrl-Z  ^Z ends file? '
	db	'  Take-echo on/off  display commands?' 
	db	cr,lf
	db 	'  End-of-line char  cr or whatever   '
	db	'  Terminal type and parameters'
	db	cr,lf
	db	'  Errorlevel number   for DOS Batch  '
	db	'  TCP/IP address,mask,nameserver etc'
	db	cr,lf
	db      '  Escape-char  ^]   or whatever      '
	db	'  Timer     on/off  time packet waiting'
	db	cr,lf
	db	'  File (Character-set, Type, Warning)'
	db	'  Translation IN  Connect mode rcv''d char'
	db	cr,lf
	db	'  Flow-control  none xon/xoff rts/cts'
	db	'  Transfer Character-set (on wire) '
	db	cr,lf
	db	'  Handshake xon/xoff/cr/lf/bell/esc..'
	db	'  Transmit  parameters, for scripts'
	db	cr,lf
	db	'  Incomplete file   keep/discard     '
	db	'  Unknown-character-set (keep/cancel)'
	db	cr,lf
	db	'  Input timeout, etc  (for scripts)  '
	db	'  Warning   on/off  if file renamed'
	db	cr,lf
	db	'  Key         key-ident   definition '
	db	'  Windows  number of sliding window slots'
	db	'$'

settab	 db	55					; Set table
	mkeyw	'Alarm',setalrm
	mkeyw	'Attributes',setatt
	mkeyw	'Baud',baudst
	mkeyw	'Bell',bellst
	mkeyw	'Block-check-type',blkset
	mkeyw	'COM1',com1port
	mkeyw	'COM2',com2port
	mkeyw	'COM3',com3port
	mkeyw	'COM4',com4port
	mkeyw	'Control-character',cntlset
	mkeyw	'Count',takectr
	mkeyw	'Debug',debst
	mkeyw	'Default-disk',cwdir
	mkeyw	'Delay',setdely
	mkeyw	'Destination',desset
	mkeyw	'Display',disply
	mkeyw	'Dump',setdmp
	mkeyw	'Duplex',setdup
	mkeyw	'End-of-Line',eolset
	mkeyw	'EOF',seteof
	mkeyw	'Errorlevel',seterl
	mkeyw	'Escape-character',escset
	mkeyw	'File',setfile
	mkeyw	'Flow-control',floset
	mkeyw	'Handshake',hndset
	mkeyw	'Incomplete',abfset
	mkeyw	'Input',inpset
	mkeyw	'Key',setkey
	mkeyw	'Line',coms
	mkeyw	'Local-echo',lcal
	mkeyw	'Mode-line',modl
	mkeyw	'NetBios-name',setnbios
	mkeyw	'Output',setoutput
	mkeyw	'Parity',setpar
	mkeyw	'Port',coms
	mkeyw	'Printer',setprn
	mkeyw	'Prompt',promset
	mkeyw	'Receive',recset
	mkeyw	'Remote',remset
	mkeyw	'Retry',retryset
	mkeyw	'Rollback',setrollb
	mkeyw	'Send',sendset
	mkeyw	'Server',setsrv
	mkeyw	'Speed',baudst
	mkeyw	'Take-echo',takset
	mkeyw	'TCP/IP',tcpipset
	mkeyw	'Terminal',vts
	mkeyw	'Timer',timset
	mkeyw	'Transfer',sxfer
	mkeyw	'xfer',sxfer		; hidden synonym
	mkeyw	'Translation',setrx
	mkeyw	'Transmit',setxmit
	mkeyw	'Unknown-character-set',unkchset
	mkeyw	'Warning',filwar
	mkeyw	'Windows',winset
 
setfitab db	5			; Set File command table
	mkeyw	'Character-Set',1
	mkeyw	'Collision',0
	mkeyw	'Display',3
	mkeyw	'Type',2
	mkeyw	'Warning',0

xfertab	db	3			; SET TRANSFER table
	mkeyw	'Character-set',0
	mkeyw	'Locking-shift',1
	mkeyw	'Translation',2

xfertab1 db	3			; SET TRANSFER LOCKING-SHIFT
	mkeyw	'Off',lock_disable
	mkeyw	'On',lock_enable
	mkeyw	'Forced',lock_force

xfertab2 db	2			; SET TRANSFER TRANSLATION
	mkeyw	'Readable',0
	mkeyw	'Invertible',1

xfchtab	db	6			; SET TRANSFER CHARACTER-SET
	mkeyw	'Transparent',xfr_xparent	; no translation
	mkeyw	'Latin1 ISO 8859-1',xfr_latin1	; ISO 8859-1, Latin-1
	mkeyw	'Latin2 ISO 8859-2',xfr_latin2	; ISO 8859-2, Latin-2
	mkeyw	'Hebrew ISO 8859-8',xfr_hebiso	; ISO 8859-8 Hebrew-ISO
	mkeyw	'Cyrillic ISO 8859-5',xfr_cyrillic; ISO 8859-5/Cyrillic, CP866
	mkeyw	'Japanese-EUC',xfr_japanese	; Japanese-EUC

xftyptab db	2			; SET FILE TYPE table
	mkeyw	'Binary',1		; Binary = as-is
	mkeyw	'Text',0		; Text = can change char sets

warntab	db	6			; File Warning table
	mkeyw	'Overwrite',1		; overwrite
	mkeyw	'Rename',0		; rename
	mkeyw	'Discard',4 		; discard
	mkeyw	'No-supersede',4	; discard
	mkeyw	'on (rename)',0		; old form
	mkeyw	'off (overwrite)',1	; old form

unkctab db	2			; unknown character-set disposition
	mkeyw	'Keep',0
	mkeyw	'Cancel',1

atttab	db	6			; SET ATTRIBUTES table
	mkeyw	'Off',00ffh		; all off
	mkeyw	'On',10ffh		; all on (high byte is on/off)
	mkeyw	'Character-set',attchr	; Character set
	mkeyw	'Date-Time',attdate	; Date and Time
	mkeyw	'Length',attlen		; Length
	mkeyw	'Type',atttype		; Type

comtab	db	2			; table of COM ports
	mkeyw	'COM3',4		; offset of COM3 address
	mkeyw	'COM4',6		; offset of COM4 address

cntltab	db	2			; SET CONTROL table
	mkeyw	'Prefixed',0		; 0 = send with prefix
	mkeyw	'Unprefixed',1		; 1 = send as-is

stsrtb	db	10			; Number of options
	mkeyw	'Packet-length',srpack
	mkeyw	'Padchar',srpad
	mkeyw	'Padding',srnpd
	mkeyw	'Pause',srpaus
	mkeyw	'Start-of-packet',srsoh
	mkeyw	'Quote',srquo
	mkeyw	'End-of-packet',sreol
	mkeyw	'Timeout',srtim
	mkeyw	'Double-char',srdbl
	mkeyw	'Ignore-char',srign

ontab	db	2
	mkeyw	'off',0
	mkeyw	'on',1

outputtab db	1			; Set OUTPUT
	mkeyw	'PACING',setopace

distab	db	5 			; Set Display mode
	mkeyw	'7-bit',7		; controls bit d8bit in flags.remflg
	mkeyw	'8-bit',8		; sets d8bit
	mkeyw	'Quiet',dquiet		; values defined in header file
	mkeyw	'Regular',dregular
	mkeyw	'Serial',dserial

distab2	db	3			; for SET FILE DISPLAY
	mkeyw	'Quiet',dquiet		; values defined in header file
	mkeyw	'Regular',dregular
	mkeyw	'Serial',dserial

; If abort when receiving files, can keep what we have or discard
abftab	db	2
	mkeyw	'Discard',1
	mkeyw	'Keep',0

flotab	db	5
	mkeyw	'none',0
	mkeyw	'xon/xoff',1+2		; both directions
	mkeyw	'incoming-xon/xoff',2
	mkeyw	'outgoing-xon/xoff',1
	mkeyw	'RTS/CTS',4

hndtab	db	8
	mkeyw	'none',0
	mkeyw	'bell',bell
	mkeyw	'cr',cr
	mkeyw	'esc',escape
	mkeyw	'lf',lf
	mkeyw	'xoff',xoff
	mkeyw	'xon',xon
	mkeyw	'code',0ffh		; allow general numerial code

duptab	db	2			; SET DUPLEX table
	mkeyw	'full',0
	mkeyw	'half',1

gettab	db	3			; GETOK dispatch table
	mkeyw	'Yes',kssuc		; success = yes
	mkeyw	'OK',kssuc		; ditto
	mkeyw	'No',ksgen		; general failure

inptab	db	4				; Scripts. Set Input
	mkeyw	'Case',inpcas			;[jrs]
	mkeyw	'Default-timeout',inptmo	;[jrs]
	mkeyw	'Echo',inpeco			;[jrs]
	mkeyw	'Timeout-action',inpact		;[jrs]

xmitab	db	4			; SET TRANSMIT table
	mkeyw	'Fill-empty-line',0
	mkeyw	'Line-Feeds-sent',1
	mkeyw	'Pause',3
	mkeyw	'Prompt',2

debtab	db	4			; Set Debug command
	mkeyw	'Off',0
	mkeyw	'On',logpkt+logses
	mkeyw	'Packets',logpkt
	mkeyw	'Session',logses

logtab	db	3			; LOG command
	mkeyw	'Packets',logpkt
	mkeyw	'Session',logses
	mkeyw	'Transactions',logtrn

srvdetab db	14			; Server Enable/Disable list
	mkeyw	'All',0fffh
	mkeyw	'CD',cwdflg
	mkeyw	'CWD',cwdflg
	mkeyw	'Delete',delflg
	mkeyw	'Dir',dirflg
	mkeyw	'Finish',finflg
	mkeyw	'Get',getsflg
	mkeyw	'Host',hostflg
	mkeyw	'Kermit',kerflg
	mkeyw	'Login',pasflg
	mkeyw	'Print',prtflg
	mkeyw	'Send',sndflg
	mkeyw	'Space',spcflg
	mkeyw	'Type',typflg

trnstab	db	2			; Set Translation table
	mkeyw	'Input',1
	mkeyw	'Keyboard',2

tcptable db	12			; TCP/IP command
	mkeyw	'address',1		; local Internet address
	mkeyw	'domain',2		; local domain string
	mkeyw	'broadcast',8		; broadcast of all 0's or all 1's
	mkeyw	'gateway',4		; gateway address
	mkeyw	'primary-nameserver',5	; address
	mkeyw	'secondary-nameserver',6
	mkeyw	'subnetmask',3		; our subnet mask
	mkeyw	'host',7		; host's IP name or IP number
	mkeyw	'Packet-Driver-interrupt',9
	mkeyw	'Telnet-term-type',10	; Options term type
	mkeyw	'NewLine-Mode',11 	; CR-NUL vs CRLF
	mkeyw	'debug-Options',12

hosthlp	db	cr,lf,'Internet name or number (ddd.ddd.ddd.ddd) of '
	db	'the remote machine$'
domainhlp db	cr,lf,'Name of your domain$'
subnethlp db	cr,lf,'Subnetmask, decimal ddd.ddd.ddd.ddd$'
addrhelp db	cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd, of this'
	db	' machine or BOOTP or RARP$'
iphelp	db	cr,lf,'Internet address, decimal ddd.ddd.ddd.ddd$'
domainbad db	cr,lf,'?Bad domain name, use is such as my.domain.name$'
addressbad db	cr,lf,'?string is too long$'
hostbad	db	cr,lf,'?Bad host, use IP name or IP number$'
tcppdinthlp db	cr,lf,'Interrupt on PC for Packet Driver, \x60 to \x7f'
	db	' or use 0 for automatic search,'
	db	cr,lf,' or ODI to use Novell''s ODI interface$'
tcpttyhlp db	cr,lf,' Telnet Options terminal identification override '
	db	'string.'
	db	cr,lf,' This does NOT modify the real terminal type.'
	db	' Press ENTER to remove this',cr,lf 
	db	' override and report the real terminal type.$'
tcpnlhlp db	cr,lf,' ON sends CR LF for each CR, OFF sends CR NUL$'

tcpaddress db	'unknown',(16-($-tcpaddress)) dup (0),0
tcpsubnet  db	'255.255.255.0',(16-($-tcpsubnet)) dup (0),0
tcpdomain  db	'unknown',(32-($-tcpdomain)) dup (0),0
tcpgateway db	'unknown',(16-($-tcpgateway)) dup (0),0
tcpprimens db	'unknown',(16-($-tcpprimens)) dup (0),0
tcpsecondns db	'unknown',(16-($-tcpsecondns)) dup (0),0
tcphost	db	(60 -($-tcphost)) dup (0),0
tcpbcast db	'255.255.255.255',(16-($-tcpbcast)) dup (0),0
tcpbtpserver db	17 dup (0)		; bootp server (response)
tcpport	dw	23			; TCP port
tcppdint dw	0			; Packet Driver interrupt
tcpttbuf db	32 dup (0),0		; term-type-override buffer
tcpnewline db	1			; NewLine-Mode (default is on)
tcpdebug db	0			; Options debugging (0 is off)

tcpdata	dw	offset tcpaddress	; externally visible far pointers
	dw	offset tcpsubnet	; keep in this order
	dw	offset tcpdomain
	dw	offset tcpgateway
	dw	offset tcpprimens
	dw	offset tcpsecondns
	dw	offset tcphost
	dw	offset tcpbcast
	dw	offset tcpport
	dw	offset tcppdint
	dw	offset tcpttbuf
	dw	offset tcpbtpserver
	dw	offset tcpnewline
	dw	offset tcpdebug

; MACRO DATA STRUCTURES mcctab
mcclen	equ	macmax*10		; length of mcctab
mcctab	db	0			; macro name table entries
	db	mcclen dup (0)		; room for macro structures
; END OF MACRO DATA STRUCTURES

ibmmac	db	'IBM '			; startup IBM macro definition + space
	db	'set timer on,set parity mark,set local-echo on,'
	db	'set handshake xon,set flow none,',0	; asciiz

	even
prmptr	dw	kerm			; pointer to prompt
tempptr	dw	0			; pointer into work buffer
domacptr dw	0			; pointer to DO MAC string
min	dw	0 
max	dw	0 
numerr	dw	0
numhlp	dw	0
temp	dw	0
temp1	dw	0			; Temporary storage
temp2	dw	0			; Temporary storage
askecho db	0			; ask's echo control flag
temptc	db	3,0,0,'T',0,0		; temp, for takclos, word cnt,<null>T#
deftemp	dw	0
stkadr	dw	0	; non-zero if replacement keyboard xlator present
mccptr	dw	mcctab 			; ptr to first free byte in mcctab
macptr	dw	0			; temp to hold segment of string
npages	dw	10 			; # of pages of scrolling on each side
rollwidth dw	0			; columns to roll back 80..207
portirq	db	4 dup (0)		; user specified IRQ's for COM1..4
data	ends

code1	segment
	extrn	makebuf:far
code1	ends

code	segment
	extrn comnd:near, baudst:near, prompt:near, coms:near, cwdir:near
	extrn isfile:near, strlen:near, strcpy:near, cnvlin:near
	extrn katoi:near, decout:near, vts:near, setalrm:near, serrst:near
	extrn prnopen:near, pntflsh:near, takrd:near, prtasz:near
	extrn setnbios:near	; in MSXIBM, needs stub for other machines

	assume	cs:code, ds:data, es:nothing

; DO defined macro command
; DO macname variable variable   also defines variables \%1, \%2, ...\%9
DOCOM	PROC	NEAR
	mov	dx,offset mcctab	; table of macro defs
	xor	bx,bx			; help is table
	mov	ah,cmkey		; get key word (macro name)
	call	comnd			; get pointer to keyword structure
	jnc	docom1			; nc = success, bx = 16 bit data
	ret				; failure
docom1:	mov	domacptr,bx		; segment of definition string
	mov	comand.cmquiet,0	; permit command echoing
	mov	bx,offset decbuf	; point to borrowed work buffer
	mov	word ptr[bx],0		; clear buffer
	mov	dx,offset dohlp		; help
	mov	comand.cmblen,length rdbuf ; length of analysis buffer
	mov	ah,cmline		; get line of text, if any
	call	comnd
	jnc	docom2			; nc = success
	ret				; failure
docom2:	mov	deftemp,ax		; save byte count of command args
	call	hidemac			; hide previous \%0..\%9 macros
	call	getname			; get name of this macro
	mov	cx,word ptr rdbuf	; length of "\%0 plus found name"
	call	dodecom			; add keyword+def using DEF MAC below
	jnc	docom2a			; nc = success
	ret
docom2a:call	docnv			; convert macro string
	jnc	docom2b			; nc = success
	ret
docom2b:mov	max,1			; temp for counting 1 + number args
	mov	word ptr rdbuf+4,' 1'	; number of first variable
docom3:	mov	word ptr rdbuf,0	; clear length field, install \%x name
	mov	word ptr rdbuf+2,'%\'	; start with '\%1 '
	mov	word ptr rdbuf+6,0	; clear text field
	mov	tempptr,offset rdbuf+6	; pointer to location of found word
	xor	ch,ch			; make cx = 1 - 9
	mov	cl,rdbuf+4		; cx = word # of interest, for getwrd
	sub	cl,'0'			; remove ascii bias
	mov	si,offset decbuf	; source = work buffer (borrowed)
	call	getwrd			; get CX-th word from  work buf (1-9)
	cmp	deftemp,0		; length of word, was it found?
	je	docom4			; e = no, end variable definition part
	add	deftemp,4		; count '\%n ' in command line length
	inc	max			; one more argument
	mov	cx,deftemp		; command length for dodecom
	call	dodecom			; add keyword+def using DEF MAC below
	jnc	docom3a
	ret				; failure
docom3a:inc	rdbuf+4			; inc number of variable in '\%n '
	cmp	rdbuf+4,'9'
	jbe	docom3			; do '1' through '9', if available

					; DO the macro itself
docom4:	cmp	taklev,maxtak		; room in take level?
	jl	docom5			; l = yes, continue
	mov	dx,offset ermes4	; else complain
	jmp	reterr
docom5:	inc	taklev			; increment take level
	add	takadr,size takinfo	; create a Take macro
	mov	bx,takadr		; point to current structure
	push	es
	mov	es,domacptr		; segment of macro definition string
	mov	[bx].takbuf,es		; remember in Take structure
	mov	cx,es:word ptr [0]	; length of definition string
	pop	es
	mov	[bx].takcnt,cx		; # of chars in buffer
	mov	[bx].taktyp,0ffh	; flag as a macro
	mov	[bx].takptr,2		; point to beginning of def text
	mov	cx,max			; 1 + number of arguments
	mov	[bx].takargc,cx
	clc				; success
	ret
DOCOM	ENDP

; Create a new macro, named <0>T<taklev digit>, with the command line of the
; original macro modified to replace bare commas with Carriage Returns.
; Enter with domacptr pointing at the segment of the macro's definition.
; Return with domacptr pointing at the new buffer created by dodecom.
docnv	proc	near
	cmp	taklev,maxtak		; room in take level?
	jb	docnv1			; b = yes
	mov	dx,offset ermes4	; say too many Take files
	mov	ah,prstr		; display error message
	int	dos
	stc				; set carry for failure
	ret

docnv1:	push	es
	mov	word ptr rdbuf,3	; length of name, 3 bytes <null>Tn
	mov	rdbuf+2,0
	mov	rdbuf+3,'T'		; name of <null>Tn
	mov	al,taklev		; Take level digit
	inc	al			; for what will be next Take level
	add	al,'0'			; add ascii bias
	mov	rdbuf+4,al		; last of the name
	mov	rdbuf+5,' '		; separate dummy definition
	mov	ax,domacptr
	mov	es,ax			; seg of definition
	xor	si,si			; offset of definition
	mov	di,offset rdbuf+6	; destination
	mov	cx,es:[si]		; read count of string
	add	si,2			; point at string itself
	xor	bx,bx			; brace count
	mov	dl,braceop		; opening brace (we count them up)
	mov	dh,bracecl		; closing brace (we count them down)
	xor	bp,bp			; offset of last closing brace+1
	cmp	es:[si],dl		; starts with opening brace?
	jne	docnv2			; ne = no
	inc	si			; skip this new leading space
	dec	cx			; and don't count it either
	inc	bh			; say opening brace was found
docnv2:	mov	al,es:[si]		; read a char
	inc	si
	cmp	al,dl			; opening brace?
	jne	docnv3			; ne = no
	inc	bl			; count brace level
	jmp	short docnv5
docnv3:	cmp	al,dh			; closing brace?
	jne	docnv4			; ne = no
	dec	bl
	or	bl,bl			; below 0?
	jg	docnv4			; g = no, still in braces
	jz	docnv5			; matching interior braces
	or	bh,bh			; was there an opening brace?
	jz	docnv5			; z = no, record this one
	xor	bx,bx			; found opening match, reset to zero
	jmp	short docnv6		; omit the brace
docnv4:	or	bl,bl			; in braced clause?
	jnz	docnv5			; nz = yes, treat comma as literal
	cmp	al,','			; unbraced comma?
	jne	docnv5			; ne = no
	mov	al,CR			; replace bare comma with CR
docnv5:	mov	[di],al
	inc	di
docnv6:	loop	docnv2
	pop	es
	cmp	byte ptr [di-1],cr	; ends on a Carriage Return?
	je	docnv7			; e = yes
	mov	byte ptr [di],cr	; insert one to do sync execution
	inc	di
docnv7:	mov	byte ptr [di],0		; null terminator, for safety
	sub	di,offset rdbuf+2	; start of string (skips count)
	mov	cx,di			; length of string
	call	dodecom			; define macro from rdbuf+2
	mov	domacptr,ax		; seg of new string
	ret
docnv	endp

; Extract CX-th word (cx = 1-9) from buffer (DI). Enter with si = source
; string and tempptr pointing at destination. Returns deftemp (count) of
; transferred characters. Allow string in curly braces to exist as a word.
; Adjacent curly braced strings are separate "words":
;    {this is word-one}{this is word-two}word-three.
; First level curly braces are removed.
; All registers preserved.
getwrd	proc	near
	push	si
	push	di
	push	es
	push	ds
	pop	es			; set es to data segment
getwr1:	push	cx			; save word counter (1-9)
	mov	deftemp,0		; no bytes transferred yet
	mov	di,tempptr		; where to store word/string
	mov	byte ptr [di],0		; clear destination
	mov	dx,si			; start looking here in work buf
	call	strlen			; cx = remaining length of work buf
	jcxz	getwr6			; z = nothing there, quit
getwr2:	lodsb
	cmp	al,' '			; skip leading whitespace
	loope	getwr2
	dec	si			; return to break char
					; Parse curly brace delimited string
					; end with si after closing brace
	xor	dl,dl			; assume "opening brace" is a null
	mov	dh,' '			; assume "closing brace" is a space
	mov	cx,1			; we are at brace level 1
	cmp	byte ptr [si],braceop	; starting with a real opening brace?
	jne	getwr3			; ne = no
	inc	si			; skip opening brace
	mov	dl,braceop		; opening brace (we count them up)
	mov	dh,bracecl		; closing brace (we count them down)
getwr3:	cld				; search forward
	lodsb				; read a char
	stosb				; store in output buffer
	or	al,al			; at end of text?
	jnz	getwr3a			; nz = no
	dec	si			; stay at null terminator
	dec	di
	jmp	short getwr6		; we are done with this "word"
getwr3a:inc	deftemp			; count copied char
	cmp	al,dl			; an opening brace?
	jne	getwr4			; ne = no
	inc	cx			; yes, increment brace level
	jmp	short getwr3		;  and continue scanning

getwr4:	cmp	al,dh			; closing brace?
	jne	getwr3			; ne = no, continue scanning
	dec	cx			; yes, decrement brace level
	cmp	byte ptr [si],0		; have we just read the last char?
	jne	getwr5			; no, continue scanning
	xor	cx,cx			; yes, this is the closing brace
getwr5:	or	cx,cx			; at level 0?
	jg	getwr3			; g = no, #opening <> #closing braces
	dec	di			; don't write closing brace
	dec	deftemp			; do not count closing brace
getwr6:	pop	cx			; recover word counter
	mov	byte ptr [di],0
	jcxz	getwrx			; just in case
	loop	getwr1			; do until desired word is copied
getwrx:	pop	es
	pop	di
	pop	si
	ret
getwrd	endp

; Get macro name, given the action pointer in domacptr.
; Return rdbuf as word:length that follows, then "\%0 macro-name"
getname proc	near
	push	bx
	push	cx
	push	dx
	push	si
	push	di
	mov	dx,domacptr		; action word to be matched
	mov	bx,offset mcctab+1	; table of macro names, skip count
	mov	word ptr rdbuf,4	; name length and space
	mov	word ptr rdbuf+2,'%\'	; define '\%0 '
	mov	word ptr rdbuf+4,' 0'
	mov	cl,mcctab		; number of entries
	xor	ch,ch
	jcxz	getnam3			; z = empty table
getnam1:push	cx
	mov	cx,[bx]			; length of name
	mov	si,bx			; point at structure member
	add	si,2			; plus count
	add	si,cx			; plus length of name
	mov	ax,[si]			; get action word
	cmp	ax,dx			; correct action word?
	jne	getnam2			; ne = no
	push	es
	push	ds
	pop	es
	add	word ptr rdbuf,cx	; length of macro \%0 + name
	mov	di,offset rdbuf+6	; where to store text
	mov	si,bx
	add	si,2			; source of text
	cld
	rep	movsb			; copy name to rdbuf+6
	mov	byte ptr [di],0		; null terminator
	pop	es
	pop	cx
	jmp	short getnam3		; exit
getnam2:mov	ax,[bx]			; get length of name
	add	ax,4			; plus count and word pointer
	add	bx,ax			; point to next entry
	pop	cx
	loop	getnam1			; look at next entry
getnam3:pop	di
	pop	si
	pop	dx
	pop	cx
	pop	bx
	ret
getname	endp

; Renames macros \%0..\%9 by changing the first two characters of the name
; to be <null><taklev>. Used to preserve old \%n macros and not show them.
hidemac proc	near
	push	bx
	push	cx
	mov	bx,offset mcctab+1	; table of macro names, skip count
	mov	cl,mcctab		; number of entries
	xor	ch,ch
	jcxz	hidema3			; z = empty table
hidema1:cmp	word ptr [bx],3		; name length, do three byte names
	jne	hidema2			; ne = not three chars
	cmp	word ptr [bx+2],'%\'	; starts with correct prefix?
	jne	hidema2			; ne = no
	mov	al,byte ptr [bx+4]	; third char of name
	cmp	al,'0'			; in digits?
	jb	hidema2			; b = no
	cmp	al,'9'
	ja	hidema2
	xor	al,al			; prepare new prefix
	mov	ah,taklev		; of <null><taklev>
	mov	[bx+2],ax		; change the macro name
hidema2:mov	ax,[bx]			; get length of name
	add	ax,4			; plus count and word pointer
	add	bx,ax			; point to next entry
	loop	hidema1			; look at next entry
hidema3:pop	cx
	pop	bx
	ret
hidemac	endp
 
; Removes all current \%0..\%9 macros and renames <null><taklev> macros by
; changing the first two characters of the names \%n from <null><taklev> to
; be "\%". Used to recover old \%n macros from hidemac.
unhidemac proc	near
	push	cx
	push	dx
	push	di
	mov	di,offset temptc	; temp macro name
	mov	word ptr [di+2],'%\'	; prefix for "\%n"
	mov	cl,'0'			; trailer for name
	xor	ch,ch			; null terminator
unhide1:mov	[di+4],cx		; compose number
	call	remtab			; remove "\%n" macro
	inc	cl
	cmp	cl,'9'			; done?
	jna	unhide1			; na = no, look at next entry
		       			; now do rename of <null><taklev>n
unhide2:mov	di,offset mcctab+1	; table of macro names, skip count
	mov	cl,mcctab		; number of entries
	xor	ch,ch
	jcxz	unhide5			; z = empty table
	xor	dl,dl			; macro prefix to examine
	mov	dh,taklev
unhide3:cmp	word ptr [di],3		; do only "<null><taklev>n" names
	jne	unhide4			; ne = not three chars
	mov	al,[di+4]		; get char of name
	cmp	al,'0'			; is it a char in range for \%0..\%9?
	jb	unhide4			; b = no
	cmp	al,'9'			; still in range?
	ja	unhide4			; a = no
	cmp	word ptr [di+2],dx	; starts with <null><taklev> prefix?
	jne	unhide4			; ne = no
	mov	[di+2],'%\'		; change the macro name back to "\%n"
unhide4:mov	ax,[di]			; get length of name
	add	ax,4			; plus count and word pointer
	add	di,ax			; point to next entry
	loop	unhide3			; look at next entry
unhide5:pop	di
	pop	dx
	pop	cx
	ret
unhidemac endp

; DEFINE and ASSIGN macro commands
; Data structures comments. Macro name is stored in table mcctab as if we
; had used macro mkeyw, such as       mkeyw 'mymac',offset my_definition.
; In detail:	dw	length of name
;		db	'name'
;		dw	segment:0 of definition string
; Mcctab begins with a byte holding the number of macros in the table; one,
;  IBM, is established at assembly time. Mcctab is 10*macmax bytes long.
; Pointer mccptr holds the offset of the next free byte in mcctab.
; Definition strings are stored in individually allocated memory as
;		dw	length of definition string below
;		db	'definition string'
; A new definition is read into buffer rdbuf+2, where word rdbuf is reserved
;  to hold the length of the macro's name during intermediate processing.
; If the definition is absent then the macro is removed from the tables.
;
; ASSIGN is equivalent to DEFINE, except in the definition string substitution
; variable names are expanded to their definitions.
; DEFINE does not expand substitution variables.
; Both commands will remove a first level curly brace pair if, and only if,
; the definition begins and ends with them (trailing whitespace is allowed).
ASSIGN	PROC	NEAR
	mov	defkind,0		; flag command as ASSIGN, vs DEFINE
	jmp	short dodefcom		; common code
ASSIGN	ENDP

DODEF	PROC	NEAR
	mov	defkind,1		; flag command as DEFINE, vs ASSIGN
DODEFCOM:
	mov	comand.cmper,1		; do not react to '\%' in macro name
	mov	ah,cmword
	mov	dx,offset rdbuf+2	; buffer for macro name
	mov	word ptr rdbuf,0
	mov	comand.cmblen,length rdbuf ; length of analysis buffer
	mov	bx,offset macmsg
	call	comnd			; get macro name
	jnc	dodef1			; nc = success
	ret				; failure
dodef1:	or	ax,ax			; null entry?
	jnz	dodef2			; nz = no
	mov	dx,offset ermes6	; more parameters needed
	jmp	reterr

dodef2:	mov	bx,offset rdbuf+2	; start of string
	cmp	word ptr [bx],'%\'	; \%<char> substitution variable?
	jne	dodef2b			; ne = no
	cmp	ax,2			; count, but missing <char>?
	ja	dodef2a			; a = no
	mov	byte ptr [bx+2],'_'	; slip in an underscore
dodef2a:mov	ax,3			; limit to \%<char>, one char name

dodef2b:add	bx,ax			; point to string terminator
	mov	byte ptr [bx],' '	; replace null with space separator
	mov	word ptr [bx+1],0	; terminator, in case no command
	inc	bx			; where definition will start
	mov	ax,cmdblen		; length of rdbuf
	sub	ax,bx			; - (current offset - offset rdbuf)
	add	ax,offset rdbuf		; ax = amount of buffer used
	mov	comand.cmblen,ax	; our new buffer length
	mov	al,defkind		; get ASSIGN/DEFINE flag
	mov	comand.cmper,al		; react (DEF) to '\%' in definition
	mov	ah,cmline		; get a line of text
	mov	dx,offset macmsg	; help, bx is buffer offset
	push	bx			; save starting offset
	call	comnd			; get macro definition text
	pop	bx
	jnc	dodef3			; nc = success
	ret				; failure
dodef3:	add	bx,ax			; end of command line
	mov	cx,bx
	sub	cx,offset rdbuf+2	; length of command line
;;	jmp	dodecom
DODEF	ENDP

; Make a macro table entry and allocate buffer space.
; Enter with rdbuf+2 et seq = <macro name><spaces><arg><spaces><arg> ...
; and CX = byte count of line, starting at rdbuf+2.
; Word rdbuf+0 computed here as length of keyword.
; Allocates memory based on analyzed size of command line, returns memory
; segment in macptr and in AX. Returns carry set if failure.
DODECOM	PROC	NEAR
	push	si			; macro name in rdbuf+1 et seq
	push	di			; cmd line length in deftemp
	push	es
	push	ds			; address data segment
	pop	es
	mov	deftemp,cx		; cmd line len, cx = running counter
	mov	rdbuf,0			; number of chars in keyword so far
					; uppercase the keyword, look for end
	mov	si,offset rdbuf+2	; point at macro name itself
	xor	dx,dx			; a counter
	cld				; strings go forward
dode2:	lodsb				; get a byte
	cmp	al,'a'			; map lower case to upper
	jb	dode3
	cmp	al,'z'
	ja	dode3
	sub	al,'a'-'A'
	mov	[si-1],al		; uppercase if necessary
dode3:	inc	dx			; increment char count of keyword
	cmp	al,' '			; is this the break character?
	loopne	dode2			; no, loop thru rest of word
	jne	dode4			; ne = did not end with break char
	dec	dx			; yes, don't count in length
dode4:	mov	di,offset rdbuf		; point at mac name length
	mov	[di],dx			; insert length in rdbuf
	push	dx			; save length around call
	call	remtab			; remove any duplicate keyword
					; check for free space for keyword
	pop	ax			; keyword text length
	add	ax,4			; plus count and word pointer
	add	ax,mccptr		; add to free space pointer
	cmp	ax,offset mcctab+mcclen ; enough room for name?
	jb	dode5			; b = yes
	mov	dx,offset ermes1	; too many macro names
	pop	es
	pop	di
	pop	si
	jmp	reterr

dode5:	mov	dx,si			; trim off leading/trailing spaces
	call	strlen
	mov	di,si			; si = definition source address
	jcxz	dode5a			; z = empty string
	add	di,cx			; start + length
	dec	di			; last char of string
	std
	mov	al,' '			; scan off trailing spaces
	repe	scasb
	cld
	mov	byte ptr [di+2],0	; plant new terminator
dode5a:	mov	dx,si
	call	strlen			; get new length into cx
	cld
	mov	di,si			; scan after keyword name
	mov	al,' '			; remove leading spaces in string
	repe	scasb
	jne	dode6			; ne = have some text
	pop	es			; all spaces
	pop	di
	pop	si
	clc				; success
	ret
dode6:	dec	di			; offset auto increment of rep
	mov	si,di			; new start of string
	mov	dx,si			; source of definition text
	call	strlen			; get length of string into cx
	mov	deftemp,cx		; remember it here
					; install new keyword
	jcxz	dode10			; z = no def, exit now
	mov	bx,cx			; string length, in bytes
	add	bx,2+1+15		; count + null term + round up
	mov	cl,4
	shr	bx,cl			; convert to paragraphs (divide by 16)
	mov	cx,bx			; remember desired paragraphs
	mov	ah,alloc		; allocate a memory block
	int	dos
	jc	dode12			; c = error, not enough memory
 	cmp	bx,cx			; obtained vs wanted
	jae	dode7			; ae = enough
	mov	es,ax			; allocated segment
	mov	ah,freemem		; free it again
	int	dos
	jmp	short dode12		; quit here

dode7:	mov	macptr,ax		; store new segment
	mov	es,ax			; segment of string
	xor	di,di			; offset of count word
	mov	cx,deftemp		; length of definition string
	mov	ax,cx
	cld
	stosw				; store length of string
	rep	movsb			; copy string
	mov	bx,offset mcctab	
	mov	dx,offset rdbuf		; count word + name string
	call	addtab
dode10:	mov	ax,macptr		; return buffer segment to caller
	pop	es
	pop	di
	pop	si
	clc				; success
	ret
dode12:	pop	es			; no memory, clean stack
	pop	di
	pop	si
	mov	dx,offset ermes2	; no room for definition
	mov	ah,prstr
	int	dos
	stc
	ret
DODECOM	ENDP

; ASK <variable or macro name> <prompt string>
; Defines indicated variable/macro with text from user at keyboard or pipe
; (but not from a Take/macro). Prompt string is required.
; ASKQ does the same, but does not echo user's response.
ASKQ	PROC	NEAR
	mov	askecho,1		; temp to flag as Quiet version
	jmp	short ask0		; do common code
ASKQ	ENDP

ASK	PROC	NEAR
	mov	askecho,0		; temp to flag as echoing version
ask0:					; common code for ASK and ASKQ
	mov	dx,offset rdbuf+2	; point to work buffer
	mov	word ptr rdbuf,0
	mov	bx,offset askhlp1	; help
	mov	comand.cmper,1		; do not expand variable name
	mov	ah,cmword		; get variable name
	call	comnd
	jnc	ask1			; nc = success
	ret				; failure
ask1:	or	ax,ax			; anything given?
	jnz	ask2			; nz = yes
	mov	dx,offset ermes6	; more parameters needed
	jmp	reterr

ask2:	cmp	word ptr rdbuf+2,'%\'	; \%<char> substitution variable?
	jne	ask2b			; ne = no
	cmp	ax,2			; but missing <char>
	ja	ask2a			; a = no
	mov	rdbuf+4,'_'		; slip in an underscore
ask2a:	mov	ax,3			; limit to a single char
ask2b:	mov	bx,offset rdbuf+2	; start of name
	add	bx,ax			; plus length of variable name
	mov	byte ptr [bx],' '	; put space separator after name
	inc	ax			; count space
	mov	numhlp,ax		; remember length here
					; get ASK command prompt string
	mov	bx,offset decbuf	; borrowed buffer for prompt
	mov	byte ptr [bx],0		; safety terminator
	mov	dx,offset askhlp2
	mov	comand.cmblen,127	; our buffer length
	sub	comand.cmblen,ax	;  minus part used above
	mov	ah,cmline		; get prompt string
	call	comnd
	jnc	ask3			; nc = success
	ret				; failure
ask3:	or	ax,ax			; anything given?
	jnz	ask4			; nz = yes
	mov	dx,offset ermes6	; more parameters needed
	jmp	reterr

ask4:	mov	ax,takadr		; we could be in a macro or Take file
	mov	temp2,ax		; save Take address
	mov	al,taklev
	xor	ah,ah
	mov	temp1,ax		; and Take level
	mov	dx,size takinfo		; bytes for each current Take
	mul	dx			; times number of active Take/macros
	sub	takadr,ax		; clear Take address as if no
	mov	taklev,0		;  Take/macro were active so that
					;  user input is from kbd or pipe
	mov	word ptr [bx],0020h	; printing terminator for prompt
	mov	si,offset decbuf
	mov	di,si			; convert in-place
	call	cnvlin			; convert backslash items
	mov	dx,si			; converted prompt string, asciiz
 	call	prompt			; use our prompt
	mov	bx,offset rdbuf+129	; use this buffer for raw user input
	mov	word ptr [bx],0		; insert terminator
	mov	dl,askecho		; get echo/quiet flag
	mov	comand.cmquiet,dl	; 0 if echoing
	mov	dx,offset askhlp3	; help for user input
	mov	ah,cmline		; read user's input string
	call	comnd
	mov	comand.cmquiet,0	; permit echoing again
	mov	cx,temp2
	mov	takadr,cx		; restore Take address
	mov	cx,temp1
	mov	taklev,cl		; restore Take level
	jnc	ask5			; nc = success
	ret				; Control-C, quit now
ask5:	mov	cx,ax			; length of entry
	mov	si,offset rdbuf+129	; source string
	mov	di,offset rdbuf+2	; start of variable name
	add	di,numhlp		; di points to final user string
	push	es			; save es
	push	ds
	pop	es			; set es to data segment
	cld
	jcxz	ask8			; z = empty
	rep	movsb			; copy string
ask8:	xor	al,al			; get null terminator
	stosb				; plant it
	pop	es
 	mov	dx,offset rdbuf+2	; command buffer beginning
	call	strlen			; CX=len of <variable>< ><user string>
	jmp	DODECOM			; define the macro/variable and exit
ASK	ENDP

; GETOK <prompt>   displays prompt or default prompt, asks for affirmative
; user reply, returns success/fail status.
getok	proc	near
	mov	bx,offset rdbuf		; point to work buffer
	mov	word ptr [bx],0		; safety terminator
	mov	dx,offset getokhlp
	mov	comand.cmblen,127	; our buffer length
	mov	comand.cmcr,1		; bare cr is ok
	mov	ah,cmline		; get prompt string
	mov	comand.cmcr,0
	call	comnd
	jnc	getok1			; nc = success
	ret				; failure
getok1:	or	ax,ax			; anything given?
	jnz	getok2			; nz = yes
	mov	si,offset getdef	; default prompt
	mov	di,offset rdbuf
	call	strcpy			; paste in default prompt

getok2:	mov	ax,takadr		; we could be in a macro or Take file
	mov	temp2,ax		; save Take address
	mov	al,taklev
	xor	ah,ah
	mov	temp1,ax		; and Take level
	mov	dx,size takinfo		; bytes for each current Take
	mul	dx			; times number of active Take/macros
	sub	takadr,ax		; clear Take address as if no
	mov	taklev,0		;  Take/macro were active so that
					;  user input is from kbd or pipe
	mov	si,offset rdbuf
	mov	di,si			; convert in-place
	call	cnvlin			; convert backslash items
	mov	dx,si
	call	strlen			; get length to cx
	mov	bx,cx
	mov	word ptr [si+bx],0020h	; printing terminator for prompt
getok3:	mov	dx,offset rdbuf		; converted prompt string, asciiz
 	call	prompt			; use our prompt
	mov	flags.cxzflg,0		; clear Control-C indicator
	mov	dx,offset gettab	; use this table
	xor	bx,bx			; table is help
	mov	comand.cmcr,1		; null response permitted
	mov	ah,cmkey		; read user's input word
	call	comnd
	mov	comand.cmcr,0
	jnc	getok4			; nc = success
	cmp	flags.cxzflg,'C'	; did user type Control-C to quit?
	jne	short getok3		; ne = no, syntax failure, reprompt
	stc				; set carry flag again
	jmp	short getok5		; exit failure
getok4:	push	bx
	mov	ah,cmeol		; get c/r confirmation
	call	comnd
	pop	bx			; recover keyword 16 bit value
getok5:	mov	cx,temp2
	mov	takadr,cx		; restore Take address
	mov	cx,temp1
	mov	taklev,cl		; restore Take level
	jnc	getok6			; nc = success
	mov	kstatus,ksgen		; failure
	ret				; Control-C, quit now
getok6:	mov	kstatus,bx		; return status
	ret
getok	endp

; Initialize macro IBM at Kermit startup time
initibm	proc	near
	mov	si,offset ibmmac	; text of IBM macro
	mov	di,offset rdbuf+2	; where command lines go
	call	strcpy			; copy it there
	mov	dx,di			; get length of command line
	call	strlen			; set cx to length, for dodecom
	jmp	dodecom			; now define the macro
initibm	endp

; Open a disk based Take file buffer. Define macro named "<null>T<'taklev'>",
; in mcctab and allocate 128 byte uninitiated buffer for disk i/o. Leading null
; is to prevent user from employing the same name accidentally. Return seg
; of buffer in [takadr].takbuf and set [takadr].takptr to offset of first
; byte after leading count byte. Uses dodecom to make this macro.
; Return carry clear for success, carry set for failure.

TAKOPEN	PROC	NEAR
	push	ax
	push	bx
	push	cx
	push	dx
	cmp	taklev,maxtak		; room in take level?
	jb	takope1			; b = yes
	mov	dx,offset ermes4	; say too many Take files
	mov	ah,prstr		; display error message
	int	dos
	stc				; set carry for failure
	jmp	short takope2

takope1:mov	word ptr rdbuf,3	; length of name, 3 bytes <null>Tn
	mov	rdbuf+2,0
	mov	rdbuf+3,'T'		; name of <null>Tn
	mov	al,taklev		; Take level digit
	inc	al			; for what will be next Take level
	add	al,'0'			; add ascii bias
	mov	rdbuf+4,al		; last of the name
	mov	rdbuf+5,' '		; separate dummy definition
	mov	cx,tbufsiz		; fill with dummy non-blank data
	push	cx			; length of buffer, for dodecom
	push	di
	push	es			; save es
	push	ds			; set es to data segment
	pop	es
	cld
	mov	al,'.'			; dummy fill pattern
	mov	di,offset rdbuf+6	; definition text starts here
	rep	stosb			; store the pattern
	pop	es
	pop	di
	pop	cx			; get command length again
	call	dodecom			; define our Take macro
	jc	takope2			; c = failure
	xor	ax,ax
	xor	cx,cx
	cmp	taklev,0		; at top level now?
	je	takope3			; e = yes
	mov	bx,takadr
	mov	ax,[bx].takargc		; get argument count
	mov	cx,[bx].takctr		; get COUNT
takope3:add	takadr,size takinfo	; pointer to new Take structure
	inc	taklev
	mov	bx,takadr		; pointer to new Take structure
	mov	[bx].takargc,ax		; copy in old argc
	mov	[bx].takctr,cx		; copy in old count
	mov	ax,macptr		; segment of buffer
	mov	[bx].takbuf,ax		; segment of Take buffer
	mov	[bx].takcnt,tbufsiz-2	; number of unread bytes
	mov	[bx].takptr,2		; init pointer to definition itself
	clc				; carry clear for success
takope2:pop	dx
	pop	cx
	pop	bx
	pop	ax
	ret
TAKOPEN	ENDP

; Close Take file. Enter at Take level to be closed. Removes pseudo macro
; name <null>Tn and its buffer, closes disk file, pops Take level.

TAKCLOS	PROC	NEAR
	cmp	taklev,0		; anything to close?
	jle	takclo3			; le = no
	push	ax
	push	bx
	push	cx
	mov	al,taklev		; Take level digit
	add	al,'0'			; add ascii bias
	mov	temptc+2,0
	mov	temptc+3,'T'
	mov	temptc+4,al		; last of the name
	push	di
	mov	di,offset temptc	; pointer for remtab
	call	remtab			; remove possible old macro and buffer
	pop	di
	mov	bx,takadr		; point to Take structure
	mov	al,[bx].taktyp
	cmp	[bx].taktyp,0feh	; disk file?
	jne	takclo1			; ne = no, no buffer to deallocate
	mov	bx,[bx].takhnd		; get file handle
	mov	ah,close2		; close file
	int	dos
	dec	taklev			; pop disk file Take level
	sub	takadr,size takinfo	; get previous Take's address
	jmp	short takclo2

takclo1:dec	taklev			; pop macro Take level
	sub	takadr,size takinfo	; get previous Take's address
	cmp	al,0ffh			; regular macro?
	jne	takclo2			; ne = no, no unhiding necessary
	call	unhidemac		; rename previous \%n macros
takclo2:pop	cx
	pop	bx
	pop	ax			; close prev Take/Macro if at EOF too
 	cmp	taklev,0		; Take/macro still open?
	je	takclo3			; e = no
	push	bx
	mov	bx,takadr		; get it's address
	cmp	[bx].takcnt,0		; is it at EOF?
	pop	bx
	ja	takclo3			; a = no
	call	takrd			; empty Take, try filling buf again
	push	bx
	mov	bx,takadr		; get it's address
	cmp	[bx].takcnt,0		; is it at EOF?
	pop	bx
	ja	takclo3			; a = not an empty Take file
	jmp	takclos			; yes, close it too
takclo3:ret
TAKCLOS	ENDP

; POP/END command. Defend against command parser closing the Take/Macro at
; the end of file. Return optional trailing number in ERRORLEVEL (errlev).
POPCMD	proc	near
	mov	ah,cmline		; get optional error value and msg
	mov	bx,offset rdbuf+1
	mov	rdbuf,'\'		; in case the user did not specify
	mov	dx,offset pophlp	; help on numerical argument
	mov	comand.cmcr,1		; bare c/r's allowed
	call	comnd
	mov	comand.cmcr,0		; restore normal state
	jc	popcmd3			; c = failure
	mov	ah,cmeol		; confirm
	call	comnd
	jc	popcmd3
	mov	si,offset rdbuf
	cmp	byte ptr [si+1],'\'	; user specified?
	jne	popcmd1			; ne = no, use ours
	inc	si			; yes, use theirs
popcmd1:call	katoi			; convert to number in ax
	jc	popcmd2			; c = not a number
	mov	errlev,al		; return value in ERRORLEVEL
	mov	kstatus,ax		; and in STATUS
	mov	di,si			; msg pointer, convert in-place
	call	cnvlin			; convert braces and numbers
popcmd4:lodsb				; read a msg char
	or	al,al			; null terminator?
	jz	popcmd2			; z = empty string
	cmp	al,' '			; leading white space?
	je	popcmd4			; be = leading white space
	dec	si			; backup to non-white char
	mov	di,si			; msg pointer, convert in-place
	call	cnvlin			; convert braces and numbers
	mov	dx,offset crlf
	mov	ah,prstr
	int	dos
	mov	dx,si			; message
	call	prtasz
popcmd2:mov	al,oldtak		; Take level previous to this cmd
	sub	al,taklev		; minus Take level now
	ja	popcmd3			; a = have exited macro already
	jmp	takclos			; close current Macro/Take
popcmd3:ret
POPCMD	endp

; add an entry to a keyword table
; enter with bx = table address, dx = ptr to new entry, macptr = string seg
; mccptr = offset of free bytes in table mcctab.
; no check is made to see if the entry fits in the table.
addtab	proc	near
	push	cx
	push	si
	push	es
	push	bp
	cld
	mov	ax,ds
	mov	es,ax		; address data segment
	mov	bp,bx		; remember where macro name table starts
	mov	cl,[bx]		; pick up length of table
	xor	ch,ch
	inc	bx		; point to actual table
	jcxz	addta4		; cx = 0 if table is presently empty

addta1:	push	cx		; preserve count
	mov	si,dx		; point to entry
	lodsw			; get length of new entry
	mov	cx,[bx]		; and length of table entry
	cmp	ax,cx		; are they the same?
	lahf			; remember result of comparison
	jae	addta2		; is new smaller? ae = no, use table length
	mov	cx,ax		; else use length of new entry
addta2:	lea	di,[bx+2]	; point to actual keyword
	repe	cmpsb		; compare strings
	pop	cx		; restore count
	jb	addta4		; below, insert before this one
	jne	addta3		; not below or same, keep going
	sahf			; same. get back result of length comparison
	jb	addta4		; if new len is smaller, insert here
	jne	addta3		; if not same size, keep going
	mov	si,bx		; else this is where entry goes
	jmp	short addta6	; no insertion required
addta3:	mov	ax,[bx]		; length of keyword
	add	bx,ax		; skip this entry
	add	bx,4		; length word and 16 bit value
	loop	addta1		; and keep looking
addta4:	mov	si,bx		; this is first location to move
	mov	di,bx
	inc	ds:byte ptr [bp] ; remember we're adding one
	jcxz	addta6		; z = no more entries, forget this stuff
addta5:	mov	bx,[di]		; get length
	lea	di,[bx+di+4]	; end is origin + length + 4 for len, value
	loop	addta5		; loop thru remaining keywords
	mov	cx,di
	sub	cx,si		; compute # of bytes to move
	push	si		; preserve loc for new entry
	mov	si,di		; first to move is last
	dec	si		; minus one
	mov	di,dx		; new entry
	mov	bx,[di]		; get length
	lea	di,[bx+si+4]	; dest is source + length of new + 4
	std			; move backward
	rep	movsb		; move the table down (compress it)
	cld			; put flag back
	pop	si
addta6:	mov	di,si		; this is where new entry goes
	mov	si,dx		; this is where it comes from
	mov	cx,[si]		; length of name
	add	cx,2		; include count byte
	add	mccptr,cx	; update free space pointer: cnt+name
	rep	movsb		; insert new entry
	mov	ax,macptr	; and string address
	stosw
	add	mccptr,2	; plus string address
	pop	bp
	pop	es
	pop	si
	pop	cx
	ret
addtab	endp

; If new keyword matches an existing one then remove existing keyword,
; its string definition, compress tables mcctab and macbuf, readjust string
; pointers for each macro name, reduce number of macro table entries by one.
; Enter with DI pointing at length word of mac name (followed by mac name).
; Otherwise, exit with no changes.  13 June 1987 [jrd]
remtab	proc	near
	push	ax
	push	bx
	push	cx
	push	si
	push	di
	mov	bx,temp			; preserve
	push	bx
	mov	bx,offset mcctab+1	; table of macro keywords
	mov	temp,0			; temp = current keyword
	cmp	byte ptr mcctab,0	; any macros defined?
	jne	remta1			; ne = yes
	jmp	remtax			; else exit now
remta1:					; match table keyword and text word
	mov	si,di			; pointer to user's cnt+name
	mov	cx,[si]			; length of user's macro name
	add	si,2			; point to new macro name
	cmp	cx,[bx]			; compare length vs table keyword
	jne	remta4			; ne = not equal lengths, try another
	push	si			; lengths match, how about spelling?
	push	bx
	add	bx,2			; point at start of keyword
remta2:	mov	ah,[bx]			; keyword char
	mov	al,[si]			; new text char
	cmp	al,ah			; test characters
	jne	remta3			; ne = no match
	inc 	si			; move to next char
	inc	bx
	loop	remta2			; loop through entire length
remta3:	pop	bx
	pop	si
	jcxz	remta6			; z: cx = 0, exit with match;
					;  else select next keyword
remta4:	inc	temp			; number of keyword to test next
	mov	cx,temp
	cmp	cl,mcctab		; all done? Recall, temp starts at 0
	jb	remta5			; b = not yet
	jmp	remtax			; exhausted search, unsuccessfully
remta5:	mov	ax,[bx]			; cnt (keyword length from macro)
	add	ax,4			; skip count and word pointer
	add	bx,ax			; bx = start of next keyword slot
	jmp	short remta1		; do another comparison
					; new name already present as a macro
remta6:	cld				; clear macro string and macro name
	push	ds
	pop	es			; set es to data segment
	mov	temp,bx			; save ptr to found keyword
	mov	ax,[bx]			; cnt (keyword length of macro)
	add	ax,2			; skip cnt
	add	bx,ax			; point to string segment field
	add	ax,2			; count segment field bytes
	sub	mccptr,ax		; readjust free space ptr for names
	push	bx
	push	es
	mov	es,[bx]			; segment of string
	mov	ax,ds			; check for being in our data segment
	cmp	ax,[bx]			; same as our data seg?
	je	remta7			; e = yes, don't free that
	mov	ah,freemem		; free that memory block
	int	dos
remta7:	pop	es
	pop	bx
					; clear keyword table mcctab
	add	bx,2			; compute source = next keyword
	mov	si,bx			; address of next keyword
	mov	di,temp			; address of found keyword
	mov	cx,offset mcctab+mcclen ; address of buffer end
	sub	cx,si			; amount to move
	jcxz	remtax			; cx = 0 means none
	rep	movsb			; move down keywords (deletes current)
	dec	mcctab			; one less keyword
remtax:	pop	temp			; recover temp variable
	pop	di
	pop	si
	pop	cx
	pop	bx
	pop	ax
	ret
remtab	endp

; Common Get keyword + Get Confirm sequence. Call with dx = keyword table,
; bx = help message offset. Returns result in BX. Modifies AX, BX.
; Returns carry clear if sucessful else carry set. Used in many places below.
keyend	proc	near
	mov	ah,cmkey
	call	comnd
	jnc	keyend1			; nc = success
	ret				; failure
keyend1:push	bx			; save returned results around call
	mov	ah,cmeol		; get c/r confirmation
	call	comnd
	pop	bx			; recover keyword 16 bit value
	ret				; return with carry from comnd
keyend	endp

srvdsa	proc	near			; DISABLE Server commands
	mov	dx,offset srvdetab
	mov	bx,offset sdshlp
	call	keyend
	jc	srvdsa1			; c = failure
	cmp	apctrap,0		; disable from APC
	jne	srvdsa1			; ne = yes
	or	denyflg,bx		; turn on bit (deny) for that item
srvdsa1:ret
srvdsa	endp

srvena	proc	near			; ENABLE Server commands
	mov	dx,offset srvdetab	; keyword table
	mov	bx,offset sdshlp	; help on keywords
	call	keyend
	jc	srvena1			; c = failure
	cmp	apctrap,0		; disable from APC
	jne	srvena1			; ne = yes
	not	bx			; invert bits
	and	denyflg,bx		; turn off (enable) selected item
srvena1:ret
srvena	endp


; This is the SET command
; Called analyzers return carry clear for success, else carry set.
SETCOM	PROC	NEAR			; Dispatch all SET commands from here
	mov	kstatus,kssuc		; global status, success
	mov	dx,offset settab	; Parse a keyword from the set table
	mov	bx,offset sethlp
	mov	ah,cmkey
	call	comnd
	jc	setcom1			; c = failure
	jmp	bx			; execute analyzer routine
setcom1:ret
SETCOM	endp

SETATT	PROC	NEAR			; Set attributes on | off
	mov	dx,offset atttab
	xor	bx,bx
	mov	ah,cmkey
	call	comnd
	jc	setatt3			; c = failure
	mov	dx,bx			; hold results in dx
	cmp	dl,0ffh			; ON/OFF (all of them)?
	je	setatt1			; e = yes
	push	dx
	mov	dx,offset ontab		; get on/off state
	xor	bx,bx
	mov	ah,cmkey
	call	comnd
	pop	dx
	jc	setatt3			; c = failure
	mov	dh,bl			; store on/off state in dh
setatt1:push	dx
	mov	ah,cmeol
	call	comnd
	pop	dx
	jc	setatt3
	mov	al,flags.attflg		; current flags
	not	dl			; all but those affected
	and	al,dl			; turn off affected flags
	or	dh,dh			; off (dh = 0)?
	jz	setatt2			; z = yes
	not	dl			; affected flags back again as ones
	or	al,dl			; turn on affected flags
setatt2:mov	flags.attflg,al
setatt3:ret
SETATT	ENDP

; SET BAUD or SET SPEED
; See system dependent routine BAUDST in file MSXxxx.ASM

; SET BELL on or off

BELLST	PROC	NEAR
	mov	dx,offset ontab		; on/off table
	xor	bx,bx			; help
	call	keyend
	jc	bellst1			; c = failure
	mov	flags.belflg,bl
bellst1:ret
BELLST	ENDP

; SET BLOCK-CHECK

BLKSET	PROC	NEAR
	mov	dx,offset blktab	; table
	xor	bx,bx			; help, use table
	call	keyend
	jc	blkset1			; c = failure
	mov	dtrans.chklen,bl	; use this char as initial checksum
blkset1:ret
BLKSET	ENDP


; Set port addresses for COM1 .. COM4 at Kermit initialization time via
; Environment. Called by command parser while doing Environment reading in
; mssker.asm and via SET COM1 .. SET COM4.
COM1PORT proc	near
	mov	bx,0			; offset of com1 port address
	jmp	short comport
COM1PORT endp
COM2PORT proc	near
	mov	bx,2			; offset of com2 port address
	jmp	short comport
COM2PORT endp
COM3PORT proc	near
	mov	bx,4			; offset of com3 port address
	jmp	short comport
COM3PORT endp

COM4PORT proc	near
	mov	bx,6			; offset of com4 port address
;;	jmp	comport
COM4PORT endp

COMPORT	proc	near			; worker for above
	push	bx			; save offset
	mov	dx,offset rdbuf+1
	mov	word ptr rdbuf,0
	mov	bx,offset comhlp
	mov	ah,cmword		; get port address number
	call	comnd
	jnc	compor3
	pop	bx			; fail
	ret
compor3:mov	numerr,0		; no error message
	mov	min,100h		; smallest number
	mov	max,0fff0h		; largest magnitude
	mov	numhlp,0		; help
	call	numwd			; parse this word
	jnc	compor4			; nc = success, value in ax
	pop	bx
	ret
compor4:mov	temp1,ax		; save port address
	mov	dx,offset rdbuf+1
	mov	word ptr rdbuf,0
	mov	bx,offset irqhlp
	mov	temp2,0
	mov	ah,cmword		; read IRQ
	call	comnd
	jnc	compor5
	pop	bx
	ret
compor5:push	ax
	mov	ah,cmeol		; get command confirmation
	call	comnd
	pop	ax
	jnc	compor5a		; nc = success
	ret
compor5a:or	ax,ax			; anything given?
	jz	compor7			; z = no
	mov	numhlp,0		; help
	mov	numerr,0		; no error message
	mov	min,2			; smallest number
	mov	max,15			; largest magnitude
	call	numwd			; parse this word
	jnc	compor6			; nc = success
	pop	bx
	ret
compor6:mov	temp2,ax		; save IRQ
compor7:pop	bx			; recover offset
	cmp	word ptr machnam,'BI'	; check for "IBM-PC"
	jne	compor1			; ne = not this name, fail
	cmp	word ptr machnam+2,'-M'
	jne	compor1
	cmp	word ptr machnam+4,'CP'
	jne	compor1
	push	es
	mov	al,flags.comflg		; current comms port
	dec	al			; count from 0, as per Bios
	shl	al,1			; double to use word index of Bios
	cmp	al,bl			; using this port now?
	jne	compor2			; ne = no
	call	serrst			; reset the port
compor2:mov	cx,40h			; segment 40h
	mov	es,cx
	mov	ax,temp1		; port address
	mov	es:[bx],ax		; set port address
	pop	es
	shr	bl,1			; coms port offset 0,2,4,6 to 0,1,2,3
	mov	ax,temp2		; IRQ
	mov	portirq[bx],al
	clc
compor1:ret
COMPORT	endp

; Set CONTROL PREFIXED <code>, CONTROL UNPREFIXED <code>, code can be ALL
cntlset	proc	near
	push	es
	mov	di,seg decbuf		; copy protlist to work buffer decbuf
	mov	es,di
	mov	si,offset protlist
	mov	di,offset decbuf
	mov	cx,32
	cld
	rep	movsb
	pop	es

	mov	dx,offset cntltab	; table
	mov	bx,offset cntlhlp	; help
	mov	ah,cmkey
	call	comnd
	jc	cntlsetx		; c = failure
	mov	rdbuf,bl		; save operation value
cntlse1:mov	ah,cmword		; get optional error value and msg
	mov	dx,offset rdbuf+2
	mov	rdbuf+1,'\'		; in case the user did not specify
	mov	bx,offset ctlhlp	; help on numerical argument
	call	comnd
	jc	cntlsetx		; c = failure
	mov	si,offset rdbuf+2
	or	ax,ax			; anything given?
	jnz	cntlse2			; nz = yes
	mov	ah,cmeol		; confirm
	call	comnd
	jc	cntlsetx		; c = failure
	push	es			; copy work buffer decbuf to protlist
	mov	di,seg protlist
	mov	es,di
	mov	di,offset protlist
	mov	si,offset decbuf
	mov	cx,32
	cld
	rep	movsb
	pop	es
	clc
	ret

cntlse2:mov	al,[si]			; look for ALL
	or	al,al			; end of string?
	jz	cntlse1			; z = yes, get more user input
	cmp	al,','			; comma separator?
	jne	cntlse2a		; ne = no
	inc	si			; skip it
	jmp	short cntlse2
cntlse2a:or	al,20h			; to lower
	cmp	al,'a'			; a in ALL?
	je	cntlse8			; e = got ALL
	cmp	byte ptr [si],'\'	; user specified?
	je	cntlse3			; e = yes
	dec	si
	mov	byte ptr [si],'\'	; insert prefix
cntlse3:call	katoi			; convert to number in ax
	jc	cntlsety		; c = failure
	cmp	al,159			; out of range?
	ja	cntlsety		; a = yes
	cmp	al,128			; in 8-bit range?
	jae	cntlse4			; ae = yes
	cmp	al,31			; out of range?
	ja	cntlsety		; a = yes
cntlse4:mov	ah,rdbuf		; protected/unprotected pointer 0/1
	mov	bl,al			; char
	and	bl,not 80h		; strip high bit from index
	xor	bh,bh
	or	ah,ah			; protecting?
	jz	cntlse6			; z = yes
	mov	ah,1			; assume unprotecting 7-bit char
	and	al,80h			; get high bit
	jz	cntlse5			; z = no high bit
	mov	ah,80h			; set high bit flag
cntlse5:or	decbuf[bx],ah		; set unprotection bit
	jmp	cntlse2			; get more input

cntlse6:mov	ah,1			; assume protecting 7-bit char
	and	al,80h			; get high bit
	jz	cntlse7			; z = no high bit
	mov	ah,80h			; set high bit flag
cntlse7:not	ah			; invert bits
	and	decbuf[bx],ah		; clear the unprotection bit
	jmp	cntlse2			; get more input

cntlsetx:ret				; success or failure
					; process ALL
cntlse8:mov	cx,32
	xor	bx,bx
	mov	al,rdbuf		; get kind of operation
	or	al,al			; prefix (0)?
	je	cntlse9			; e = yes
	mov	al,81h			; unprefix all (7 and 8 bit)
cntlse9:mov	decbuf[bx],al		; set the state
	inc	bx
	loop	cntlse9			; do all
	jmp	cntlse1			; get more user input

cntlsety:mov	ah,prstr
	mov	dx,offset badcntlmsg	; say out of range
	int	dos
	jmp	cntlse1			; get more input
cntlset	endp

; SET COUNTER number	for script IF COUNTER number <command>
TAKECTR	PROC	NEAR
	mov	min,0			; get decimal char code
	mov	max,65535		; range is 0 to 65535 decimal
	mov	numhlp,offset takchlp	; help message
	mov	numerr,0		; error message
	call	num0			; convert number, return it in ax
	jc	takect2			; c = error
	push	ax			; save numerical code
	mov	ah,cmeol
	call	comnd			; get a confirm
	pop	ax			; recover ax
	jc	takect2			; c = failure
	cmp	taklev,0		; in a Take file?
	je	takect4			; e = no
	push	bx
	mov	bx,takadr
	mov	[bx].takctr,ax		; set COUNT value
	pop	bx
	clc				; success
takect2:ret
takect4:mov	dx,offset takcerr	; say must be in Take file
	jmp	reterr			; display msg and return carry clear
TAKECTR	ENDP

; SET DEBUG {OFF | ON | SESSSION | PACKETS}

DEBST	PROC       NEAR
	mov	dx,offset debtab
	mov	bx,offset debhlp
	call	keyend
	jnc	debst1			; nc = success
	ret				; failure
debst1:	or	flags.debug,bl		; set the mode, except for Off
	or	bx,bx			; OFF?
	jnz	debst2			; nz = no
	mov	flags.debug,bl		; set the DEBUG flags off
debst2:	clc				; success
	ret
DEBST	ENDP

; SET DESTINATION   of incoming files

DESSET	PROC	NEAR
	mov	dx,offset destab
	xor	bx,bx
	call	keyend
	jc	desset1			; c = failure
	mov	flags.destflg,bl	; set the destination flag
desset1:ret
DESSET	ENDP

; SET DEFAULT-DISK    for sending/receiving, etc
; See cwdir in file mssker

; SET DELAY seconds   Used only for SEND command in local mode
SETDELY	PROC	NEAR
	mov	min,0			; smallest acceptable value
	mov	max,63			; largest acceptable value
	mov	numhlp,offset delyhlp	; help message
	mov	numerr,0		; complaint message
	call	num0			; parse numerical input
	jc	setdly1			; c = error
	mov	trans.sdelay,al
setdly1:ret				; success or failure
SETDELY	ENDP

; SET DISPLAY Quiet/Regular/Serial/7-Bit/8-Bit (inverse of Set Remote on/off)
; Accepts two keywords in one command
disply	proc	near
	mov	ah,cmkey
	mov	dx,offset distab
	mov	bx,offset dishlp
	call	comnd
	jnc	displ0			; nc = success
	ret				; return failure
displ0:	mov	temp1,bx		; save parsed value
	mov	temp2,0ffffh		; assume no second keyword
	mov	comand.cmcr,1		; bare CR's are allowed
	mov	ah,cmkey		; parse for second keyword
	mov	dx,offset distab
	mov	bx,offset dishlp
	call	comnd
	jc	displ1			; no keyword
	mov	temp2,bx		; get key value
displ1:	mov	comand.cmcr,0		; bare CR's are not allowed
	mov	ah,cmeol
	call	comnd			; confirm
	jnc	displ2			; nc = success
	ret				; failure
displ2:	mov	ax,temp1		; examine first key value
	call	dispcom			; do common code
	mov	ax,temp2		; examine second key value
;	jmp	dispcom			; finish in common code

dispcom:or	ax,ax			; check range
	jle	dispc3			; le = not legal, ignore
	cmp	al,7			; 7-8 bit value?
	jge	dispc2			; ge = yes
	and	flags.remflg,not(dquiet+dregular+dserial)
	or	flags.remflg,al		; set display mode
	clc				; success
	ret				; check next key value
dispc2:	cmp	al,8			; set 8-bit wide display?
	ja	dispc3			; a = bad value
	and	flags.remflg,not d8bit	; assume want 7 bit mode
	cmp	al,7			; really want 7 bit mode?
	je	dispc3			; e = yes
	or	flags.remflg,d8bit	; set 8 bit flag
dispc3:	clc				; success
	ret				; end of display common code
disply	endp


; Set Dump filename  for saving screen images on disk.
; Puts filename in global string dmpname
setdmp	proc	near
	mov	dx,offset rdbuf		; work area
	mov	rdbuf,0			; clear it
	mov 	bx,offset dmphlp	; help message
	mov	ah,cmword		; allow paths
	call	comnd
	jc	setdmp2			; c = failure
	mov	ah,cmeol
	call	comnd
	jc	setdmp2			; c = failure
	mov	dx,offset rdbuf		; assume we will use this text
	call	strlen			; filename given?
	mov	si,dx			; for strcpy
	or	cx,cx			; length of user's filename
	jg	setdmp1			; g = filename is given
	mov	si,offset dmpdefnam	; no name, use default instead
setdmp1:mov	di,offset dmpname	; copy to globally available loc
	call	strcpy
	clc
setdmp2:ret
setdmp	endp

; Set DUPLEX {FULL, HALF}
setdup	proc	near
	xor	bx,bx
	mov	dx,offset duptab
	call	keyend
	jc	setdup1			; c = failure
	mov	si,portval
	mov	[si].duplex,bl		; set value
	mov	[si].ecoflg,0		; turn off local echoing
	or	bl,bl			; full duplex?
	jz	setdup1			; z = yes
	mov	[si].floflg,0		; no flow control for half duplex
	mov	[si].ecoflg,1		; turn on local echoing
	call	serrst			; reset port so opening uses above
setdup1:ret
setdup	endp

; SET EOF

SETEOF	PROC	NEAR
	xor	bx,bx
	mov	dx,offset seoftab
	call	keyend
	jc	seteof1			; c = failure
	mov	flags.eofcz,bl		; set value
seteof1:ret
SETEOF	ENDP

; SET End-of-Packet char (for Sent packets)
; Archic, here for downward compatibility
EOLSET	PROC	NEAR
	mov	stflg,'S'		; set send/receive flag to Send
	jmp	sreol			; use Set Send/Rec routine do the work
EOLSET	ENDP

; SET ERRORLEVEL number
SETERL	PROC	NEAR
	mov	numhlp,offset erlhlp	; help
	mov	numerr,0		; error message
	mov	min,0			; smallest number
	mov	max,255			; largest magnitude
	call	num0			; parse numerical input
	jc	seterl1			; c = error
	mov	errlev,al		; store result
	clc
seterl1:ret
SETERL	ENDP

; SET ESCAPE character.
; Accept literal control codes and \### numbers. [jrd] 18 Oct 1987
ESCSET	PROC	NEAR
	mov	ah,cmword
	mov	dx,offset rdbuf		; work space
	mov	word ptr rdbuf,0	; clear it
	mov	bx,offset eschlp	; help
	call	comnd
	jc	escse2			; c = failure
	or	ax,ax			; anything given?
	jnz	escse1			; nz = yes
	mov	dx,offset ermes6	; more parameters needed
	jmp	reterr
escse1:	mov	ah,cmeol		; get a confirm
	call	comnd
	jc	escse2			; c = failure
	mov	si,offset rdbuf		; source of chars
	call	katoi			; convert escaped numbers to binary
	cmp	ax,spc			; is it a control code?
	jae	escse3			; ae = no, complain
	or	ax,ax			; non-zero too?
	jz	escse3			; z = zero
	mov	trans.escchr,al		; save new escape char code
	clc
escse2:	ret
escse3:	mov	dx,offset escerr
	jmp	reterr
ESCSET	ENDP

; SET FILE {DISPLAY, WARNING, TYPE, CHARACTER-SET}
SETFILE	proc	near
	mov	dx,offset setfitab	; SET FILE table
	xor	bx,bx
	mov	ah,cmkey
	call	comnd
	jc	setfiy			; c = failure
	or	bl,bl			; Warning?
	jnz	setfi1			; nz = no
					; entry point for old SET WARNING
FILWAR:	mov	dx,offset warntab	; warning table, on, off, no-super
	xor	bx,bx
	call	keyend
	jc	setfiy			; c = failure
	mov	flags.flwflg,bl		; set the filewarning flag
setfiy:	ret

setfi1:	cmp	bl,1			; SET FILE CHARACTER-SET?
	jne	setfi2			; ne = no
	mov	dx,offset setchtab	; table of char sets
	xor	bx,bx
	call	keyend			; get the set id
	jc	setfiy			; c = error
	mov	flags.chrset,bx		; save the id
	cmp	bx,866			; setting CP866?
	jne	setfi1a			; ne = no
	cmp	dtrans.xchset,xfr_cyrillic ; using TRANSFER of Cryillic?
	je	setfi1a			; e = yes
	mov	dtrans.xchset,xfr_cyrillic ; force TRANSFER of Cyrillic
	mov	trans.xchset,xfr_cyrillic
	mov	ah,prstr
	mov	dx,offset setchmsg	; show warning
	int	dos
	clc
	ret
setfi1a:cmp	bx,932			; setting Shift-JIS?
	jne	setfi1b			; ne = no
	mov	dtrans.xchset,xfr_japanese ; force TRANSFER of Japanese-EUC
	mov	trans.xchset,xfr_japanese
	mov	ah,prstr
	mov	dx,offset setchmsg2	; show warning
	int	dos
	clc
	ret
setfi1b:cmp	bx,862			; setting CP862?
	jne	setfi1c			; ne = no
	mov	dtrans.xchset,xfr_hebiso ; force TRANSFER of Latin-Hebrew
	mov	trans.xchset,xfr_hebiso
	mov	ah,prstr
	mov	dx,offset setchmsg3	; show warning
	int	dos
setfi1c:clc
	ret

setfi2:	cmp	bl,2			; SET FILE TYPE?
	jne	setfi3			; ne = 3
	mov	dx,offset xftyptab	; table of types
	xor	bx,bx
	call	keyend
	jc	setfix			; c = error
	mov	dtrans.xtype,bl		; store transfer type
	mov	trans.xtype,bl		; store transfer type
	ret
setfi3:	cmp	bl,3			; SET FILE DISPLAY?
	jne	setfix			; ne = no
	mov	dx,offset distab2	; table
	xor	bx,bx
	call	keyend
	jc	setfix			; c = failure
	and	flags.remflg,not(dquiet+dregular+dserial)
	or	flags.remflg,bl		; set display mode
	clc
setfix:	ret
SETFILE	endp

; SET FLOW-CONTROL {NONE, XONXOFF, RTS/CTS}

FLOSET	PROC	NEAR
	mov	dx,offset flotab
  	xor	bx,bx
	call	keyend
	jc	floset3			; c = failure
	mov	si,portval
	mov	ax,floxon		; xon/xoff pair
	or	bx,bx			; any flow control?
	jz	floset1			; z = none
	test	bx,1+2			; using xon/xoff?
	jnz	floset2			; nz = xon/xoff
	cmp	flags.comflg,4		; UART? (RTS/CTS case)
	ja	floset4			; a = no, error
floset1:xor	ax,ax			; clear chars for RTS/CTS and none
floset2:mov	[si].flowc,ax		; flow control values
	mov	[si].floflg,bl		; flow control kind
	call	serrst			; reset port so opening uses above
	clc
floset3:ret
floset4:mov	dx,offset ermes7	; error message
	jmp	reterr
FLOSET	ENDP

; SET HANDSHAKE
; Add ability to accept general decimal code.
HNDSET	PROC	NEAR
	mov	dx,offset hndtab	; table to scan
	mov	bx,offset hnd1hlp	; help message
	mov	ah,cmkey
	call	comnd
	jc	hnd2			; c = failure
	cmp	bl,0ffh			; want a general char code?
	jne	hnd1			; ne = no
	mov	min,0			; get decimal char code
	mov	max,255			; range is 0 to 255 decimal
	mov	numhlp,offset erlhlp	; help msg
	mov	numerr,0		; error message
	call	num0			; convert number, return it in ax
	jc	hnd2			; c = error
	mov	bx,ax			; recover numerical code
hnd1:	push	bx			; handshake type
	mov	ah,cmeol
	call	comnd			; get a confirm
	pop	bx			; recover bx
	jc	hnd2			; c = failure
	mov	si,portval
	or	bl,bl			; setting handshake off?
	jz	hnd0			; z = yes
	mov	[si].hndflg,1		; turn on handshaking
	mov	[si].hands,bl		; use this char as the handshake
	clc				; success
	ret
hnd0:	mov	[si].hndflg,bl		; no handshaking
	clc				; success
hnd2:	ret
HNDSET	ENDP

;   SET INCOMPLETE file disposition
 
ABFSET	PROC	NEAR
	mov	dx,offset abftab
	xor	bx,bx
	call	keyend
	jc	abfset1			; c = failure
	mov	flags.abfflg,bl		; Set the aborted file flag
abfset1:ret
ABFSET	ENDP
;
; Set Input commands (default-timeout, timeout-action, case, echo)
; By Jim Strudevant [jrs]
INPSET	PROC	NEAR
	mov	ah,cmkey		; key word
	mov	dx,offset inptab	; from inputtable
	xor	bx,bx			; no hints
	call	comnd			; get the word
	jc	inpset1			; c = failure
	jmp	bx			; do the sub command
inpset1:ret
;
; Set Input Default-timeout in seconds
;
inptmo:	mov	numhlp,offset intoms	; help
	mov	numerr,0		; error message
	mov	min,0			; smallest number
	mov	max,-1			; largest magnitude
	call	num0			; parse numerical input
	jc	inptmo1			; c = error
	mov	script.indfto,ax	; store result
inptmo1:ret
;
; Set Input Timeout action (proceed or quit)
;
inpact:	mov	dx,offset inactb	; from this list
	xor	bx,bx			; no hints
	call	keyend			; get it
	jc	inpact1			; c = failure
	mov	script.inactv,bl	; save the action
inpact1:ret
;
; Set Input Echo on or off
;
inpeco:	mov	dx,offset ontab		; from this list
	xor	bx,bx			; no hints
	call	keyend			; get it
	jc	inpeco1			; c = failure
	mov	script.inecho,bl	; save the action
inpeco1:ret
;
; Set Input Case observe or ignore
;
inpcas:	mov	dx,offset incstb	; from this list
	xor	bx,bx			; no hints
	call	keyend			; get it
	jc	inpcas1			; c = failure
	mov	script.incasv,bl	; save the action
inpcas1:ret
INPSET	ENDP

; Set length of script buffer for INPUT/REINPUT at Kermit initialization
; time via Environment. Called by command parser while doing Environment
; reading in mssker.asm. Do not call after Kermit has initialized.
SETINPBUF proc	near
	mov	scpbuflen,128		; store default buffer length
	mov	numhlp,0		; no help
	mov	numerr,0		; no error message
	mov	min,2			; smallest number (must be non-zero)
	mov	max,65535		; largest magnitude (16 bits worth)
	call	num0			; parse numerical input
	jc	setinpbx		; c = error
	mov	scpbuflen,ax		; store result
	clc
setinpbx:ret
SETINPBUF endp

; SET KEY
; Jumps to new Set Key routine
setkey	proc	near		
	cmp	stkadr,0	; keyboard translator present?
	je	setk4		; e = no, use this routine
	mov	bx,stkadr	; yes, get offset of procedure
	jmp	bx		; jump to keyboard translator
setk4:	mov	dx,offset ermes5
	jmp	reterr		; else print error message
setkey	endp

; SET LOCAL-ECHO {ON | OFF}
 
LCAL	PROC	NEAR
	mov	dx,offset ontab
	xor	bx,bx
	call	keyend
	jc	lcal1			; c = failure
	mov	si,portval
	mov	[si].ecoflg,bl		; Set the local echo flag
lcal1:	ret
LCAL	ENDP

; LOG  {PACKETS | SESSION | TRANSACTION} filename

setcpt	proc	near
	mov	dx,offset logtab	; kinds of logging
	mov	bx,offset loghlp	; help on kind of logging
	mov	ah,cmkey		; parse keyword
	call	comnd
	jnc	setcp20			; nc = success
	ret				; failure
setcp20:mov	numhlp,bx		; save the parsed value
	mov	dx,offset rdbuf		; holds the complete filename
	mov	rdbuf,0			; clear buffer
	mov 	bx,offset filhlp	; ask for filename
	mov	ah,cmword		; allow paths
	call	comnd
	jnc	setcp21			; nc = success
	ret				; failure
setcp21:mov	ah,cmeol
	call	comnd			; get a confirm
	jnc	setcp22			; nc = success
	ret				; failure
setcp22:mov	bx,numhlp		; recover kind of logging
	mov	dx,offset rdbuf		; length of filename to cx
	call	strlen			; length of given filename
	test	bl,logpkt		; packet logging?
	jz	setcp2			; z = no, try others
	mov	dx,offset lpktnam	; filename
	jcxz	setcp1			; z = no filename given
	mov	si,offset rdbuf		; get new name
	mov	di,dx			; destination
	call	strcpy			; replace old name
setcp1:	cmp	ploghnd,-1		; packet log file already open?
	je	setcp6			; e = no, open it
	jmp	setcp16			; say file is open already

setcp2:	test	bl,logses		; session logging?
	jz	setcp4			; z = no, try others
	mov	dx,offset lsesnam	; use default name
	jcxz	setcp3			; z = no filename given
	mov	si,offset rdbuf		; get new name
	mov	di,dx			; destination
	call	strcpy			; replace old name
setcp3:	cmp	sloghnd,-1		; transaction file already open?
	je	setcp6			; e = no, open it
	jmp	setcp16			; say file is open already

setcp4:	test	bl,logtrn		; transaction logging?
	jz	setcp14			; z = no, error
	mov	dx,offset ltranam	; use default name
	jcxz	setcp5			; z = no filename given
	mov	si,offset rdbuf		; get new name
	mov	di,dx			; destination
	call	strcpy			; replace old name
setcp5:	cmp	tloghnd,-1		; transaction file already open?
	je	setcp6			; e = no, open it
	jmp	setcp16			; say file is open already

setcp6:	mov	ax,dx			; place for filename for isfile
	call	isfile			; does file exist already?
	jc	setcp7			; c = does not exist so use create
	test	byte ptr filtst.dta+21,1fh ; file attributes, ok to write?
	jnz	setcp14			; nz = no, use error exit	
	mov	ah,open2		; open existing file
	mov	al,1+1			;  for writing and reading
	int	dos
	jc	setcp14			; if carry then error
	mov	bx,ax			; file handle for seeking
	xor	cx,cx			; high order displacement
	xor	dx,dx			; low order part of displacement
	mov	ah,lseek		; seek to EOF (to do appending)
	mov	al,2			; says to EOF
	int	dos
	jmp	short setcp8

setcp7:	test	filtst.fstat,80h	; access problem?
	jnz	setcp14			; nz = yes, stop here
	mov	ah,creat2		; function is create
	mov	cx,20H			; turn on archive bit
	int	dos			; create the file, DOS 2.0
	jc	setcp14			; if carry bit set then error
	mov	bx,ax			; file handle

setcp8:	cmp	numhlp,logpkt		; packet logging?
	jne	setcp9			; ne = no
	mov	ploghnd,bx		; save transaction log handle here
	jmp	short setcp12
setcp9:	cmp	numhlp,logses		; session logging?
	jne	setcp10			; ne = no
	mov	sloghnd,bx		; save session log handle here
	jmp	short setcp12
setcp10:mov	tloghnd,bx		; save transaction log handle here

setcp12:mov	ax,numhlp		; kind of Logging
	or	flags.capflg,al		; accumulate kinds of logging
	clc				; success
	ret

setcp14:mov	dx,offset errcap	; give error message
	jmp	reterr			; and display it

setcp16:mov	ah,prstr		; file already open
	mov	dx,offset erropn
	int	dos
	clc				; return success
	ret
setcpt	endp
 
; SET MODE LINE

MODL	PROC	NEAR
	mov	dx,offset ontab		; parse an on or off
	xor	bx,bx			; no special help
	call	keyend
	jc	modl1			; c = failure
	mov	flags.modflg,bl		; set flag appropriately
modl1:	ret
MODL	ENDP

; SET OUTPUT commands
setoutput proc	near
	mov	dx,offset outputtab	; OUTPUT command table
	xor	bx,bx			; no special help
	mov	ah,cmkey
	call	comnd
	jc	setout1			; c = failure
	jmp	short setopace
setout1:ret	
setoutput endp

; Set OUTPUT Pacing <number millisec between chars>
setopace proc	near
	mov	numhlp,offset opacehlp	; help
	mov	numerr,0		; no error message
	mov	min,0			; smallest number
	mov	max,65535		; largest magnitude (16 bits worth)
	call	num0			; parse numerical input
	jc	setopac1		; c = error
	mov	outpace,ax		; store result
	clc
setopac1:ret
setopace endp

; SET PARITY
 
SETPAR	PROC	NEAR
	mov	dx,offset partab	; parity table
	xor	bx,bx
	call	keyend
	jnc	setp1			; nc = success
	ret
setp1:	mov	si,portval
	mov	[si].parflg,bl		; store the parity flag
	call	serrst			; reset port so opening uses above
	clc
	ret
SETPAR	ENDP

; Set Print filename  for writing material to printers.
; Puts filename in global string prnname
setprn	proc	near
	mov	dx,offset rdbuf		; work area
	mov	rdbuf,0			; clear it
	mov 	bx,offset prnhlp	; help message
	mov	ah,cmword		; allow paths
	call	comnd
	jc	setprn3			; c = failure
	mov	ah,cmeol
	call	comnd
	jc	setprn3			; c = failure
	mov	dx,offset rdbuf		; assume we will use this text
	call	strlen			; filename given?
	mov	si,dx			; for strcpy
	or	cx,cx			; length of user's filename
	jg	setprn1			; g = filename is given
	mov	si,offset prndefnam	; no name, use default instead
setprn1:mov	di,offset prnname	; copy to globally available loc
	call	strcpy
	cmp	prnhand,0		; handle already in use?
	jle	setprn2			; le = no
	call	pntflsh			; flush current buffer
	mov	bx,prnhand		; close the file now
	cmp	bx,4			; don't close DOS PRN
	je	setprn2			; e = already available
	mov	ah,close2
	int	dos
setprn2:call	prnopen			; open printer now, may set carry
	jnc	setprn3			; nc = success
	mov	ah,prstr
	mov	dx,offset prnerr	; say can't open the file
	int	dos
	mov	si,offset prndefnam	; use default name as fallback
	mov	di,offset prnname	; copy to globally available loc
	call	strcpy
	mov	prnhand,4		; declare handle to be DOS PRN
setprn3:ret
setprn	endp

; SET PROMPT  Allow user to change the "Kermit-MS>" prompt
; {string} and \number notation permitted to represent special chars.
; String will be made asciiz

PROMSET	PROC	NEAR
	mov	ah,cmline
	mov	bx,offset rdbuf		; Read in the prompt
	mov	word ptr [bx],0		; clear buffer
	mov	dx,offset prmmsg
	mov	comand.cmblen,60	; 60 byte limit
	call	comnd
	jc	prom2			; c = failure
	or	ax,ax			; prompt string?
	jnz	prom0			; nz = yes
	mov	ax,offset kerm		; no, restore default prompt
	jmp	short prom1
prom0:	push	si			; parse \### constants into
	push	di			;  1 byte binary numbers inline
	mov	si,offset rdbuf		; source = new prompt string
	mov	byte ptr [si-1+length rdbuf],0 ; plant null terminator
	mov	di,offset prm		; destination
	call	cnvlin			; convert \### in string to binary
	pop	di
	pop	si
	mov	bx,cx			; get byte count
	mov	prm[bx],0		; insert null terminator
	mov	ax,offset prm
prom1:	mov	prmptr,ax		; remember it
	clc				; success
prom2:	ret
PROMSET	ENDP

; SET SERVER {LOGIN username password | TIMEOUT}

SETSRV	PROC	NEAR
	mov	dx,offset srvtab	; set server table
	xor	bx,bx			; use table for help
	mov	ah,cmkey		; get keyword
	call	comnd
	jnc	setsrv1			; c = success
	ret
setsrv1:cmp	apctrap,0		; disable from APC?
	jne	setsrvx			; ne = yes
	cmp	bl,1			; Login?
	jne	setsrv2			; ne = no
	test	flags.remflg,dserver	; acting as a server now?
	jz	setsrv3			; z = no
	stc				; fail
	ret
setsrv3:mov	dx,offset rdbuf		; where to store local username
	mov	bx,offset luserh	; help
	mov	comand.cmblen,16	; buffer length
	mov	ah,cmword		; get username
	call	comnd
	jc	setsrvx
	mov	bx,offset rdbuf+30	; where to store local password
	mov	dx,offset lpassh	; help
	mov	comand.cmblen,16	; buffer length
	mov	ah,cmline		; get password, allow spaces
	call	comnd
	jc	setsrvx
	mov	si,offset rdbuf		; only now do we transfer to the
	mov	di,offset luser		; active buffers
	call	strcpy
	mov	si,offset rdbuf+30
	mov	di,offset lpass
	call	strcpy
	clc
	ret

setsrv2:mov	min,0			; Timeout, smallest acceptable value
	mov	max,255			; largest acceptable value, one byte
	mov	numhlp,offset srvthlp	; help message
	mov	numerr,0		; complaint message
	call	num0			; parse numerical input
	jc	setsrvx			; c = error
	mov	srvtmo,al		; store timeout value
	clc				; success
setsrvx:ret
	
SETSRV	ENDP

; SET RETRY value. Changes the packet retry limit.

RETRYSET PROC	NEAR
	mov	min,1			; smallest acceptable value
	mov	max,63			; largest acceptable value
	mov	numhlp,offset retryhlp	; help message
	mov	numerr,0		; complaint message
	call	num0			; parse numerical input
	jc	retrys1			; c = error
	mov	maxtry,al
retrys1:ret
RETRYSET ENDP

; Set number of screens in terminal emulator rollback buffer at Kermit
; initialization time via Environment. Called by command parser while doing
; Environment reading in mssker.asm. Do not call after Kermit has initialized.
SETROLLB proc	near
	mov	numhlp,offset rollhlp	; help
	mov	numerr,0		; no error message
	mov	min,0			; smallest number
	mov	max,8000		; largest magnitude
	call	num0			; parse numerical input
	jc	setrol1			; c = error
	mov	npages,ax		; store result
	clc
setrol1:ret
SETROLLB endp

; Set width of rollback screens in terminal emulator rollback buffer at Kermit
; initialization time via Environment. Called by command parser while doing
; Environment reading in mssker.asm. Do not call after Kermit has initialized.
SETWIDTH proc	near
	mov	rollwidth,80		; default width of rolled screen
	mov	numhlp,0		; no help
	mov	numerr,0		; no error message
	mov	min,80			; smallest number
	mov	max,207			; largest magnitude (16 bits worth)
	call	num0			; parse numerical input
	jc	setwid1			; c = error
	mov	rollwidth,ax		; store result
	clc
setwid1:ret
SETWIDTH endp

; SET TAKE-ECHO	 on or off

TAKSET	PROC	NEAR
	mov	dx,offset ontab
	xor	bx,bx
	call	keyend
	jc	takset1			; c = failure
	mov	flags.takflg,bl
takset1:ret
TAKSET	ENDP

; SET TIMER     on or off during file transfer

TIMSET	PROC	NEAR
	mov	dx,offset ontab
	xor	bx,bx
	call	keyend
	jc	timset1			; c = failure
	mov	flags.timflg,bl
timset1:ret
TIMSET	ENDP

; SET WINDOW number of windows
WINSET	PROC	NEAR
	mov	min,1			; smallest acceptable value
	mov	max,maxwind		; largest acceptable value
	mov	numhlp,offset winhelp	; help message
	mov	numerr,0		; complaint message
	call	num0			; parse numerical input
	jc	winse5			; c = error
	mov	dtrans.windo,al		; store default window size
	mov	trans.windo,al		; and in active variable for makebuf
	clc				; success
winse5:	ret
WINSET	ENDP

; SET SEND parameters

SENDSET	PROC	NEAR
	mov	stflg,'S'		; Setting SEND parameter 
	mov	dx,offset stsrtb	; Parse a keyword
	xor	bx,bx			; no specific help
	mov	ah,cmkey
	call	comnd
	jc	sendset1		; c = failure
	jmp	bx			; do the action routine
sendset1:ret
SENDSET	ENDP

; SET RECEIVE parameters

recset:	mov	stflg,'R'		; Setting RECEIVE paramter
	mov	dx,offset stsrtb	; Parse a keyword
	xor	bx,bx			; no specific help
	mov	ah,cmkey
	call	comnd
	jc	recset1			; c = failure
	jmp	bx			; do the action routine
recset1:ret

remset	proc	near			; Set REMOTE ON/OFF
	mov	dx,offset ontab
	mov	bx,offset remhlp
	call	keyend
	jc	remset2			; c = failure
	and	flags.remflg,not (dquiet+dserial+dregular) ; no display bits
	or	bl,bl			; want off state? (same as regular)
	jz	remset1			; z = yes
	or	flags.remflg,dquiet	; else on = quiet display
	clc
	ret
remset1:or	flags.remflg,dregular	; off = regular display
	clc
remset2:ret
remset	endp


; SET Send and Receive End-of-Packet char

sreol	PROC	NEAR
	mov	min,0			; lowest acceptable value
	mov	max,1FH			; largest acceptable value
	mov	numhlp,offset eophlp	; help message
	mov	numerr,0		; error message address
	call	num0			; get numerical input
	jc	sreol3			; c = error
	cmp	stflg,'S'		; setting SEND paramter?
	je	sreol1
	mov	trans.reol,al
	jmp	short sreol2
sreol1:	mov	dtrans.seol,al
sreol2:	mov	ah,dtrans.seol
	mov	trans.seol,ah
	clc
sreol3:	ret
sreol	ENDP


; SET SEND and RECEIVE start-of-header

srsoh:	mov	min,0
	mov	max,7eh			; allow printables (control=normal)
	mov	numhlp,offset sohhlp	; reuse help message
	mov	numerr,0		; error message
	call	num0		; Common routine for parsing numerical input
	jc	srsoh2			; c = error
	cmp	stflg,'S'		; setting SEND paramter?
	je	srsoh1
	mov	trans.rsoh,al		; set Receive soh
	clc				; success
	ret
srsoh1:	mov	trans.ssoh,al		; set Send soh
	clc				; success
	ret
srsoh2:	ret

; SET Send Double-char

srdbl	PROC	NEAR
	mov	min,0			; lowest acceptable value
	mov	max,0ffh		; largest acceptable value
	mov	numhlp,offset dblhlp	; help
	mov	numerr,0		; error message address
	call	num0			; get numerical input
	jc	sreol3			; c = error
	cmp	stflg,'R'		; setting Receive paramter?
	je	srdbl1			; e = yes, no action
	mov	trans.sdbl,al		; store character to be doubled
	mov	dtrans.sdbl,al
	clc
srdbl1:	ret
srdbl	ENDP

; SET Receive Ignore-char

srign	PROC	NEAR
	mov	min,0			; lowest acceptable value
	mov	max,0ffh		; largest acceptable value
	mov	numhlp,offset dblhlp	; reuse help
	mov	numerr,0		; error message address
	call	num0			; get numerical input
	jc	srign1			; c = error
	cmp	stflg,'S'		; setting SEND paramter?
	je	srign1			; e = yes, no action
	mov	trans.rign,al		; store character to be ignored
	mov	dtrans.rign,al
	clc
srign1:	ret
srign	ENDP

; SET SEND and	RECEIVE TIMEOUT

srtim:	mov	min,0
	mov	max,94
	mov	numhlp,offset timhlp	; Reuse help message
	mov	numerr,0		; error message
	call	num0		; Common routine for parsing numerical input
	jc	srtim3			; c = error
	cmp	stflg,'S'		; Setting SEND paramter?
	je	srtim1
	mov	trans.rtime,al
	jmp	short srtim2
srtim1:	mov	dtrans.stime,al
srtim2:	mov	ah,dtrans.stime
	mov	trans.stime,ah
	clc
srtim3:	ret

; SET SEND and RECEIVE PACKET LENGTH
; dtrans items are real, trans items are just for SHOW information

srpack:	mov	min,20
	mov	max,9024
	mov	numhlp,offset pakhlp	; help
	mov	numerr,offset pakerr	; error message
	call	num0
	jnc	srpaks0			; nc = success
	ret				; failure
srpaks0:cmp	stflg,'S'		; setting send value?
	jne	srpakr			; ne = receive
	mov	dtrans.slong,ax		; set send max value
	mov	trans.slong,ax		; store current active length
	mov	dtrans.spsiz,dspsiz	; set regular 94 byte default
	mov	trans.spsiz,dspsiz	; ditto
	cmp	ax,dspsiz		; longer than regular packet?
	jae	srpaks1			; ae = yes
	mov	dtrans.spsiz,al		; shrink regular packet size too
	mov	trans.spsiz,al		; shrink regular packet size too
srpaks1:clc				; success
	ret

srpakr:	mov	dtrans.rlong,ax		; set receive max value
	mov	trans.rlong,ax		; store active length
	mov	dtrans.rpsiz,drpsiz	; set regular to default 94 bytes
	mov	trans.rpsiz,drpsiz
	mov	trans.rpsiz,drpsiz
	cmp	ax,drpsiz		; longer than a regular packet?
	jae	srpakr1			; ae = yes
	mov	dtrans.rpsiz,al		; shrink regular packet size too
	mov	trans.rpsiz,al
srpakr1:clc				; success
	ret


; SET SEND and RECEIVE number of padding characters

srnpd:	mov	min,0
	mov	max,94
	mov	numhlp,offset timhlp	; reuse help message
	mov	numerr,0		; error message
	call	num0			; Parse numerical input
	jc	srnpd3			; c = error
	cmp	stflg,'S'		; Setting SEND paramter?
	je	srnpd1			; e = yes
	mov	trans.rpad,al		; set Receive padding
	jmp	short srnpd2
srnpd1:	mov	dtrans.spad,al		; set default Send padding
srnpd2:	mov	al,dtrans.spad
	mov	trans.spad,al    	; update active array for I and S pkts
	clc
srnpd3:	ret

; SET SEND and RECEIVE padding character

srpad:	mov	min,0
	mov	max,127
	mov	numhlp,offset padhlp
	mov	numerr,offset padhlp
	call	num0			; parse numerical input
	jc	srpad4			; c = error
	cmp	ah,127			; this is allowed
	je	srpad1
	cmp	ah,32
	jb	srpad1			; between 0 and 31 is OK too
	mov	ah,prstr
	mov	dx,offset padhlp
	int	dos
srpad1:	cmp	stflg,'S'		; Send?
	je	srpad2			; e = yes, else Receive
	mov	trans.rpadch,al		; store receive pad char
	jmp	short srpad3
srpad2:	mov	dtrans.spadch,al	; store Send pad char
srpad3:	mov	ah,dtrans.spadch
	mov	trans.spadch,ah  	; update active array for I and S pkts
	clc				; success
srpad4:	ret

; SET SEND and	RECEIVE control character prefix

srquo:	mov	min,33
	mov	max,126
	mov	numhlp,offset quohlp	; help message
	mov	numerr,0		; error message
	call	num0			; Parse numerical input
	jc	srquo3			; c = error
	cmp	stflg,'S'		; Setting outgoing quote char?
	je	srquo1			; e = yes
	mov	trans.rquote,al		; set Receive quote char
	jmp	short srquo2
srquo1:	mov	dtrans.squote,al	; set Send quote char
srquo2:	clc
srquo3:	ret

; SET SEND Pause number	of milliseconds

srpaus:	mov	min,0
	mov	max,65383
	mov	numhlp,offset pauhlp	; help
	mov	numerr,0
	call	num0			; Parse numerical input
	pushf				; save carry for error state
	cmp	stflg,'S'		; Setting SEND paramter?
	je	srpau0
	popf
	mov	dx,offset ermes5	; "Not implemented" msg
	jmp	reterr			; print error message
srpau0:	popf
	jc	srpau1			; c = error
	mov	spause,ax		; store value
srpau1:	ret

; SET TCP/IP address nnn.nnn.nnn.nnn
; SET TCP/IP subnetmask nnn.nnn.nnn.nnn
; SET TCP/IP gateway nnn.nnn.nnn.nnn
; SET TCP/IP primary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP secondary-nameserver nnn.nnn.nnn.nnn
; SET TCP/IP domain string

tcpipset proc	near
	mov	ah,cmkey		; get keyword
	mov	dx,offset tcptable	; table
	xor	bx,bx			; help
	call	comnd
	jnc	tcpse1
	ret
tcpse1:	mov	word ptr rdbuf,bx	; keyword index
	mov	comand.cmblen,17	; length of user's buffer
	cmp	bx,1			; local address?
	jne	tcpse1a			; ne = no
	mov	bx,offset addrhelp	; address help
	jmp	short tcpse4
tcpse1a:cmp	bx,2			; domain name?
	jne	tcpse2			; ne = no
	mov	bx,offset domainhlp	; domain help
	mov	comand.cmblen,32	; length of user's buffer
	jmp	short tcpse4
tcpse2:	cmp	bx,6			; subnet mask?
	jne	tcpse3			; ne = no
	mov	bx,offset subnethlp
	jmp	short tcpse4
tcpse3:	cmp	bx,7			; Host?
	jne	tcpse3a			; ne = no
	mov	bx,offset hosthlp
	mov	comand.cmblen,60	; length of user's buffer
	jmp	short tcpse4
tcpse3a:cmp	bx,9			; PD interrupt?
	jne	tcpse3b			; ne = no
	mov	bx,offset tcppdinthlp
	jmp	short tcpse4
tcpse3b:cmp	bx,10			; term type?
	jne	tcpse3c			; ne = no
	mov	bx,offset tcpttyhlp
	mov	comand.cmblen,32	; length of user's buffer
	jmp	short tcpse4
tcpse3c:cmp	bx,11			; newline mode?
	jne	tcpse3d			; ne = no
	jmp	tcpse13
tcpse3d:cmp	bx,12			; debug mode?
	jne	tcpse3e			; ne = no
	jmp	tcpse14

tcpse3e:mov	bx,offset iphelp	; Internet number help
tcpse4:	mov	ah,cmword		; get a string
	mov	dx,offset rdbuf+2	; work buffer
	call	comnd
	jnc	tcpse5
	ret
tcpse5:	push	ax			; save string length in ax
	mov	ah,cmeol
	call	comnd
	pop	ax
	jnc	tcpse6
	ret
tcpse6:	mov	si,offset rdbuf+2	; user's string
	mov	bx,word ptr rdbuf	; comand kind
	cmp	bx,2			; domain?
	jne	tcpse8			; ne = no
	mov	di,offset tcpdomain
	cmp	ax,32			; exceeded 32 chars?
	jbe	tcpse7			; be = no
	mov	ah,prstr
	mov	dx,offset domainbad	; compain
	int	dos
	stc
	ret
tcpse7:	cmp	ax,32			; address oversized?
	jbe	tcpse9			; be = no
	mov	ah,prstr
	mov	dx,offset addressbad	; say bad address
	int	dos
	stc
	ret
tcpse8:	mov	di,offset tcpaddress
	cmp	bx,1			; local address?
	je	tcpse9			; e = yes
	mov	di,offset tcpsubnet
	cmp	bx,3			; subnet?
	je	tcpse9			; e = yes
	mov	di,offset tcpgateway
	cmp	bx,4			; gateway?
	je	tcpse9
	mov	di,offset tcpprimens
	cmp	bx,5			; primary-nameserver?
	je	tcpse9
	mov	di,offset tcpsecondns	; secondary-nameserer
	cmp	bx,6
	je	tcpse9
	mov	di,offset tcphost	; host name or number
	cmp	bx,7
	je	tcpse9
	mov	di,offset tcpbcast	; broadcast
tcpse9:	cmp	bx,9			; port or other?
	jae	tcpse10			; ae = yes
	call	strcpy
	clc
	ret
tcpse10:cmp	bx,9			; PD interrupt?
	jne	tcpse12			; ne = no
	mov	si,offset rdbuf+2
	cmp	byte ptr [si],'\'	; backslash present?
	je	tcpse11			; e = yes
	dec	si
	mov	byte ptr [si],'\'
tcpse11:mov	ax,word ptr [si+1]
	and	ax,not 2020h		; to upper case
	cmp	ax,'DO'			; ODI?
	je	tcpse11a		; e = yes, use "DO"
	push	bx
	call	katoi			; number to ax
	pop	bx
tcpse11a:mov	tcppdint,ax
	clc
	ret
tcpse12:cmp	bx,10			; term-type string?
	jne	tcpse13			; ne = no
	mov	si,offset rdbuf+2
	mov	di,offset tcpttbuf	; copy string to holding place
	call	strcpy
	clc
	ret
tcpse13:cmp	bx,11			; newline mode?
	jne	tcpse14			; ne = no
	mov	dx,offset ontab		; on/off table
	mov	bx,offset tcpnlhlp	; help
	call	keyend
	jc	tcpse14			; fail
	mov	tcpnewline,bl		; set mode
	clc
	ret
tcpse14:cmp	bx,12			; debug mode?
	jne	tcpse15			; ne = no
	mov	dx,offset ontab		; on/off table
	xor	bx,bx			; help
	call	keyend
	jc	tcpse15			; fail
	mov	tcpdebug,bl		; set mode
	clc
	ret
tcpse15:stc				; fail
	ret
tcpipset endp

; SET TRANSFER  CHARACTER-SET {Latin1, Shift-JIS, Transparent}
; SET TRANSFER  TRANSLATION {Readable, Invertible}
sxfer	proc	near
	mov	dx,offset xfertab	; table of TRANSFER keywords
	xor	bx,bx
	mov	ah,cmkey		; get next keyword
	call	comnd
	jc	sxfer1			; c = error
	or	bl,bl			; Character-set?
	jnz	sxfer2			; nz = no
	mov	dx,offset xfchtab	; Character-set table
	mov	bx,offset xfchhlp	; help text
	call	keyend
	jc	sxfer1			; c = error
	mov	dtrans.xchset,bl	; store transfer char set ident
	mov	trans.xchset,bl		; store transfer char set ident
	cmp	bl,xfr_cyrillic		; Cyrillic?
	jne	sxfer9			; ne = no
	mov	ax,flags.chrset		; get current file character set
	mov	flags.chrset,866	; force CP866
	cmp	ax,866			; was CP866/LATIN5 File Character set?
	je	sxfer8			; e = yes
	mov	dx,offset xfchbad	; show warning message
	mov	ah,prstr
	int	dos
sxfer8:	clc
sxfer1:	ret
sxfer9:	cmp	bl,xfr_japanese		; Japanese-EUC?
	jne	sxfer10			; ne = no
	mov	ax,flags.chrset		; get current file character set
	mov	flags.chrset,932	; force Shift-JIS
	cmp	ax,932			; was Shift-JIS File Character set?
	je	sxfer8			; e = yes
	mov	dx,offset xfchbad2	; show warning message
	mov	ah,prstr
	int	dos
	clc
	ret
sxfer10:cmp	bl,xfr_hebiso		; Hebrew-ISO?
	jne	sxfer8			; ne = no
	mov	ax,flags.chrset		; get current file character set
	mov	flags.chrset,862	; force CP 862
	cmp	ax,862			; was CP862 the File Character set?
	je	sxfer8			; e = yes
	mov	dx,offset xfchbad3	; show warning message
	mov	ah,prstr
	int	dos
	clc
	ret

sxfer2:	cmp	bx,1			; LOCKING-SHIFT?
	jne	sxfer3			; ne = no
	mov	dx,offset xfertab1	; off, on, forced table
	mov	bx,offset xferhlp1
	call	keyend
	jc	sxfer1
	mov	dtrans.lshift,bl	; save state
	mov	trans.lshift,bl
	clc
	ret
sxfer3:	mov	dx,offset xfertab2	; TRANSLATION table
	mov	bx,offset xfchhlp2	; help text
	call	keyend
	jc	sxfer1			; c = error
	mov	dtrans.xchri,bl		; store readable/invertible flag
	mov	trans.xchri,bl
	clc
	ret
sxfer	endp

; SET TRANSLATION 		  Connect mode translate characters
; SET TRANSLATION INPUT {Original-byte New-byte | ON | OFF}
; SET TRANSLATION KEYBOARD {ON | OFF}, default is ON

SETRX	PROC	NEAR			; translate incoming serial port char
	mov	ah,cmkey
	mov	dx,offset trnstab	; direction table (just one entry)
	xor	bx,bx			; no help
	call	comnd
	jnc	setrx0			; nc = success
	ret				; failure
setrx0:	cmp	bx,2			; Keyboard?
	jne	setrx0b			; ne = no
	jmp	setr11			; do keyboard
setrx0b:mov	dx,offset rdbuf		; our work space
	mov	word ptr rdbuf,0	; insert terminator
	mov	bx,offset srxhlp1	; first help message
	mov	ah,cmword		; parse a word
	call	comnd			; get incoming byte pattern
	jnc	setrx0a			; nc = success
	ret
setrx0a:or	ax,ax			; any text given?
	jz	setr6			; nz = no
	mov	temp,ax			; save byte count here
	mov	ax,word ptr rdbuf	; get first two characters
	or	ax,2020h		; convert upper to lower case
	cmp	ax,'fo'			; first part of word OFF?
	je	setr6			; e = yes, go analyze
	cmp	ax,'no'			; word ON?
	je	setr6			; e = yes, go do it
	mov	si,offset rdbuf		; convert text to number
	call	katoi			; number converter procedure, to ax
	jnc	setr1			; nc = success	
	cmp	temp,1			; just one character given?
	jne	setr6			; ne = no, so bad code
setr1:	mov	min,ax			; save byte code here
	mov	dx,offset rdbuf		; our work space
	mov	word ptr rdbuf,0	; insert terminator
	mov	bx,offset srxhlp1	; first help message
	mov	ah,cmword		; parse a word
	call	comnd			; get incoming byte pattern
	jnc	setr2			; nc = success
	ret				; failure
setr2:	or	ax,ax			; any text given?
	jz	setr6			; z = no
	mov	temp,ax			; save byte count here
	mov	si,offset rdbuf		; convert text to number
	call	katoi			; number converter procedure
	jnc	setr3			; nc = success
	cmp	temp,1			; just one character given?
	jne	setr6			; ne = no, so bad code or ON/OFF
setr3:	mov	max,ax			; save byte code here
	mov	ah,cmeol		; get a confirm
	call	comnd
	jnc	setr3a			; nc = success
	ret				; failure
setr3a:	mov	bx,min			; bl = incoming byte code
	xor	bh,bh
	mov	ax,max			; al = local (translated) byte code
	mov	rxtable [bx],al		; store in rx translate table
	clc				; success
	ret

setr6:	mov	ah,cmeol		; get a confirm
	call	comnd
	jnc	setr6a			; nc = success
	ret				; failure
setr6a:	mov	dx,offset badrx		; assume bad construction
	or	word ptr rdbuf,2020h	; convert to lower case
	or	rdbuf+2,20h		; first three chars
	cmp	word ptr rdbuf,'fo'	; key word OFF?
	jne	setr8			; ne = no
	cmp	rdbuf+2,'f'		; last letter of OFF?
	jne	setr8			; ne = no
	mov	rxtable+256,0		; OFF is status byte = zero
	mov	dx,offset rxoffmsg	; say translation is turned off
	jmp	short setr9
setr8:	cmp	word ptr rdbuf,'no'	; keyword ON?
	jne	setr9a			; ne = no, error
	mov	rxtable+256,1		; ON is status byte non-zero
	mov	dx,offset rxonmsg	; say translation is turned on
setr9:	cmp	taklev,0		; executing from a Take file?
	je	setr9a			; e = no
	cmp	flags.takflg,0		; echo contents of Take file?
	je	setr10			; e = no
setr9a:	mov	ah,prstr		; bad number message
	int	dos
setr10:	clc
	ret
setr11:	mov	ah,cmkey		; SET TRANSLATION KEYBOARD
	mov	dx,offset ontab		; on/off
	xor	bx,bx
	call	comnd
	jnc	setr12			; nc = success
	ret
setr12:	mov	ah,cmeol		; get a confirm
	call	comnd
	jnc	setr13			; nc = success
	ret				; failure
setr13:	mov	flags.xltkbd,bl		; set keyboard translation on/off
	clc
	ret
SETRX	ENDP

; SET TRANSMIT {FILL, LF, Prompt} {ON, OFF, or value}
SETXMIT	proc	near
	mov	dx,offset xmitab	; TRANSMIT keyword table
	xor	bx,bx
	mov	ah,cmkey		; get keyword
	call	comnd
	jnc	setxmi1			; nc = success
	ret
setxmi1:cmp	bl,2			; SET TRANSMIT PROMPT?
	jne	setxmi2			; ne = no
	mov	ah,cmword
	mov	dx,offset rdbuf+1	; put answer here
	mov	bx,offset xpmthlp
	call	comnd
	jc	setxmi1d		; c = error
	push	ax			; save length
	mov	ah,cmeol		; get a confirm
	call	comnd
	pop	cx			; recover length to cx
	jc	setxmi1d		; c = failure
	mov	al,rdbuf+1
	cmp	cx,1			; a single char?
	je	setxmi1c		; e = yes, use it as the prompt char
	mov	si,offset rdbuf+1
	cmp	byte ptr [si],'\'	; already quoted?
	je	setxmi1b		; e = yes
	mov	rdbuf,'\'		; add a numerical quote
	dec	si			; point to our escape char
setxmi1b:call	katoi			; convert number in rdbuf
	jc	setxmi1d		; c = no number, error
setxmi1c:mov	script.xmitpmt,al	; store new prompt value
setxmi1d:ret

setxmi2:cmp	bl,1			; LF?
	jne	setxmi3			; ne = no
	mov	dx,offset ontab		; on or off table
	xor	bx,bx
	call	keyend
	jc	setxmi2a		; c = failure
	mov	script.xmitlf,bl	; set the xmitlf flag
setxmi2a:ret

setxmi3:cmp	bl,0			; FILL?
	jne	setxmi8			; ne = no
	mov	ah,cmword		; FILL, get a word sized token
	mov	dx,offset rdbuf+1	; put it here
	mov	bx,offset xfilhlp	; help
	call	comnd
	jc	setxmix			; c = failure
	push	ax			; save length in ah
	mov	ah,cmeol		; get a confirm
	call	comnd
	pop	ax
	jc	setxmix			; c = failure
	cmp	ax,1			; just one character?
	ja	setxmi4			; a = no, there's more
	mov	al,rdbuf+1		; get the char
	mov	script.xmitfill,al	; store Fill char
	ret
setxmi4:mov	ax,word ptr rdbuf+1
	or	ax,2020h		; to lower
	cmp	ax,'on'			; "none"?
	jne	setxmi5			; ne = no
	mov	script.xmitfill,0	; no Filling
	ret
setxmi5:cmp	ax,'ps'			; "space"?
	jne	setxmi6			; ne = no
	mov	script.xmitfill,' '	; use space as filler
	ret
setxmi6:mov	si,offset rdbuf+1
	cmp	byte ptr [si],'\'	; already quoted?
	je	setxmi7			; e = yes
	mov	rdbuf,'\'		; add a numerical quote
	dec	si			; point to our escape char
setxmi7:call	katoi			; convert number in rdbuf
	jc	setxmix			; c = no number, error
	mov	script.xmitfill,al	; set the xmitfill flag
	ret
setxmi8:mov	ah,cmword		; PAUSE milliseconds
	mov	dx,offset rdbuf+1	; put answer here
	mov	bx,offset xpauhlp
	call	comnd
	jc	setxmix			; c = error
	push	ax			; save length
	mov	ah,cmeol		; get a confirm
	call	comnd
	pop	cx			; recover length to cx
	jc	setxmix			; c = failure
	mov	si,offset rdbuf+1
	cmp	byte ptr [si],'\'	; already quoted?
	je	setxmi9			; e = yes
	mov	rdbuf,'\'		; add a numerical quote
	dec	si			; point to our escape char
setxmi9:call	katoi			; convert number in rdbuf
	jc	setxmix			; c = no number, error
	mov	script.xmitpause,ax	; set the xmitpause flag
setxmix:ret
SETXMIT	endp

; SET UNKNOWN-CHARACTER-SET {DISCARD, KEEP}, default is KEEP
unkchset proc	near
	mov	dx,offset unkctab	; keep/reject keyword table
	mov	bx,offset unkchhlp
	call	keyend
	jc	unkchx			; c = failure
	mov	flags.unkchs,bl		; 0 = keep, else reject
unkchx:	ret
unkchset endp

; Common routine for parsing numerical input
; Enter with numhlp = offset of help message, numerr = offset of optional
;  error message, min, max = allowable range of values.
; Returns value in ax, or does parse error return.
; Changes ax,bx,dx,si.			[jrd] 18 Oct 1987
num0:	mov	dx,offset rdbuf+1	; were to put text
	mov	word ptr rdbuf,0	; clear the buffer
	mov	bx,numhlp		; help text
	mov	ah,cmword		; get a word
	call	comnd
	jc	num0x			; c = failure
	mov	ah,cmeol
	call	comnd			; Get a confirm
	jc	num0x			; c = failure
					; second entry point
numwd:	mov	si,offset rdbuf+1
	cmp	rdbuf+1,'\'		; already quoted?
	je	num0a			; e = yes
	mov	rdbuf,'\'		; add a numerical quote
	dec	si			; point to our escape char
num0a:	call	katoi			; convert number in rdbuf
	jc	num0er			; c = no number, error
	cmp	ax,max			; largest permitted value
	ja	num0er			; a = error
	cmp	ax,min			; smallest permitted value
	jb	num0er			; b = error
	clc
num0x:	ret				; return value in ax

num0er:	mov	ah,prstr
	mov	dx,numerr		; comand-specific error message, if any
	or	dx,dx			; was any given?
	jz	num0e1			; z = no, use generic msg
	int	dos			; show given error message
	jmp	short num0e2
num0e1:	mov	dx,offset nummsg1	; get address of numeric error message
	int	dos
	mov	ax,min			; smallest permitted number
	call	decout			; display decimal number in ax
	mov	ah,prstr
	mov	dx,offset nummsg2	; "and"
	int	dos
	mov	ax,max			; largest permitted number
	call	decout
	mov	ah,prstr
	mov	dx,offset crlf
	int	dos
num0e2:	stc
	ret

; routine to print an error message, then exit without error status
; expects message in dx
reterr	proc	near
	mov	ah,prstr
	int	dos
	clc
	ret
reterr	endp

code	ends
	end
