don't do a tcsetattr/window ioctl unless asked to
[unix-history] / usr / src / bin / stty / stty.c
CommitLineData
356242cc 1/*-
8adbaed7 2 * Copyright (c) 1989, 1991 The Regents of the University of California.
356242cc
KB
3 * All rights reserved.
4 *
7bcd1bb8 5 * %sccs.include.redist.c%
18949a0b
DF
6 */
7
ba3dc8b4 8#ifndef lint
18949a0b 9char copyright[] =
8adbaed7 10"@(#) Copyright (c) 1989, 1991 The Regents of the University of California.\n\
18949a0b 11 All rights reserved.\n";
356242cc 12#endif /* not lint */
18949a0b
DF
13
14#ifndef lint
163abe81 15static char sccsid[] = "@(#)stty.c 5.26 (Berkeley) %G%";
356242cc 16#endif /* not lint */
18949a0b 17
2ea9e68e 18#include <sys/types.h>
4f05342b 19#include <sys/ioctl.h>
8adbaed7
KB
20#include <termios.h>
21#include <fcntl.h>
2ea9e68e 22#include <errno.h>
8adbaed7 23#include <unistd.h>
14fd0bf8 24#include <stdio.h>
8adbaed7
KB
25#include <ctype.h>
26#include <stdlib.h>
27#include <string.h>
28#include "stty.h"
29#include "extern.h"
16b6b22b 30
8adbaed7 31static void usage __P((void));
b24648a6 32
2ea9e68e 33main(argc, argv)
8adbaed7
KB
34 int argc;
35 char **argv;
16b6b22b 36{
2ea9e68e 37 extern char *optarg;
61439c4c 38 extern int opterr, optind;
8adbaed7
KB
39 extern struct cchar cchars1[], cchars2[];
40 extern struct modes cmodes[], imodes[], lmodes[], omodes[];
41 register struct modes *mp;
42 register struct cchar *cp;
43 struct winsize win;
44 struct termios t;
45 enum FMT fmt;
163abe81 46 int ch, ctl, ldisc, set, tmp, wset;
8adbaed7
KB
47
48 ctl = STDIN_FILENO;
49 fmt = NOTSET;
61439c4c 50 opterr = 0;
13c7f8d6
KB
51 while (strspn(argv[optind], "-aefg") == strlen(argv[optind]) &&
52 (ch = getopt(argc, argv, "aef:g")) != EOF)
8adbaed7
KB
53 switch(ch) {
54 case 'a': /* undocumented: POSIX compatibility */
55 fmt = POSIX;
56 break;
57 case 'e':
58 fmt = BSD;
59 break;
60 case 'f':
61 if ((ctl = open(optarg, O_RDONLY | O_NONBLOCK)) < 0)
13c7f8d6 62 err("%s: %s", optarg, strerror(errno));
8adbaed7
KB
63 break;
64 case 'g':
65 fmt = GFLAG;
66 break;
67 case '?':
8adbaed7 68 default:
8adbaed7
KB
69 goto args;
70 }
71
72args: argc -= optind;
73 argv += optind;
2ea9e68e 74
2ea9e68e 75 if (ioctl(ctl, TIOCGETD, &ldisc) < 0)
8adbaed7 76 err("TIOCGETD: %s", strerror(errno));
2ea9e68e 77 if (tcgetattr(ctl, &t) < 0)
8adbaed7 78 err("tcgetattr: %s", strerror(errno));
2ea9e68e 79 if (ioctl(ctl, TIOCGWINSZ, &win) < 0)
8adbaed7 80 warn("TIOCGWINSZ: %s\n", strerror(errno));
2ea9e68e 81
8adbaed7
KB
82 checkredirect(); /* conversion aid */
83
84 switch(fmt) {
85 case NOTSET:
86 if (*argv)
87 break;
88 /* FALLTHROUGH */
89 case BSD:
90 case POSIX:
91 print(&t, &win, ldisc, fmt);
92 break;
93 case GFLAG:
94 gprint(&t, &win, ldisc);
95 break;
ba3dc8b4 96 }
2ea9e68e 97
8adbaed7
KB
98#define CHK(s) (**argv == s[0] && !strcmp(*argv, s))
99
163abe81 100 for (set = wset = 0; *argv; ++argv) {
8adbaed7
KB
101 if (CHK("-nl")) {
102 t.c_iflag |= ICRNL;
103 t.c_oflag |= ONLCR;
163abe81 104 set = 1;
8adbaed7 105 continue;
16b6b22b 106 }
8adbaed7
KB
107 if (CHK("all")) {
108 print(&t, &win, ldisc, BSD);
109 continue;
16b6b22b 110 }
8adbaed7
KB
111 if (CHK("-cbreak"))
112 goto reset;
113 if (CHK("cbreak")) {
114 t.c_iflag | BRKINT|IXON|IMAXBEL;
115 t.c_oflag |= OPOST;
116 t.c_lflag |= ISIG|IEXTEN;
117 t.c_lflag &= ~ICANON;
163abe81 118 set = 1;
8adbaed7 119 continue;
16b6b22b 120 }
8adbaed7
KB
121 if (CHK("cols")) {
122 if (!*++argv)
123 err("option requires an argument -- cols");
124 goto columns;
5e9810bc 125 }
8adbaed7
KB
126 if (CHK("columns")) {
127 if (!*++argv)
128 err("option requires an argument -- columns");
129columns: win.ws_col = atoi(*argv);
163abe81 130 wset = 1;
8adbaed7 131 continue;
16b6b22b 132 }
8adbaed7
KB
133 if (CHK("cooked"))
134 goto reset;
135 if (CHK("dec")) {
2ea9e68e
MT
136 t.c_cc[VERASE] = (u_char)0177;
137 t.c_cc[VKILL] = CTRL('u');
138 t.c_cc[VINTR] = CTRL('c');
139 t.c_lflag &= ~ECHOPRT;
140 t.c_lflag |= ECHOE|ECHOKE|ECHOCTL;
141 t.c_iflag &= ~IXANY;
163abe81 142 set = 1;
8adbaed7
KB
143 continue;
144 }
145 if (CHK("everything")) {
146 print(&t, &win, ldisc, BSD);
147 continue;
148 }
149 if (CHK("-extproc")) {
150 tmp = 0;
151 ioctl(ctl, TIOCEXT, &tmp);
152 continue;
153 }
163abe81 154 if (CHK("extproc")) {
8adbaed7
KB
155 tmp = 1;
156 ioctl(ctl, TIOCEXT, &tmp);
157 continue;
158 }
159 if (CHK("ispeed")) {
160 if (!*++argv)
161 err("option requires an argument -- ispeed");
162 cfsetispeed(&t, atoi(*argv));
163abe81 163 set = 1;
8adbaed7
KB
164 continue;
165 }
166 if (CHK("new"))
167 goto tty;
168 if (CHK("nl")) {
169 t.c_iflag &= ~ICRNL;
170 t.c_oflag &= ~ONLCR;
163abe81 171 set = 1;
8adbaed7
KB
172 continue;
173 }
174 if (CHK("old"))
175 goto tty;
176 if (CHK("ospeed")) {
177 if (!*++argv)
178 err("option requires an argument -- ospeed");
179 cfsetospeed(&t, atoi(*argv));
163abe81 180 set = 1;
8adbaed7 181 continue;
16b6b22b 182 }
8adbaed7
KB
183 if (CHK("-raw"))
184 goto reset;
185 if (CHK("raw")) {
c086ab51
MK
186 cfmakeraw(&t);
187 t.c_cflag &= ~(CSIZE|PARENB);
188 t.c_cflag |= CS8;
163abe81 189 set = 1;
8adbaed7 190 continue;
c086ab51 191 }
8adbaed7
KB
192 if (CHK("rows")) {
193 if (!*++argv)
194 err("option requires an argument -- rows");
195 win.ws_row = atoi(*argv);
163abe81 196 wset = 1;
8adbaed7 197 continue;
be51e567 198 }
8adbaed7
KB
199 if (CHK("sane")) {
200reset: t.c_cflag = TTYDEF_CFLAG | (t.c_cflag & CLOCAL);
c086ab51
MK
201 t.c_iflag = TTYDEF_IFLAG;
202 t.c_iflag |= ICRNL;
203 /* preserve user-preference flags in lflag */
204#define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH)
205 t.c_lflag = TTYDEF_LFLAG | (t.c_lflag & LKEEP);
206 t.c_oflag = TTYDEF_OFLAG;
163abe81 207 set = 1;
8adbaed7 208 continue;
2ea9e68e 209 }
8adbaed7
KB
210 if (CHK("size")) {
211 (void)printf("%d %d\n", win.ws_row, win.ws_col);
212 continue;
4f05342b 213 }
8adbaed7
KB
214 if (CHK("speed")) {
215 (void)printf("%d\n", cfgetospeed(&t));
216 continue;
b893a630 217 }
8adbaed7
KB
218 if (CHK("tty")) {
219tty: tmp = TTYDISC;
220 if (ioctl(0, TIOCSETD, &tmp) < 0)
221 err("TIOCSETD: %s", strerror(errno));
222 continue;
2ea9e68e 223 }
8adbaed7
KB
224
225 for (mp = cmodes; mp->name; ++mp)
226 if (CHK(mp->name)) {
227 t.c_cflag &= ~mp->unset;
228 t.c_cflag |= mp->set;
163abe81 229 set = 1;
2ea9e68e
MT
230 goto next;
231 }
8adbaed7
KB
232 for (mp = imodes; mp->name; ++mp)
233 if (CHK(mp->name)) {
234 t.c_iflag &= ~mp->unset;
235 t.c_iflag |= mp->set;
163abe81 236 set = 1;
2ea9e68e 237 goto next;
16b6b22b 238 }
8adbaed7
KB
239 for (mp = lmodes; mp->name; ++mp)
240 if (CHK(mp->name)) {
241 t.c_lflag &= ~mp->unset;
242 t.c_lflag |= mp->set;
163abe81 243 set = 1;
2ea9e68e
MT
244 goto next;
245 }
8adbaed7
KB
246 for (mp = omodes; mp->name; ++mp)
247 if (CHK(mp->name)) {
248 t.c_oflag &= ~mp->unset;
249 t.c_oflag |= mp->set;
163abe81 250 set = 1;
2ea9e68e
MT
251 goto next;
252 }
8adbaed7
KB
253 for (cp = cchars1; cp->name; ++cp) {
254 if (!CHK(cp->name))
255 continue;
256 goto ccfound;
257 }
258 for (cp = cchars2; cp->name; ++cp) {
259 if (!CHK(cp->name))
260 continue;
261ccfound: if (!*++argv)
262 err("option requires an argument -- %s",
263 cp->name);
f4cec85e 264 if (CHK("undef") || CHK("<undef>"))
8adbaed7
KB
265 t.c_cc[cp->sub] = _POSIX_VDISABLE;
266 else if (**argv == '^')
267 t.c_cc[cp->sub] =
268 ((*argv)[1] == '?') ? 0177 :
269 ((*argv)[1] == '-') ? _POSIX_VDISABLE :
270 (*argv)[1] & 037;
271 else
272 t.c_cc[cp->sub] = **argv;
163abe81 273 set = 1;
8adbaed7 274 goto next;
2ea9e68e 275 }
8adbaed7 276
2ea9e68e
MT
277 if (isdigit(**argv)) {
278 cfsetospeed(&t, atoi(*argv));
279 cfsetispeed(&t, atoi(*argv));
280 goto next;
281 }
8adbaed7
KB
282 if (!strncmp(*argv, "gfmt1", sizeof("gfmt1") - 1)) {
283 gread(&t, *argv + sizeof("gfmt1") - 1);
6d749894
MT
284 goto next;
285 }
8adbaed7
KB
286
287 err("illegal option -- %s", *argv);
288next: continue;
16b6b22b 289 }
8adbaed7 290
163abe81 291 if (set && tcsetattr(ctl, 0, &t) < 0)
8adbaed7 292 err("tcsetattr: %s", strerror(errno));
163abe81 293 if (wset && ioctl(ctl, TIOCSWINSZ, &win) < 0)
8adbaed7 294 warn("TIOCSWINSZ: %s", strerror(errno));
2ea9e68e 295 exit(0);
16b6b22b
BJ
296}
297
8adbaed7
KB
298static void
299usage()
16b6b22b 300{
8adbaed7 301 (void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n");
2ea9e68e 302 exit(1);
16b6b22b 303}