xref: /titanic_44/usr/src/ucbcmd/stty/sttyparse.c (revision b7f45089ccbe01bab3d7c7377b49d80d2ae18a69)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 1997 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <termio.h>
37 #include <sys/stermio.h>
38 #include <sys/termiox.h>
39 #include "stty.h"
40 
41 static char	*s_arg;			/* s_arg: ptr to mode to be set */
42 static int	match;
43 static int gct(), eq(), encode();
44 
45 /* set terminal modes for supplied options */
46 char *
47 sttyparse(argc, argv, term, ocb, cb, termiox, winsize)
48 int	argc;
49 char	*argv[];
50 int	term; /* type of tty device, -1 means allow all options,
51 	       * no sanity check
52 	       */
53 struct	termio	*ocb;
54 struct	termios	*cb;
55 struct	termiox	*termiox;
56 struct	winsize	*winsize;
57 {
58 	register i;
59 	extern	const struct	speeds	speeds[];
60 	extern	const struct	mds	lmodes[];
61 	extern	const struct	mds	nlmodes[];
62 	extern	const struct	mds	cmodes[];
63 	extern	const struct	mds	ncmodes[];
64 	extern	const struct	mds	imodes[];
65 	extern	const struct	mds	nimodes[];
66 	extern	const struct	mds	omodes[];
67 	extern	const struct	mds	hmodes[];
68 	extern	const struct	mds	clkmodes[];
69 
70 	while(--argc > 0) {
71 
72 		s_arg = *++argv;
73 		match = 0;
74 		if ((term & ASYNC) || term == -1) {
75 			if (eqarg("erase", argc) && --argc)
76 				cb->c_cc[VERASE] = gct(*++argv, term);
77 			else if (eqarg("intr", argc) && --argc)
78 				cb->c_cc[VINTR] = gct(*++argv, term);
79 			else if (eqarg("quit", argc) && --argc)
80 				cb->c_cc[VQUIT] = gct(*++argv, term);
81 			else if (eqarg("eof", argc) && --argc)
82 				cb->c_cc[VEOF] = gct(*++argv, term);
83 			else if (eqarg("min", argc) && --argc)
84 				cb->c_cc[VMIN] = atoi(*++argv);
85 			else if (eqarg("eol", argc) && --argc)
86 				cb->c_cc[VEOL] = gct(*++argv, term);
87 			else if (eqarg("brk", argc) && --argc)
88 				cb->c_cc[VEOL] = gct(*++argv, term);
89 			else if (eqarg("eol2", argc) && --argc)
90 				cb->c_cc[VEOL2] = gct(*++argv, term);
91 			else if (eqarg("time", argc) && --argc)
92 				cb->c_cc[VTIME] = atoi(*++argv);
93 			else if (eqarg("kill", argc) && --argc)
94 				cb->c_cc[VKILL] = gct(*++argv, term);
95 			else if (eqarg("swtch", argc) && --argc)
96 				cb->c_cc[VSWTCH] = gct(*++argv, term);
97 			if(match)
98 				continue;
99 			if((term & TERMIOS) || term == -1) {
100 				if (eqarg("start", argc) && --argc)
101 					cb->c_cc[VSTART] = gct(*++argv, term);
102 				else if (eqarg("stop", argc) && --argc)
103 					cb->c_cc[VSTOP] = gct(*++argv, term);
104 				else if (eqarg("susp", argc) && --argc)
105 					cb->c_cc[VSUSP] = gct(*++argv, term);
106 				else if (eqarg("dsusp", argc) && --argc)
107 					cb->c_cc[VDSUSP] = gct(*++argv, term);
108 				else if (eqarg("rprnt", argc) && --argc)
109 					cb->c_cc[VREPRINT] = gct(*++argv, term);
110 				else if (eqarg("flush", argc) && --argc)
111 					cb->c_cc[VDISCARD] = gct(*++argv, term);
112 				else if (eqarg("werase", argc) && --argc)
113 					cb->c_cc[VWERASE] = gct(*++argv, term);
114 				else if (eqarg("lnext", argc) && --argc)
115 					cb->c_cc[VLNEXT] = gct(*++argv, term);
116 			}
117 			if(match)
118 				continue;
119 			if (eq("ek")) {
120 				cb->c_cc[VERASE] = CERASE;
121 				cb->c_cc[VKILL] = CKILL;
122 			}
123 			else if (eq("crt") || eq("newcrt")) {
124 				cb->c_lflag &= ~ECHOPRT;
125 				cb->c_lflag |= ECHOE|ECHOCTL;
126 				if (cfgetospeed(cb) >= B1200)
127 					cb->c_lflag |= ECHOKE;
128 			}
129 			else if (eq("dec")) {
130 				cb->c_cc[VERASE] = 0177;
131 				cb->c_cc[VKILL] = CTRL('u');
132 				cb->c_cc[VINTR] = CTRL('c');
133 				cb->c_lflag &= ~ECHOPRT;
134 				cb->c_lflag |= ECHOE|ECHOCTL|IEXTEN;
135 				if (cfgetospeed(cb) >= B1200)
136 					cb->c_lflag |= ECHOKE;
137 			}
138 			else if (eqarg("line", argc) && (!(term & TERMIOS) || term == -1) && --argc) {
139 				ocb->c_line = atoi(*++argv);
140 				continue;
141 			}
142 			else if (eq("raw") || eq("cbreak")) {
143 				cb->c_cc[VMIN] = 1;
144 				cb->c_cc[VTIME] = 0;
145 			}
146 			else if (eq("-raw") || eq("-cbreak") || eq("cooked")) {
147 				cb->c_cc[VEOF] = CEOF;
148 				cb->c_cc[VEOL] = CNUL;
149 			}
150 			else if(eq("sane")) {
151 				cb->c_cc[VERASE] = CERASE;
152 				cb->c_cc[VKILL] = CKILL;
153 				cb->c_cc[VQUIT] = CQUIT;
154 				cb->c_cc[VINTR] = CINTR;
155 				cb->c_cc[VEOF] = CEOF;
156 				cb->c_cc[VEOL] = CNUL;
157 							   /* SWTCH purposely not set */
158 			}
159 			else if((term & TERMIOS) && eqarg("ospeed", argc) && --argc) {
160 				s_arg = *++argv;
161 				match = 0;
162 				for(i=0; speeds[i].string; i++)
163 					if(eq(speeds[i].string))
164 					    cfsetospeed(cb, speeds[i].speed);
165 				if(!match)
166 					return s_arg;
167 				continue;
168 			}
169 			else if((term & TERMIOS) && eqarg("ispeed", argc) && --argc) {
170 				s_arg = *++argv;
171 				match = 0;
172 				for(i=0; speeds[i].string; i++)
173 					if(eq(speeds[i].string))
174 					    cfsetispeed(cb, speeds[i].speed);
175 				if(!match)
176 					return s_arg;
177 				continue;
178 			}
179 			else if (argc == 0) {
180 				(void) fprintf(stderr, "stty: No argument for \"%s\"\n", s_arg);
181 				exit(1);
182 			}
183 			for(i=0; speeds[i].string; i++)
184 				if(eq(speeds[i].string)) {
185 					cfsetospeed(cb, B0);
186 					cfsetispeed(cb, B0);
187 					cfsetospeed(cb, speeds[i].speed);
188 				}
189 		}
190 		if ((!(term & ASYNC) || term == -1) && eqarg("ctab", argc) && --argc) {
191 			cb->c_cc[7] = gct(*++argv, term);
192 			continue;
193 		}
194 		else if (argc == 0) {
195 			(void) fprintf(stderr, "stty: No argument for \"%s\"\n", s_arg);
196 			exit(1);
197 		}
198 
199 		for(i=0; imodes[i].string; i++)
200 			if(eq(imodes[i].string)) {
201 				cb->c_iflag &= ~imodes[i].reset;
202 				cb->c_iflag |= imodes[i].set;
203 			}
204 		if((term & TERMIOS) || term == -1) {
205 			for(i=0; nimodes[i].string; i++)
206 				if(eq(nimodes[i].string)) {
207 					cb->c_iflag &= ~nimodes[i].reset;
208 					cb->c_iflag |= nimodes[i].set;
209 				}
210 		}
211 
212 		for(i=0; omodes[i].string; i++)
213 			if(eq(omodes[i].string)) {
214 				cb->c_oflag &= ~omodes[i].reset;
215 				cb->c_oflag |= omodes[i].set;
216 			}
217 		if((!(term & ASYNC) || term == -1) && eq("sane")) {
218 			cb->c_oflag |= TAB3;
219 			continue;
220 		}
221 		for(i=0; cmodes[i].string; i++)
222 			if(eq(cmodes[i].string)) {
223 				cb->c_cflag &= ~cmodes[i].reset;
224 				cb->c_cflag |= cmodes[i].set;
225 			}
226 		if((term & TERMIOS) || term == -1)
227 			for(i=0; ncmodes[i].string; i++)
228 				if(eq(ncmodes[i].string)) {
229 					cb->c_cflag &= ~ncmodes[i].reset;
230 					cb->c_cflag |= ncmodes[i].set;
231 				}
232 		for(i=0; lmodes[i].string; i++)
233 			if(eq(lmodes[i].string)) {
234 				cb->c_lflag &= ~lmodes[i].reset;
235 				cb->c_lflag |= lmodes[i].set;
236 			}
237 		if((term & TERMIOS) || term == -1)
238 			for(i=0; nlmodes[i].string; i++)
239 				if(eq(nlmodes[i].string)) {
240 					cb->c_lflag &= ~nlmodes[i].reset;
241 					cb->c_lflag |= nlmodes[i].set;
242 				}
243 		if((term & FLOW) || term == -1) {
244 			for(i=0; hmodes[i].string; i++)
245 				if(eq(hmodes[i].string)) {
246 					termiox->x_hflag &= ~hmodes[i].reset;
247 					termiox->x_hflag |= hmodes[i].set;
248 				}
249 			for(i=0; clkmodes[i].string; i++)
250 				if(eq(clkmodes[i].string)) {
251 					termiox->x_cflag &= ~clkmodes[i].reset;
252 					termiox->x_cflag |= clkmodes[i].set;
253 				}
254 
255 		}
256 		if(eqarg("rows", argc) && --argc)
257 			winsize->ws_row = atoi(*++argv);
258 		else if((eqarg("columns", argc) || eqarg("cols", argc)) && --argc)
259 			winsize->ws_col = atoi(*++argv);
260 		else if(eqarg("xpixels", argc) && --argc)
261 			winsize->ws_xpixel = atoi(*++argv);
262 		else if(eqarg("ypixels", argc) && --argc)
263 			winsize->ws_ypixel = atoi(*++argv);
264 		else if (argc == 0) {
265 			(void) fprintf(stderr, "stty: No argument for \"%s\"\n", s_arg);
266 			exit(1);
267 		}
268 		if(!match)
269 			if(!encode(cb, term)) {
270 				return(s_arg); /* parsing failed */
271 			}
272 	}
273 	return((char *)0);
274 }
275 
276 static int eq(string)
277 char *string;
278 {
279 	register i;
280 
281 	if(!s_arg)
282 		return(0);
283 	i = 0;
284 loop:
285 	if(s_arg[i] != string[i])
286 		return(0);
287 	if(s_arg[i++] != '\0')
288 		goto loop;
289 	match++;
290 	return(1);
291 }
292 
293 /* Checks for options that require an argument */
294 static int
295 eqarg(string, argc)
296 char *string;
297 int argc;
298 {
299 	int status;
300 
301 	if ((status = eq(string)) == 1) {
302 		if (argc <= 1) {
303 			(void) fprintf(stderr, "stty: No argument for \"%s\"\n",
304 					 	s_arg);
305 			exit(1);
306 		}
307 	}
308 	return(status);
309 }
310 
311 /* get pseudo control characters from terminal */
312 /* and convert to internal representation      */
313 static int gct(cp, term)
314 register char *cp;
315 int term;
316 {
317 	register c;
318 
319 	c = *cp++;
320 	if (c == '^') {
321 		c = *cp;
322 		if (c == '?')
323 			c = 0177;		/* map '^?' to DEL */
324 		else if (c == '-')
325 			c = (term & TERMIOS) ? _POSIX_VDISABLE : 0200;		/* map '^-' to undefined */
326 		else
327 			c &= 037;
328 	}
329 	return(c);
330 }
331 
332 /* get modes of tty device and fill in applicable structures */
333 int
334 get_ttymode(fd, termio, termios, stermio, termiox, winsize)
335 int fd;
336 struct termio *termio;
337 struct termios *termios;
338 struct stio *stermio;
339 struct termiox *termiox;
340 struct winsize *winsize;
341 {
342 	int i;
343 	int term = 0;
344 	if(ioctl(fd, STGET, stermio) == -1) {
345 		term |= ASYNC;
346 		if(ioctl(fd, TCGETS, termios) == -1) {
347 			if(ioctl(fd, TCGETA, termio) == -1)
348 				return -1;
349 			termios->c_lflag = termio->c_lflag;
350 			termios->c_oflag = termio->c_oflag;
351 			termios->c_iflag = termio->c_iflag;
352 			termios->c_cflag = termio->c_cflag;
353 			for(i = 0; i < NCC; i++)
354 				termios->c_cc[i] = termio->c_cc[i];
355 		} else
356 			term |= TERMIOS;
357 	}
358 	else {
359 		termios->c_cc[7] = (unsigned)stermio->tab;
360 		termios->c_lflag = stermio->lmode;
361 		termios->c_oflag = stermio->omode;
362 		termios->c_iflag = stermio->imode;
363 	}
364 
365 	if(ioctl(fd, TCGETX, termiox) == 0)
366 		term |= FLOW;
367 
368 	if(ioctl(fd, TIOCGWINSZ, winsize) == 0)
369 		term |= WINDOW;
370 	return term;
371 }
372 
373 /* set tty modes */
374 int
375 set_ttymode(fd, term, termio, termios, stermio, termiox, winsize, owinsize)
376 int fd, term;
377 struct termio *termio;
378 struct termios *termios;
379 struct stio *stermio;
380 struct termiox *termiox;
381 struct winsize *winsize, *owinsize;
382 {
383 	int i;
384 	if (term & ASYNC) {
385 		if(term & TERMIOS) {
386 			if(ioctl(fd, TCSETSW, termios) == -1)
387 				return -1;
388 		} else {
389 			termio->c_lflag = termios->c_lflag;
390 			termio->c_oflag = termios->c_oflag;
391 			termio->c_iflag = termios->c_iflag;
392 			termio->c_cflag = termios->c_cflag;
393 			for(i = 0; i < NCC; i++)
394 				termio->c_cc[i] = termios->c_cc[i];
395 			if(ioctl(fd, TCSETAW, termio) == -1)
396 				return -1;
397 		}
398 
399 	} else {
400 		stermio->imode = termios->c_iflag;
401 		stermio->omode = termios->c_oflag;
402 		stermio->lmode = termios->c_lflag;
403 		stermio->tab = termios->c_cc[7];
404 		if (ioctl(fd, STSET, stermio) == -1)
405 			return -1;
406 	}
407 	if(term & FLOW) {
408 		if(ioctl(fd, TCSETXW, termiox) == -1)
409 			return -1;
410 	}
411 	if((owinsize->ws_col != winsize->ws_col
412 	   || owinsize->ws_row != winsize->ws_row)
413 	   && ioctl(0, TIOCSWINSZ, winsize) != 0)
414 		return -1;
415 	return 0;
416 }
417 
418 static int encode(cb, term)
419 struct	termios	*cb;
420 int term;
421 {
422 	unsigned long grab[20], i;
423 	int last;
424 	i = sscanf(s_arg,
425 	"%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx:%lx",
426 	&grab[0],&grab[1],&grab[2],&grab[3],&grab[4],&grab[5],&grab[6],
427 	&grab[7],&grab[8],&grab[9],&grab[10],&grab[11],
428 	&grab[12], &grab[13], &grab[14], &grab[15],
429 	&grab[16], &grab[17], &grab[18], &grab[19]);
430 
431 	if((term & TERMIOS) && i < 20 && term != -1 || i < 12)
432 		return(0);
433 	cb->c_iflag = grab[0];
434 	cb->c_oflag = grab[1];
435 	cb->c_cflag = grab[2];
436 	cb->c_lflag = grab[3];
437 
438 	if(term & TERMIOS)
439 		last = NCCS - 1;
440 	else
441 		last = NCC;
442 	for(i=0; i<last; i++)
443 		cb->c_cc[i] = (unsigned char) grab[i+4];
444 	return(1);
445 }
446 
447