xref: /onnv-gate/usr/src/ucbcmd/tset/tset.c (revision 9354:9559ac454e7e)
1669Schin /*
2*9354STim.Marsland@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
3669Schin  * Use is subject to license terms.
4669Schin  */
5669Schin 
60Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
70Sstevel@tonic-gate /*	  All Rights Reserved  	*/
80Sstevel@tonic-gate 
90Sstevel@tonic-gate 
100Sstevel@tonic-gate /*
110Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
120Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
130Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
140Sstevel@tonic-gate  */
150Sstevel@tonic-gate 
160Sstevel@tonic-gate /*
17*9354STim.Marsland@Sun.COM  *  TSET -- set terminal modes
18*9354STim.Marsland@Sun.COM  *
19*9354STim.Marsland@Sun.COM  *	This program does sophisticated terminal initialization.
20*9354STim.Marsland@Sun.COM  *	I recommend that you include it in your .profile or .login
21*9354STim.Marsland@Sun.COM  *	file to initialize whatever terminal you are on.
22*9354STim.Marsland@Sun.COM  *
23*9354STim.Marsland@Sun.COM  *	There are several features:
24*9354STim.Marsland@Sun.COM  *
25*9354STim.Marsland@Sun.COM  *	A special file or sequence (as controlled by the termcap file)
26*9354STim.Marsland@Sun.COM  *	is sent to the terminal.
27*9354STim.Marsland@Sun.COM  *
28*9354STim.Marsland@Sun.COM  *	Mode bits are set on a per-terminal_type basis (much better
29*9354STim.Marsland@Sun.COM  *	than UNIX itself).  This allows special delays, automatic
30*9354STim.Marsland@Sun.COM  *	tabs, etc.
31*9354STim.Marsland@Sun.COM  *
32*9354STim.Marsland@Sun.COM  *	Erase and Kill characters can be set to whatever you want.
33*9354STim.Marsland@Sun.COM  *	Default is to change erase to control-H on a terminal which
34*9354STim.Marsland@Sun.COM  *	can overstrike, and leave it alone on anything else.  Kill
35*9354STim.Marsland@Sun.COM  *	is always left alone unless specifically requested.  These
36*9354STim.Marsland@Sun.COM  *	characters can be represented as "^X" meaning control-X;
37*9354STim.Marsland@Sun.COM  *	X is any character.
38*9354STim.Marsland@Sun.COM  *
39*9354STim.Marsland@Sun.COM  *	Terminals which are dialups or plugboard types can be aliased
40*9354STim.Marsland@Sun.COM  *	to whatever type you may have in your home or office.  Thus,
41*9354STim.Marsland@Sun.COM  *	if you know that when you dial up you will always be on a
42*9354STim.Marsland@Sun.COM  *	TI 733, you can specify that fact to tset.  You can represent
43*9354STim.Marsland@Sun.COM  *	a type as "?type".  This will ask you what type you want it
44*9354STim.Marsland@Sun.COM  *	to be -- if you reply with just a newline, it will default
45*9354STim.Marsland@Sun.COM  *	to the type given.
46*9354STim.Marsland@Sun.COM  *
47*9354STim.Marsland@Sun.COM  *	The current terminal type can be queried.
48*9354STim.Marsland@Sun.COM  *
49*9354STim.Marsland@Sun.COM  *	Usage:
50*9354STim.Marsland@Sun.COM  *		tset [-] [-EC] [-eC] [-kC] [-iC] [-s] [-h] [-u] [-r]
51*9354STim.Marsland@Sun.COM  *			[-m [ident] [test baudrate] :type]
52*9354STim.Marsland@Sun.COM  *			[-Q] [-I] [-S] [type]
53*9354STim.Marsland@Sun.COM  *
54*9354STim.Marsland@Sun.COM  *		In systems with environments, use:
55*9354STim.Marsland@Sun.COM  *			eval `tset -s ...`
56*9354STim.Marsland@Sun.COM  *		Actually, this doesn't work in old csh's.
57*9354STim.Marsland@Sun.COM  *		Instead, use:
58*9354STim.Marsland@Sun.COM  *			tset -s ... > tset.tmp
59*9354STim.Marsland@Sun.COM  *			source tset.tmp
60*9354STim.Marsland@Sun.COM  *			rm tset.tmp
61*9354STim.Marsland@Sun.COM  *		or:
62*9354STim.Marsland@Sun.COM  *			set noglob
63*9354STim.Marsland@Sun.COM  *			set term=(`tset -S ....`)
64*9354STim.Marsland@Sun.COM  *			setenv TERM $term[1]
65*9354STim.Marsland@Sun.COM  *			setenv TERMCAP "$term[2]"
66*9354STim.Marsland@Sun.COM  *			unset term
67*9354STim.Marsland@Sun.COM  *			unset noglob
68*9354STim.Marsland@Sun.COM  *
69*9354STim.Marsland@Sun.COM  *	Positional Parameters:
70*9354STim.Marsland@Sun.COM  *		type -- the terminal type to force.  If this is
71*9354STim.Marsland@Sun.COM  *			specified, initialization is for this
72*9354STim.Marsland@Sun.COM  *			terminal type.
73*9354STim.Marsland@Sun.COM  *
74*9354STim.Marsland@Sun.COM  *	Flags:
75*9354STim.Marsland@Sun.COM  *		- -- report terminal type.  Whatever type is
76*9354STim.Marsland@Sun.COM  *			decided on is reported.  If no other flags
77*9354STim.Marsland@Sun.COM  *			are stated, the only affect is to write
78*9354STim.Marsland@Sun.COM  *			the terminal type on the standard output.
79*9354STim.Marsland@Sun.COM  *		-r -- report to user in addition to other flags.
80*9354STim.Marsland@Sun.COM  *		-EC -- set the erase character to C on all terminals
81*9354STim.Marsland@Sun.COM  *			except those which cannot backspace (e.g.,
82*9354STim.Marsland@Sun.COM  *			a TTY 33).  C defaults to control-H.
83*9354STim.Marsland@Sun.COM  *		-eC -- set the erase character to C on all terminals.
84*9354STim.Marsland@Sun.COM  *			C defaults to control-H.  If not specified,
85*9354STim.Marsland@Sun.COM  *			the erase character is untouched; however, if
86*9354STim.Marsland@Sun.COM  *			not specified and the erase character is NULL
87*9354STim.Marsland@Sun.COM  *			(zero byte), the erase character is set to CERASE.
88*9354STim.Marsland@Sun.COM  *		-kC -- set the kill character to C on all terminals.
89*9354STim.Marsland@Sun.COM  *			Default for C is control-U.  If not specified,
90*9354STim.Marsland@Sun.COM  *			the kill character is untouched; however, if
91*9354STim.Marsland@Sun.COM  *			not specified and the kill character is NULL
92*9354STim.Marsland@Sun.COM  *			(zero byte), the kill character is set to CKILL.
93*9354STim.Marsland@Sun.COM  *		-iC -- set the interrupt character to C on all terminals.
94*9354STim.Marsland@Sun.COM  *			Default for C is control-C.  If not specified, the
95*9354STim.Marsland@Sun.COM  *			interrupt character is untouched; however, if
96*9354STim.Marsland@Sun.COM  *			not specified and the interrupt character is NULL
97*9354STim.Marsland@Sun.COM  *			(zero byte), the interrupt character is set to
98*9354STim.Marsland@Sun.COM  *			control-C.
99*9354STim.Marsland@Sun.COM  *		-qC -- reserved for setable quit character.
100*9354STim.Marsland@Sun.COM  *		-m -- map the system identified type to some user
101*9354STim.Marsland@Sun.COM  *			specified type. The mapping can be baud rate
102*9354STim.Marsland@Sun.COM  *			dependent. This replaces the old -d, -p flags.
103*9354STim.Marsland@Sun.COM  *			(-d type  ->  -m dialup:type)
104*9354STim.Marsland@Sun.COM  *			(-p type  ->  -m plug:type)
105*9354STim.Marsland@Sun.COM  *			Syntax:	-m identifier [test baudrate] :type
106*9354STim.Marsland@Sun.COM  *			where: ``identifier'' is terminal type found in
107*9354STim.Marsland@Sun.COM  *			/etc/ttys for this port, (abscence of an identifier
108*9354STim.Marsland@Sun.COM  *			matches any identifier); ``test'' may be any combination
109*9354STim.Marsland@Sun.COM  *			of  >  =  <  !  @; ``baudrate'' is as with stty(1);
110*9354STim.Marsland@Sun.COM  *			``type'' is the actual terminal type to use if the
111*9354STim.Marsland@Sun.COM  *			mapping condition is met. Multiple maps are scanned
112*9354STim.Marsland@Sun.COM  *			in order and the first match prevails.
113*9354STim.Marsland@Sun.COM  *		-n -- If the new tty driver from UCB is available, this flag
114*9354STim.Marsland@Sun.COM  *			will activate the new options for erase and kill
115*9354STim.Marsland@Sun.COM  *			processing. This will be different for printers
116*9354STim.Marsland@Sun.COM  *			and crt's. For crts, if the baud rate is < 1200 then
117*9354STim.Marsland@Sun.COM  *			erase and kill don't remove characters from the screen.
118*9354STim.Marsland@Sun.COM  *		-h -- don't read htmp file.  Normally the terminal type
119*9354STim.Marsland@Sun.COM  *			is determined by reading the htmp file or the
120*9354STim.Marsland@Sun.COM  *			environment (unless some mapping is specified).
121*9354STim.Marsland@Sun.COM  *			This forces a read of the ttytype file -- useful
122*9354STim.Marsland@Sun.COM  *			when htmp is somehow wrong. (V6 only)
123*9354STim.Marsland@Sun.COM  *		-u -- don't update htmp.  It seemed like this should
124*9354STim.Marsland@Sun.COM  *			be put in.  Note that htmp is never actually
125*9354STim.Marsland@Sun.COM  *			written if there are no changes, so don't bother
126*9354STim.Marsland@Sun.COM  *			bother using this for efficiency reasons alone.
127*9354STim.Marsland@Sun.COM  *		-s -- output setenv commands for TERM.  This can be
128*9354STim.Marsland@Sun.COM  *			used with
129*9354STim.Marsland@Sun.COM  *				`tset -s ...`
130*9354STim.Marsland@Sun.COM  *			and is to be prefered to:
131*9354STim.Marsland@Sun.COM  *				setenv TERM `tset - ...`
132*9354STim.Marsland@Sun.COM  *			because -s sets the TERMCAP variable also.
133*9354STim.Marsland@Sun.COM  *		-S -- Similar to -s but outputs 2 strings suitable for
134*9354STim.Marsland@Sun.COM  *			use in csh .login files as follows:
135*9354STim.Marsland@Sun.COM  *				set noglob
136*9354STim.Marsland@Sun.COM  *				set term=(`tset -S .....`)
137*9354STim.Marsland@Sun.COM  *				setenv TERM $term[1]
138*9354STim.Marsland@Sun.COM  *				setenv TERMCAP "$term[2]"
139*9354STim.Marsland@Sun.COM  *				unset term
140*9354STim.Marsland@Sun.COM  *				unset noglob
141*9354STim.Marsland@Sun.COM  *		-Q -- be quiet.  don't output 'Erase set to' etc.
142*9354STim.Marsland@Sun.COM  *		-I -- don't do terminal initialization (is & if
143*9354STim.Marsland@Sun.COM  *			strings).
144*9354STim.Marsland@Sun.COM  *		-v -- On virtual terminal systems, don't set up a
145*9354STim.Marsland@Sun.COM  *			virtual terminal.  Otherwise tset will tell
146*9354STim.Marsland@Sun.COM  *			the operating system what kind of terminal you
147*9354STim.Marsland@Sun.COM  *			are on (if it is a known terminal) and fix up
148*9354STim.Marsland@Sun.COM  *			the output of -s to use virtual terminal sequences.
149*9354STim.Marsland@Sun.COM  *
150*9354STim.Marsland@Sun.COM  *	Files:
151*9354STim.Marsland@Sun.COM  *		/etc/ttys
152*9354STim.Marsland@Sun.COM  *			contains a terminal id -> terminal type
153*9354STim.Marsland@Sun.COM  *			mapping; used when any user mapping is specified,
154*9354STim.Marsland@Sun.COM  *			or the environment doesn't have TERM set.
155*9354STim.Marsland@Sun.COM  *		/etc/termcap
156*9354STim.Marsland@Sun.COM  *			a terminal_type -> terminal_capabilities
157*9354STim.Marsland@Sun.COM  *			mapping.
158*9354STim.Marsland@Sun.COM  *
159*9354STim.Marsland@Sun.COM  *	Return Codes:
160*9354STim.Marsland@Sun.COM  *		-1 -- couldn't open termcap.
161*9354STim.Marsland@Sun.COM  *		1 -- bad terminal type, or standard output not tty.
162*9354STim.Marsland@Sun.COM  *		0 -- ok.
163*9354STim.Marsland@Sun.COM  *
164*9354STim.Marsland@Sun.COM  *	Defined Constants:
165*9354STim.Marsland@Sun.COM  *		DIALUP -- the type code for a dialup port.
166*9354STim.Marsland@Sun.COM  *		PLUGBOARD -- the type code for a plugboard port.
167*9354STim.Marsland@Sun.COM  *		ARPANET -- the type code for an arpanet port.
168*9354STim.Marsland@Sun.COM  *		BACKSPACE -- control-H, the default for -e.
169*9354STim.Marsland@Sun.COM  *		CNTL('U') -- control-U, the default for -k.
170*9354STim.Marsland@Sun.COM  *		OLDERASE -- the ancient default erase character.
171*9354STim.Marsland@Sun.COM  *		FILEDES -- the file descriptor to do the operation
172*9354STim.Marsland@Sun.COM  *			on, nominally 1 or 2.
173*9354STim.Marsland@Sun.COM  *		STDOUT -- the standard output file descriptor.
174*9354STim.Marsland@Sun.COM  *		UIDMASK -- the bit pattern to mask with the getuid()
175*9354STim.Marsland@Sun.COM  *			call to get just the user id.
176*9354STim.Marsland@Sun.COM  *		GTTYN -- defines file containing generalized ttynames
177*9354STim.Marsland@Sun.COM  *			and compiles code to look there.
178*9354STim.Marsland@Sun.COM  *
179*9354STim.Marsland@Sun.COM  *	Requires:
180*9354STim.Marsland@Sun.COM  *		Routines to handle htmp, ttys, and termcap.
181*9354STim.Marsland@Sun.COM  *
182*9354STim.Marsland@Sun.COM  *	Compilation Flags:
183*9354STim.Marsland@Sun.COM  *		OLDFLAGS -- must be defined to compile code for any of
184*9354STim.Marsland@Sun.COM  *			the -d, -p, or -a flags.
185*9354STim.Marsland@Sun.COM  *		OLDDIALUP -- accept the -d flag.
186*9354STim.Marsland@Sun.COM  *		OLDPLUGBOARD -- accept the -p flag.
187*9354STim.Marsland@Sun.COM  *		OLDARPANET -- accept the -a flag.
188*9354STim.Marsland@Sun.COM  *		V6 -- if clear, use environments, not htmp.
189*9354STim.Marsland@Sun.COM  *			also use TIOCSETN rather than stty to avoid flushing
190*9354STim.Marsland@Sun.COM  *		GTTYN -- if set, compiles code to look at /etc/ttys.
191*9354STim.Marsland@Sun.COM  *
192*9354STim.Marsland@Sun.COM  *	Trace Flags:
193*9354STim.Marsland@Sun.COM  *		none
194*9354STim.Marsland@Sun.COM  *
195*9354STim.Marsland@Sun.COM  *	Diagnostics:
196*9354STim.Marsland@Sun.COM  *		Bad flag
197*9354STim.Marsland@Sun.COM  *			An incorrect option was specified.
198*9354STim.Marsland@Sun.COM  *		Too few args
199*9354STim.Marsland@Sun.COM  *			more command line arguments are required.
200*9354STim.Marsland@Sun.COM  *		Unexpected arg
201*9354STim.Marsland@Sun.COM  *			wrong type of argument was encountered.
202*9354STim.Marsland@Sun.COM  *		Cannot open ...
203*9354STim.Marsland@Sun.COM  *			The specified file could not be openned.
204*9354STim.Marsland@Sun.COM  *		Type ... unknown
205*9354STim.Marsland@Sun.COM  *			An unknown terminal type was specified.
206*9354STim.Marsland@Sun.COM  *		Cannot update htmp
207*9354STim.Marsland@Sun.COM  *			Cannot update htmp file when the standard
208*9354STim.Marsland@Sun.COM  *			output is not a terminal.
209*9354STim.Marsland@Sun.COM  *		Erase set to ...
210*9354STim.Marsland@Sun.COM  *			Telling that the erase character has been
211*9354STim.Marsland@Sun.COM  *			set to the specified character.
212*9354STim.Marsland@Sun.COM  *		Kill set to ...
213*9354STim.Marsland@Sun.COM  *			Ditto for kill
214*9354STim.Marsland@Sun.COM  *		Erase is ...    Kill is ...
215*9354STim.Marsland@Sun.COM  *			Tells that the erase/kill characters were
216*9354STim.Marsland@Sun.COM  *			wierd before, but they are being left as-is.
217*9354STim.Marsland@Sun.COM  *		Not a terminal
218*9354STim.Marsland@Sun.COM  *			Set if FILEDES is not a terminal.
219*9354STim.Marsland@Sun.COM  *
220*9354STim.Marsland@Sun.COM  *	Compilation Instructions:
221*9354STim.Marsland@Sun.COM  *		cc -n -O tset.c -ltermlib
222*9354STim.Marsland@Sun.COM  *		mv a.out tset
223*9354STim.Marsland@Sun.COM  *		chown bin tset
224*9354STim.Marsland@Sun.COM  *		chmod 4755 tset
225*9354STim.Marsland@Sun.COM  *
226*9354STim.Marsland@Sun.COM  *		where 'bin' should be whoever owns the 'htmp' file.
227*9354STim.Marsland@Sun.COM  *		If 'htmp' is 666, then tset need not be setuid.
228*9354STim.Marsland@Sun.COM  *
229*9354STim.Marsland@Sun.COM  *		For version 6 the compile command should be:
230*9354STim.Marsland@Sun.COM  *		cc -n -O -I/usr/include/retrofit tset.c -ltermlib -lretro -lS
231*9354STim.Marsland@Sun.COM  *
232*9354STim.Marsland@Sun.COM  *
233*9354STim.Marsland@Sun.COM  *	History:
234*9354STim.Marsland@Sun.COM  *		1/81 -- Added alias checking for mapping identifiers.
235*9354STim.Marsland@Sun.COM  *		7/80 -- '-S' added. '-m' mapping added. TERMCAP string
236*9354STim.Marsland@Sun.COM  *			cleaned up.
237*9354STim.Marsland@Sun.COM  *		3/80 -- Changed to use tputs.  Prc & flush added.
238*9354STim.Marsland@Sun.COM  *		10/79 -- '-s' option extended to handle TERMCAP
239*9354STim.Marsland@Sun.COM  *			variable, set noglob, quote the entry,
240*9354STim.Marsland@Sun.COM  *			and know about the Bourne shell.  Terminal
241*9354STim.Marsland@Sun.COM  *			initialization moved to before any information
242*9354STim.Marsland@Sun.COM  *			output so screen clears would not screw you.
243*9354STim.Marsland@Sun.COM  *			'-Q' option added.
244*9354STim.Marsland@Sun.COM  *		8/79 -- '-' option alone changed to only output
245*9354STim.Marsland@Sun.COM  *			type.  '-s' option added.  'VERSION7'
246*9354STim.Marsland@Sun.COM  *			changed to 'V6' for compatibility.
247*9354STim.Marsland@Sun.COM  *		12/78 -- modified for eventual migration to VAX/UNIX,
248*9354STim.Marsland@Sun.COM  *			so the '-' option is changed to output only
249*9354STim.Marsland@Sun.COM  *			the terminal type to STDOUT instead of
250*9354STim.Marsland@Sun.COM  *			FILEDES.
251*9354STim.Marsland@Sun.COM  *		9/78 -- '-' and '-p' options added (now fully
252*9354STim.Marsland@Sun.COM  *			compatible with ttytype!), and spaces are
253*9354STim.Marsland@Sun.COM  *			permitted between the -d and the type.
254*9354STim.Marsland@Sun.COM  *		8/78 -- The sense of -h and -u were reversed, and the
255*9354STim.Marsland@Sun.COM  *			-f flag is dropped -- same effect is available
256*9354STim.Marsland@Sun.COM  *			by just stating the terminal type.
257*9354STim.Marsland@Sun.COM  *		10/77 -- Written.
258*9354STim.Marsland@Sun.COM  */
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 
261*9354STim.Marsland@Sun.COM #define	index strchr
262*9354STim.Marsland@Sun.COM #define	rindex strrchr
263*9354STim.Marsland@Sun.COM #define	curerase modes.c_cc[VERASE]
264*9354STim.Marsland@Sun.COM #define	curkill modes.c_cc[VKILL]
265*9354STim.Marsland@Sun.COM #define	curintr modes.c_cc[VINTR]
266*9354STim.Marsland@Sun.COM #define	olderase oldmodes.c_cc[VERASE]
267*9354STim.Marsland@Sun.COM #define	oldkill oldmodes.c_cc[VKILL]
268*9354STim.Marsland@Sun.COM #define	oldintr oldmodes.c_cc[VINTR]
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate #include	<stdio.h>
2710Sstevel@tonic-gate #include	<termio.h>
2720Sstevel@tonic-gate #include	<signal.h>
2730Sstevel@tonic-gate 
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate #define	YES		1
2760Sstevel@tonic-gate #define	NO		0
2770Sstevel@tonic-gate #undef CNTL
2780Sstevel@tonic-gate #define	CNTL(c)		((c)&037)
2790Sstevel@tonic-gate #define	BACKSPACE	(CNTL('H'))
2800Sstevel@tonic-gate #define	isdigit(c)	(c >= '0' && c <= '9')
2810Sstevel@tonic-gate #define	isalnum(c)	(c > ' ' && (index("<@=>!:|\177", c) == NULL))
2820Sstevel@tonic-gate #define	OLDERASE	'#'
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate /* default special characters */
2850Sstevel@tonic-gate #ifndef CERASE
2860Sstevel@tonic-gate #define	CERASE	'\177'
2870Sstevel@tonic-gate #endif
2880Sstevel@tonic-gate #ifndef CKILL
2890Sstevel@tonic-gate #define	CKILL	CNTL('U')
2900Sstevel@tonic-gate #endif
2910Sstevel@tonic-gate #ifndef CINTR
2920Sstevel@tonic-gate #define	CINTR	CNTL('C')
2930Sstevel@tonic-gate #endif
2940Sstevel@tonic-gate #ifndef CDSUSP
2950Sstevel@tonic-gate #define	CQUIT	034		/* FS, ^\ */
2960Sstevel@tonic-gate #define	CSTART	CNTL('Q')
2970Sstevel@tonic-gate #define	CSTOP	CNTL('S')
2980Sstevel@tonic-gate #define	CEOF	CNTL('D')
2990Sstevel@tonic-gate #define	CEOT	CEOF
3000Sstevel@tonic-gate #define	CBRK	0377
3010Sstevel@tonic-gate #define	CSUSP	CNTL('Z')
3020Sstevel@tonic-gate #define	CDSUSP	CNTL('Y')
3030Sstevel@tonic-gate #define	CRPRNT	CNTL('R')
3040Sstevel@tonic-gate #define	CFLUSH	CNTL('O')
3050Sstevel@tonic-gate #define	CWERASE	CNTL('W')
3060Sstevel@tonic-gate #define	CLNEXT	CNTL('V')
3070Sstevel@tonic-gate #endif
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate #define	FILEDES		2	/* do gtty/stty on this descriptor */
3100Sstevel@tonic-gate #define	STDOUT		1	/* output of -s/-S to this descriptor */
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate #define	UIDMASK		-1
3130Sstevel@tonic-gate 
314*9354STim.Marsland@Sun.COM #define	USAGE	"usage: tset [-] [-rsIQS] [-eC] [-kC] "	\
315*9354STim.Marsland@Sun.COM 		"[-iC] [-m [ident][test speed]:type] [type]\n"
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate #define	OLDFLAGS
3180Sstevel@tonic-gate #define	DIALUP		"dialup"
3190Sstevel@tonic-gate #define	OLDDIALUP	"sd"
3200Sstevel@tonic-gate #define	PLUGBOARD	"plugboard"
3210Sstevel@tonic-gate #define	OLDPLUGBOARD	"sp"
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate #define	DEFTYPE		"unknown"
3240Sstevel@tonic-gate 
3250Sstevel@tonic-gate #define	NOTTY		'x'
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate /*
3280Sstevel@tonic-gate  * Baud Rate Conditionals
3290Sstevel@tonic-gate  */
3300Sstevel@tonic-gate #define	ANY		0
3310Sstevel@tonic-gate #define	GT		1
3320Sstevel@tonic-gate #define	EQ		2
3330Sstevel@tonic-gate #define	LT		4
3340Sstevel@tonic-gate #define	GE		(GT|EQ)
3350Sstevel@tonic-gate #define	LE		(LT|EQ)
3360Sstevel@tonic-gate #define	NE		(GT|LT)
3370Sstevel@tonic-gate #define	ALL		(GT|EQ|LT)
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate #define	NMAP		10
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate struct	map {
3440Sstevel@tonic-gate 	char *Ident;
3450Sstevel@tonic-gate 	char Test;
3460Sstevel@tonic-gate 	char Speed;
3470Sstevel@tonic-gate 	char *Type;
3480Sstevel@tonic-gate } map[NMAP];
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate struct map *Map = map;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate /* This should be available in an include file */
3530Sstevel@tonic-gate struct
3540Sstevel@tonic-gate {
3550Sstevel@tonic-gate 	char	*string;
3560Sstevel@tonic-gate 	int	speed;
3570Sstevel@tonic-gate 	int	baudrate;
3580Sstevel@tonic-gate } speeds[] = {
3590Sstevel@tonic-gate 	"0",	B0,	0,
3600Sstevel@tonic-gate 	"50",	B50,	50,
3610Sstevel@tonic-gate 	"75",	B75,	75,
3620Sstevel@tonic-gate 	"110",	B110,	110,
3630Sstevel@tonic-gate 	"134",	B134,	134,
364*9354STim.Marsland@Sun.COM 	"134.5", B134,	134,
3650Sstevel@tonic-gate 	"150",	B150,	150,
3660Sstevel@tonic-gate 	"200",	B200,	200,
3670Sstevel@tonic-gate 	"300",	B300,	300,
3680Sstevel@tonic-gate 	"600",	B600,	600,
3690Sstevel@tonic-gate 	"1200",	B1200,	1200,
3700Sstevel@tonic-gate 	"1800",	B1800,	1800,
3710Sstevel@tonic-gate 	"2400",	B2400,	2400,
3720Sstevel@tonic-gate 	"4800",	B4800,	4800,
3730Sstevel@tonic-gate 	"9600",	B9600,	9600,
374*9354STim.Marsland@Sun.COM 	"19200", EXTA,	19200,
3750Sstevel@tonic-gate 	"exta",	EXTA,	19200,
3760Sstevel@tonic-gate 	"extb",	EXTB,	38400,
377*9354STim.Marsland@Sun.COM 	"57600", B57600,	57600,
378*9354STim.Marsland@Sun.COM 	"76800", B76800,	76800,
379*9354STim.Marsland@Sun.COM 	"115200", B115200, 115200,
380*9354STim.Marsland@Sun.COM 	"153600", B153600, 153600,
381*9354STim.Marsland@Sun.COM 	"230400", B230400, 230400,
382*9354STim.Marsland@Sun.COM 	"307200", B307200, 307200,
383*9354STim.Marsland@Sun.COM 	"460800", B460800, 460800,
384*9354STim.Marsland@Sun.COM 	"921600", B921600, 921600,
3850Sstevel@tonic-gate 	0,
3860Sstevel@tonic-gate };
3870Sstevel@tonic-gate 
3880Sstevel@tonic-gate signed char Erase_char;		/* new erase character */
3890Sstevel@tonic-gate char	Kill_char;		/* new kill character */
3900Sstevel@tonic-gate char	Intr_char;		/* new interrupt character */
391*9354STim.Marsland@Sun.COM char	Specialerase;	/* set => Erase_char only on terminals with backspace */
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate char	Ttyid = NOTTY;		/* terminal identifier */
3940Sstevel@tonic-gate char	*TtyType;		/* type of terminal */
3950Sstevel@tonic-gate char	*DefType;		/* default type if none other computed */
3960Sstevel@tonic-gate char	*NewType;		/* mapping identifier based on old flags */
3970Sstevel@tonic-gate int	Mapped;			/* mapping has been specified */
3980Sstevel@tonic-gate int	Dash_u;			/* don't update htmp */
3990Sstevel@tonic-gate int	Dash_h;			/* don't read htmp */
4000Sstevel@tonic-gate int	DoSetenv;		/* output setenv commands */
4010Sstevel@tonic-gate int	BeQuiet;		/* be quiet */
4020Sstevel@tonic-gate int	NoInit;			/* don't output initialization string */
4030Sstevel@tonic-gate int	IsReset;		/* invoked as reset */
4040Sstevel@tonic-gate int	Report;			/* report current type */
4050Sstevel@tonic-gate int	Ureport;		/* report to user */
4060Sstevel@tonic-gate int	RepOnly;		/* report only */
4070Sstevel@tonic-gate int	CmndLine;		/* output full command lines (-s option) */
4080Sstevel@tonic-gate int	Ask;			/* ask user for termtype */
4090Sstevel@tonic-gate int	DoVirtTerm = YES;	/* Set up a virtual terminal */
4100Sstevel@tonic-gate int	PadBaud;		/* Min rate of padding needed */
4110Sstevel@tonic-gate 
412*9354STim.Marsland@Sun.COM #define	CAPBUFSIZ	1024
4130Sstevel@tonic-gate char	Capbuf[CAPBUFSIZ];	/* line from /etc/termcap for this TtyType */
4140Sstevel@tonic-gate char	*Ttycap;		/* termcap line from termcap or environ */
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate char	Aliasbuf[128];
4170Sstevel@tonic-gate char	*Alias[16];
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate extern char *strcpy();
4200Sstevel@tonic-gate extern char *index();
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate struct delay
4230Sstevel@tonic-gate {
4240Sstevel@tonic-gate 	int	d_delay;
4250Sstevel@tonic-gate 	int	d_bits;
4260Sstevel@tonic-gate };
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate #include	"tset.delays.h"
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate struct termio	mode;
4310Sstevel@tonic-gate struct termio	oldmode;
4320Sstevel@tonic-gate struct termios	modes;
4330Sstevel@tonic-gate struct termios	oldmodes;
4340Sstevel@tonic-gate int		istermios;
4350Sstevel@tonic-gate 
436669Schin void reportek(char *, char, char, char);
437669Schin void setdelay(char *, struct delay [], tcflag_t, tcflag_t *);
438669Schin void prs(char *);
439669Schin void prc(char);
440669Schin void flush(void);
441669Schin void cat(char *);
442669Schin void bmove(char *, char *, int);
443669Schin void makealias(char *);
444669Schin void wrtermcap(char *);
445*9354STim.Marsland@Sun.COM void fatal(char *, char *);
4460Sstevel@tonic-gate char reset();			/* Routine for checking&resetting chars */
4470Sstevel@tonic-gate 
448669Schin int
main(int argc,char * argv[])449669Schin main(int argc, char *argv[])
4500Sstevel@tonic-gate {
4510Sstevel@tonic-gate 	char		buf[CAPBUFSIZ];
4520Sstevel@tonic-gate 	char		termbuf[32];
4530Sstevel@tonic-gate 	auto char	*bufp;
454669Schin 	char		*p;
4550Sstevel@tonic-gate 	char		*command;
456669Schin 	int		i;
4570Sstevel@tonic-gate 	int		Break;
4580Sstevel@tonic-gate 	int		Not;
4590Sstevel@tonic-gate 	char		*nextarg();
4600Sstevel@tonic-gate 	char		*mapped();
4610Sstevel@tonic-gate 	extern char	*rindex();
4620Sstevel@tonic-gate 	struct winsize	win;
4630Sstevel@tonic-gate 	extern char	*getenv();
4640Sstevel@tonic-gate 	extern char	*tgetstr();
4650Sstevel@tonic-gate 	char		bs_char;
4660Sstevel@tonic-gate 	int		csh;
4670Sstevel@tonic-gate 	int		settle = NO;
4680Sstevel@tonic-gate 	void		setmode();
4690Sstevel@tonic-gate 	extern char	PC;
4700Sstevel@tonic-gate 	extern short	ospeed;
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) {
473*9354STim.Marsland@Sun.COM 		if (ioctl(FILEDES, TCGETA, (char *)&mode) < 0) {
4740Sstevel@tonic-gate 			prs("Not a terminal\n");
4750Sstevel@tonic-gate 			exit(1);
4760Sstevel@tonic-gate 		}
477*9354STim.Marsland@Sun.COM 		bmove((char *)&mode, (char *)&oldmode, sizeof (mode));
4780Sstevel@tonic-gate 		modes.c_lflag = oldmodes.c_lflag = mode.c_lflag;
4790Sstevel@tonic-gate 		modes.c_oflag = oldmodes.c_oflag = mode.c_oflag;
4800Sstevel@tonic-gate 		modes.c_iflag = oldmodes.c_iflag = mode.c_iflag;
4810Sstevel@tonic-gate 		modes.c_cflag = oldmodes.c_cflag = mode.c_cflag;
482*9354STim.Marsland@Sun.COM 		for (i = 0; i < NCC; i++)
4830Sstevel@tonic-gate 			modes.c_cc[i] = oldmodes.c_cc[i] = mode.c_cc[i];
4840Sstevel@tonic-gate 	} else
485*9354STim.Marsland@Sun.COM 		bmove((char *)&modes, (char *)&oldmodes, sizeof (modes));
4860Sstevel@tonic-gate 	ospeed = cfgetospeed(&modes);
4870Sstevel@tonic-gate 	(void) signal(SIGINT, setmode);
4880Sstevel@tonic-gate 	(void) signal(SIGQUIT, setmode);
4890Sstevel@tonic-gate 	(void) signal(SIGTERM, setmode);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	if (command = rindex(argv[0], '/'))
4920Sstevel@tonic-gate 		command++;
4930Sstevel@tonic-gate 	else
4940Sstevel@tonic-gate 		command = argv[0];
495*9354STim.Marsland@Sun.COM 	if (sequal(command, "reset")) {
4960Sstevel@tonic-gate 		/*
4970Sstevel@tonic-gate 		 * Reset the teletype mode bits to a sensible state.
4980Sstevel@tonic-gate 		 * Copied from the program by Kurt Shoens & Mark Horton.
4990Sstevel@tonic-gate 		 * Very useful after crapping out in raw.
5000Sstevel@tonic-gate 		 */
5010Sstevel@tonic-gate 		if ((istermios = ioctl(FILEDES, TCGETS, (char *)&modes)) < 0) {
5020Sstevel@tonic-gate 			(void) ioctl(FILEDES, TCGETA, (char *)&mode);
5030Sstevel@tonic-gate 			modes.c_lflag = mode.c_lflag;
5040Sstevel@tonic-gate 			modes.c_oflag = mode.c_oflag;
5050Sstevel@tonic-gate 			modes.c_iflag = mode.c_iflag;
5060Sstevel@tonic-gate 			modes.c_cflag = mode.c_cflag;
507*9354STim.Marsland@Sun.COM 			for (i = 0; i < NCC; i++)
5080Sstevel@tonic-gate 				modes.c_cc[i] = mode.c_cc[i];
5090Sstevel@tonic-gate 		}
5100Sstevel@tonic-gate 		curerase = reset(curerase, CERASE);
5110Sstevel@tonic-gate 		curkill = reset(curkill, CKILL);
5120Sstevel@tonic-gate 		curintr = reset(curintr, CINTR);
5130Sstevel@tonic-gate 		modes.c_cc[VQUIT] = reset(modes.c_cc[VQUIT], CQUIT);
5140Sstevel@tonic-gate 		modes.c_cc[VEOF] = reset(modes.c_cc[VEOF], CEOF);
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 		modes.c_iflag |= (BRKINT|ISTRIP|ICRNL|IXON);
5170Sstevel@tonic-gate 		modes.c_iflag &= ~(IGNBRK|PARMRK|INPCK|INLCR|IGNCR|IUCLC|IXOFF);
5180Sstevel@tonic-gate 		modes.c_oflag |= (OPOST|ONLCR);
5190Sstevel@tonic-gate 		modes.c_oflag &= ~(OLCUC|OCRNL|ONOCR|ONLRET|OFILL|OFDEL|
520*9354STim.Marsland@Sun.COM 		    NLDLY|CRDLY|TABDLY|BSDLY|VTDLY|FFDLY);
5210Sstevel@tonic-gate 		modes.c_cflag |= (CS7|CREAD);
5220Sstevel@tonic-gate 		modes.c_cflag &= ~(PARODD|CLOCAL);
5230Sstevel@tonic-gate 		modes.c_lflag |= (ISIG|ICANON|ECHO|ECHOK);
5240Sstevel@tonic-gate 		modes.c_lflag &= ~(XCASE|ECHONL|NOFLSH);
525*9354STim.Marsland@Sun.COM 		if (istermios < 0) {
5260Sstevel@tonic-gate 			mode.c_lflag = modes.c_lflag;
5270Sstevel@tonic-gate 			mode.c_oflag = modes.c_oflag;
5280Sstevel@tonic-gate 			mode.c_iflag = modes.c_iflag;
5290Sstevel@tonic-gate 			mode.c_cflag = modes.c_cflag;
530*9354STim.Marsland@Sun.COM 			for (i = 0; i < NCC; i++)
5310Sstevel@tonic-gate 				mode.c_cc[i] = modes.c_cc[i];
5320Sstevel@tonic-gate 			(void) ioctl(FILEDES, TCSETAW, (char *)&mode);
5330Sstevel@tonic-gate 		} else
5340Sstevel@tonic-gate 			(void) ioctl(FILEDES, TCSETSW, (char *)&modes);
5350Sstevel@tonic-gate 		Dash_u = YES;
5360Sstevel@tonic-gate 		BeQuiet = YES;
5370Sstevel@tonic-gate 		IsReset = YES;
538*9354STim.Marsland@Sun.COM 	} else if (argc == 2 && sequal(argv[1], "-")) {
5390Sstevel@tonic-gate 		RepOnly = YES;
5400Sstevel@tonic-gate 		Dash_u = YES;
5410Sstevel@tonic-gate 	}
5420Sstevel@tonic-gate 	argc--;
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	/* scan argument list and collect flags */
545*9354STim.Marsland@Sun.COM 	while (--argc >= 0) {
5460Sstevel@tonic-gate 		p = *++argv;
547*9354STim.Marsland@Sun.COM 		if (*p == '-') {
5480Sstevel@tonic-gate 			if (*++p == NULL)
5490Sstevel@tonic-gate 				Report = YES; /* report current terminal type */
550*9354STim.Marsland@Sun.COM 			else
551*9354STim.Marsland@Sun.COM 				while (*p)
552*9354STim.Marsland@Sun.COM 					switch (*p++) {
5530Sstevel@tonic-gate 
554*9354STim.Marsland@Sun.COM 			case 'r':	/* report to user */
5550Sstevel@tonic-gate 				Ureport = YES;
5560Sstevel@tonic-gate 				continue;
5570Sstevel@tonic-gate 
558*9354STim.Marsland@Sun.COM 			case 'E':
559*9354STim.Marsland@Sun.COM 				/* special erase: operate on all but TTY33 */
5600Sstevel@tonic-gate 				Specialerase = YES;
5610Sstevel@tonic-gate 				/* explicit fall-through to -e case */
5620Sstevel@tonic-gate 
563*9354STim.Marsland@Sun.COM 			case 'e':	/* erase character */
5640Sstevel@tonic-gate 				if (*p == NULL)
5650Sstevel@tonic-gate 					Erase_char = -1;
566*9354STim.Marsland@Sun.COM 				else {
5670Sstevel@tonic-gate 					if (*p == '^' && p[1] != NULL)
5680Sstevel@tonic-gate 						if (*++p == '?')
5690Sstevel@tonic-gate 							Erase_char = '\177';
5700Sstevel@tonic-gate 						else
5710Sstevel@tonic-gate 							Erase_char = CNTL(*p);
5720Sstevel@tonic-gate 					else
5730Sstevel@tonic-gate 						Erase_char = *p;
5740Sstevel@tonic-gate 					p++;
5750Sstevel@tonic-gate 				}
5760Sstevel@tonic-gate 				continue;
5770Sstevel@tonic-gate 
578*9354STim.Marsland@Sun.COM 			case 'i':	/* interrupt character */
5790Sstevel@tonic-gate 				if (*p == NULL)
5800Sstevel@tonic-gate 					Intr_char = CNTL('C');
581*9354STim.Marsland@Sun.COM 				else {
5820Sstevel@tonic-gate 					if (*p == '^' && p[1] != NULL)
5830Sstevel@tonic-gate 						if (*++p == '?')
5840Sstevel@tonic-gate 							Intr_char = '\177';
5850Sstevel@tonic-gate 						else
5860Sstevel@tonic-gate 							Intr_char = CNTL(*p);
5870Sstevel@tonic-gate 					else
5880Sstevel@tonic-gate 						Intr_char = *p;
5890Sstevel@tonic-gate 					p++;
5900Sstevel@tonic-gate 				}
5910Sstevel@tonic-gate 				continue;
5920Sstevel@tonic-gate 
593*9354STim.Marsland@Sun.COM 			case 'k':	/* kill character */
5940Sstevel@tonic-gate 				if (*p == NULL)
5950Sstevel@tonic-gate 					Kill_char = CNTL('U');
596*9354STim.Marsland@Sun.COM 				else {
5970Sstevel@tonic-gate 					if (*p == '^' && p[1] != NULL)
5980Sstevel@tonic-gate 						if (*++p == '?')
5990Sstevel@tonic-gate 							Kill_char = '\177';
6000Sstevel@tonic-gate 						else
6010Sstevel@tonic-gate 							Kill_char = CNTL(*p);
6020Sstevel@tonic-gate 					else
6030Sstevel@tonic-gate 						Kill_char = *p;
6040Sstevel@tonic-gate 					p++;
6050Sstevel@tonic-gate 				}
6060Sstevel@tonic-gate 				continue;
6070Sstevel@tonic-gate 
608*9354STim.Marsland@Sun.COM #ifdef OLDFLAGS
609*9354STim.Marsland@Sun.COM #ifdef	OLDDIALUP
610*9354STim.Marsland@Sun.COM 			case 'd':	/* dialup type */
6110Sstevel@tonic-gate 				NewType = DIALUP;
6120Sstevel@tonic-gate 				goto mapold;
613*9354STim.Marsland@Sun.COM #endif
6140Sstevel@tonic-gate 
615*9354STim.Marsland@Sun.COM #ifdef OLDPLUGBOARD
616*9354STim.Marsland@Sun.COM 			case 'p':	/* plugboard type */
6170Sstevel@tonic-gate 				NewType = PLUGBOARD;
6180Sstevel@tonic-gate 				goto mapold;
619*9354STim.Marsland@Sun.COM #endif
6200Sstevel@tonic-gate 
621*9354STim.Marsland@Sun.COM #ifdef OLDARPANET
622*9354STim.Marsland@Sun.COM 			case 'a':	/* arpanet type */
6230Sstevel@tonic-gate 				Newtype = ARPANET;
6240Sstevel@tonic-gate 				goto mapold;
625*9354STim.Marsland@Sun.COM #endif
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate mapold:				Map->Ident = NewType;
6280Sstevel@tonic-gate 				Map->Test = ALL;
629*9354STim.Marsland@Sun.COM 				if (*p == NULL) {
6300Sstevel@tonic-gate 					p = nextarg(argc--, argv++);
6310Sstevel@tonic-gate 				}
6320Sstevel@tonic-gate 				Map->Type = p;
6330Sstevel@tonic-gate 				Map++;
6340Sstevel@tonic-gate 				Mapped = YES;
6350Sstevel@tonic-gate 				p = "";
6360Sstevel@tonic-gate 				continue;
637*9354STim.Marsland@Sun.COM #endif
6380Sstevel@tonic-gate 
639*9354STim.Marsland@Sun.COM 			case 'm':	/* map identifier to type */
640*9354STim.Marsland@Sun.COM 				/*
641*9354STim.Marsland@Sun.COM 				 * This code is very loose. Almost no
642*9354STim.Marsland@Sun.COM 				 * syntax checking is done!! However,
643*9354STim.Marsland@Sun.COM 				 * illegal syntax will only produce
644*9354STim.Marsland@Sun.COM 				 * weird results.
645*9354STim.Marsland@Sun.COM 				 */
646*9354STim.Marsland@Sun.COM 				if (*p == NULL) {
6470Sstevel@tonic-gate 					p = nextarg(argc--, argv++);
6480Sstevel@tonic-gate 				}
649*9354STim.Marsland@Sun.COM 				if (isalnum(*p)) {
6500Sstevel@tonic-gate 					Map->Ident = p;	/* identifier */
6510Sstevel@tonic-gate 					while (isalnum(*p)) p++;
6520Sstevel@tonic-gate 				}
6530Sstevel@tonic-gate 				else
6540Sstevel@tonic-gate 					Map->Ident = "";
6550Sstevel@tonic-gate 				Break = NO;
6560Sstevel@tonic-gate 				Not = NO;
657*9354STim.Marsland@Sun.COM 				while (!Break)
658*9354STim.Marsland@Sun.COM 					switch (*p) {
6590Sstevel@tonic-gate 					case NULL:
6600Sstevel@tonic-gate 						p = nextarg(argc--, argv++);
6610Sstevel@tonic-gate 						continue;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 					case ':':	/* mapped type */
6640Sstevel@tonic-gate 						*p++ = NULL;
6650Sstevel@tonic-gate 						Break = YES;
6660Sstevel@tonic-gate 						continue;
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 					case '>':	/* conditional */
6690Sstevel@tonic-gate 						Map->Test |= GT;
6700Sstevel@tonic-gate 						*p++ = NULL;
6710Sstevel@tonic-gate 						continue;
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 					case '<':	/* conditional */
6740Sstevel@tonic-gate 						Map->Test |= LT;
6750Sstevel@tonic-gate 						*p++ = NULL;
6760Sstevel@tonic-gate 						continue;
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 					case '=':	/* conditional */
6790Sstevel@tonic-gate 					case '@':
6800Sstevel@tonic-gate 						Map->Test |= EQ;
6810Sstevel@tonic-gate 						*p++ = NULL;
6820Sstevel@tonic-gate 						continue;
683*9354STim.Marsland@Sun.COM 
6840Sstevel@tonic-gate 					case '!':	/* invert conditions */
6850Sstevel@tonic-gate 						Not = ~Not;
6860Sstevel@tonic-gate 						*p++ = NULL;
6870Sstevel@tonic-gate 						continue;
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 					case 'B':	/* Baud rate */
6900Sstevel@tonic-gate 						p++;
6910Sstevel@tonic-gate 						/* intentional fallthru */
6920Sstevel@tonic-gate 					default:
693*9354STim.Marsland@Sun.COM 						if (isdigit(*p) || *p == 'e') {
694*9354STim.Marsland@Sun.COM 							Map->Speed =
695*9354STim.Marsland@Sun.COM 							    baudrate(p);
696*9354STim.Marsland@Sun.COM 							while (isalnum(*p) ||
697*9354STim.Marsland@Sun.COM 							    *p == '.')
6980Sstevel@tonic-gate 								p++;
699*9354STim.Marsland@Sun.COM 						} else
7000Sstevel@tonic-gate 							Break = YES;
7010Sstevel@tonic-gate 						continue;
7020Sstevel@tonic-gate 				}
703*9354STim.Marsland@Sun.COM 				if (Not) {	/* invert sense of test */
7040Sstevel@tonic-gate 					Map->Test = (~(Map->Test))&ALL;
7050Sstevel@tonic-gate 				}
706*9354STim.Marsland@Sun.COM 				if (*p == NULL) {
7070Sstevel@tonic-gate 					p = nextarg(argc--, argv++);
7080Sstevel@tonic-gate 				}
7090Sstevel@tonic-gate 				Map->Type = p;
7100Sstevel@tonic-gate 				p = "";
7110Sstevel@tonic-gate 				Map++;
7120Sstevel@tonic-gate 				Mapped = YES;
7130Sstevel@tonic-gate 				continue;
7140Sstevel@tonic-gate 
715*9354STim.Marsland@Sun.COM 			case 'h':	/* don't get type from htmp or env */
7160Sstevel@tonic-gate 				Dash_h = YES;
7170Sstevel@tonic-gate 				continue;
7180Sstevel@tonic-gate 
719*9354STim.Marsland@Sun.COM 			case 'u':	/* don't update htmp */
7200Sstevel@tonic-gate 				Dash_u = YES;
7210Sstevel@tonic-gate 				continue;
7220Sstevel@tonic-gate 
723*9354STim.Marsland@Sun.COM 			case 's':	/* output setenv commands */
7240Sstevel@tonic-gate 				DoSetenv = YES;
7250Sstevel@tonic-gate 				CmndLine = YES;
7260Sstevel@tonic-gate 				continue;
7270Sstevel@tonic-gate 
728*9354STim.Marsland@Sun.COM 			case 'S':	/* output setenv strings */
7290Sstevel@tonic-gate 				DoSetenv = YES;
7300Sstevel@tonic-gate 				CmndLine = NO;
7310Sstevel@tonic-gate 				continue;
7320Sstevel@tonic-gate 
733*9354STim.Marsland@Sun.COM 			case 'Q':	/* be quiet */
7340Sstevel@tonic-gate 				BeQuiet = YES;
7350Sstevel@tonic-gate 				continue;
7360Sstevel@tonic-gate 
737*9354STim.Marsland@Sun.COM 			case 'I':	/* no initialization */
7380Sstevel@tonic-gate 				NoInit = YES;
7390Sstevel@tonic-gate 				continue;
7400Sstevel@tonic-gate 
741*9354STim.Marsland@Sun.COM 			case 'A':	/* Ask user */
7420Sstevel@tonic-gate 				Ask = YES;
7430Sstevel@tonic-gate 				continue;
744*9354STim.Marsland@Sun.COM 
745*9354STim.Marsland@Sun.COM 			case 'v':	/* no virtual terminal */
7460Sstevel@tonic-gate 				DoVirtTerm = NO;
7470Sstevel@tonic-gate 				continue;
7480Sstevel@tonic-gate 
749*9354STim.Marsland@Sun.COM 			default:
7500Sstevel@tonic-gate 				*p-- = NULL;
7510Sstevel@tonic-gate 				fatal("Bad flag -", p);
7520Sstevel@tonic-gate 			}
753*9354STim.Marsland@Sun.COM 		} else {
7540Sstevel@tonic-gate 			/* terminal type */
7550Sstevel@tonic-gate 			DefType = p;
7560Sstevel@tonic-gate 		}
7570Sstevel@tonic-gate 	}
7580Sstevel@tonic-gate 
759*9354STim.Marsland@Sun.COM 	if (DefType) {
760*9354STim.Marsland@Sun.COM 		if (Mapped) {
7610Sstevel@tonic-gate 			Map->Ident = "";	/* means "map any type" */
7620Sstevel@tonic-gate 			Map->Test = ALL;	/* at all baud rates */
7630Sstevel@tonic-gate 			Map->Type = DefType;	/* to the default type */
764*9354STim.Marsland@Sun.COM 		} else
7650Sstevel@tonic-gate 			TtyType = DefType;
7660Sstevel@tonic-gate 	}
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	/*
7690Sstevel@tonic-gate 	 * Get rid of $TERMCAP, if it's there, so we get a real
7700Sstevel@tonic-gate 	 * entry from /etc/termcap.  This prevents us from being
7710Sstevel@tonic-gate 	 * fooled by out of date stuff in the environment, and
7720Sstevel@tonic-gate 	 * makes tabs work right on CB/Unix.
7730Sstevel@tonic-gate 	 */
7740Sstevel@tonic-gate 	bufp = getenv("TERMCAP");
7750Sstevel@tonic-gate 	if (bufp && *bufp != '/')
7760Sstevel@tonic-gate 		(void) strcpy(bufp-8, "NOTHING"); /* overwrite only "TERMCAP" */
7770Sstevel@tonic-gate 	/* get current idea of terminal type from environment */
7780Sstevel@tonic-gate 	if (!Dash_h && TtyType == 0)
7790Sstevel@tonic-gate 		TtyType = getenv("TERM");
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 	if (!RepOnly && Ttyid == NOTTY && (TtyType == 0 || !Dash_h))
7820Sstevel@tonic-gate 		Ttyid = ttyname(FILEDES);
7830Sstevel@tonic-gate 
7840Sstevel@tonic-gate 	/* If still undefined, use DEFTYPE */
785*9354STim.Marsland@Sun.COM 	if (TtyType == 0) {
7860Sstevel@tonic-gate 		TtyType = DEFTYPE;
7870Sstevel@tonic-gate 	}
7880Sstevel@tonic-gate 
7890Sstevel@tonic-gate 	/* check for dialup or other mapping */
790*9354STim.Marsland@Sun.COM 	if (Mapped) {
7910Sstevel@tonic-gate 		if (!(Alias[0] && isalias(TtyType)))
7920Sstevel@tonic-gate 			if (tgetent(Capbuf, TtyType) > 0)
7930Sstevel@tonic-gate 				makealias(Capbuf);
7940Sstevel@tonic-gate 		TtyType = mapped(TtyType);
7950Sstevel@tonic-gate 	}
7960Sstevel@tonic-gate 
7970Sstevel@tonic-gate 	/* TtyType now contains a pointer to the type of the terminal */
7980Sstevel@tonic-gate 	/* If the first character is '?', ask the user */
799*9354STim.Marsland@Sun.COM 	if (TtyType[0] == '?') {
8000Sstevel@tonic-gate 		Ask = YES;
8010Sstevel@tonic-gate 		TtyType++;
8020Sstevel@tonic-gate 		if (TtyType[0] == '\0')
8030Sstevel@tonic-gate 			TtyType = DEFTYPE;
8040Sstevel@tonic-gate 	}
805*9354STim.Marsland@Sun.COM 	if (Ask) {
8060Sstevel@tonic-gate ask:
8070Sstevel@tonic-gate 		prs("TERM = (");
8080Sstevel@tonic-gate 		prs(TtyType);
8090Sstevel@tonic-gate 		prs(") ");
8100Sstevel@tonic-gate 		flush();
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 		/* read the terminal.  If not empty, set type */
813*9354STim.Marsland@Sun.COM 		i = read(2, termbuf, sizeof (termbuf) - 1);
814*9354STim.Marsland@Sun.COM 		if (i > 0) {
8150Sstevel@tonic-gate 			if (termbuf[i - 1] == '\n')
8160Sstevel@tonic-gate 				i--;
8170Sstevel@tonic-gate 			termbuf[i] = '\0';
8180Sstevel@tonic-gate 			if (termbuf[0] != '\0')
8190Sstevel@tonic-gate 				TtyType = termbuf;
8200Sstevel@tonic-gate 		}
8210Sstevel@tonic-gate 	}
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	/* get terminal capabilities */
8240Sstevel@tonic-gate 	if (!(Alias[0] && isalias(TtyType))) {
825*9354STim.Marsland@Sun.COM 		switch (tgetent(Capbuf, TtyType)) {
826*9354STim.Marsland@Sun.COM 		case -1:
8270Sstevel@tonic-gate 			prs("Cannot find termcap\n");
8280Sstevel@tonic-gate 			flush();
8290Sstevel@tonic-gate 			exit(-1);
8300Sstevel@tonic-gate 
831*9354STim.Marsland@Sun.COM 		case 0:
8320Sstevel@tonic-gate 			prs("Type ");
8330Sstevel@tonic-gate 			prs(TtyType);
8340Sstevel@tonic-gate 			prs(" unknown\n");
8350Sstevel@tonic-gate 			flush();
836*9354STim.Marsland@Sun.COM 			if (DoSetenv) {
8370Sstevel@tonic-gate 				TtyType = DEFTYPE;
8380Sstevel@tonic-gate 				Alias[0] = '\0';
8390Sstevel@tonic-gate 				goto ask;
840*9354STim.Marsland@Sun.COM 			} else
8410Sstevel@tonic-gate 				exit(1);
8420Sstevel@tonic-gate 		}
8430Sstevel@tonic-gate 	}
8440Sstevel@tonic-gate 	Ttycap = Capbuf;
8450Sstevel@tonic-gate 
846*9354STim.Marsland@Sun.COM 	if (!RepOnly) {
8470Sstevel@tonic-gate 		/* determine erase and kill characters */
8480Sstevel@tonic-gate 		if (Specialerase && !tgetflag("bs"))
8490Sstevel@tonic-gate 			Erase_char = 0;
8500Sstevel@tonic-gate 		bufp = buf;
8510Sstevel@tonic-gate 		p = tgetstr("kb", &bufp);
8520Sstevel@tonic-gate 		if (p == NULL || p[1] != '\0')
8530Sstevel@tonic-gate 			p = tgetstr("bc", &bufp);
8540Sstevel@tonic-gate 		if (p != NULL && p[1] == '\0')
8550Sstevel@tonic-gate 			bs_char = p[0];
8560Sstevel@tonic-gate 		else if (tgetflag("bs"))
8570Sstevel@tonic-gate 			bs_char = BACKSPACE;
8580Sstevel@tonic-gate 		else
8590Sstevel@tonic-gate 			bs_char = 0;
8600Sstevel@tonic-gate 		/*
8610Sstevel@tonic-gate 		 * The next statement can't be fixed, because now users
8620Sstevel@tonic-gate 		 * depend on keeping their erase character as DEL if the
8630Sstevel@tonic-gate 		 * system set it there.  People who want backspace have
8640Sstevel@tonic-gate 		 * to say tset -e.
8650Sstevel@tonic-gate 		 */
866*9354STim.Marsland@Sun.COM 		if (Erase_char == 0 && !tgetflag("os") &&
867*9354STim.Marsland@Sun.COM 		    curerase == OLDERASE) {
8680Sstevel@tonic-gate 			if (tgetflag("bs") || bs_char != 0)
8690Sstevel@tonic-gate 				Erase_char = -1;
8700Sstevel@tonic-gate 		}
8710Sstevel@tonic-gate 		if (Erase_char < 0)
8720Sstevel@tonic-gate 			Erase_char = (bs_char != 0) ? bs_char : BACKSPACE;
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 		if (curerase == 0)
8750Sstevel@tonic-gate 			curerase = CERASE;
8760Sstevel@tonic-gate 		if (Erase_char != 0)
8770Sstevel@tonic-gate 			curerase = Erase_char;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 		if (curintr == 0)
8800Sstevel@tonic-gate 			curintr = CINTR;
8810Sstevel@tonic-gate 		if (Intr_char != 0)
8820Sstevel@tonic-gate 			curintr = Intr_char;
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 		if (curkill == 0)
8850Sstevel@tonic-gate 			curkill = CKILL;
8860Sstevel@tonic-gate 		if (Kill_char != 0)
8870Sstevel@tonic-gate 			curkill = Kill_char;
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 		/* set modes */
8900Sstevel@tonic-gate 		PadBaud = tgetnum("pb");	/* OK if fails */
891*9354STim.Marsland@Sun.COM 		for (i = 0; speeds[i].string; i++)
8920Sstevel@tonic-gate 			if (speeds[i].baudrate == PadBaud) {
8930Sstevel@tonic-gate 				PadBaud = speeds[i].speed;
8940Sstevel@tonic-gate 				break;
8950Sstevel@tonic-gate 			}
8960Sstevel@tonic-gate 		setdelay("dC", CRdelay, CRbits, &modes.c_oflag);
8970Sstevel@tonic-gate 		setdelay("dN", NLdelay, NLbits, &modes.c_oflag);
8980Sstevel@tonic-gate 		setdelay("dB", BSdelay, BSbits, &modes.c_oflag);
8990Sstevel@tonic-gate 		setdelay("dF", FFdelay, FFbits, &modes.c_oflag);
9000Sstevel@tonic-gate 		setdelay("dT", TBdelay, TBbits, &modes.c_oflag);
9010Sstevel@tonic-gate 		setdelay("dV", VTdelay, VTbits, &modes.c_oflag);
9020Sstevel@tonic-gate 
9030Sstevel@tonic-gate 		if (tgetflag("UC") || (command[0] & 0140) == 0100) {
9040Sstevel@tonic-gate 			modes.c_iflag |= IUCLC;
9050Sstevel@tonic-gate 			modes.c_oflag |= OLCUC;
9060Sstevel@tonic-gate 			modes.c_cflag |= XCASE;
907*9354STim.Marsland@Sun.COM 		} else if (tgetflag("LC")) {
9080Sstevel@tonic-gate 			modes.c_iflag &= ~IUCLC;
9090Sstevel@tonic-gate 			modes.c_oflag &= ~OLCUC;
9100Sstevel@tonic-gate 			modes.c_cflag &= ~XCASE;
9110Sstevel@tonic-gate 		}
9120Sstevel@tonic-gate 		modes.c_iflag &= ~(PARMRK|INPCK);
9130Sstevel@tonic-gate 		modes.c_lflag |= ICANON;
9140Sstevel@tonic-gate 		if (tgetflag("EP")) {
9150Sstevel@tonic-gate 			modes.c_iflag |= INPCK;
9160Sstevel@tonic-gate 			modes.c_cflag |= PARENB;
9170Sstevel@tonic-gate 			modes.c_cflag &= ~PARODD;
9180Sstevel@tonic-gate 		}
9190Sstevel@tonic-gate 		if (tgetflag("OP")) {
9200Sstevel@tonic-gate 			modes.c_iflag |= INPCK;
9210Sstevel@tonic-gate 			modes.c_cflag |= PARENB;
9220Sstevel@tonic-gate 			modes.c_cflag |= PARODD;
9230Sstevel@tonic-gate 		}
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 		modes.c_oflag |= ONLCR;
9260Sstevel@tonic-gate 		modes.c_iflag |= ICRNL;
9270Sstevel@tonic-gate 		modes.c_lflag |= ECHO;
9280Sstevel@tonic-gate 		modes.c_oflag |= TAB3;
9290Sstevel@tonic-gate 		if (tgetflag("NL")) {	/* new line, not line feed */
9300Sstevel@tonic-gate 			modes.c_oflag &= ~ONLCR;
9310Sstevel@tonic-gate 			modes.c_iflag &= ~ICRNL;
9320Sstevel@tonic-gate 		}
9330Sstevel@tonic-gate 		if (tgetflag("HD"))	/* half duplex */
9340Sstevel@tonic-gate 			modes.c_lflag &= ~ECHO;
9350Sstevel@tonic-gate 		if (tgetflag("pt"))	/* print tabs */
9360Sstevel@tonic-gate 			modes.c_oflag &= ~TAB3;
937*9354STim.Marsland@Sun.COM 
9380Sstevel@tonic-gate 		modes.c_lflag |= (ECHOE|ECHOK);
939*9354STim.Marsland@Sun.COM 		if (tgetflag("hc")) {	/* set printer modes */
9400Sstevel@tonic-gate 			modes.c_lflag &= ~ECHOE;
9410Sstevel@tonic-gate 		}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 		/* get pad character */
9440Sstevel@tonic-gate 		bufp = buf;
9450Sstevel@tonic-gate 		if (tgetstr("pc", &bufp) != 0)
9460Sstevel@tonic-gate 			PC = buf[0];
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 		/* output startup string */
949*9354STim.Marsland@Sun.COM 		if (!NoInit) {
950*9354STim.Marsland@Sun.COM 			if (oldmodes.c_oflag&(TAB3|ONLCR|OCRNL|ONLRET)) {
9510Sstevel@tonic-gate 				oldmodes.c_oflag &= (TAB3|ONLCR|OCRNL|ONLRET);
9520Sstevel@tonic-gate 				setmode(-1);
9530Sstevel@tonic-gate 			}
9540Sstevel@tonic-gate 			if (settabs()) {
9550Sstevel@tonic-gate 				settle = YES;
9560Sstevel@tonic-gate 				flush();
9570Sstevel@tonic-gate 			}
9580Sstevel@tonic-gate 			bufp = buf;
959*9354STim.Marsland@Sun.COM 			if (IsReset && tgetstr("rs", &bufp) != 0 ||
960*9354STim.Marsland@Sun.COM 			    tgetstr("is", &bufp) != 0) {
9610Sstevel@tonic-gate 				tputs(buf, 0, prc);
9620Sstevel@tonic-gate 				settle = YES;
9630Sstevel@tonic-gate 				flush();
9640Sstevel@tonic-gate 			}
9650Sstevel@tonic-gate 			bufp = buf;
9660Sstevel@tonic-gate 			if (IsReset && tgetstr("rf", &bufp) != 0 ||
967*9354STim.Marsland@Sun.COM 			    tgetstr("if", &bufp) != 0) {
9680Sstevel@tonic-gate 				cat(buf);
9690Sstevel@tonic-gate 				settle = YES;
9700Sstevel@tonic-gate 			}
971*9354STim.Marsland@Sun.COM 			if (settle) {
9720Sstevel@tonic-gate 				prc('\r');
9730Sstevel@tonic-gate 				if (IsReset)
9740Sstevel@tonic-gate 					prc('\n');  /* newline too */
9750Sstevel@tonic-gate 				flush();
9760Sstevel@tonic-gate 				sleep(1);	/* let terminal settle down */
9770Sstevel@tonic-gate 			}
9780Sstevel@tonic-gate 		}
9790Sstevel@tonic-gate 
9800Sstevel@tonic-gate 		setmode(0);	/* set new modes, if they've changed */
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 		/* set up environment for the shell we are using */
9830Sstevel@tonic-gate 		/* (this code is rather heuristic, checking for $SHELL */
9840Sstevel@tonic-gate 		/* ending in the 3 characters "csh") */
9850Sstevel@tonic-gate 		csh = NO;
986*9354STim.Marsland@Sun.COM 		if (DoSetenv) {
9870Sstevel@tonic-gate 			char *sh;
9880Sstevel@tonic-gate 
989*9354STim.Marsland@Sun.COM 			if ((sh = getenv("SHELL")) && (i = strlen(sh)) >= 3) {
990*9354STim.Marsland@Sun.COM 				if ((csh = sequal(&sh[i-3], "csh")) && CmndLine)
991*9354STim.Marsland@Sun.COM 					(void) write(STDOUT,
992*9354STim.Marsland@Sun.COM 					    "set noglob;\n", 12);
9930Sstevel@tonic-gate 			}
994*9354STim.Marsland@Sun.COM 			if (!csh) {	/* running Bourne shell */
995*9354STim.Marsland@Sun.COM 				(void) write(STDOUT,
996*9354STim.Marsland@Sun.COM 				    "export TERMCAP TERM;\n", 21);
997*9354STim.Marsland@Sun.COM 			}
9980Sstevel@tonic-gate 		}
9990Sstevel@tonic-gate 	}
10000Sstevel@tonic-gate 
10010Sstevel@tonic-gate 	/* report type if appropriate */
1002*9354STim.Marsland@Sun.COM 	if (DoSetenv || Report || Ureport) {
10030Sstevel@tonic-gate 		/* if type is the short name, find first alias (if any) */
10040Sstevel@tonic-gate 		makealias(Ttycap);
10050Sstevel@tonic-gate 		if (sequal(TtyType, Alias[0]) && Alias[1]) {
10060Sstevel@tonic-gate 			TtyType = Alias[1];
10070Sstevel@tonic-gate 		}
10080Sstevel@tonic-gate 
1009*9354STim.Marsland@Sun.COM 		if (DoSetenv) {
1010*9354STim.Marsland@Sun.COM 			if (csh) {
10110Sstevel@tonic-gate 				if (CmndLine)
1012*9354STim.Marsland@Sun.COM 					(void) write(STDOUT,
1013*9354STim.Marsland@Sun.COM 					    "setenv TERM ", 12);
10140Sstevel@tonic-gate 				(void) write(STDOUT, TtyType, strlen(TtyType));
10150Sstevel@tonic-gate 				(void) write(STDOUT, " ", 1);
10160Sstevel@tonic-gate 				if (CmndLine)
1017*9354STim.Marsland@Sun.COM 					(void) write(STDOUT, ";\n", 2);
1018*9354STim.Marsland@Sun.COM 			} else {
10190Sstevel@tonic-gate 				(void) write(STDOUT, "TERM=", 5);
10200Sstevel@tonic-gate 				(void) write(STDOUT, TtyType, strlen(TtyType));
10210Sstevel@tonic-gate 				(void) write(STDOUT, ";\n", 2);
10220Sstevel@tonic-gate 			}
1023*9354STim.Marsland@Sun.COM 		} else if (Report) {
10240Sstevel@tonic-gate 			(void) write(STDOUT, TtyType, strlen(TtyType));
10250Sstevel@tonic-gate 			(void) write(STDOUT, "\n", 1);
10260Sstevel@tonic-gate 		}
1027*9354STim.Marsland@Sun.COM 		if (Ureport) {
10280Sstevel@tonic-gate 			prs("Terminal type is ");
10290Sstevel@tonic-gate 			prs(TtyType);
10300Sstevel@tonic-gate 			prs("\n");
10310Sstevel@tonic-gate 			flush();
10320Sstevel@tonic-gate 		}
10330Sstevel@tonic-gate 
1034*9354STim.Marsland@Sun.COM 		if (DoSetenv) {
1035*9354STim.Marsland@Sun.COM 			if (csh) {
1036*9354STim.Marsland@Sun.COM 				if (CmndLine)
1037*9354STim.Marsland@Sun.COM 					(void) write(STDOUT,
1038*9354STim.Marsland@Sun.COM 					    "setenv TERMCAP '", 16);
1039*9354STim.Marsland@Sun.COM 			} else
1040*9354STim.Marsland@Sun.COM 				(void) write(STDOUT, "TERMCAP='", 9);
10410Sstevel@tonic-gate 			wrtermcap(Ttycap);
1042*9354STim.Marsland@Sun.COM 			if (csh) {
1043*9354STim.Marsland@Sun.COM 				if (CmndLine) {
1044*9354STim.Marsland@Sun.COM 					(void) write(STDOUT, "';\n", 3);
1045*9354STim.Marsland@Sun.COM 					(void) write(STDOUT,
1046*9354STim.Marsland@Sun.COM 					    "unset noglob;\n", 14);
10470Sstevel@tonic-gate 				}
1048*9354STim.Marsland@Sun.COM 			} else
10490Sstevel@tonic-gate 				(void) write(STDOUT, "';\n", 3);
10500Sstevel@tonic-gate 		}
10510Sstevel@tonic-gate 	}
10520Sstevel@tonic-gate 
10530Sstevel@tonic-gate 	if (RepOnly)
10540Sstevel@tonic-gate 		exit(0);
10550Sstevel@tonic-gate 
10560Sstevel@tonic-gate 	/* tell about changing erase, kill and interrupt characters */
10570Sstevel@tonic-gate 	reportek("Erase", curerase, olderase, CERASE);
10580Sstevel@tonic-gate 	reportek("Kill", curkill, oldkill, CKILL);
10590Sstevel@tonic-gate 	reportek("Interrupt", curintr, oldintr, CINTR);
10600Sstevel@tonic-gate 
1061669Schin 	return (0);
10620Sstevel@tonic-gate }
10630Sstevel@tonic-gate 
10640Sstevel@tonic-gate /*
10650Sstevel@tonic-gate  * Set the hardware tabs on the terminal, using the ct (clear all tabs),
10660Sstevel@tonic-gate  * st (set one tab) and ch (horizontal cursor addressing) capabilities.
10670Sstevel@tonic-gate  * This is done before if and is, so they can patch in case we blow this.
10680Sstevel@tonic-gate  */
1069669Schin int
settabs(void)1070669Schin settabs(void)
10710Sstevel@tonic-gate {
10720Sstevel@tonic-gate 	char caps[100];
10730Sstevel@tonic-gate 	char *capsp = caps;
10740Sstevel@tonic-gate 	char *clear_tabs, *set_tab, *set_column, *set_pos;
10750Sstevel@tonic-gate 	char *tg_out, *tgoto();
10760Sstevel@tonic-gate 	int c;
10770Sstevel@tonic-gate 	extern char *tgetstr();
10780Sstevel@tonic-gate 	int lines, columns;
10790Sstevel@tonic-gate 
10800Sstevel@tonic-gate 	clear_tabs = tgetstr("ct", &capsp);
10810Sstevel@tonic-gate 	set_tab = tgetstr("st", &capsp);
10820Sstevel@tonic-gate 	set_column = tgetstr("ch", &capsp);
10830Sstevel@tonic-gate 	if (set_column == 0)
10840Sstevel@tonic-gate 		set_pos = tgetstr("cm", &capsp);
10850Sstevel@tonic-gate 
10860Sstevel@tonic-gate 	if (clear_tabs && set_tab) {
10870Sstevel@tonic-gate 		prc('\r');	/* force to be at left margin */
10880Sstevel@tonic-gate 		tputs(clear_tabs, 0, prc);
10890Sstevel@tonic-gate 	}
10900Sstevel@tonic-gate 	if (set_tab) {
10910Sstevel@tonic-gate 		columns = tgetnum("co");
10920Sstevel@tonic-gate 		lines = tgetnum("li");
1093*9354STim.Marsland@Sun.COM 		for (c = 0; c < columns; c += 8) {
10940Sstevel@tonic-gate 			/* get to that column. */
10950Sstevel@tonic-gate 			tg_out = "OOPS";	/* also returned by tgoto */
10960Sstevel@tonic-gate 			if (set_column)
10970Sstevel@tonic-gate 				tg_out = tgoto(set_column, 0, c);
10980Sstevel@tonic-gate 			if (*tg_out == 'O' && set_pos)
10990Sstevel@tonic-gate 				tg_out = tgoto(set_pos, c, lines-1);
11000Sstevel@tonic-gate 			if (*tg_out != 'O')
11010Sstevel@tonic-gate 				tputs(tg_out, 1, prc);
11020Sstevel@tonic-gate 			else if (c != 0) {
11030Sstevel@tonic-gate 				prc(' '); prc(' '); prc(' '); prc(' ');
11040Sstevel@tonic-gate 				prc(' '); prc(' '); prc(' '); prc(' ');
11050Sstevel@tonic-gate 			}
11060Sstevel@tonic-gate 			/* set the tab */
11070Sstevel@tonic-gate 			tputs(set_tab, 0, prc);
11080Sstevel@tonic-gate 		}
11090Sstevel@tonic-gate 		prc('\r');
1110669Schin 		return (1);
11110Sstevel@tonic-gate 	}
1112669Schin 	return (0);
11130Sstevel@tonic-gate }
11140Sstevel@tonic-gate 
1115*9354STim.Marsland@Sun.COM /*
1116*9354STim.Marsland@Sun.COM  * flag serves several purposes:
11170Sstevel@tonic-gate  *	if called as the result of a signal, flag will be > 0.
11180Sstevel@tonic-gate  *	if called from terminal init, flag == -1 means reset "oldmode".
11190Sstevel@tonic-gate  *	called with flag == 0 at end of normal mode processing.
11200Sstevel@tonic-gate  */
1121*9354STim.Marsland@Sun.COM void
setmode(int flag)1122*9354STim.Marsland@Sun.COM setmode(int flag)
11230Sstevel@tonic-gate {
11240Sstevel@tonic-gate 	struct termio *ttymode;
11250Sstevel@tonic-gate 	struct termios *ttymodes;
1126669Schin 	int i;
11270Sstevel@tonic-gate 
11280Sstevel@tonic-gate 	ttymode = (struct termio *)0;
11290Sstevel@tonic-gate 	ttymodes = (struct termios *)0;
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	if (flag < 0) { /* unconditionally reset oldmode (called from init) */
11320Sstevel@tonic-gate 		if (istermios < 0) {
1133*9354STim.Marsland@Sun.COM 			oldmode.c_lflag = oldmodes.c_lflag;
1134*9354STim.Marsland@Sun.COM 			oldmode.c_oflag = oldmodes.c_oflag;
1135*9354STim.Marsland@Sun.COM 			oldmode.c_iflag = oldmodes.c_iflag;
1136*9354STim.Marsland@Sun.COM 			oldmode.c_cflag = oldmodes.c_cflag;
1137*9354STim.Marsland@Sun.COM 			for (i = 0; i < NCC; i++)
1138*9354STim.Marsland@Sun.COM 				oldmode.c_cc[i] = oldmodes.c_cc[i];
1139*9354STim.Marsland@Sun.COM 			ttymode = &oldmode;
11400Sstevel@tonic-gate 		} else
1141*9354STim.Marsland@Sun.COM 			ttymodes = &oldmodes;
11420Sstevel@tonic-gate 	} else {
11430Sstevel@tonic-gate 		if (istermios < 0) {
1144*9354STim.Marsland@Sun.COM 			oldmode.c_lflag = oldmodes.c_lflag;
1145*9354STim.Marsland@Sun.COM 			oldmode.c_oflag = oldmodes.c_oflag;
1146*9354STim.Marsland@Sun.COM 			oldmode.c_iflag = oldmodes.c_iflag;
1147*9354STim.Marsland@Sun.COM 			oldmode.c_cflag = oldmodes.c_cflag;
1148*9354STim.Marsland@Sun.COM 			for (i = 0; i < NCC; i++)
1149*9354STim.Marsland@Sun.COM 				oldmode.c_cc[i] = oldmodes.c_cc[i];
1150*9354STim.Marsland@Sun.COM 			mode.c_lflag = modes.c_lflag;
1151*9354STim.Marsland@Sun.COM 			mode.c_oflag = modes.c_oflag;
1152*9354STim.Marsland@Sun.COM 			mode.c_iflag = modes.c_iflag;
1153*9354STim.Marsland@Sun.COM 			mode.c_cflag = modes.c_cflag;
1154*9354STim.Marsland@Sun.COM 			for (i = 0; i < NCC; i++)
1155*9354STim.Marsland@Sun.COM 				mode.c_cc[i] = modes.c_cc[i];
1156*9354STim.Marsland@Sun.COM 			if (!bequal((char *)&mode, (char *)&oldmode,
1157*9354STim.Marsland@Sun.COM 			    sizeof (mode)))
11580Sstevel@tonic-gate 				ttymode = &mode;
11590Sstevel@tonic-gate 		} else if (!bequal((char *)&modes, (char *)&oldmodes,
1160*9354STim.Marsland@Sun.COM 		    sizeof (modes)))
1161*9354STim.Marsland@Sun.COM 			ttymodes = &modes;
11620Sstevel@tonic-gate 	}
1163*9354STim.Marsland@Sun.COM 
1164*9354STim.Marsland@Sun.COM 	if (ttymode) {
11650Sstevel@tonic-gate 		(void) ioctl(FILEDES, TCSETAW, (char *)ttymode);
11660Sstevel@tonic-gate 	} else if (ttymodes) {
11670Sstevel@tonic-gate 		(void) ioctl(FILEDES, TCSETSW, (char *)ttymodes);
11680Sstevel@tonic-gate 	}
11690Sstevel@tonic-gate 	if (flag > 0)	/* trapped signal */
11700Sstevel@tonic-gate 		exit(1);
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate 
1173669Schin void
reportek(char * name,char new,char old,char def)1174669Schin reportek(char *name, char new, char old, char def)
11750Sstevel@tonic-gate {
1176669Schin 	char	o;
1177669Schin 	char	n;
1178669Schin 	char	*p;
11790Sstevel@tonic-gate 	char		buf[32];
11800Sstevel@tonic-gate 	char		*bufp;
11810Sstevel@tonic-gate 	extern char *tgetstr();
11820Sstevel@tonic-gate 
11830Sstevel@tonic-gate 	if (BeQuiet)
11840Sstevel@tonic-gate 		return;
11850Sstevel@tonic-gate 	o = old;
11860Sstevel@tonic-gate 	n = new;
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 	if (o == n && n == def)
11890Sstevel@tonic-gate 		return;
11900Sstevel@tonic-gate 	prs(name);
11910Sstevel@tonic-gate 	if (o == n)
11920Sstevel@tonic-gate 		prs(" is ");
11930Sstevel@tonic-gate 	else
11940Sstevel@tonic-gate 		prs(" set to ");
11950Sstevel@tonic-gate 	bufp = buf;
11960Sstevel@tonic-gate 	if (tgetstr("kb", &bufp) > (char *)0 && n == buf[0] && buf[1] == NULL)
11970Sstevel@tonic-gate 		prs("Backspace\n");
11980Sstevel@tonic-gate 	else if (n == 0177)
11990Sstevel@tonic-gate 		prs("Delete\n");
1200*9354STim.Marsland@Sun.COM 	else {
1201*9354STim.Marsland@Sun.COM 		if (n < 040) {
12020Sstevel@tonic-gate 			prs("Ctrl-");
12030Sstevel@tonic-gate 			n ^= 0100;
12040Sstevel@tonic-gate 		}
12050Sstevel@tonic-gate 		p = "x\n";
12060Sstevel@tonic-gate 		p[0] = n;
12070Sstevel@tonic-gate 		prs(p);
12080Sstevel@tonic-gate 	}
12090Sstevel@tonic-gate 	flush();
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate 
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 
1214669Schin void
setdelay(char * cap,struct delay dtab[],tcflag_t bits,tcflag_t * flags)1215669Schin setdelay(char *cap, struct delay dtab[], tcflag_t bits, tcflag_t *flags)
12160Sstevel@tonic-gate {
1217669Schin 	int		i;
1218669Schin 	struct delay	*p;
12190Sstevel@tonic-gate 	extern short	ospeed;
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 	/* see if this capability exists at all */
12220Sstevel@tonic-gate 	i = tgetnum(cap);
12230Sstevel@tonic-gate 	if (i < 0)
12240Sstevel@tonic-gate 		i = 0;
12250Sstevel@tonic-gate 	/* No padding at speeds below PadBaud */
12260Sstevel@tonic-gate 	if (PadBaud > ospeed)
12270Sstevel@tonic-gate 		i = 0;
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate 	/* clear out the bits, replace with new ones */
12300Sstevel@tonic-gate 	*flags &= ~bits;
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 	/* scan dtab for first entry with adequate delay */
1233*9354STim.Marsland@Sun.COM 	for (p = dtab; p->d_delay >= 0; p++) {
1234*9354STim.Marsland@Sun.COM 		if (p->d_delay >= i) {
12350Sstevel@tonic-gate 			p++;
12360Sstevel@tonic-gate 			break;
12370Sstevel@tonic-gate 		}
12380Sstevel@tonic-gate 	}
12390Sstevel@tonic-gate 
12400Sstevel@tonic-gate 	/* use last entry if none will do */
1241669Schin 	*flags |= (tcflag_t)((--p)->d_bits);
12420Sstevel@tonic-gate }
12430Sstevel@tonic-gate 
1244669Schin void
prs(char * s)1245669Schin prs(char *s)
12460Sstevel@tonic-gate {
12470Sstevel@tonic-gate 	while (*s != '\0')
12480Sstevel@tonic-gate 		prc(*s++);
12490Sstevel@tonic-gate }
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 
12520Sstevel@tonic-gate char	OutBuf[256];
12530Sstevel@tonic-gate int	OutPtr;
12540Sstevel@tonic-gate 
1255669Schin void
prc(char c)1256669Schin prc(char c)
12570Sstevel@tonic-gate {
12580Sstevel@tonic-gate 	OutBuf[OutPtr++] = c;
1259*9354STim.Marsland@Sun.COM 	if (OutPtr >= sizeof (OutBuf))
12600Sstevel@tonic-gate 		flush();
12610Sstevel@tonic-gate }
12620Sstevel@tonic-gate 
1263669Schin void
flush(void)1264669Schin flush(void)
12650Sstevel@tonic-gate {
12660Sstevel@tonic-gate 	if (OutPtr > 0)
12670Sstevel@tonic-gate 		(void) write(2, OutBuf, OutPtr);
12680Sstevel@tonic-gate 	OutPtr = 0;
12690Sstevel@tonic-gate }
12700Sstevel@tonic-gate 
1271669Schin void
cat(char * file)1272669Schin cat(char *file)
12730Sstevel@tonic-gate {
1274669Schin 	int	fd;
1275669Schin 	int	i;
12760Sstevel@tonic-gate 	char		buf[BUFSIZ];
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	fd = open(file, 0);
1279*9354STim.Marsland@Sun.COM 	if (fd < 0) {
12800Sstevel@tonic-gate 		prs("Cannot open ");
12810Sstevel@tonic-gate 		prs(file);
12820Sstevel@tonic-gate 		prs("\n");
12830Sstevel@tonic-gate 		flush();
12840Sstevel@tonic-gate 		return;
12850Sstevel@tonic-gate 	}
12860Sstevel@tonic-gate 
12870Sstevel@tonic-gate 	while ((i = read(fd, buf, BUFSIZ)) > 0)
12880Sstevel@tonic-gate 		(void) write(FILEDES, buf, i);
12890Sstevel@tonic-gate 
12900Sstevel@tonic-gate 	(void) close(fd);
12910Sstevel@tonic-gate }
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate 
1294669Schin void
bmove(char * from,char * to,int length)1295669Schin bmove(char *from, char *to, int length)
12960Sstevel@tonic-gate {
1297669Schin 	char	*p, *q;
1298669Schin 	int	i;
12990Sstevel@tonic-gate 
13000Sstevel@tonic-gate 	i = length;
13010Sstevel@tonic-gate 	p = from;
13020Sstevel@tonic-gate 	q = to;
13030Sstevel@tonic-gate 
13040Sstevel@tonic-gate 	while (i-- > 0)
13050Sstevel@tonic-gate 		*q++ = *p++;
13060Sstevel@tonic-gate }
13070Sstevel@tonic-gate 
13080Sstevel@tonic-gate 
1309669Schin int
bequal(char * a,char * b,int len)1310669Schin bequal(char *a, char *b, int len)	/* must be same thru len chars */
13110Sstevel@tonic-gate {
1312669Schin 	char	*p, *q;
1313669Schin 	int	i;
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 	i = len;
13160Sstevel@tonic-gate 	p = a;
13170Sstevel@tonic-gate 	q = b;
13180Sstevel@tonic-gate 
1319*9354STim.Marsland@Sun.COM 	while ((*p == *q) && --i > 0) {
13200Sstevel@tonic-gate 		p++; q++;
13210Sstevel@tonic-gate 	}
13220Sstevel@tonic-gate 	return ((*p == *q) && i >= 0);
13230Sstevel@tonic-gate }
13240Sstevel@tonic-gate 
1325669Schin int
sequal(char * a,char * b)1326669Schin sequal(char *a, char *b)	/* must be same thru NULL */
13270Sstevel@tonic-gate {
1328669Schin 	char *p = a, *q = b;
13290Sstevel@tonic-gate 
1330*9354STim.Marsland@Sun.COM 	while (*p && *q && (*p == *q)) {
13310Sstevel@tonic-gate 		p++; q++;
13320Sstevel@tonic-gate 	}
13330Sstevel@tonic-gate 	return (*p == *q);
13340Sstevel@tonic-gate }
13350Sstevel@tonic-gate 
1336669Schin void
makealias(char * buf)1337669Schin makealias(char *buf)
13380Sstevel@tonic-gate {
1339669Schin 	int i;
1340669Schin 	char *a;
1341669Schin 	char *b;
13420Sstevel@tonic-gate 
13430Sstevel@tonic-gate 	Alias[0] = a = Aliasbuf;
13440Sstevel@tonic-gate 	b = buf;
13450Sstevel@tonic-gate 	i = 1;
13460Sstevel@tonic-gate 	while (*b && *b != ':') {
13470Sstevel@tonic-gate 		if (*b == '|') {
13480Sstevel@tonic-gate 			*a++ = NULL;
13490Sstevel@tonic-gate 			Alias[i++] = a;
13500Sstevel@tonic-gate 			b++;
1351*9354STim.Marsland@Sun.COM 		} else
13520Sstevel@tonic-gate 			*a++ = *b++;
13530Sstevel@tonic-gate 	}
13540Sstevel@tonic-gate 	*a = NULL;
13550Sstevel@tonic-gate 	Alias[i] = NULL;
1356*9354STim.Marsland@Sun.COM #ifdef	DEB
1357*9354STim.Marsland@Sun.COM 	for (i = 0; Alias[i]; printf("A:%s\n", Alias[i++]))
1358*9354STim.Marsland@Sun.COM 		;
1359*9354STim.Marsland@Sun.COM #endif
13600Sstevel@tonic-gate }
13610Sstevel@tonic-gate 
1362669Schin int
isalias(char * ident)1363669Schin isalias(char *ident)	/* is ident same as one of the aliases? */
13640Sstevel@tonic-gate {
13650Sstevel@tonic-gate 	char **a = Alias;
13660Sstevel@tonic-gate 
13670Sstevel@tonic-gate 	if (*a)
13680Sstevel@tonic-gate 		while (*a)
13690Sstevel@tonic-gate 			if (sequal(ident, *a))
1370*9354STim.Marsland@Sun.COM 				return (YES);
13710Sstevel@tonic-gate 			else
13720Sstevel@tonic-gate 				a++;
1373*9354STim.Marsland@Sun.COM 	return (NO);
13740Sstevel@tonic-gate }
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 
13770Sstevel@tonic-gate /*
13780Sstevel@tonic-gate  * routine to output the string for the environment TERMCAP variable
13790Sstevel@tonic-gate  */
13800Sstevel@tonic-gate #define	WHITE(c)	(c == ' ' || c == '\t')
13810Sstevel@tonic-gate char delcap[128][2];
13820Sstevel@tonic-gate int ncap = 0;
13830Sstevel@tonic-gate 
1384669Schin void
wrtermcap(char * bp)1385669Schin wrtermcap(char *bp)
13860Sstevel@tonic-gate {
13870Sstevel@tonic-gate 	char buf[CAPBUFSIZ];
13880Sstevel@tonic-gate 	char *p = buf;
13890Sstevel@tonic-gate 	char *tp;
13900Sstevel@tonic-gate 	char *putbuf();
13910Sstevel@tonic-gate 	int space, empty;
13920Sstevel@tonic-gate 
13930Sstevel@tonic-gate 	/* discard names with blanks */
1394*9354STim.Marsland@Sun.COM /* May not be desireable ? */
13950Sstevel@tonic-gate 	while (*bp && *bp != ':') {
13960Sstevel@tonic-gate 		if (*bp == '|') {
13970Sstevel@tonic-gate 			tp = bp+1;
13980Sstevel@tonic-gate 			space = NO;
13990Sstevel@tonic-gate 			while (*tp && *tp != '|' && *tp != ':') {
1400*9354STim.Marsland@Sun.COM 				space = (space || WHITE(*tp));
14010Sstevel@tonic-gate 				tp++;
14020Sstevel@tonic-gate 			}
14030Sstevel@tonic-gate 			if (space) {
14040Sstevel@tonic-gate 				bp = tp;
14050Sstevel@tonic-gate 				continue;
14060Sstevel@tonic-gate 			}
14070Sstevel@tonic-gate 		}
14080Sstevel@tonic-gate 		*p++ = *bp++;
14090Sstevel@tonic-gate 	}
1410*9354STim.Marsland@Sun.COM /* */
14110Sstevel@tonic-gate 
14120Sstevel@tonic-gate 	while (*bp) {
14130Sstevel@tonic-gate 		switch (*bp) {
14140Sstevel@tonic-gate 		case ':':	/* discard empty, cancelled  or dupl fields */
1415*9354STim.Marsland@Sun.COM 			tp = bp + 1;
14160Sstevel@tonic-gate 			empty = YES;
14170Sstevel@tonic-gate 			while (*tp && *tp != ':') {
1418*9354STim.Marsland@Sun.COM 				empty = (empty && WHITE(*tp));
14190Sstevel@tonic-gate 				tp++;
14200Sstevel@tonic-gate 			}
14210Sstevel@tonic-gate 			if (empty || cancelled(bp+1)) {
14220Sstevel@tonic-gate 				bp = tp;
14230Sstevel@tonic-gate 				continue;
14240Sstevel@tonic-gate 			}
14250Sstevel@tonic-gate 			break;
14260Sstevel@tonic-gate 
14270Sstevel@tonic-gate 		case ' ':	/* no spaces in output */
14280Sstevel@tonic-gate 			p = putbuf(p, "\\040");
14290Sstevel@tonic-gate 			bp++;
14300Sstevel@tonic-gate 			continue;
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 		case '!':	/* the shell thinks this is history */
14330Sstevel@tonic-gate 			p = putbuf(p, "\\041");
14340Sstevel@tonic-gate 			bp++;
14350Sstevel@tonic-gate 			continue;
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 		case ',':	/* the shell thinks this is history */
14380Sstevel@tonic-gate 			p = putbuf(p, "\\054");
14390Sstevel@tonic-gate 			bp++;
14400Sstevel@tonic-gate 			continue;
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 		case '"':	/* no quotes in output */
14430Sstevel@tonic-gate 			p = putbuf(p, "\\042");
14440Sstevel@tonic-gate 			bp++;
14450Sstevel@tonic-gate 			continue;
14460Sstevel@tonic-gate 
14470Sstevel@tonic-gate 		case '\'':	/* no quotes in output */
14480Sstevel@tonic-gate 			p = putbuf(p, "\\047");
14490Sstevel@tonic-gate 			bp++;
14500Sstevel@tonic-gate 			continue;
14510Sstevel@tonic-gate 
14520Sstevel@tonic-gate 		case '`':	/* no back quotes in output */
14530Sstevel@tonic-gate 			p = putbuf(p, "\\140");
14540Sstevel@tonic-gate 			bp++;
14550Sstevel@tonic-gate 			continue;
14560Sstevel@tonic-gate 
14570Sstevel@tonic-gate 		case '\\':
14580Sstevel@tonic-gate 		case '^':	/* anything following is OK */
14590Sstevel@tonic-gate 			*p++ = *bp++;
14600Sstevel@tonic-gate 		}
14610Sstevel@tonic-gate 		*p++ = *bp++;
14620Sstevel@tonic-gate 	}
14630Sstevel@tonic-gate 	*p++ = ':';	/* we skipped the last : with the : lookahead hack */
1464*9354STim.Marsland@Sun.COM 	(void) write(STDOUT, buf, p-buf);
14650Sstevel@tonic-gate }
14660Sstevel@tonic-gate 
1467669Schin int
cancelled(char * cap)1468669Schin cancelled(char *cap)
14690Sstevel@tonic-gate {
1470669Schin 	int i;
14710Sstevel@tonic-gate 
1472*9354STim.Marsland@Sun.COM 	for (i = 0; i < ncap; i++) {
14730Sstevel@tonic-gate 		if (cap[0] == delcap[i][0] && cap[1] == delcap[i][1])
14740Sstevel@tonic-gate 			return (YES);
14750Sstevel@tonic-gate 	}
14760Sstevel@tonic-gate 	/* delete a second occurrance of the same capability */
14770Sstevel@tonic-gate 	delcap[ncap][0] = cap[0];
14780Sstevel@tonic-gate 	delcap[ncap][1] = cap[1];
14790Sstevel@tonic-gate 	ncap++;
14800Sstevel@tonic-gate 	return (cap[2] == '@');
14810Sstevel@tonic-gate }
14820Sstevel@tonic-gate 
14830Sstevel@tonic-gate char *
putbuf(ptr,str)14840Sstevel@tonic-gate putbuf(ptr, str)
14850Sstevel@tonic-gate char	*ptr;
14860Sstevel@tonic-gate char	*str;
14870Sstevel@tonic-gate {
14880Sstevel@tonic-gate 	char buf[20];
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	while (*str) {
14910Sstevel@tonic-gate 		switch (*str) {
14920Sstevel@tonic-gate 		case '\033':
14930Sstevel@tonic-gate 			ptr = putbuf(ptr, "\\E");
14940Sstevel@tonic-gate 			str++;
14950Sstevel@tonic-gate 			break;
14960Sstevel@tonic-gate 		default:
14970Sstevel@tonic-gate 			if (*str <= ' ') {
14980Sstevel@tonic-gate 				(void) sprintf(buf, "\\%03o", *str);
14990Sstevel@tonic-gate 				ptr = putbuf(ptr, buf);
15000Sstevel@tonic-gate 				str++;
15010Sstevel@tonic-gate 			} else
15020Sstevel@tonic-gate 				*ptr++ = *str++;
15030Sstevel@tonic-gate 		}
15040Sstevel@tonic-gate 	}
15050Sstevel@tonic-gate 	return (ptr);
15060Sstevel@tonic-gate }
15070Sstevel@tonic-gate 
1508669Schin int
baudrate(char * p)1509669Schin baudrate(char *p)
15100Sstevel@tonic-gate {
15110Sstevel@tonic-gate 	char buf[8];
15120Sstevel@tonic-gate 	int i = 0;
15130Sstevel@tonic-gate 
15140Sstevel@tonic-gate 	while (i < 7 && (isalnum(*p) || *p == '.'))
15150Sstevel@tonic-gate 		buf[i++] = *p++;
15160Sstevel@tonic-gate 	buf[i] = NULL;
1517*9354STim.Marsland@Sun.COM 	for (i = 0; speeds[i].string; i++)
15180Sstevel@tonic-gate 		if (sequal(speeds[i].string, buf))
15190Sstevel@tonic-gate 			return (speeds[i].speed);
15200Sstevel@tonic-gate 	return (-1);
15210Sstevel@tonic-gate }
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate char *
mapped(type)15240Sstevel@tonic-gate mapped(type)
15250Sstevel@tonic-gate char	*type;
15260Sstevel@tonic-gate {
15270Sstevel@tonic-gate 	extern short	ospeed;
15280Sstevel@tonic-gate 	int	match;
15290Sstevel@tonic-gate 
1530*9354STim.Marsland@Sun.COM #ifdef DEB
1531*9354STim.Marsland@Sun.COM 	printf("spd:%d\n", ospeed);
15320Sstevel@tonic-gate 	prmap();
1533*9354STim.Marsland@Sun.COM #endif
15340Sstevel@tonic-gate 	Map = map;
1535*9354STim.Marsland@Sun.COM 	while (Map->Ident) {
1536*9354STim.Marsland@Sun.COM 		if (*(Map->Ident) == NULL ||
1537*9354STim.Marsland@Sun.COM 		    sequal(Map->Ident, type) || isalias(Map->Ident)) {
15380Sstevel@tonic-gate 			match = NO;
1539*9354STim.Marsland@Sun.COM 			switch (Map->Test) {
1540*9354STim.Marsland@Sun.COM 			case ANY:	/* no test specified */
1541*9354STim.Marsland@Sun.COM 			case ALL:
1542*9354STim.Marsland@Sun.COM 				match = YES;
1543*9354STim.Marsland@Sun.COM 				break;
15440Sstevel@tonic-gate 
1545*9354STim.Marsland@Sun.COM 			case GT:
1546*9354STim.Marsland@Sun.COM 				match = (ospeed > Map->Speed);
1547*9354STim.Marsland@Sun.COM 				break;
1548*9354STim.Marsland@Sun.COM 
1549*9354STim.Marsland@Sun.COM 			case GE:
1550*9354STim.Marsland@Sun.COM 				match = (ospeed >= Map->Speed);
1551*9354STim.Marsland@Sun.COM 				break;
15520Sstevel@tonic-gate 
1553*9354STim.Marsland@Sun.COM 			case EQ:
1554*9354STim.Marsland@Sun.COM 				match = (ospeed == Map->Speed);
1555*9354STim.Marsland@Sun.COM 				break;
15560Sstevel@tonic-gate 
1557*9354STim.Marsland@Sun.COM 			case LE:
1558*9354STim.Marsland@Sun.COM 				match = (ospeed <= Map->Speed);
1559*9354STim.Marsland@Sun.COM 				break;
15600Sstevel@tonic-gate 
1561*9354STim.Marsland@Sun.COM 			case LT:
1562*9354STim.Marsland@Sun.COM 				match = (ospeed < Map->Speed);
1563*9354STim.Marsland@Sun.COM 				break;
15640Sstevel@tonic-gate 
1565*9354STim.Marsland@Sun.COM 			case NE:
1566*9354STim.Marsland@Sun.COM 				match = (ospeed != Map->Speed);
1567*9354STim.Marsland@Sun.COM 				break;
15680Sstevel@tonic-gate 			}
15690Sstevel@tonic-gate 			if (match)
15700Sstevel@tonic-gate 				return (Map->Type);
15710Sstevel@tonic-gate 		}
15720Sstevel@tonic-gate 		Map++;
15730Sstevel@tonic-gate 	}
15740Sstevel@tonic-gate 	/* no match found; return given type */
15750Sstevel@tonic-gate 	return (type);
15760Sstevel@tonic-gate }
15770Sstevel@tonic-gate 
1578*9354STim.Marsland@Sun.COM #ifdef DEB
prmap()15790Sstevel@tonic-gate prmap()
15800Sstevel@tonic-gate {
15810Sstevel@tonic-gate 	Map = map;
1582*9354STim.Marsland@Sun.COM 	while (Map->Ident) {
1583*9354STim.Marsland@Sun.COM 		printf("%s t:%d s:%d %s\n",
1584*9354STim.Marsland@Sun.COM 		    Map->Ident, Map->Test, Map->Speed, Map->Type);
1585*9354STim.Marsland@Sun.COM 		Map++;
15860Sstevel@tonic-gate 	}
15870Sstevel@tonic-gate }
1588*9354STim.Marsland@Sun.COM #endif
15890Sstevel@tonic-gate 
15900Sstevel@tonic-gate char *
nextarg(argc,argv)15910Sstevel@tonic-gate nextarg(argc, argv)
15920Sstevel@tonic-gate int	argc;
15930Sstevel@tonic-gate char	*argv[];
15940Sstevel@tonic-gate {
15950Sstevel@tonic-gate 	if (argc <= 0)
1596*9354STim.Marsland@Sun.COM 		fatal("Too few args: ", *argv);
15970Sstevel@tonic-gate 	if (*(*++argv) == '-')
1598*9354STim.Marsland@Sun.COM 		fatal("Unexpected arg: ", *argv);
15990Sstevel@tonic-gate 	return (*argv);
16000Sstevel@tonic-gate }
16010Sstevel@tonic-gate 
1602669Schin void
fatal(char * mesg,char * obj)1603*9354STim.Marsland@Sun.COM fatal(char *mesg, char *obj)
16040Sstevel@tonic-gate {
1605*9354STim.Marsland@Sun.COM 	prs(mesg);
1606*9354STim.Marsland@Sun.COM 	prs(obj);
1607*9354STim.Marsland@Sun.COM 	prc('\n');
1608*9354STim.Marsland@Sun.COM 	prs(USAGE);
16090Sstevel@tonic-gate 	flush();
16100Sstevel@tonic-gate 	exit(1);
16110Sstevel@tonic-gate }
16120Sstevel@tonic-gate 
16130Sstevel@tonic-gate 
16140Sstevel@tonic-gate /*
16150Sstevel@tonic-gate  * Stolen from /usr/src/ucb/reset.c, which this mod obsoletes.
16160Sstevel@tonic-gate  */
16170Sstevel@tonic-gate char
reset(ch,def)16180Sstevel@tonic-gate reset(ch, def)
16190Sstevel@tonic-gate 	char ch;
16200Sstevel@tonic-gate 	int def;
16210Sstevel@tonic-gate {
16220Sstevel@tonic-gate 	if (ch == 0 || (ch&0377) == 0377)
1623*9354STim.Marsland@Sun.COM 		return (def);
1624*9354STim.Marsland@Sun.COM 	return (ch);
16250Sstevel@tonic-gate }
1626