Home | History | Annotate | Download | only in stty
      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 *
     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 
    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
    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      */
    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
    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
    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 
    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