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