xref: /onnv-gate/usr/src/cmd/ttymon/sttyparse.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 1999-2002 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate /*
28*0Sstevel@tonic-gate  * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
29*0Sstevel@tonic-gate  * All Rights Reserved
30*0Sstevel@tonic-gate  *
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate 
33*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate #include <stdio.h>
36*0Sstevel@tonic-gate #include <unistd.h>
37*0Sstevel@tonic-gate #include <stdlib.h>
38*0Sstevel@tonic-gate #include <libintl.h>
39*0Sstevel@tonic-gate #include <sys/types.h>
40*0Sstevel@tonic-gate #include <ctype.h>
41*0Sstevel@tonic-gate #include <termio.h>
42*0Sstevel@tonic-gate #include <sys/stermio.h>
43*0Sstevel@tonic-gate #include <sys/termiox.h>
44*0Sstevel@tonic-gate #ifdef EUC
45*0Sstevel@tonic-gate #include <sys/param.h>
46*0Sstevel@tonic-gate #include <sys/stropts.h>
47*0Sstevel@tonic-gate #include <sys/eucioctl.h>
48*0Sstevel@tonic-gate #include <sys/csiioctl.h>
49*0Sstevel@tonic-gate #include <sys/stream.h>
50*0Sstevel@tonic-gate #include <sys/termios.h>
51*0Sstevel@tonic-gate #include <sys/ldterm.h>
52*0Sstevel@tonic-gate #include <getwidth.h>
53*0Sstevel@tonic-gate #endif /* EUC */
54*0Sstevel@tonic-gate #include "stty.h"
55*0Sstevel@tonic-gate #include <locale.h>
56*0Sstevel@tonic-gate #include <string.h>
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate static char	*s_arg;			/* s_arg: ptr to mode to be set */
59*0Sstevel@tonic-gate static int	match;
60*0Sstevel@tonic-gate #ifdef EUC
61*0Sstevel@tonic-gate static int parse_encoded(struct termios *, ldterm_cs_data_user_t *, int);
62*0Sstevel@tonic-gate #else
63*0Sstevel@tonic-gate static int parse_encoded(struct termios *);
64*0Sstevel@tonic-gate #endif /* EUC */
65*0Sstevel@tonic-gate static int eq(const char *string);
66*0Sstevel@tonic-gate static int gct(char *cp, int term);
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate /* set terminal modes for supplied options */
69*0Sstevel@tonic-gate char *
sttyparse(int argc,char * argv[],int term,struct termio * ocb,struct termios * cb,struct termiox * termiox,struct winsize * winsize,eucwidth_t * wp,struct eucioc * kwp,ldterm_cs_data_user_t * cswp,ldterm_cs_data_user_t * kcswp)70*0Sstevel@tonic-gate sttyparse(int argc, char *argv[], int term, struct termio *ocb,
71*0Sstevel@tonic-gate 	struct termios *cb, struct termiox *termiox, struct winsize *winsize
72*0Sstevel@tonic-gate #ifdef EUC
73*0Sstevel@tonic-gate 	/* */, eucwidth_t *wp, struct eucioc *kwp, ldterm_cs_data_user_t *cswp,
74*0Sstevel@tonic-gate 	ldterm_cs_data_user_t *kcswp
75*0Sstevel@tonic-gate #endif /* EUC */
76*0Sstevel@tonic-gate 	/* */)
77*0Sstevel@tonic-gate {
78*0Sstevel@tonic-gate 	int i;
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate 	while (--argc > 0) {
81*0Sstevel@tonic-gate 		s_arg = *++argv;
82*0Sstevel@tonic-gate 		match = 0;
83*0Sstevel@tonic-gate 		if (term & ASYNC) {
84*0Sstevel@tonic-gate 			if (eq("erase") && --argc)
85*0Sstevel@tonic-gate 				cb->c_cc[VERASE] = gct(*++argv, term);
86*0Sstevel@tonic-gate 			else if (eq("intr") && --argc)
87*0Sstevel@tonic-gate 				cb->c_cc[VINTR] = gct(*++argv, term);
88*0Sstevel@tonic-gate 			else if (eq("quit") && --argc)
89*0Sstevel@tonic-gate 				cb->c_cc[VQUIT] = gct(*++argv, term);
90*0Sstevel@tonic-gate 			else if (eq("eof") && --argc)
91*0Sstevel@tonic-gate 				cb->c_cc[VEOF] = gct(*++argv, term);
92*0Sstevel@tonic-gate 			else if (eq("min") && --argc) {
93*0Sstevel@tonic-gate 				if (isdigit((unsigned char)argv[1][0]))
94*0Sstevel@tonic-gate 					cb->c_cc[VMIN] = atoi(*++argv);
95*0Sstevel@tonic-gate 				else
96*0Sstevel@tonic-gate 					cb->c_cc[VMIN] = gct(*++argv, term);
97*0Sstevel@tonic-gate 			} else if (eq("eol") && --argc)
98*0Sstevel@tonic-gate 				cb->c_cc[VEOL] = gct(*++argv, term);
99*0Sstevel@tonic-gate 			else if (eq("eol2") && --argc)
100*0Sstevel@tonic-gate 				cb->c_cc[VEOL2] = gct(*++argv, term);
101*0Sstevel@tonic-gate 			else if (eq("time") && --argc) {
102*0Sstevel@tonic-gate 				if (isdigit((unsigned char)argv[1][0]))
103*0Sstevel@tonic-gate 					cb->c_cc[VTIME] = atoi(*++argv);
104*0Sstevel@tonic-gate 				else
105*0Sstevel@tonic-gate 					cb->c_cc[VTIME] = gct(*++argv, term);
106*0Sstevel@tonic-gate 			} else if (eq("kill") && --argc)
107*0Sstevel@tonic-gate 				cb->c_cc[VKILL] = gct(*++argv, term);
108*0Sstevel@tonic-gate 			else if (eq("swtch") && --argc)
109*0Sstevel@tonic-gate 				cb->c_cc[VSWTCH] = gct(*++argv, term);
110*0Sstevel@tonic-gate 			if (match)
111*0Sstevel@tonic-gate 				continue;
112*0Sstevel@tonic-gate 			if (term & TERMIOS) {
113*0Sstevel@tonic-gate 				if (eq("start") && --argc)
114*0Sstevel@tonic-gate 					cb->c_cc[VSTART] = gct(*++argv, term);
115*0Sstevel@tonic-gate 				else if (eq("stop") && --argc)
116*0Sstevel@tonic-gate 					cb->c_cc[VSTOP] = gct(*++argv, term);
117*0Sstevel@tonic-gate 				else if (eq("susp") && --argc)
118*0Sstevel@tonic-gate 					cb->c_cc[VSUSP] = gct(*++argv, term);
119*0Sstevel@tonic-gate 				else if (eq("dsusp") && --argc)
120*0Sstevel@tonic-gate 					cb->c_cc[VDSUSP] = gct(*++argv, term);
121*0Sstevel@tonic-gate 				else if (eq("rprnt") && --argc)
122*0Sstevel@tonic-gate 					cb->c_cc[VREPRINT] = gct(*++argv, term);
123*0Sstevel@tonic-gate 				else if (eq("reprint") && --argc)
124*0Sstevel@tonic-gate 					cb->c_cc[VREPRINT] = gct(*++argv, term);
125*0Sstevel@tonic-gate 				else if (eq("discard") && --argc)
126*0Sstevel@tonic-gate 					cb->c_cc[VDISCARD] = gct(*++argv, term);
127*0Sstevel@tonic-gate 				else if (eq("flush") && --argc)
128*0Sstevel@tonic-gate 					cb->c_cc[VDISCARD] = gct(*++argv, term);
129*0Sstevel@tonic-gate 				else if (eq("werase") && --argc)
130*0Sstevel@tonic-gate 					cb->c_cc[VWERASE] = gct(*++argv, term);
131*0Sstevel@tonic-gate 				else if (eq("lnext") && --argc)
132*0Sstevel@tonic-gate 					cb->c_cc[VLNEXT] = gct(*++argv, term);
133*0Sstevel@tonic-gate 			}
134*0Sstevel@tonic-gate 			if (match)
135*0Sstevel@tonic-gate 				continue;
136*0Sstevel@tonic-gate 			if (eq("ek")) {
137*0Sstevel@tonic-gate 				cb->c_cc[VERASE] = CERASE;
138*0Sstevel@tonic-gate 				cb->c_cc[VKILL] = CKILL;
139*0Sstevel@tonic-gate 			} else if (eq("line") &&
140*0Sstevel@tonic-gate 				    !(term & TERMIOS) && --argc) {
141*0Sstevel@tonic-gate 				ocb->c_line = atoi(*++argv);
142*0Sstevel@tonic-gate 				continue;
143*0Sstevel@tonic-gate 			} else if (eq("raw")) {
144*0Sstevel@tonic-gate 				cb->c_cc[VMIN] = 1;
145*0Sstevel@tonic-gate 				cb->c_cc[VTIME] = 0;
146*0Sstevel@tonic-gate 			} else if (eq("-raw") | eq("cooked")) {
147*0Sstevel@tonic-gate 				cb->c_cc[VEOF] = CEOF;
148*0Sstevel@tonic-gate 				cb->c_cc[VEOL] = CNUL;
149*0Sstevel@tonic-gate 			} else if (eq("sane")) {
150*0Sstevel@tonic-gate 				cb->c_cc[VERASE] = CERASE;
151*0Sstevel@tonic-gate 				cb->c_cc[VKILL] = CKILL;
152*0Sstevel@tonic-gate 				cb->c_cc[VQUIT] = CQUIT;
153*0Sstevel@tonic-gate 				cb->c_cc[VINTR] = CINTR;
154*0Sstevel@tonic-gate 				cb->c_cc[VEOF] = CEOF;
155*0Sstevel@tonic-gate 				cb->c_cc[VEOL] = CNUL;
156*0Sstevel@tonic-gate 				/* SWTCH purposely not set */
157*0Sstevel@tonic-gate #ifdef EUC
158*0Sstevel@tonic-gate 			} else if (eq("defeucw")) {
159*0Sstevel@tonic-gate 				kwp->eucw[0] = '\001';
160*0Sstevel@tonic-gate 				kwp->eucw[1] =
161*0Sstevel@tonic-gate 				    (unsigned char)(wp->_eucw1 & 0177);
162*0Sstevel@tonic-gate 				kwp->eucw[2] =
163*0Sstevel@tonic-gate 				    (unsigned char)(wp->_eucw2 & 0177);
164*0Sstevel@tonic-gate 				kwp->eucw[3] =
165*0Sstevel@tonic-gate 				    (unsigned char)(wp->_eucw3 & 0177);
166*0Sstevel@tonic-gate 
167*0Sstevel@tonic-gate 				kwp->scrw[0] = '\001';
168*0Sstevel@tonic-gate 				kwp->scrw[1] =
169*0Sstevel@tonic-gate 				    (unsigned char)(wp->_scrw1 & 0177);
170*0Sstevel@tonic-gate 				kwp->scrw[2] =
171*0Sstevel@tonic-gate 				    (unsigned char)(wp->_scrw2 & 0177);
172*0Sstevel@tonic-gate 				kwp->scrw[3] =
173*0Sstevel@tonic-gate 				    (unsigned char)(wp->_scrw3 & 0177);
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 				(void) memcpy((void *)kcswp, (const void *)cswp,
176*0Sstevel@tonic-gate 						sizeof (ldterm_cs_data_user_t));
177*0Sstevel@tonic-gate #endif /* EUC */
178*0Sstevel@tonic-gate 			} else if ((term & TERMIOS) && eq("ospeed") && --argc) {
179*0Sstevel@tonic-gate 				s_arg = *++argv;
180*0Sstevel@tonic-gate 				for (match = 0, i = 0; speeds[i].string; i++) {
181*0Sstevel@tonic-gate 					if (eq(speeds[i].string)) {
182*0Sstevel@tonic-gate 						(void) cfsetospeed(cb,
183*0Sstevel@tonic-gate 						    speeds[i].code);
184*0Sstevel@tonic-gate 						break;
185*0Sstevel@tonic-gate 					}
186*0Sstevel@tonic-gate 				}
187*0Sstevel@tonic-gate 				if (!match)
188*0Sstevel@tonic-gate 					return (s_arg);
189*0Sstevel@tonic-gate 				continue;
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 			} else if ((term & TERMIOS) && eq("ispeed") && --argc) {
192*0Sstevel@tonic-gate 				s_arg = *++argv;
193*0Sstevel@tonic-gate 				for (match = 0, i = 0; speeds[i].string; i++) {
194*0Sstevel@tonic-gate 					if (eq(speeds[i].string)) {
195*0Sstevel@tonic-gate 						(void) cfsetispeed(cb,
196*0Sstevel@tonic-gate 						    speeds[i].code);
197*0Sstevel@tonic-gate 						break;
198*0Sstevel@tonic-gate 					}
199*0Sstevel@tonic-gate 				}
200*0Sstevel@tonic-gate 				if (!match)
201*0Sstevel@tonic-gate 					return (s_arg);
202*0Sstevel@tonic-gate 				continue;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 			} else {
205*0Sstevel@tonic-gate 				for (match = 0, i = 0; speeds[i].string; i++) {
206*0Sstevel@tonic-gate 					if (eq(speeds[i].string)) {
207*0Sstevel@tonic-gate 						(void) cfsetospeed(cb,
208*0Sstevel@tonic-gate 						    speeds[i].code);
209*0Sstevel@tonic-gate 						(void) cfsetispeed(cb,
210*0Sstevel@tonic-gate 						    speeds[i].code);
211*0Sstevel@tonic-gate 						break;
212*0Sstevel@tonic-gate 					}
213*0Sstevel@tonic-gate 				}
214*0Sstevel@tonic-gate 			}
215*0Sstevel@tonic-gate 		}
216*0Sstevel@tonic-gate 		if (!(term & ASYNC) && eq("ctab") && --argc) {
217*0Sstevel@tonic-gate 			cb->c_cc[7] = gct(*++argv, term);
218*0Sstevel@tonic-gate 			continue;
219*0Sstevel@tonic-gate 		}
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 		for (i = 0; imodes[i].string; i++)
222*0Sstevel@tonic-gate 			if (eq(imodes[i].string)) {
223*0Sstevel@tonic-gate 				cb->c_iflag &= ~imodes[i].reset;
224*0Sstevel@tonic-gate 				cb->c_iflag |= imodes[i].set;
225*0Sstevel@tonic-gate #ifdef EUC
226*0Sstevel@tonic-gate 				if (wp->_multibyte &&
227*0Sstevel@tonic-gate 				(eq("-raw") || eq("cooked") || eq("sane")))
228*0Sstevel@tonic-gate 					cb->c_iflag &= ~ISTRIP;
229*0Sstevel@tonic-gate #endif /* EUC */
230*0Sstevel@tonic-gate 			}
231*0Sstevel@tonic-gate 		if (term & TERMIOS) {
232*0Sstevel@tonic-gate 			for (i = 0; nimodes[i].string; i++)
233*0Sstevel@tonic-gate 				if (eq(nimodes[i].string)) {
234*0Sstevel@tonic-gate 					cb->c_iflag &= ~nimodes[i].reset;
235*0Sstevel@tonic-gate 					cb->c_iflag |= nimodes[i].set;
236*0Sstevel@tonic-gate 				}
237*0Sstevel@tonic-gate 		}
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 		for (i = 0; omodes[i].string; i++)
240*0Sstevel@tonic-gate 			if (eq(omodes[i].string)) {
241*0Sstevel@tonic-gate 				cb->c_oflag &= ~omodes[i].reset;
242*0Sstevel@tonic-gate 				cb->c_oflag |= omodes[i].set;
243*0Sstevel@tonic-gate 			}
244*0Sstevel@tonic-gate 		if (!(term & ASYNC) && eq("sane")) {
245*0Sstevel@tonic-gate 			cb->c_oflag |= TAB3;
246*0Sstevel@tonic-gate 			continue;
247*0Sstevel@tonic-gate 		}
248*0Sstevel@tonic-gate 		for (i = 0; cmodes[i].string; i++)
249*0Sstevel@tonic-gate 			if (eq(cmodes[i].string)) {
250*0Sstevel@tonic-gate 				cb->c_cflag &= ~cmodes[i].reset;
251*0Sstevel@tonic-gate 				cb->c_cflag |= cmodes[i].set;
252*0Sstevel@tonic-gate #ifdef EUC
253*0Sstevel@tonic-gate 				if (wp->_multibyte &&
254*0Sstevel@tonic-gate 				(eq("-raw") || eq("cooked") || eq("sane"))) {
255*0Sstevel@tonic-gate 					cb->c_cflag &= ~(CS7|PARENB);
256*0Sstevel@tonic-gate 					cb->c_cflag |= CS8;
257*0Sstevel@tonic-gate 				}
258*0Sstevel@tonic-gate #endif /* EUC */
259*0Sstevel@tonic-gate 			}
260*0Sstevel@tonic-gate 		if (term & TERMIOS)
261*0Sstevel@tonic-gate 			for (i = 0; ncmodes[i].string; i++)
262*0Sstevel@tonic-gate 				if (eq(ncmodes[i].string)) {
263*0Sstevel@tonic-gate 					cb->c_cflag &= ~ncmodes[i].reset;
264*0Sstevel@tonic-gate 					cb->c_cflag |= ncmodes[i].set;
265*0Sstevel@tonic-gate 				}
266*0Sstevel@tonic-gate 		for (i = 0; lmodes[i].string; i++)
267*0Sstevel@tonic-gate 			if (eq(lmodes[i].string)) {
268*0Sstevel@tonic-gate 				cb->c_lflag &= ~lmodes[i].reset;
269*0Sstevel@tonic-gate 				cb->c_lflag |= lmodes[i].set;
270*0Sstevel@tonic-gate 			}
271*0Sstevel@tonic-gate 		if (term & TERMIOS)
272*0Sstevel@tonic-gate 			for (i = 0; nlmodes[i].string; i++)
273*0Sstevel@tonic-gate 				if (eq(nlmodes[i].string)) {
274*0Sstevel@tonic-gate 					cb->c_lflag &= ~nlmodes[i].reset;
275*0Sstevel@tonic-gate 					cb->c_lflag |= nlmodes[i].set;
276*0Sstevel@tonic-gate 				}
277*0Sstevel@tonic-gate 		if (term & FLOW) {
278*0Sstevel@tonic-gate 			for (i = 0; hmodes[i].string; i++)
279*0Sstevel@tonic-gate 				if (eq(hmodes[i].string)) {
280*0Sstevel@tonic-gate 					termiox->x_hflag &= ~hmodes[i].reset;
281*0Sstevel@tonic-gate 					termiox->x_hflag |= hmodes[i].set;
282*0Sstevel@tonic-gate 				}
283*0Sstevel@tonic-gate 			for (i = 0; clkmodes[i].string; i++)
284*0Sstevel@tonic-gate 				if (eq(clkmodes[i].string)) {
285*0Sstevel@tonic-gate 					termiox->x_cflag &= ~clkmodes[i].reset;
286*0Sstevel@tonic-gate 					termiox->x_cflag |= clkmodes[i].set;
287*0Sstevel@tonic-gate 				}
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 		}
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 		if (eq("rows") && --argc)
292*0Sstevel@tonic-gate 			winsize->ws_row = atoi(*++argv);
293*0Sstevel@tonic-gate 		else if ((eq("columns") || eq("cols")) && --argc)
294*0Sstevel@tonic-gate 			winsize->ws_col = atoi(*++argv);
295*0Sstevel@tonic-gate 		else if (eq("xpixels") && --argc)
296*0Sstevel@tonic-gate 			winsize->ws_xpixel = atoi(*++argv);
297*0Sstevel@tonic-gate 		else if (eq("ypixels") && --argc)
298*0Sstevel@tonic-gate 			winsize->ws_ypixel = atoi(*++argv);
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 		if (!match) {
301*0Sstevel@tonic-gate #ifdef EUC
302*0Sstevel@tonic-gate 			if (!parse_encoded(cb, kcswp, term)) {
303*0Sstevel@tonic-gate #else
304*0Sstevel@tonic-gate 			if (!parse_encoded(cb)) {
305*0Sstevel@tonic-gate #endif /* EUC */
306*0Sstevel@tonic-gate 				return (s_arg); /* parsing failed */
307*0Sstevel@tonic-gate 			}
308*0Sstevel@tonic-gate 		}
309*0Sstevel@tonic-gate 	}
310*0Sstevel@tonic-gate 	return ((char *)0);
311*0Sstevel@tonic-gate }
312*0Sstevel@tonic-gate 
313*0Sstevel@tonic-gate static int
314*0Sstevel@tonic-gate eq(const char *string)
315*0Sstevel@tonic-gate {
316*0Sstevel@tonic-gate 	int i;
317*0Sstevel@tonic-gate 
318*0Sstevel@tonic-gate 	if (!s_arg)
319*0Sstevel@tonic-gate 		return (0);
320*0Sstevel@tonic-gate 	i = 0;
321*0Sstevel@tonic-gate loop:
322*0Sstevel@tonic-gate 	if (s_arg[i] != string[i])
323*0Sstevel@tonic-gate 		return (0);
324*0Sstevel@tonic-gate 	if (s_arg[i++] != '\0')
325*0Sstevel@tonic-gate 		goto loop;
326*0Sstevel@tonic-gate 	match++;
327*0Sstevel@tonic-gate 	return (1);
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate /* get pseudo control characters from terminal  */
331*0Sstevel@tonic-gate /* and convert to internal representation	*/
332*0Sstevel@tonic-gate static int
333*0Sstevel@tonic-gate gct(char *cp, int term)
334*0Sstevel@tonic-gate {
335*0Sstevel@tonic-gate 	int c;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	c = *cp;
338*0Sstevel@tonic-gate 	if (c == '^') {
339*0Sstevel@tonic-gate 		c = *++cp;
340*0Sstevel@tonic-gate 		if (c == '?')
341*0Sstevel@tonic-gate 			c = 0177;		/* map '^?' to 0177 */
342*0Sstevel@tonic-gate 		else if (c == '-') {
343*0Sstevel@tonic-gate 			/* map '^-' to undefined */
344*0Sstevel@tonic-gate 			c = (term & TERMIOS) ? _POSIX_VDISABLE : 0200;
345*0Sstevel@tonic-gate 		} else
346*0Sstevel@tonic-gate 			c &= 037;
347*0Sstevel@tonic-gate 	} else if (strcmp(cp, "undef") == 0) {
348*0Sstevel@tonic-gate 		/* map "undef" to undefined */
349*0Sstevel@tonic-gate 		c = (term & TERMIOS) ? _POSIX_VDISABLE : 0200;
350*0Sstevel@tonic-gate 	}
351*0Sstevel@tonic-gate 	return (c);
352*0Sstevel@tonic-gate }
353*0Sstevel@tonic-gate 
354*0Sstevel@tonic-gate /* get modes of tty device and fill in applicable structures */
355*0Sstevel@tonic-gate int
356*0Sstevel@tonic-gate get_ttymode(int fd, struct termio *termio, struct termios *termios,
357*0Sstevel@tonic-gate 	struct stio *stermio, struct termiox *termiox, struct winsize *winsize
358*0Sstevel@tonic-gate #ifdef EUC
359*0Sstevel@tonic-gate 	/* */, struct eucioc *kwp, ldterm_cs_data_user_t *kcswp
360*0Sstevel@tonic-gate #endif /* EUC */
361*0Sstevel@tonic-gate 	/* */)
362*0Sstevel@tonic-gate {
363*0Sstevel@tonic-gate 	int i;
364*0Sstevel@tonic-gate 	int term = 0;
365*0Sstevel@tonic-gate #ifdef EUC
366*0Sstevel@tonic-gate 	struct strioctl cmd;
367*0Sstevel@tonic-gate #endif /* EUC */
368*0Sstevel@tonic-gate 	if (ioctl(fd, STGET, stermio) == -1) {
369*0Sstevel@tonic-gate 		term |= ASYNC;
370*0Sstevel@tonic-gate 		if (ioctl(fd, TCGETS, termios) == -1) {
371*0Sstevel@tonic-gate 			if (ioctl(fd, TCGETA, termio) == -1)
372*0Sstevel@tonic-gate 				return (-1);
373*0Sstevel@tonic-gate 			termios->c_lflag = termio->c_lflag;
374*0Sstevel@tonic-gate 			termios->c_oflag = termio->c_oflag;
375*0Sstevel@tonic-gate 			termios->c_iflag = termio->c_iflag;
376*0Sstevel@tonic-gate 			termios->c_cflag = termio->c_cflag;
377*0Sstevel@tonic-gate 			for (i = 0; i < NCC; i++)
378*0Sstevel@tonic-gate 				termios->c_cc[i] = termio->c_cc[i];
379*0Sstevel@tonic-gate 		} else
380*0Sstevel@tonic-gate 			term |= TERMIOS;
381*0Sstevel@tonic-gate 	} else {
382*0Sstevel@tonic-gate 		termios->c_cc[7] = (unsigned)stermio->tab;
383*0Sstevel@tonic-gate 		termios->c_lflag = stermio->lmode;
384*0Sstevel@tonic-gate 		termios->c_oflag = stermio->omode;
385*0Sstevel@tonic-gate 		termios->c_iflag = stermio->imode;
386*0Sstevel@tonic-gate 	}
387*0Sstevel@tonic-gate 
388*0Sstevel@tonic-gate 	if (ioctl(fd, TCGETX, termiox) == 0)
389*0Sstevel@tonic-gate 		term |= FLOW;
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 	if (ioctl(fd, TIOCGWINSZ, winsize) == 0)
392*0Sstevel@tonic-gate 		term |= WINDOW;
393*0Sstevel@tonic-gate #ifdef EUC
394*0Sstevel@tonic-gate 	cmd.ic_cmd = EUC_WGET;
395*0Sstevel@tonic-gate 	cmd.ic_timout = 0;
396*0Sstevel@tonic-gate 	cmd.ic_len = sizeof (struct eucioc);
397*0Sstevel@tonic-gate 	cmd.ic_dp = (char *)kwp;
398*0Sstevel@tonic-gate 
399*0Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &cmd) == 0)
400*0Sstevel@tonic-gate 		term |= EUCW;
401*0Sstevel@tonic-gate 
402*0Sstevel@tonic-gate 	cmd.ic_cmd = CSDATA_GET;
403*0Sstevel@tonic-gate 	cmd.ic_timout = 0;
404*0Sstevel@tonic-gate 	cmd.ic_len = sizeof (ldterm_cs_data_user_t);
405*0Sstevel@tonic-gate 	cmd.ic_dp = (char *)kcswp;
406*0Sstevel@tonic-gate 
407*0Sstevel@tonic-gate 	if (ioctl(fd, I_STR, &cmd) == 0)
408*0Sstevel@tonic-gate 		term |= CSIW;
409*0Sstevel@tonic-gate 	else
410*0Sstevel@tonic-gate 		(void) memset((void *)kcswp, 0, sizeof (ldterm_cs_data_user_t));
411*0Sstevel@tonic-gate #endif /* EUC */
412*0Sstevel@tonic-gate 	return (term);
413*0Sstevel@tonic-gate }
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate /* set tty modes */
416*0Sstevel@tonic-gate int
417*0Sstevel@tonic-gate set_ttymode(int fd, int term, struct termio *termio, struct termios *termios,
418*0Sstevel@tonic-gate 	struct stio *stermio, struct termiox *termiox, struct winsize *winsize,
419*0Sstevel@tonic-gate 	struct winsize *owinsize
420*0Sstevel@tonic-gate #ifdef EUC
421*0Sstevel@tonic-gate 	/* */, struct eucioc *kwp, ldterm_cs_data_user_t *kcswp,
422*0Sstevel@tonic-gate 	int invalid_ldterm_dat_file
423*0Sstevel@tonic-gate #endif /* EUC */
424*0Sstevel@tonic-gate 	/* */)
425*0Sstevel@tonic-gate {
426*0Sstevel@tonic-gate 	int i;
427*0Sstevel@tonic-gate #ifdef EUC
428*0Sstevel@tonic-gate 	struct strioctl cmd;
429*0Sstevel@tonic-gate #endif /* EUC */
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate 	if (term & ASYNC) {
432*0Sstevel@tonic-gate 		if (term & TERMIOS) {
433*0Sstevel@tonic-gate 			if (ioctl(fd, TCSETSW, termios) == -1)
434*0Sstevel@tonic-gate 				return (-1);
435*0Sstevel@tonic-gate 		} else {
436*0Sstevel@tonic-gate 			termio->c_lflag = termios->c_lflag;
437*0Sstevel@tonic-gate 			termio->c_oflag = termios->c_oflag;
438*0Sstevel@tonic-gate 			termio->c_iflag = termios->c_iflag;
439*0Sstevel@tonic-gate 			termio->c_cflag = termios->c_cflag;
440*0Sstevel@tonic-gate 			for (i = 0; i < NCC; i++)
441*0Sstevel@tonic-gate 				termio->c_cc[i] = termios->c_cc[i];
442*0Sstevel@tonic-gate 			if (ioctl(fd, TCSETAW, termio) == -1)
443*0Sstevel@tonic-gate 				return (-1);
444*0Sstevel@tonic-gate 		}
445*0Sstevel@tonic-gate 
446*0Sstevel@tonic-gate 	} else {
447*0Sstevel@tonic-gate 		stermio->imode = termios->c_iflag;
448*0Sstevel@tonic-gate 		stermio->omode = termios->c_oflag;
449*0Sstevel@tonic-gate 		stermio->lmode = termios->c_lflag;
450*0Sstevel@tonic-gate 		stermio->tab = termios->c_cc[7];
451*0Sstevel@tonic-gate 		if (ioctl(fd, STSET, stermio) == -1)
452*0Sstevel@tonic-gate 			return (-1);
453*0Sstevel@tonic-gate 	}
454*0Sstevel@tonic-gate 	if (term & FLOW) {
455*0Sstevel@tonic-gate 		if (ioctl(fd, TCSETXW, termiox) == -1)
456*0Sstevel@tonic-gate 			return (-1);
457*0Sstevel@tonic-gate 	}
458*0Sstevel@tonic-gate 	if ((owinsize->ws_col != winsize->ws_col ||
459*0Sstevel@tonic-gate 	    owinsize->ws_row != winsize->ws_row ||
460*0Sstevel@tonic-gate 	    owinsize->ws_xpixel != winsize->ws_xpixel ||
461*0Sstevel@tonic-gate 	    owinsize->ws_ypixel != winsize->ws_ypixel) &&
462*0Sstevel@tonic-gate 	    ioctl(0, TIOCSWINSZ, winsize) != 0)
463*0Sstevel@tonic-gate 		return (-1);
464*0Sstevel@tonic-gate #ifdef EUC
465*0Sstevel@tonic-gate 	/*
466*0Sstevel@tonic-gate 	 * If the ldterm.dat file contains valid, non-EUC codeset info,
467*0Sstevel@tonic-gate 	 * send downstream CSDATA_SET. Otherwise, try EUC_WSET.
468*0Sstevel@tonic-gate 	 */
469*0Sstevel@tonic-gate 	if (invalid_ldterm_dat_file) {
470*0Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
471*0Sstevel@tonic-gate 		"stty: can't set codeset width due to invalid ldterm.dat.\n"));
472*0Sstevel@tonic-gate 		return (-1);
473*0Sstevel@tonic-gate 	} else if ((term & CSIW) && kcswp->version) {
474*0Sstevel@tonic-gate 		cmd.ic_cmd = CSDATA_SET;
475*0Sstevel@tonic-gate 		cmd.ic_timout = 0;
476*0Sstevel@tonic-gate 		cmd.ic_len = sizeof (ldterm_cs_data_user_t);
477*0Sstevel@tonic-gate 		cmd.ic_dp = (char *)kcswp;
478*0Sstevel@tonic-gate 		if (ioctl(fd, I_STR, &cmd) != 0) {
479*0Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
480*0Sstevel@tonic-gate 				"stty: can't set codeset width.\n"));
481*0Sstevel@tonic-gate 			return (-1);
482*0Sstevel@tonic-gate 		}
483*0Sstevel@tonic-gate 	} else if (term & EUCW) {
484*0Sstevel@tonic-gate 		cmd.ic_cmd = EUC_WSET;
485*0Sstevel@tonic-gate 		cmd.ic_timout = 0;
486*0Sstevel@tonic-gate 		cmd.ic_len = sizeof (struct eucioc);
487*0Sstevel@tonic-gate 		cmd.ic_dp = (char *)kwp;
488*0Sstevel@tonic-gate 		if (ioctl(fd, I_STR, &cmd) != 0) {
489*0Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
490*0Sstevel@tonic-gate 				"stty: can't set EUC codeset width.\n"));
491*0Sstevel@tonic-gate 			return (-1);
492*0Sstevel@tonic-gate 		}
493*0Sstevel@tonic-gate 	}
494*0Sstevel@tonic-gate #endif /* EUC */
495*0Sstevel@tonic-gate 	return (0);
496*0Sstevel@tonic-gate }
497*0Sstevel@tonic-gate 
498*0Sstevel@tonic-gate static int
499*0Sstevel@tonic-gate parse_encoded(struct termios *cb
500*0Sstevel@tonic-gate #ifdef EUC
501*0Sstevel@tonic-gate 	/* */, ldterm_cs_data_user_t *kcswp, int term
502*0Sstevel@tonic-gate #endif /* EUC */
503*0Sstevel@tonic-gate 	/* */)
504*0Sstevel@tonic-gate {
505*0Sstevel@tonic-gate 	unsigned long grab[NUM_FIELDS];
506*0Sstevel@tonic-gate 	int last, i;
507*0Sstevel@tonic-gate #ifdef EUC
508*0Sstevel@tonic-gate 	long l;
509*0Sstevel@tonic-gate 	char s[3];
510*0Sstevel@tonic-gate 	char *t;
511*0Sstevel@tonic-gate 	char *r;
512*0Sstevel@tonic-gate 	uchar_t *g;
513*0Sstevel@tonic-gate 	ldterm_cs_data_user_t ecswp;
514*0Sstevel@tonic-gate #endif /* EUC */
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate 	/*
517*0Sstevel@tonic-gate 	 * Although there are only 16 control chars defined as of April 1995,
518*0Sstevel@tonic-gate 	 * parse_encoded() and prencode()  will not have to be changed if up to
519*0Sstevel@tonic-gate 	 * MAX_CC control chars are defined in the future.
520*0Sstevel@tonic-gate 	 * Scan the fields of "stty -g" output into the grab array.
521*0Sstevel@tonic-gate 	 * Set a total of NUM_FIELDS fields (NUM_MODES modes + MAX_CC
522*0Sstevel@tonic-gate 	 * control chars).
523*0Sstevel@tonic-gate 	 */
524*0Sstevel@tonic-gate 	i = sscanf(s_arg, "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:"
525*0Sstevel@tonic-gate 	    "%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
526*0Sstevel@tonic-gate 	    &grab[0], &grab[1], &grab[2], &grab[3], &grab[4], &grab[5],
527*0Sstevel@tonic-gate 	    &grab[6], &grab[7], &grab[8], &grab[9], &grab[10], &grab[11],
528*0Sstevel@tonic-gate 	    &grab[12], &grab[13], &grab[14], &grab[15],	&grab[16], &grab[17],
529*0Sstevel@tonic-gate 	    &grab[18], &grab[19], &grab[20], &grab[21]);
530*0Sstevel@tonic-gate 
531*0Sstevel@tonic-gate 	if (i < 12)
532*0Sstevel@tonic-gate 		return (0);
533*0Sstevel@tonic-gate 	cb->c_iflag = grab[0];
534*0Sstevel@tonic-gate 	cb->c_oflag = grab[1];
535*0Sstevel@tonic-gate 	cb->c_cflag = grab[2];
536*0Sstevel@tonic-gate 	cb->c_lflag = grab[3];
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 	last = i - NUM_MODES;
539*0Sstevel@tonic-gate 	for (i = 0; i < last; i++)
540*0Sstevel@tonic-gate 		cb->c_cc[i] = (unsigned char) grab[i+NUM_MODES];
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate #ifdef EUC
543*0Sstevel@tonic-gate 	/* This is to fulfill PSARC/1999/140 TCR2. */
544*0Sstevel@tonic-gate 	if (term & CSIW) {
545*0Sstevel@tonic-gate 		r = strdup(s_arg);
546*0Sstevel@tonic-gate 		if (r == (char *)NULL) {
547*0Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
548*0Sstevel@tonic-gate 				"no more memory - try again later\n"));
549*0Sstevel@tonic-gate 			return (0);
550*0Sstevel@tonic-gate 		}
551*0Sstevel@tonic-gate 		t = strtok(r, ":");
552*0Sstevel@tonic-gate 		for (i = 0; t != NULL && i < 22; i++) {
553*0Sstevel@tonic-gate 			t = strtok(NULL, ":");
554*0Sstevel@tonic-gate 		}
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 		if (t == NULL) {
557*0Sstevel@tonic-gate 			free((void *)r);
558*0Sstevel@tonic-gate 			return (0);
559*0Sstevel@tonic-gate 		}
560*0Sstevel@tonic-gate 		ecswp.version = (uchar_t)strtol(t, (char **)NULL, 16);
561*0Sstevel@tonic-gate 		if (ecswp.version > LDTERM_DATA_VERSION ||
562*0Sstevel@tonic-gate 		    ecswp.version == 0) {
563*0Sstevel@tonic-gate 			free((void *)r);
564*0Sstevel@tonic-gate 			return (0);
565*0Sstevel@tonic-gate 		}
566*0Sstevel@tonic-gate 
567*0Sstevel@tonic-gate 		if ((t = strtok(NULL, ":")) == NULL) {
568*0Sstevel@tonic-gate 			free((void *)r);
569*0Sstevel@tonic-gate 			return (0);
570*0Sstevel@tonic-gate 		}
571*0Sstevel@tonic-gate 		ecswp.codeset_type = (uchar_t)strtol(t, (char **)NULL, 16);
572*0Sstevel@tonic-gate 		if (ecswp.codeset_type < LDTERM_CS_TYPE_MIN ||
573*0Sstevel@tonic-gate 		    ecswp.codeset_type > LDTERM_CS_TYPE_MAX) {
574*0Sstevel@tonic-gate 			free((void *)r);
575*0Sstevel@tonic-gate 			return (0);
576*0Sstevel@tonic-gate 		}
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate 		if ((t = strtok(NULL, ":")) == NULL) {
579*0Sstevel@tonic-gate 			free((void *)r);
580*0Sstevel@tonic-gate 			return (0);
581*0Sstevel@tonic-gate 		}
582*0Sstevel@tonic-gate 		ecswp.csinfo_num = (uchar_t)strtol(t, (char **)NULL, 16);
583*0Sstevel@tonic-gate 		if ((ecswp.codeset_type == LDTERM_CS_TYPE_EUC &&
584*0Sstevel@tonic-gate 		    ecswp.csinfo_num > 3) ||
585*0Sstevel@tonic-gate 		    (ecswp.codeset_type == LDTERM_CS_TYPE_PCCS &&
586*0Sstevel@tonic-gate 		    (ecswp.csinfo_num < 1 || ecswp.csinfo_num > 10))) {
587*0Sstevel@tonic-gate 			free((void *)r);
588*0Sstevel@tonic-gate 			return (0);
589*0Sstevel@tonic-gate 		}
590*0Sstevel@tonic-gate 
591*0Sstevel@tonic-gate 		if ((t = strtok(NULL, ":")) == NULL) {
592*0Sstevel@tonic-gate 			free((void *)r);
593*0Sstevel@tonic-gate 			return (0);
594*0Sstevel@tonic-gate 		}
595*0Sstevel@tonic-gate 		s[2] = '\0';
596*0Sstevel@tonic-gate 		for (i = 0; *t != 0 && i < MAXNAMELEN; i++) {
597*0Sstevel@tonic-gate 			if (*(t + 1) == (char)NULL) {
598*0Sstevel@tonic-gate 				free((void *)r);
599*0Sstevel@tonic-gate 				return (0);
600*0Sstevel@tonic-gate 			}
601*0Sstevel@tonic-gate 			s[0] = *t++;
602*0Sstevel@tonic-gate 			s[1] = *t++;
603*0Sstevel@tonic-gate 			ecswp.locale_name[i] = (char)strtol(s, (char **)NULL,
604*0Sstevel@tonic-gate 								16);
605*0Sstevel@tonic-gate 		}
606*0Sstevel@tonic-gate 		if (i >= MAXNAMELEN) {
607*0Sstevel@tonic-gate 			free((void *)r);
608*0Sstevel@tonic-gate 			return (0);
609*0Sstevel@tonic-gate 		}
610*0Sstevel@tonic-gate 		ecswp.locale_name[i] = '\0';
611*0Sstevel@tonic-gate 
612*0Sstevel@tonic-gate 		g = (uchar_t *)ecswp.eucpc_data;
613*0Sstevel@tonic-gate 		for (i = 0; i < (LDTERM_CS_MAX_CODESETS * 4); i++) {
614*0Sstevel@tonic-gate 			if ((t = strtok(NULL, ":")) == NULL) {
615*0Sstevel@tonic-gate 				free((void *)r);
616*0Sstevel@tonic-gate 				return (0);
617*0Sstevel@tonic-gate 			}
618*0Sstevel@tonic-gate 			l = strtol(t, (char **)NULL, 16);
619*0Sstevel@tonic-gate 			if (l < 0 || l > 255) {
620*0Sstevel@tonic-gate 				free((void *)r);
621*0Sstevel@tonic-gate 				return (0);
622*0Sstevel@tonic-gate 			}
623*0Sstevel@tonic-gate 			*g++ = (uchar_t)l;
624*0Sstevel@tonic-gate 		}
625*0Sstevel@tonic-gate 
626*0Sstevel@tonic-gate 		/* We got the 'ecswp' all filled up now; let's copy. */
627*0Sstevel@tonic-gate 		(void) memcpy((void *)kcswp, (const void *)&ecswp,
628*0Sstevel@tonic-gate 				sizeof (ldterm_cs_data_user_t));
629*0Sstevel@tonic-gate 	}
630*0Sstevel@tonic-gate #endif /* EUC */
631*0Sstevel@tonic-gate 
632*0Sstevel@tonic-gate 	return (1);
633*0Sstevel@tonic-gate }
634