Commit | Line | Data |
---|---|---|
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 | 9 | char 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 | 15 | static 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 | 31 | static void usage __P((void)); |
b24648a6 | 32 | |
2ea9e68e | 33 | main(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 | ||
72 | args: 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"); | |
129 | columns: 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")) { |
200 | reset: 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")) { |
219 | tty: 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; | |
261 | ccfound: 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); | |
288 | next: 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 |
298 | static void |
299 | usage() | |
16b6b22b | 300 | { |
8adbaed7 | 301 | (void)fprintf(stderr, "usage: stty: [-eg] [-f file] [options]\n"); |
2ea9e68e | 302 | exit(1); |
16b6b22b | 303 | } |