1 /* 2 * Copyright (c) 1980, 1989 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 char copyright[] = 9 "@(#) Copyright (c) 1980, 1989 Regents of the University of California.\n\ 10 All rights reserved.\n"; 11 #endif not lint 12 13 #ifndef lint 14 static char sccsid[] = "@(#)stty.c 5.18 (Berkeley) 09/14/90"; 15 #endif not lint 16 17 /* 18 * set teletype modes 19 */ 20 21 #include <sys/types.h> 22 #include <sys/stat.h> 23 #include <sys/ioctl.h> 24 #include <sys/syslog.h> 25 #define KERNEL 26 #include <sys/tty.h> 27 #undef KERNEL 28 #include <sys/termios.h> 29 #include <sys/file.h> 30 #include <errno.h> 31 #include <ctype.h> 32 #include <stdio.h> 33 34 #define eq(s1, s2) (strcmp((s1), (s2)) == 0) 35 #define WRAPCOL 65 36 37 struct modes { 38 char *name; 39 long set; 40 long unset; 41 }; 42 43 struct modes imodes[] = { 44 "ignbrk", IGNBRK, 0, 45 "-ignbrk", 0, IGNBRK, 46 "brkint", BRKINT, 0, 47 "-brkint", 0, BRKINT, 48 "ignpar", IGNPAR, 0, 49 "-ignpar", 0, IGNPAR, 50 "parmrk", PARMRK, 0, 51 "-parmrk", 0, PARMRK, 52 "inpck", INPCK, 0, 53 "-inpck", 0, INPCK, 54 "istrip", ISTRIP, 0, 55 "-istrip", 0, ISTRIP, 56 "inlcr", INLCR, 0, 57 "-inlcr", 0, INLCR, 58 "igncr", IGNCR, 0, 59 "-igncr", 0, IGNCR, 60 "icrnl", ICRNL, 0, 61 "-icrnl", 0, ICRNL, 62 "ixon", IXON, 0, 63 "-ixon", 0, IXON, 64 "flow", IXON, 0, 65 "-flow", 0, IXON, 66 "ixoff", IXOFF, 0, 67 "-ixoff", 0, IXOFF, 68 "tandem", IXOFF, 0, 69 "-tandem", 0, IXOFF, 70 "ixany", IXANY, 0, 71 "-ixany", 0, IXANY, 72 "decctlq", 0, IXANY, 73 "-decctlq", IXANY, 0, 74 "imaxbel", IMAXBEL, 0, 75 "-imaxbel", 0, IMAXBEL, 76 0 77 }; 78 79 struct modes omodes[] = { 80 "opost", OPOST, 0, 81 "-opost", 0, OPOST, 82 "-litout", OPOST, 0, 83 "litout", 0, OPOST, 84 "onlcr", ONLCR, 0, 85 "-onlcr", 0, ONLCR, 86 "tabs", 0, OXTABS, /* "preserve" tabs */ 87 "-tabs", OXTABS, 0, 88 "xtabs", OXTABS, 0, 89 "-xtabs", 0, OXTABS, 90 "oxtabs", OXTABS, 0, 91 "-oxtabs", 0, OXTABS, 92 0 93 }; 94 95 struct modes cmodes[] = { 96 "cs5", CS5, CSIZE, 97 "cs6", CS6, CSIZE, 98 "cs7", CS7, CSIZE, 99 "cs8", CS8, CSIZE, 100 "cstopb", CSTOPB, 0, 101 "-cstopb", 0, CSTOPB, 102 "cread", CREAD, 0, 103 "-cread", 0, CREAD, 104 "parenb", PARENB, 0, 105 "-parenb", 0, PARENB, 106 "parodd", PARODD, 0, 107 "-parodd", 0, PARODD, 108 "parity", PARENB | CS7, PARODD | CSIZE, 109 "evenp", PARENB | CS7, PARODD | CSIZE, 110 "oddp", PARENB | CS7 | PARODD, CSIZE, 111 "-parity", CS8, PARODD | PARENB | CSIZE, 112 "pass8", CS8, PARODD | PARENB | CSIZE, 113 "-evenp", CS8, PARODD | PARENB | CSIZE, 114 "-oddp", CS8, PARODD | PARENB | CSIZE, 115 "hupcl", HUPCL, 0, 116 "-hupcl", 0, HUPCL, 117 "hup", HUPCL, 0, 118 "-hup", 0, HUPCL, 119 "clocal", CLOCAL, 0, 120 "-clocal", 0, CLOCAL, 121 "crtscts", CRTSCTS, 0, 122 "-crtscts", 0, CRTSCTS, 123 0 124 }; 125 126 struct modes lmodes[] = { 127 "echo", ECHO, 0, 128 "-echo", 0, ECHO, 129 "echoe", ECHOE, 0, 130 "-echoe", 0, ECHOE, 131 "crterase", ECHOE, 0, 132 "-crterase", 0, ECHOE, 133 "crtbs", ECHOE, 0, /* crtbs not supported, close enough */ 134 "-crtbs", 0, ECHOE, 135 "echok", ECHOK, 0, 136 "-echok", 0, ECHOK, 137 "echoke", ECHOKE, 0, 138 "-echoke", 0, ECHOKE, 139 "crtkill", ECHOKE, 0, 140 "-crtkill", 0, ECHOKE, 141 "altwerase", ALTWERASE, 0, 142 "-altwerase", 0, ALTWERASE, 143 "iexten", IEXTEN, 0, 144 "-iexten", 0, IEXTEN, 145 "echonl", ECHONL, 0, 146 "-echonl", 0, ECHONL, 147 "echoctl", ECHOCTL, 0, 148 "-echoctl", 0, ECHOCTL, 149 "ctlecho", ECHOCTL, 0, 150 "-ctlecho", 0, ECHOCTL, 151 "echoprt", ECHOPRT, 0, 152 "-echoprt", 0, ECHOPRT, 153 "prterase", ECHOPRT, 0, 154 "-prterase", 0, ECHOPRT, 155 "isig", ISIG, 0, 156 "-isig", 0, ISIG, 157 "icanon", ICANON, 0, 158 "-icanon", 0, ICANON, 159 "noflsh", NOFLSH, 0, 160 "-noflsh", 0, NOFLSH, 161 "tostop", TOSTOP, 0, 162 "-tostop", 0, TOSTOP, 163 "mdmbuf", MDMBUF, 0, 164 "-mdmbuf", 0, MDMBUF, 165 "flusho", FLUSHO, 0, 166 "-flusho", 0, FLUSHO, 167 "pendin", PENDIN, 0, 168 "-pendin", 0, PENDIN, 169 "crt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT, 170 "-crt", ECHOK, ECHOE|ECHOKE|ECHOCTL, 171 "newcrt", ECHOE|ECHOKE|ECHOCTL, ECHOK|ECHOPRT, 172 "-newcrt", ECHOK, ECHOE|ECHOKE|ECHOCTL, 173 "nokerninfo", NOKERNINFO, 0, 174 "-nokerninfo", 0, NOKERNINFO, 175 "kerninfo", 0, NOKERNINFO, 176 "-kerninfo", NOKERNINFO, 0, 177 0 178 }; 179 180 /* 181 * Special control characters. 182 * 183 * Each entry has a list of names. The first is the primary name 184 * and is used when printing the control character in the "name = val;" 185 * form. The second is an abbreviation which is guaranteed to be less 186 * than or equal to four characters in length and is primarily used 187 * when printing the values in columunar form (guarantees all will 188 * fit within 80 cols). The rest are optional aliases. 189 * All names are recognized on the command line. 190 */ 191 #define MAXNAMES 3 192 struct { 193 char *names[MAXNAMES+1]; 194 int sub; 195 u_char def; 196 } cchars[] = { 197 {{ "erase", "era" }, VERASE, CERASE, }, 198 {{ "werase", "wera" }, VWERASE, CWERASE, }, 199 {{ "kill", "kill" }, VKILL, CKILL, }, 200 {{ "intr", "int" }, VINTR, CINTR, }, 201 {{ "quit", "quit" }, VQUIT, CQUIT, }, 202 {{ "susp", "susp" }, VSUSP, CSUSP, }, 203 {{ "dsusp", "dsus" }, VDSUSP, CDSUSP, }, 204 {{ "eof", "eof" }, VEOF, CEOF, }, 205 {{ "eol", "eol", "brk" }, VEOL, CEOL, }, 206 {{ "eol2", "eol2" }, VEOL2, CEOL, }, 207 {{ "stop", "stop", "xoff" }, VSTOP, CSTOP, }, 208 {{ "start", "star", "xon" }, VSTART, CSTART, }, 209 {{ "lnext", "lnxt" }, VLNEXT, CLNEXT, }, 210 {{ "discard", "disc", "flush" }, VDISCARD, CDISCARD, }, 211 {{ "reprint", "rpnt", "rprnt" }, VREPRINT, CREPRINT, }, 212 {{ "status", "stat" }, VSTATUS, CSTATUS, }, 213 0 214 }; 215 216 struct winsize win; 217 int ldisc; 218 int dodisc; 219 int debug = 0; 220 int trace, dotrace; 221 int extproc; 222 223 #define OUT stdout /* informational output stream */ 224 #define ERR stderr /* error message stream */ 225 #define CTL 0 /* default control descriptor */ 226 int ctl = CTL; 227 228 extern errno; 229 230 #define NORMAL 0 /* only print modes differing from defaults */ 231 #define ALL 1 /* print all modes - POSIX standard format */ 232 #define ALL_BSD 2 /* print all modes - using BSD shorthand for cc's */ 233 #define GFMT 3 /* print modes in form suitable to be re-input */ 234 235 main(argc, argv) 236 char *argv[]; 237 { 238 struct termios t; 239 int i, fmt = NORMAL; 240 extern char *optarg; 241 extern int optind; 242 int ch; 243 244 argc--, argv++; 245 if (argc > 0 && eq(argv[0], "-a")) { 246 fmt = ALL; 247 argc--, argv++; 248 } 249 if (argc > 0 && eq(argv[0], "-g")) { 250 fmt = GFMT; 251 argc--, argv++; 252 } 253 if (argc > 0 && eq(argv[0], "-f")) { 254 argc--, argv++; 255 if ((ctl = open(argv[0], O_RDONLY | O_NONBLOCK)) < 0) 256 syserrexit(*argv); 257 argc--, argv++; 258 } 259 if (ioctl(ctl, TIOCGETD, &ldisc) < 0) 260 syserrexit("TIOCGETD"); 261 if (tcgetattr(ctl, &t) < 0) 262 syserrexit("tcgetattr"); 263 if (ioctl(ctl, TIOCGWINSZ, &win) < 0) 264 warning("TIOCGWINSZ: %s", strerror(errno)); 265 checkredirect(); /* conversion aid */ 266 267 if (argc == 0 || fmt) { 268 prmode(&t, ldisc, fmt); 269 exit(0); 270 } 271 272 while (*argv) { 273 if (eq("everything", *argv)) { 274 prmode(&t, ldisc, ALL_BSD); 275 exit(0); 276 } 277 if (eq("all", *argv)) { 278 prmode(&t, ldisc, ALL); 279 exit(0); 280 } 281 if (eq("old", *argv)) { 282 goto next; 283 } 284 if (eq("new", *argv)) { 285 goto next; 286 } 287 if (eq("nl", *argv)) { 288 t.c_iflag &= ~ICRNL; 289 t.c_oflag &= ~ONLCR; 290 goto next; 291 } 292 if (eq("-nl", *argv)) { 293 t.c_iflag |= ICRNL; 294 t.c_oflag |= ONLCR; 295 goto next; 296 } 297 if (eq("dec", *argv)){ 298 t.c_cc[VERASE] = (u_char)0177; 299 t.c_cc[VKILL] = CTRL('u'); 300 t.c_cc[VINTR] = CTRL('c'); 301 t.c_lflag &= ~ECHOPRT; 302 t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; 303 t.c_iflag &= ~IXANY; 304 goto next; 305 } 306 if (eq("raw", *argv)) { 307 cfmakeraw(&t); 308 t.c_cflag &= ~(CSIZE|PARENB); 309 t.c_cflag |= CS8; 310 goto next; 311 } 312 if (eq("cbreak", *argv)) { 313 t.c_iflag | BRKINT|IXON|IMAXBEL; 314 t.c_oflag |= OPOST; 315 t.c_lflag |= ISIG|IEXTEN; 316 t.c_lflag &= ~ICANON; 317 } 318 if (eq("cooked", *argv) || eq("-raw", *argv) || 319 eq("sane", *argv) || eq("-cbreak", *argv)) { 320 t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL); 321 t.c_iflag = TTYDEF_IFLAG; 322 t.c_iflag |= ICRNL; 323 /* preserve user-preference flags in lflag */ 324 #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) 325 t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP); 326 t.c_oflag = TTYDEF_OFLAG; 327 goto next; 328 } 329 if (eq("rows", *argv)) { 330 if (*(argv+1) == 0) 331 goto setit; 332 win.ws_row = atoi(*++argv); 333 goto next; 334 } 335 if (eq("ispeed", *argv)) { 336 int code; 337 if (*(argv+1) == 0) 338 errexit("missing ispeed"); 339 cfsetispeed(&t, atoi(*++argv)); 340 goto next; 341 } 342 if (eq("ospeed", *argv)) { 343 if (*(argv+1) == 0) 344 errexit("missing ospeed"); 345 cfsetospeed(&t, atoi(*++argv)); 346 goto next; 347 } 348 if (eq("cols", *argv) || eq("columns", *argv)) { 349 if (*(argv+1) == 0) 350 goto setit; 351 win.ws_col = atoi(*++argv); 352 goto next; 353 } 354 if (eq("size", *argv)) { 355 put("%d %d\n", win.ws_row, win.ws_col); 356 exit(0); 357 } 358 if (eq("extrpc", *argv) || eq("-extproc", *argv)) { 359 if (**argv == '-') 360 extproc = 0; 361 else 362 extproc = 1; 363 ioctl(ctl, TIOCEXT, &extproc); 364 } 365 if (eq("speed", *argv)) { 366 put("%d\n", cfgetospeed(&t)); 367 exit(0); 368 } 369 for (i=0; imodes[i].name; i++) 370 if (eq(imodes[i].name, *argv)) { 371 t.c_iflag &= ~imodes[i].unset; 372 t.c_iflag |= imodes[i].set; 373 goto next; 374 } 375 for (i=0; omodes[i].name; i++) 376 if (eq(omodes[i].name, *argv)) { 377 t.c_oflag &= ~omodes[i].unset; 378 t.c_oflag |= omodes[i].set; 379 goto next; 380 } 381 for (i=0; cmodes[i].name; i++) 382 if (eq(cmodes[i].name, *argv)) { 383 t.c_cflag &= ~cmodes[i].unset; 384 t.c_cflag |= cmodes[i].set; 385 goto next; 386 } 387 for (i=0; lmodes[i].name; i++) 388 if (eq(lmodes[i].name, *argv)) { 389 t.c_lflag &= ~lmodes[i].unset; 390 t.c_lflag |= lmodes[i].set; 391 goto next; 392 } 393 for (i=0; *cchars[i].names; i++) { 394 char **cp = cchars[i].names; 395 while (*cp) { 396 if (eq(*cp, *argv)) { 397 if (*++argv == 0) 398 goto setit; 399 if (eq(*argv, "undef") || 400 eq(*argv, "disable")) 401 t.c_cc[cchars[i].sub] = 402 _POSIX_VDISABLE; 403 else if (**argv == '^') 404 t.c_cc[cchars[i].sub] = 405 ((*argv)[1] == '?') ? 0177 : 406 ((*argv)[1] == '-') ? 407 _POSIX_VDISABLE : 408 (*argv)[1] & 037; 409 else 410 t.c_cc[cchars[i].sub] = **argv; 411 goto next; 412 } 413 cp++; 414 } 415 } 416 if (isdigit(**argv)) { 417 cfsetospeed(&t, atoi(*argv)); 418 cfsetispeed(&t, atoi(*argv)); 419 goto next; 420 } 421 if (strncmp(*argv, "-gfmt", sizeof ("-gfmt") - 1) == 0) { 422 gfmtset(&t, *argv); 423 goto next; 424 } 425 /* didn't match anything */ 426 errexit("unknown option: %s", *argv); 427 exit(1); 428 next: 429 argv++; 430 } 431 setit: 432 if (tcsetattr(ctl, 0, &t) < 0) 433 syserrexit("tcsetattr"); 434 if (ioctl(ctl, TIOCSWINSZ, &win) < 0) 435 warning("can't set window size"); 436 437 exit(0); 438 } 439 440 gfmtset(tp, s) 441 register struct termios *tp; 442 char *s; 443 { 444 register int cnt; 445 char sep; 446 char *saves = s; 447 int cval; 448 #define advance(c) while (*(s) && *(s) != (c)) (s)++; if (*s) (s)++ ; \ 449 else \ 450 errexit("bad gfmt operand: %s", saves) 451 #define chkeq(string) if (strncmp(s, (string), strlen(string))) \ 452 errexit("bad gfmt operand: %s", saves) 453 454 if (s == NULL) 455 errexit("missing gfmt string"); 456 advance(':'); 457 chkeq("iflag="); 458 advance('='); 459 sscanf(s, "%x", &tp->c_iflag); 460 461 advance(':'); 462 chkeq("oflag"); 463 advance('='); 464 sscanf(s, "%x", &tp->c_oflag); 465 466 advance(':'); 467 chkeq("cflag"); 468 advance('='); 469 sscanf(s, "%x", &tp->c_cflag); 470 471 advance(':'); 472 chkeq("lflag"); 473 advance('='); 474 sscanf(s, "%x", &tp->c_lflag); 475 476 advance(':'); 477 chkeq("cc="); 478 479 for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') { 480 advance(sep); 481 sscanf(s, "%o", &cval); 482 tp->c_cc[cnt] = cval; 483 } 484 485 advance(':'); 486 chkeq("ispeed="); 487 advance('='); 488 sscanf(s, "%d", &tp->c_ispeed); 489 490 advance(':'); 491 chkeq("ospeed="); 492 advance('='); 493 sscanf(s, "%d", &tp->c_ospeed); 494 } 495 496 prmode(tp, ldisc, fmt) 497 struct termios *tp; 498 { 499 long i = tp->c_iflag, 500 o = tp->c_oflag, 501 c = tp->c_cflag, 502 l = tp->c_lflag; 503 u_char *cc = tp->c_cc; 504 int ispeed = cfgetispeed(tp), 505 ospeed = cfgetospeed(tp); 506 char unknown[32], 507 *ld; 508 char *ccval(); 509 510 if (fmt == GFMT) { 511 int cnt; 512 char sep; 513 514 printf("-gfmt:iflag=%x:oflag=%x:cflag=%x:lflag=%x:cc", 515 i, o, c, l); 516 for (cnt = 0, sep = '='; cnt < NCCS; cnt++, sep = ',') 517 printf("%c%o", sep, cc[cnt]); 518 printf(":ispeed=%d:ospeed=%d:\n", ispeed, ospeed); 519 return; 520 } 521 522 /* 523 * line discipline 524 */ 525 if (ldisc != TTYDISC) { 526 switch(ldisc) { 527 case TABLDISC: 528 ld = "tablet"; 529 break; 530 case SLIPDISC: 531 ld = "slip"; 532 break; 533 default: 534 sprintf(unknown, "#%d", ldisc); 535 ld = unknown; 536 } 537 put("%s disc; ", ld); 538 } 539 /* 540 * line speed 541 */ 542 if (ispeed != ospeed) 543 put("ispeed %d baud; ospeed %d baud;", 544 ispeed, ospeed); 545 else 546 put("speed %d baud;", ispeed); 547 if (fmt) 548 put(" %d rows; %d columns;", win.ws_row, win.ws_col); 549 put("\n"); 550 551 #define lput(n, f, d) if (fmt || on(f) != d) mdput(n+on(f)) 552 /* 553 * "local" flags 554 */ 555 #define on(f) ((l&f) != 0) 556 if (debug) mdput("LFLAG: "); 557 lput("-icanon ",ICANON, 1); 558 lput("-isig ", ISIG, 1); 559 lput("-iexten ", IEXTEN, 1); 560 lput("-echo ",ECHO, 1); 561 lput("-echoe ",ECHOE, 0); 562 lput("-echok ",ECHOK, 0); 563 lput("-echoke ",ECHOKE, 0); 564 lput("-echonl ",ECHONL, 0); 565 lput("-echoctl ",ECHOCTL, 0); 566 lput("-echoprt ",ECHOPRT, 0); 567 lput("-altwerase ",ALTWERASE, 0); 568 lput("-noflsh ",NOFLSH, 0); 569 lput("-tostop ",TOSTOP, 0); 570 lput("-mdmbuf ",MDMBUF, 0); 571 lput("-flusho ",FLUSHO, 0); 572 lput("-pendin ",PENDIN, 0); 573 lput("-nokerninfo ",NOKERNINFO, 0); 574 lput("-extproc ",EXTPROC, 0); 575 /* 576 * input flags 577 */ 578 #undef on 579 #define on(f) ((i&f) != 0) 580 mdput(0); 581 if (debug) mdput("IFLAG: "); 582 lput("-istrip ", ISTRIP, 0); 583 lput("-icrnl ", ICRNL, 1); 584 lput("-inlcr ", INLCR, 0); 585 lput("-igncr ", IGNCR, 0); 586 lput("-ixon ", IXON, 1); 587 lput("-ixoff ", IXOFF, 0); 588 lput("-ixany ", IXANY, 1); 589 lput("-imaxbel ", IMAXBEL, 1); 590 lput("-ignbrk ", IGNBRK, 0); 591 lput("-brkint ", BRKINT, 1); 592 lput("-inpck ", INPCK, 0); 593 lput("-ignpar ", IGNPAR, 0); 594 lput("-parmrk ", PARMRK, 0); 595 #undef on 596 /* 597 * output flags 598 */ 599 #define on(f) ((o&f) != 0) 600 mdput(0); 601 if (debug) mdput("OFLAG: "); 602 lput("-opost ", OPOST, 1); 603 lput("-onlcr ", ONLCR, 1); 604 lput("-oxtabs ", OXTABS, 1); 605 #undef on 606 /* 607 * control flags (hardware state) 608 */ 609 #define on(f) ((c&f) != 0) 610 mdput(0); 611 if (debug) mdput("CFLAG: "); 612 lput("-cread ", CREAD, 1); 613 switch(c&CSIZE) { 614 case CS5: mdput("cs5 "); break; 615 case CS6: mdput("cs6 "); break; 616 case CS7: mdput("cs7 "); break; 617 case CS8: mdput("cs8 "); break; 618 } 619 mdput("-parenb "+on(PARENB)); 620 lput("-parodd ", PARODD, 0); 621 lput("-hupcl ", HUPCL, 1); 622 lput("-clocal ", CLOCAL, 0); 623 lput("-cstopb ", CSTOPB, 0); 624 lput("-crtscts ", CRTSCTS, 0); 625 mdput(0); 626 #undef on 627 /* 628 * special control characters 629 */ 630 if (debug) mdput("CCHARS: "); 631 if (fmt != 2) { 632 for (i=0; *cchars[i].names; i++) { 633 char temp[64]; 634 635 if (fmt || cc[cchars[i].sub] != cchars[i].def) { 636 sprintf(temp, "%s = %s; ", *cchars[i].names, 637 ccval(cc[cchars[i].sub]), fmt); 638 mdput(temp); 639 } 640 } 641 mdput(0); 642 } else { 643 for (i=0; *cchars[i].names; i++) 644 put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0), 645 *(cchars[i].names+1)); 646 printf("\n"); 647 for (i=0; *cchars[i].names; i++) 648 put("%*s", strlen(*(cchars[i].names+1)) + (i>0?1:0), 649 ccval(cc[cchars[i].sub], fmt)); 650 printf("\n"); 651 } 652 } 653 654 /* 655 * gross, but since we're changing the control descriptor 656 * from 1 to 0, most users will be probably be doing 657 * "stty > /dev/sometty" by accident. If 1 and 2 are both ttys, 658 * but not the same, assume that 1 was incorrectly redirected. 659 */ 660 checkredirect() { 661 struct stat st1, st2; 662 663 if (isatty(1) && isatty(2) && fstat(1, &st1) != -1 && 664 fstat(2, &st2) != -1 && (st1.st_rdev != st2.st_rdev)) 665 warning("stdout appears redirected, but stdin is the control descriptor"); 666 } 667 668 char * 669 ccval(c, fmt) 670 unsigned char c; 671 { 672 static char buf[128]; 673 char *bp; 674 675 *buf = 0, bp = buf; 676 if (c == _POSIX_VDISABLE) 677 if (fmt == 2) 678 return("<u>"); 679 else 680 return("<undef>"); 681 if (c & 0200) { 682 strcat(buf, "M-"); 683 *bp++ = 'M'; 684 *bp++ = '-'; 685 c &= 0177; 686 } 687 if (c == 0177) { 688 *bp++ = '^'; 689 *bp++ = '?'; 690 } 691 else if (c < 040) { 692 *bp++ = '^'; 693 *bp++ = c + '@'; 694 } 695 else 696 *bp++ = c; 697 *bp = 0; 698 return(buf); 699 } 700 701 702 mdput(s) 703 char *s; 704 { 705 static int col = 0; 706 707 if (s == (char *)0) { 708 if (col) { 709 put("\n"); 710 col = 0; 711 } 712 return; 713 } 714 if ((col += strlen(s)) > WRAPCOL) { 715 put("\n"); 716 col = strlen(s); 717 } 718 put(s); 719 } 720 721 #include <varargs.h> 722 723 put(va_alist) 724 va_dcl 725 { 726 char *fmt; 727 va_list ap; 728 729 va_start(ap); 730 fmt = va_arg(ap, char *); 731 (void) vfprintf(OUT, fmt, ap); 732 va_end(ap); 733 } 734 735 736 warning(va_alist) 737 va_dcl 738 { 739 char *fmt; 740 va_list ap; 741 742 fprintf(ERR, "stty: warning: "); 743 va_start(ap); 744 fmt = va_arg(ap, char *); 745 (void) vfprintf(ERR, fmt, ap); 746 va_end(ap); 747 fprintf(ERR, "\n"); 748 } 749 750 751 errexit(va_alist) 752 va_dcl 753 { 754 char *fmt; 755 va_list ap; 756 757 fprintf(ERR, "stty: "); 758 va_start(ap); 759 fmt = va_arg(ap, char *); 760 (void) vfprintf(ERR, fmt, ap); 761 va_end(ap); 762 fprintf(ERR, "\n"); 763 exit(1); 764 } 765 766 767 syserrexit(va_alist) 768 va_dcl 769 { 770 char *fmt; 771 va_list ap; 772 773 fprintf(ERR, "stty: "); 774 va_start(ap); 775 fmt = va_arg(ap, char *); 776 (void) vfprintf(ERR, fmt, ap); 777 va_end(ap); 778 fprintf(ERR, ": %s\n", strerror(errno)); 779 exit(1); 780 } 781