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