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 * 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 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 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 */ 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 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 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 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