147843Sbostic /*- 248945Sbostic * Copyright (c) 1989, 1991 The Regents of the University of California. 347843Sbostic * All rights reserved. 447843Sbostic * 549269Sbostic * %sccs.include.redist.c% 619907Sdist */ 719907Sdist 813073Ssam #ifndef lint 919907Sdist char copyright[] = 1048945Sbostic "@(#) Copyright (c) 1989, 1991 The Regents of the University of California.\n\ 1119907Sdist All rights reserved.\n"; 1247843Sbostic #endif /* not lint */ 1319907Sdist 1419907Sdist #ifndef lint 15*49974Sbostic static char sccsid[] = "@(#)stty.c 5.25 (Berkeley) 06/03/91"; 1647843Sbostic #endif /* not lint */ 1719907Sdist 1838674Smarc #include <sys/types.h> 1937609Sbostic #include <sys/ioctl.h> 2048945Sbostic #include <termios.h> 2148945Sbostic #include <fcntl.h> 2238674Smarc #include <errno.h> 2348945Sbostic #include <unistd.h> 2448945Sbostic #include <stdio.h> 2538674Smarc #include <ctype.h> 2648945Sbostic #include <stdlib.h> 2748945Sbostic #include <string.h> 2848945Sbostic #include "stty.h" 2948945Sbostic #include "extern.h" 301179Sbill 3148945Sbostic static void usage __P((void)); 3238674Smarc 3338674Smarc main(argc, argv) 3448945Sbostic int argc; 3548945Sbostic char **argv; 361179Sbill { 3738674Smarc extern char *optarg; 3848974Sbostic extern int opterr, optind; 3948945Sbostic extern struct cchar cchars1[], cchars2[]; 4048945Sbostic extern struct modes cmodes[], imodes[], lmodes[], omodes[]; 4148945Sbostic register struct modes *mp; 4248945Sbostic register struct cchar *cp; 4348945Sbostic struct winsize win; 4448945Sbostic struct termios t; 4548945Sbostic enum FMT fmt; 4648945Sbostic int ch, ctl, ldisc, tmp; 471179Sbill 4848945Sbostic ctl = STDIN_FILENO; 4948945Sbostic fmt = NOTSET; 5048974Sbostic opterr = 0; 51*49974Sbostic while (strspn(argv[optind], "-aefg") == strlen(argv[optind]) && 52*49974Sbostic (ch = getopt(argc, argv, "aef:g")) != EOF) 5348945Sbostic switch(ch) { 5448945Sbostic case 'a': /* undocumented: POSIX compatibility */ 5548945Sbostic fmt = POSIX; 5648945Sbostic break; 5748945Sbostic case 'e': 5848945Sbostic fmt = BSD; 5948945Sbostic break; 6048945Sbostic case 'f': 6148945Sbostic if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) 62*49974Sbostic err("%s: %s", optarg, strerror(errno)); 6348945Sbostic break; 6448945Sbostic case 'g': 6548945Sbostic fmt = GFLAG; 6648945Sbostic break; 6748945Sbostic case '?': 6848945Sbostic default: 6948945Sbostic goto args; 7048945Sbostic } 7148945Sbostic 7248945Sbostic args: argc -= optind; 7348945Sbostic argv += optind; 7448945Sbostic 7538674Smarc if (ioctl(ctl, TIOCGETD, &ldisc) < 0) 7648945Sbostic err("TIOCGETD: %s", strerror(errno)); 7738674Smarc if (tcgetattr(ctl, &t) < 0) 7848945Sbostic err("tcgetattr: %s", strerror(errno)); 7938674Smarc if (ioctl(ctl, TIOCGWINSZ, &win) < 0) 8048945Sbostic warn("TIOCGWINSZ: %s\n", strerror(errno)); 8138674Smarc 8248945Sbostic checkredirect(); /* conversion aid */ 8348945Sbostic 8448945Sbostic switch(fmt) { 8548945Sbostic case NOTSET: 8648945Sbostic if (*argv) 8748945Sbostic break; 8848945Sbostic /* FALLTHROUGH */ 8948945Sbostic case BSD: 9048945Sbostic case POSIX: 9148945Sbostic print(&t, &win, ldisc, fmt); 9248945Sbostic break; 9348945Sbostic case GFLAG: 9448945Sbostic gprint(&t, &win, ldisc); 9548945Sbostic break; 961179Sbill } 9738674Smarc 9848945Sbostic #define CHK(s) (**argv == s[0] && !strcmp(*argv, s)) 9948945Sbostic 10048945Sbostic for (; *argv; ++argv) { 10148945Sbostic if (CHK("-nl")) { 10248945Sbostic t.c_iflag |= ICRNL; 10348945Sbostic t.c_oflag |= ONLCR; 10448945Sbostic continue; 1051179Sbill } 10648945Sbostic if (CHK("all")) { 10748945Sbostic print(&t, &win, ldisc, BSD); 10848945Sbostic continue; 1091179Sbill } 11048945Sbostic if (CHK("-cbreak")) 11148945Sbostic goto reset; 11248945Sbostic if (CHK("cbreak")) { 11348945Sbostic t.c_iflag | BRKINT|IXON|IMAXBEL; 11448945Sbostic t.c_oflag |= OPOST; 11548945Sbostic t.c_lflag |= ISIG|IEXTEN; 11648945Sbostic t.c_lflag &= ~ICANON; 11748945Sbostic continue; 1181179Sbill } 11948945Sbostic if (CHK("cols")) { 12048945Sbostic if (!*++argv) 12148945Sbostic err("option requires an argument -- cols"); 12248945Sbostic goto columns; 1231179Sbill } 12448945Sbostic if (CHK("columns")) { 12548945Sbostic if (!*++argv) 12648945Sbostic err("option requires an argument -- columns"); 12748945Sbostic columns: win.ws_col = atoi(*argv); 12848945Sbostic continue; 1293797Sroot } 13048945Sbostic if (CHK("cooked")) 13148945Sbostic goto reset; 13248945Sbostic if (CHK("dec")) { 13338674Smarc t.c_cc[VERASE] = (u_char)0177; 13438674Smarc t.c_cc[VKILL] = CTRL('u'); 13538674Smarc t.c_cc[VINTR] = CTRL('c'); 13638674Smarc t.c_lflag &= ~ECHOPRT; 13738674Smarc t.c_lflag |= ECHOE|ECHOKE|ECHOCTL; 13838674Smarc t.c_iflag &= ~IXANY; 13948945Sbostic continue; 1401179Sbill } 14148945Sbostic if (CHK("everything")) { 14248945Sbostic print(&t, &win, ldisc, BSD); 14348945Sbostic continue; 14448945Sbostic } 14548945Sbostic if (CHK("-extproc")) { 14648945Sbostic tmp = 0; 14748945Sbostic ioctl(ctl, TIOCEXT, &tmp); 14848945Sbostic continue; 14948945Sbostic } 15048945Sbostic if (CHK("extrpc")) { 15148945Sbostic tmp = 1; 15248945Sbostic ioctl(ctl, TIOCEXT, &tmp); 15348945Sbostic continue; 15448945Sbostic } 15548945Sbostic if (CHK("ispeed")) { 15648945Sbostic if (!*++argv) 15748945Sbostic err("option requires an argument -- ispeed"); 15848945Sbostic cfsetispeed(&t, atoi(*argv)); 15948945Sbostic continue; 16048945Sbostic } 16148945Sbostic if (CHK("new")) 16248945Sbostic goto tty; 16348945Sbostic if (CHK("nl")) { 16448945Sbostic t.c_iflag &= ~ICRNL; 16548945Sbostic t.c_oflag &= ~ONLCR; 16648945Sbostic continue; 16748945Sbostic } 16848945Sbostic if (CHK("old")) 16948945Sbostic goto tty; 17048945Sbostic if (CHK("ospeed")) { 17148945Sbostic if (!*++argv) 17248945Sbostic err("option requires an argument -- ospeed"); 17348945Sbostic cfsetospeed(&t, atoi(*argv)); 17448945Sbostic continue; 17548945Sbostic } 17648945Sbostic if (CHK("-raw")) 17748945Sbostic goto reset; 17848945Sbostic if (CHK("raw")) { 17940169Skarels cfmakeraw(&t); 18040169Skarels t.c_cflag &= ~(CSIZE|PARENB); 18140169Skarels t.c_cflag |= CS8; 18248945Sbostic continue; 18340169Skarels } 18448945Sbostic if (CHK("rows")) { 18548945Sbostic if (!*++argv) 18648945Sbostic err("option requires an argument -- rows"); 18748945Sbostic win.ws_row = atoi(*argv); 18848945Sbostic continue; 18945029Smarc } 19048945Sbostic if (CHK("sane")) { 19148945Sbostic reset: t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL); 19240169Skarels t.c_iflag = TTYDEF_IFLAG; 19340169Skarels t.c_iflag |= ICRNL; 19440169Skarels /* preserve user-preference flags in lflag */ 19540169Skarels #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) 19640169Skarels t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP); 19740169Skarels t.c_oflag = TTYDEF_OFLAG; 19848945Sbostic continue; 19940169Skarels } 20048945Sbostic if (CHK("size")) { 20148945Sbostic (void)printf("%d %d\n", win.ws_row, win.ws_col); 20248945Sbostic continue; 20318023Sbloom } 20448945Sbostic if (CHK("speed")) { 20548945Sbostic (void)printf("%d\n", cfgetospeed(&t)); 20648945Sbostic continue; 20738674Smarc } 20848945Sbostic if (CHK("tty")) { 20948945Sbostic tty: tmp = TTYDISC; 21048945Sbostic if (ioctl(0, TIOCSETD, &tmp) < 0) 21148945Sbostic err("TIOCSETD: %s", strerror(errno)); 21248945Sbostic continue; 21338674Smarc } 21448945Sbostic 21548945Sbostic for (mp = cmodes; mp->name; ++mp) 21648945Sbostic if (CHK(mp->name)) { 21748945Sbostic t.c_cflag &= ~mp->unset; 21848945Sbostic t.c_cflag |= mp->set; 21938674Smarc goto next; 2201179Sbill } 22148945Sbostic for (mp = imodes; mp->name; ++mp) 22248945Sbostic if (CHK(mp->name)) { 22348945Sbostic t.c_iflag &= ~mp->unset; 22448945Sbostic t.c_iflag |= mp->set; 22538674Smarc goto next; 22638674Smarc } 22748945Sbostic for (mp = lmodes; mp->name; ++mp) 22848945Sbostic if (CHK(mp->name)) { 22948945Sbostic t.c_lflag &= ~mp->unset; 23048945Sbostic t.c_lflag |= mp->set; 23138674Smarc goto next; 23238674Smarc } 23348945Sbostic for (mp = omodes; mp->name; ++mp) 23448945Sbostic if (CHK(mp->name)) { 23548945Sbostic t.c_oflag &= ~mp->unset; 23648945Sbostic t.c_oflag |= mp->set; 23738674Smarc goto next; 23838674Smarc } 23948945Sbostic for (cp = cchars1; cp->name; ++cp) { 24048945Sbostic if (!CHK(cp->name)) 24148945Sbostic continue; 24248945Sbostic goto ccfound; 2431179Sbill } 24448945Sbostic for (cp = cchars2; cp->name; ++cp) { 24548945Sbostic if (!CHK(cp->name)) 24648945Sbostic continue; 24748945Sbostic ccfound: if (!*++argv) 24848945Sbostic err("option requires an argument -- %s", 24948945Sbostic cp->name); 25049847Sbostic if (CHK("undef") || CHK("<undef>")) 25148945Sbostic t.c_cc[cp->sub] = _POSIX_VDISABLE; 25248945Sbostic else if (**argv == '^') 25348945Sbostic t.c_cc[cp->sub] = 25448945Sbostic ((*argv)[1] == '?') ? 0177 : 25548945Sbostic ((*argv)[1] == '-') ? _POSIX_VDISABLE : 25648945Sbostic (*argv)[1] & 037; 25748945Sbostic else 25848945Sbostic t.c_cc[cp->sub] = **argv; 25948945Sbostic goto next; 26048945Sbostic } 26148945Sbostic 26238674Smarc if (isdigit(**argv)) { 26338674Smarc cfsetospeed(&t, atoi(*argv)); 26438674Smarc cfsetispeed(&t, atoi(*argv)); 26538674Smarc goto next; 26638674Smarc } 26748945Sbostic if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { 26848945Sbostic gread(&t, *argv + sizeof("gfmt1") - 1); 26943323Smarc goto next; 27043323Smarc } 27148945Sbostic 27248945Sbostic err("illegal option -- %s", *argv); 27348945Sbostic next: continue; 2741179Sbill } 27548945Sbostic 27638674Smarc if (tcsetattr(ctl, 0, &t) < 0) 27748945Sbostic err("tcsetattr: %s", strerror(errno)); 27838674Smarc if (ioctl(ctl, TIOCSWINSZ, &win) < 0) 27948945Sbostic warn("TIOCSWINSZ: %s", strerror(errno)); 28038674Smarc exit(0); 2811179Sbill } 2821179Sbill 28348945Sbostic static void 28448945Sbostic usage() 28543323Smarc { 28648945Sbostic (void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n"); 28738674Smarc exit(1); 28838674Smarc } 289