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