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