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