147843Sbostic /*- 2*48945Sbostic * Copyright (c) 1989, 1991 The Regents of the University of California. 347843Sbostic * All rights reserved. 447843Sbostic * 547843Sbostic * %sccs.include.proprietary.c% 619907Sdist */ 719907Sdist 813073Ssam #ifndef lint 919907Sdist char copyright[] = 10*48945Sbostic "@(#) 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*48945Sbostic static char sccsid[] = "@(#)stty.c 5.21 (Berkeley) 05/02/91"; 1647843Sbostic #endif /* not lint */ 1719907Sdist 1838674Smarc #include <sys/types.h> 1937609Sbostic #include <sys/ioctl.h> 20*48945Sbostic #include <termios.h> 21*48945Sbostic #include <fcntl.h> 2238674Smarc #include <errno.h> 23*48945Sbostic #include <unistd.h> 24*48945Sbostic #include <stdio.h> 2538674Smarc #include <ctype.h> 26*48945Sbostic #include <stdlib.h> 27*48945Sbostic #include <string.h> 28*48945Sbostic #include "stty.h" 29*48945Sbostic #include "extern.h" 301179Sbill 31*48945Sbostic static void usage __P((void)); 3238674Smarc 3338674Smarc main(argc, argv) 34*48945Sbostic int argc; 35*48945Sbostic char **argv; 361179Sbill { 3738674Smarc extern char *optarg; 3838674Smarc extern int optind; 39*48945Sbostic extern struct cchar cchars1[], cchars2[]; 40*48945Sbostic extern struct modes cmodes[], imodes[], lmodes[], omodes[]; 41*48945Sbostic register struct modes *mp; 42*48945Sbostic register struct cchar *cp; 43*48945Sbostic struct winsize win; 44*48945Sbostic struct termios t; 45*48945Sbostic enum FMT fmt; 46*48945Sbostic int ch, ctl, ldisc, tmp; 471179Sbill 48*48945Sbostic ctl = STDIN_FILENO; 49*48945Sbostic fmt = NOTSET; 50*48945Sbostic while ((ch = getopt(argc, argv, "aef:g")) != EOF) 51*48945Sbostic switch(ch) { 52*48945Sbostic case 'a': /* undocumented: POSIX compatibility */ 53*48945Sbostic fmt = POSIX; 54*48945Sbostic break; 55*48945Sbostic case 'e': 56*48945Sbostic fmt = BSD; 57*48945Sbostic break; 58*48945Sbostic case 'f': 59*48945Sbostic if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0) 60*48945Sbostic err(optarg); 61*48945Sbostic break; 62*48945Sbostic case 'g': 63*48945Sbostic fmt = GFLAG; 64*48945Sbostic break; 65*48945Sbostic case '?': 66*48945Sbostic usage(); 67*48945Sbostic default: 68*48945Sbostic --optind; 69*48945Sbostic goto args; 70*48945Sbostic } 71*48945Sbostic 72*48945Sbostic args: argc -= optind; 73*48945Sbostic argv += optind; 74*48945Sbostic 7538674Smarc if (ioctl(ctl, TIOCGETD, &ldisc) < 0) 76*48945Sbostic err("TIOCGETD: %s", strerror(errno)); 7738674Smarc if (tcgetattr(ctl, &t) < 0) 78*48945Sbostic err("tcgetattr: %s", strerror(errno)); 7938674Smarc if (ioctl(ctl, TIOCGWINSZ, &win) < 0) 80*48945Sbostic warn("TIOCGWINSZ: %s\n", strerror(errno)); 8138674Smarc 82*48945Sbostic checkredirect(); /* conversion aid */ 83*48945Sbostic 84*48945Sbostic switch(fmt) { 85*48945Sbostic case NOTSET: 86*48945Sbostic if (*argv) 87*48945Sbostic break; 88*48945Sbostic /* FALLTHROUGH */ 89*48945Sbostic case BSD: 90*48945Sbostic case POSIX: 91*48945Sbostic print(&t, &win, ldisc, fmt); 92*48945Sbostic break; 93*48945Sbostic case GFLAG: 94*48945Sbostic gprint(&t, &win, ldisc); 95*48945Sbostic break; 961179Sbill } 9738674Smarc 98*48945Sbostic #define CHK(s) (**argv == s[0] && !strcmp(*argv, s)) 99*48945Sbostic 100*48945Sbostic for (; *argv; ++argv) { 101*48945Sbostic if (CHK("-nl")) { 102*48945Sbostic t.c_iflag |= ICRNL; 103*48945Sbostic t.c_oflag |= ONLCR; 104*48945Sbostic continue; 1051179Sbill } 106*48945Sbostic if (CHK("all")) { 107*48945Sbostic print(&t, &win, ldisc, BSD); 108*48945Sbostic continue; 1091179Sbill } 110*48945Sbostic if (CHK("-cbreak")) 111*48945Sbostic goto reset; 112*48945Sbostic if (CHK("cbreak")) { 113*48945Sbostic t.c_iflag | BRKINT|IXON|IMAXBEL; 114*48945Sbostic t.c_oflag |= OPOST; 115*48945Sbostic t.c_lflag |= ISIG|IEXTEN; 116*48945Sbostic t.c_lflag &= ~ICANON; 117*48945Sbostic continue; 1181179Sbill } 119*48945Sbostic if (CHK("cols")) { 120*48945Sbostic if (!*++argv) 121*48945Sbostic err("option requires an argument -- cols"); 122*48945Sbostic goto columns; 1231179Sbill } 124*48945Sbostic if (CHK("columns")) { 125*48945Sbostic if (!*++argv) 126*48945Sbostic err("option requires an argument -- columns"); 127*48945Sbostic columns: win.ws_col = atoi(*argv); 128*48945Sbostic continue; 1293797Sroot } 130*48945Sbostic if (CHK("cooked")) 131*48945Sbostic goto reset; 132*48945Sbostic 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; 139*48945Sbostic continue; 1401179Sbill } 141*48945Sbostic if (CHK("everything")) { 142*48945Sbostic print(&t, &win, ldisc, BSD); 143*48945Sbostic continue; 144*48945Sbostic } 145*48945Sbostic if (CHK("-extproc")) { 146*48945Sbostic tmp = 0; 147*48945Sbostic ioctl(ctl, TIOCEXT, &tmp); 148*48945Sbostic continue; 149*48945Sbostic } 150*48945Sbostic if (CHK("extrpc")) { 151*48945Sbostic tmp = 1; 152*48945Sbostic ioctl(ctl, TIOCEXT, &tmp); 153*48945Sbostic continue; 154*48945Sbostic } 155*48945Sbostic if (CHK("ispeed")) { 156*48945Sbostic if (!*++argv) 157*48945Sbostic err("option requires an argument -- ispeed"); 158*48945Sbostic cfsetispeed(&t, atoi(*argv)); 159*48945Sbostic continue; 160*48945Sbostic } 161*48945Sbostic if (CHK("new")) 162*48945Sbostic goto tty; 163*48945Sbostic if (CHK("nl")) { 164*48945Sbostic t.c_iflag &= ~ICRNL; 165*48945Sbostic t.c_oflag &= ~ONLCR; 166*48945Sbostic continue; 167*48945Sbostic } 168*48945Sbostic if (CHK("old")) 169*48945Sbostic goto tty; 170*48945Sbostic if (CHK("ospeed")) { 171*48945Sbostic if (!*++argv) 172*48945Sbostic err("option requires an argument -- ospeed"); 173*48945Sbostic cfsetospeed(&t, atoi(*argv)); 174*48945Sbostic continue; 175*48945Sbostic } 176*48945Sbostic if (CHK("-raw")) 177*48945Sbostic goto reset; 178*48945Sbostic if (CHK("raw")) { 17940169Skarels cfmakeraw(&t); 18040169Skarels t.c_cflag &= ~(CSIZE|PARENB); 18140169Skarels t.c_cflag |= CS8; 182*48945Sbostic continue; 18340169Skarels } 184*48945Sbostic if (CHK("rows")) { 185*48945Sbostic if (!*++argv) 186*48945Sbostic err("option requires an argument -- rows"); 187*48945Sbostic win.ws_row = atoi(*argv); 188*48945Sbostic continue; 18945029Smarc } 190*48945Sbostic if (CHK("sane")) { 191*48945Sbostic 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; 198*48945Sbostic continue; 19940169Skarels } 200*48945Sbostic if (CHK("size")) { 201*48945Sbostic (void)printf("%d %d\n", win.ws_row, win.ws_col); 202*48945Sbostic continue; 20318023Sbloom } 204*48945Sbostic if (CHK("speed")) { 205*48945Sbostic (void)printf("%d\n", cfgetospeed(&t)); 206*48945Sbostic continue; 20738674Smarc } 208*48945Sbostic if (CHK("tty")) { 209*48945Sbostic tty: tmp = TTYDISC; 210*48945Sbostic if (ioctl(0, TIOCSETD, &tmp) < 0) 211*48945Sbostic err("TIOCSETD: %s", strerror(errno)); 212*48945Sbostic continue; 21338674Smarc } 214*48945Sbostic 215*48945Sbostic for (mp = cmodes; mp->name; ++mp) 216*48945Sbostic if (CHK(mp->name)) { 217*48945Sbostic t.c_cflag &= ~mp->unset; 218*48945Sbostic t.c_cflag |= mp->set; 21938674Smarc goto next; 2201179Sbill } 221*48945Sbostic for (mp = imodes; mp->name; ++mp) 222*48945Sbostic if (CHK(mp->name)) { 223*48945Sbostic t.c_iflag &= ~mp->unset; 224*48945Sbostic t.c_iflag |= mp->set; 22538674Smarc goto next; 22638674Smarc } 227*48945Sbostic for (mp = lmodes; mp->name; ++mp) 228*48945Sbostic if (CHK(mp->name)) { 229*48945Sbostic t.c_lflag &= ~mp->unset; 230*48945Sbostic t.c_lflag |= mp->set; 23138674Smarc goto next; 23238674Smarc } 233*48945Sbostic for (mp = omodes; mp->name; ++mp) 234*48945Sbostic if (CHK(mp->name)) { 235*48945Sbostic t.c_oflag &= ~mp->unset; 236*48945Sbostic t.c_oflag |= mp->set; 23738674Smarc goto next; 23838674Smarc } 239*48945Sbostic for (cp = cchars1; cp->name; ++cp) { 240*48945Sbostic if (!CHK(cp->name)) 241*48945Sbostic continue; 242*48945Sbostic goto ccfound; 2431179Sbill } 244*48945Sbostic for (cp = cchars2; cp->name; ++cp) { 245*48945Sbostic if (!CHK(cp->name)) 246*48945Sbostic continue; 247*48945Sbostic ccfound: if (!*++argv) 248*48945Sbostic err("option requires an argument -- %s", 249*48945Sbostic cp->name); 250*48945Sbostic if (CHK("undef") || CHK("disable")) 251*48945Sbostic t.c_cc[cp->sub] = _POSIX_VDISABLE; 252*48945Sbostic else if (**argv == '^') 253*48945Sbostic t.c_cc[cp->sub] = 254*48945Sbostic ((*argv)[1] == '?') ? 0177 : 255*48945Sbostic ((*argv)[1] == '-') ? _POSIX_VDISABLE : 256*48945Sbostic (*argv)[1] & 037; 257*48945Sbostic else 258*48945Sbostic t.c_cc[cp->sub] = **argv; 259*48945Sbostic goto next; 260*48945Sbostic } 261*48945Sbostic 26238674Smarc if (isdigit(**argv)) { 26338674Smarc cfsetospeed(&t, atoi(*argv)); 26438674Smarc cfsetispeed(&t, atoi(*argv)); 26538674Smarc goto next; 26638674Smarc } 267*48945Sbostic if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) { 268*48945Sbostic gread(&t, *argv + sizeof("gfmt1") - 1); 26943323Smarc goto next; 27043323Smarc } 271*48945Sbostic 272*48945Sbostic err("illegal option -- %s", *argv); 273*48945Sbostic next: continue; 2741179Sbill } 275*48945Sbostic 27638674Smarc if (tcsetattr(ctl, 0, &t) < 0) 277*48945Sbostic err("tcsetattr: %s", strerror(errno)); 27838674Smarc if (ioctl(ctl, TIOCSWINSZ, &win) < 0) 279*48945Sbostic warn("TIOCSWINSZ: %s", strerror(errno)); 28038674Smarc exit(0); 2811179Sbill } 2821179Sbill 283*48945Sbostic static void 284*48945Sbostic usage() 28543323Smarc { 286*48945Sbostic (void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n"); 28738674Smarc exit(1); 28838674Smarc } 289