manual page distributed with 4.2BSD
[unix-history] / usr / src / bin / stty / stty.c
CommitLineData
ba3dc8b4 1#ifndef lint
4f05342b 2static char *sccsid ="@(#)stty.c 4.15 (Berkeley) %G%";
ba3dc8b4 3#endif
16b6b22b
BJ
4/*
5 * set teletype modes
6 */
7
8#include <stdio.h>
4f05342b 9#include <sys/ioctl.h>
16b6b22b 10
ba3dc8b4
SL
11struct
12{
16b6b22b
BJ
13 char *string;
14 int speed;
15} speeds[] = {
ba3dc8b4
SL
16 "0", B0,
17 "50", B50,
18 "75", B75,
19 "110", B110,
20 "134", B134,
21 "134.5",B134,
22 "150", B150,
23 "200", B200,
24 "300", B300,
25 "600", B600,
26 "1200", B1200,
27 "1800", B1800,
28 "2400", B2400,
29 "4800", B4800,
30 "9600", B9600,
31 "exta", EXTA,
32 "19200", EXTA,
33 "extb", EXTB,
34 "38400", EXTB,
35 0,
16b6b22b 36};
ba3dc8b4
SL
37struct
38{
16b6b22b 39 char *string;
ba3dc8b4
SL
40 int set;
41 int reset;
42 int lset;
43 int lreset;
16b6b22b 44} modes[] = {
ba3dc8b4
SL
45 "even", EVENP, 0, 0, 0,
46 "-even", 0, EVENP, 0, 0,
47 "odd", ODDP, 0, 0, 0,
48 "-odd", 0, ODDP, 0, 0,
49 "raw", RAW, 0, 0, 0,
50 "-raw", 0, RAW, 0, 0,
51 "cooked", 0, RAW, 0, 0,
52 "-nl", CRMOD, 0, 0, 0,
53 "nl", 0, CRMOD, 0, 0,
54 "echo", ECHO, 0, 0, 0,
55 "-echo", 0, ECHO, 0, 0,
56 "LCASE", LCASE, 0, 0, 0,
57 "lcase", LCASE, 0, 0, 0,
58 "-LCASE", 0, LCASE, 0, 0,
59 "-lcase", 0, LCASE, 0, 0,
60 "-tabs", XTABS, 0, 0, 0,
61 "tabs", 0, XTABS, 0, 0,
62 "tandem", TANDEM, 0, 0, 0,
63 "-tandem", 0, TANDEM, 0, 0,
64 "cbreak", CBREAK, 0, 0, 0,
65 "-cbreak", 0, CBREAK, 0, 0,
66 "cr0", CR0, CR3, 0, 0,
67 "cr1", CR1, CR3, 0, 0,
68 "cr2", CR2, CR3, 0, 0,
69 "cr3", CR3, CR3, 0, 0,
70 "tab0", TAB0, XTABS, 0, 0,
71 "tab1", TAB1, XTABS, 0, 0,
72 "tab2", TAB2, XTABS, 0, 0,
73 "nl0", NL0, NL3, 0, 0,
74 "nl1", NL1, NL3, 0, 0,
75 "nl2", NL2, NL3, 0, 0,
76 "nl3", NL3, NL3, 0, 0,
77 "ff0", FF0, FF1, 0, 0,
78 "ff1", FF1, FF1, 0, 0,
79 "bs0", BS0, BS1, 0, 0,
80 "bs1", BS1, BS1, 0, 0,
81 "33", CR1, ALLDELAY, 0, 0,
82 "tty33", CR1, ALLDELAY, 0, 0,
83 "37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0,
84 "tty37", FF1+CR2+TAB1+NL1, ALLDELAY, 0, 0,
85 "05", NL2, ALLDELAY, 0, 0,
86 "vt05", NL2, ALLDELAY, 0, 0,
87 "tn", CR1, ALLDELAY, 0, 0,
88 "tn300", CR1, ALLDELAY, 0, 0,
89 "ti", CR2, ALLDELAY, 0, 0,
90 "ti700", CR2, ALLDELAY, 0, 0,
91 "tek", FF1, ALLDELAY, 0, 0,
92 "crtbs", 0, 0, LCRTBS, LPRTERA,
93 "-crtbs", 0, 0, 0, LCRTBS,
94 "prterase", 0, 0, LPRTERA, LCRTBS+LCRTKIL+LCRTERA,
95 "-prterase", 0, 0, 0, LPRTERA,
96 "crterase", 0, 0, LCRTERA, LPRTERA,
97 "-crterase", 0, 0, 0, LCRTERA,
98 "crtkill", 0, 0, LCRTKIL, LPRTERA,
99 "-crtkill", 0, 0, 0, LCRTKIL,
100 "tilde", 0, 0, LTILDE, 0,
101 "-tilde", 0, 0, 0, LTILDE,
102 "mdmbuf", 0, 0, LMDMBUF, 0,
103 "-mdmbuf", 0, 0, 0, LMDMBUF,
104 "litout", 0, 0, LLITOUT, 0,
105 "-litout", 0, 0, 0, LLITOUT,
106 "tostop", 0, 0, LTOSTOP, 0,
107 "-tostop", 0, 0, 0, LTOSTOP,
108 "flusho", 0, 0, LFLUSHO, 0,
109 "-flusho", 0, 0, 0, LFLUSHO,
110 "nohang", 0, 0, LNOHANG, 0,
111 "-nohang", 0, 0, 0, LNOHANG,
2be6f1d1 112#ifdef notdef
ba3dc8b4
SL
113 "etxack", 0, 0, LETXACK, 0,
114 "-etxack", 0, 0, 0, LETXACK,
2be6f1d1 115#endif
ba3dc8b4
SL
116 "ctlecho", 0, 0, LCTLECH, 0,
117 "-ctlecho", 0, 0, 0, LCTLECH,
118 "pendin", 0, 0, LPENDIN, 0,
119 "-pendin", 0, 0, 0, LPENDIN,
120 "decctlq", 0, 0, LDECCTQ, 0,
121 "-decctlq", 0, 0, 0, LDECCTQ,
122 "noflsh", 0, 0, LNOFLSH, 0,
123 "-noflsh", 0, 0, 0, LNOFLSH,
124 0,
16b6b22b
BJ
125};
126
ba3dc8b4
SL
127struct tchars tc;
128struct ltchars ltc;
129struct sgttyb mode;
4f05342b 130struct winsize win;
ba3dc8b4 131int lmode;
16b6b22b
BJ
132int oldisc, ldisc;
133
16b6b22b
BJ
134struct special {
135 char *name;
136 char *cp;
137 char def;
138} special[] = {
ba3dc8b4
SL
139 "erase", &mode.sg_erase, CERASE,
140 "kill", &mode.sg_kill, CKILL,
141 "intr", &tc.t_intrc, CINTR,
142 "quit", &tc.t_quitc, CQUIT,
143 "start", &tc.t_startc, CSTART,
144 "stop", &tc.t_stopc, CSTOP,
145 "eof", &tc.t_eofc, CEOF,
146 "brk", &tc.t_brkc, CBRK,
147 "susp", &ltc.t_suspc, CSUSP,
148 "dsusp", &ltc.t_dsuspc, CDSUSP,
149 "rprnt", &ltc.t_rprntc, CRPRNT,
150 "flush", &ltc.t_flushc, CFLUSH,
151 "werase", &ltc.t_werasc, CWERASE,
152 "lnext", &ltc.t_lnextc, CLNEXT,
16b6b22b
BJ
153 0
154};
155char *arg;
156
157int argc;
158char **argv;
159main(iargc, iargv)
ba3dc8b4 160char **iargv;
16b6b22b
BJ
161{
162 int i;
163 register struct special *sp;
164 char obuf[BUFSIZ];
165
166 setbuf(stderr, obuf);
167 argc = iargc;
168 argv = iargv;
ba3dc8b4 169 ioctl(1, TIOCGETP, &mode);
16b6b22b
BJ
170 ioctl(1, TIOCGETD, &ldisc);
171 oldisc = ldisc;
ba3dc8b4
SL
172 ioctl(1, TIOCGETC, &tc);
173 ioctl(1, TIOCLGET, &lmode);
174 ioctl(1, TIOCGLTC, &ltc);
4f05342b 175 ioctl(1, TIOCGWINSZ, &win);
ba3dc8b4 176 if(argc == 1) {
16b6b22b
BJ
177 prmodes(0);
178 exit(0);
179 }
180 if (argc == 2 && !strcmp(argv[1], "all")) {
181 prmodes(1);
182 exit(0);
183 }
184 if (argc == 2 && !strcmp(argv[1], "everything")) {
185 prmodes(2);
186 exit(0);
187 }
ba3dc8b4
SL
188/*
189 if (argc == 2 && !strcmp(argv[1], "all")) {
190 prmodes(2);
191 exit(0);
192 }
193*/
194 while(--argc > 0) {
16b6b22b 195 arg = *++argv;
ba3dc8b4
SL
196 if (eq("ek")){
197 mode.sg_erase = '#';
198 mode.sg_kill = '@';
16b6b22b
BJ
199 continue;
200 }
ba3dc8b4 201 if (eq("new")){
16b6b22b 202 ldisc = NTTYDISC;
ba3dc8b4 203 if (ioctl(1, TIOCSETD, &ldisc)<0)
16b6b22b
BJ
204 perror("ioctl");
205 continue;
206 }
ba3dc8b4 207 if (eq("newcrt")){
16b6b22b 208 ldisc = NTTYDISC;
ba3dc8b4
SL
209 lmode &= ~LPRTERA;
210 lmode |= LCRTBS|LCTLECH;
211 if (mode.sg_ospeed >= B1200)
212 lmode |= LCRTERA|LCRTKIL;
213 if (ioctl(1, TIOCSETD, &ldisc)<0)
16b6b22b
BJ
214 perror("ioctl");
215 continue;
216 }
ba3dc8b4
SL
217 if (eq("crt")){
218 lmode &= ~LPRTERA;
219 lmode |= LCRTBS|LCTLECH;
220 if (mode.sg_ospeed >= B1200)
221 lmode |= LCRTERA|LCRTKIL;
16b6b22b
BJ
222 continue;
223 }
ba3dc8b4
SL
224 if (eq("old")){
225 ldisc = 0;
226 if (ioctl(1, TIOCSETD, &ldisc)<0)
16b6b22b
BJ
227 perror("ioctl");
228 continue;
229 }
ba3dc8b4
SL
230 if (eq("dec")){
231 mode.sg_erase = 0177;
232 mode.sg_kill = CTRL(u);
233 tc.t_intrc = CTRL(c);
5e9810bc 234 ldisc = NTTYDISC;
ba3dc8b4
SL
235 lmode &= ~LPRTERA;
236 lmode |= LCRTBS|LCTLECH|LDECCTQ;
237 if (mode.sg_ospeed >= B1200)
238 lmode |= LCRTERA|LCRTKIL;
239 if (ioctl(1, TIOCSETD, &ldisc)<0)
5e9810bc
BJ
240 perror("ioctl");
241 continue;
242 }
16b6b22b
BJ
243 for (sp = special; sp->name; sp++)
244 if (eq(sp->name)) {
245 if (--argc == 0)
246 goto done;
247 if (**++argv == 'u')
248 *sp->cp = 0377;
249 else if (**argv == '^')
49d29e41 250 *sp->cp = ((*argv)[1] == '?') ?
16b6b22b
BJ
251 0177 : (*argv)[1] & 037;
252 else
253 *sp->cp = **argv;
254 goto cont;
255 }
256 if (eq("gspeed")) {
ba3dc8b4
SL
257 mode.sg_ispeed = B300;
258 mode.sg_ospeed = B9600;
16b6b22b
BJ
259 continue;
260 }
261 if (eq("hup")) {
ba3dc8b4 262 ioctl(1, TIOCHPCL, NULL);
16b6b22b
BJ
263 continue;
264 }
4f05342b
JB
265 if (eq("rows")) {
266 if (--argc == 0)
267 goto done;
268 win.ws_row = atoi(*++argv);
269 }
270 if (eq("columns")) {
271 if (--argc == 0)
272 goto done;
273 win.ws_col = atoi(*++argv);
274 }
ba3dc8b4
SL
275 for(i=0; speeds[i].string; i++)
276 if(eq(speeds[i].string)) {
277 mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed;
16b6b22b
BJ
278 goto cont;
279 }
280 if (eq("speed")) {
ba3dc8b4
SL
281 ioctl(open("/dev/tty", 0), TIOCGETP, &mode);
282 for(i=0; speeds[i].string; i++)
283 if (mode.sg_ospeed == speeds[i].speed) {
16b6b22b
BJ
284 printf("%s\n", speeds[i].string);
285 exit(0);
286 }
287 printf("unknown\n");
288 exit(1);
289 }
ba3dc8b4
SL
290 for(i=0; modes[i].string; i++)
291 if(eq(modes[i].string)) {
292 mode.sg_flags &= ~modes[i].reset;
293 mode.sg_flags |= modes[i].set;
294 lmode &= ~modes[i].lreset;
295 lmode |= modes[i].lset;
16b6b22b 296 }
ba3dc8b4 297 if(arg)
16b6b22b
BJ
298 fprintf(stderr,"unknown mode: %s\n", arg);
299cont:
300 ;
301 }
302done:
ba3dc8b4
SL
303 ioctl(1, TIOCSETN, &mode);
304 ioctl(1, TIOCSETC, &tc);
305 ioctl(1, TIOCSLTC, &ltc);
306 ioctl(1, TIOCLSET, &lmode);
4f05342b 307 ioctl(1, TIOCSWINSZ, &win);
16b6b22b
BJ
308}
309
310eq(string)
ba3dc8b4 311char *string;
16b6b22b
BJ
312{
313 int i;
314
ba3dc8b4
SL
315 if(!arg)
316 return(0);
16b6b22b
BJ
317 i = 0;
318loop:
ba3dc8b4 319 if(arg[i] != string[i])
16b6b22b 320 return(0);
ba3dc8b4 321 if(arg[i++] != '\0')
16b6b22b
BJ
322 goto loop;
323 arg = 0;
ba3dc8b4 324 return(1);
16b6b22b
BJ
325}
326
327prmodes(all)
328{
329 register m;
330 int any;
331
ba3dc8b4 332 if(ldisc==NETLDISC)
16b6b22b 333 fprintf(stderr, "net discipline, ");
ba3dc8b4 334 else if(ldisc==NTTYDISC)
16b6b22b 335 fprintf(stderr, "new tty, ");
ba3dc8b4 336 else if(all==2)
16b6b22b 337 fprintf(stderr, "old tty, ");
ba3dc8b4
SL
338 if(mode.sg_ispeed != mode.sg_ospeed) {
339 prspeed("input speed ", mode.sg_ispeed);
340 prspeed("output speed ", mode.sg_ospeed);
16b6b22b 341 } else
ba3dc8b4 342 prspeed("speed ", mode.sg_ispeed);
4f05342b
JB
343 if (all)
344 fprintf(stderr, ", %d rows, %d columns", win.ws_row, win.ws_col);
ba3dc8b4
SL
345 fprintf(stderr, all==2 ? "\n" : "; ");
346 m = mode.sg_flags;
347 if(all==2 || (m&(EVENP|ODDP))!=(EVENP|ODDP)) {
348 if(m & EVENP) fprintf(stderr,"even ");
349 if(m & ODDP) fprintf(stderr,"odd ");
16b6b22b 350 }
ba3dc8b4
SL
351 if(all==2 || m&RAW)
352 fprintf(stderr,"-raw "+((m&RAW)!=0));
353 if(all==2 || (m&CRMOD)==0)
354 fprintf(stderr,"-nl "+((m&CRMOD)==0));
355 if(all==2 || (m&ECHO)==0)
356 fprintf(stderr,"-echo "+((m&ECHO)!=0));
357 if(all==2 || (m&LCASE))
358 fprintf(stderr,"-lcase "+((m&LCASE)!=0));
359 if(all==2 || (m&TANDEM))
360 fprintf(stderr,"-tandem "+((m&TANDEM)!=0));
361 fprintf(stderr,"-tabs "+((m&XTABS)!=XTABS));
362 if(all==2 || (m&CBREAK))
363 fprintf(stderr,"-cbreak "+((m&CBREAK)!=0));
364 if(all==2 || (m&NLDELAY))
365 delay((m&NLDELAY)/NL1, "nl");
366 if ((m&TBDELAY)!=XTABS)
367 delay((m&TBDELAY)/TAB1, "tab");
368 if(all==2 || (m&CRDELAY))
369 delay((m&CRDELAY)/CR1, "cr");
370 if(all==2 || (m&VTDELAY))
371 delay((m&VTDELAY)/FF1, "ff");
372 if(all==2 || (m&BSDELAY))
373 delay((m&BSDELAY)/BS1, "bs");
16b6b22b
BJ
374 if (all)
375 fprintf(stderr,"\n");
376#define lpit(what,str) \
ba3dc8b4
SL
377 if (all==2||(lmode&what)) { \
378 fprintf(stderr,str+((lmode&what)!=0)); any++; \
16b6b22b
BJ
379 }
380 if (ldisc == NTTYDISC) {
ba3dc8b4
SL
381 int newcrt = (lmode&(LCTLECH|LCRTBS)) == (LCTLECH|LCRTBS) &&
382 (lmode&(LCRTERA|LCRTKIL)) ==
383 ((mode.sg_ospeed > B300) ? LCRTERA|LCRTKIL : 0);
74a327ac 384 int nothing = 1;
16b6b22b 385 if (newcrt) {
ba3dc8b4
SL
386 if (all==2)
387 fprintf(stderr, "crt: (crtbs crterase crtkill ctlecho) ");
388 else
389 fprintf(stderr, "crt ");
16b6b22b
BJ
390 any++;
391 } else {
ba3dc8b4
SL
392 lpit(LCRTBS, "-crtbs ");
393 lpit(LCRTERA, "-crterase ");
394 lpit(LCRTKIL, "-crtkill ");
395 lpit(LCTLECH, "-ctlecho ");
396 lpit(LPRTERA, "-prterase ");
16b6b22b 397 }
ba3dc8b4
SL
398 lpit(LTOSTOP, "-tostop ");
399 if (all==2) {
16b6b22b
BJ
400 fprintf(stderr, "\n");
401 any = 0;
74a327ac 402 nothing = 0;
16b6b22b 403 }
ba3dc8b4
SL
404 lpit(LTILDE, "-tilde ");
405 lpit(LFLUSHO, "-flusho ");
406 lpit(LMDMBUF, "-mdmbuf ");
407 lpit(LLITOUT, "-litout ");
408 lpit(LNOHANG, "-nohang ");
7ef182e7
BJ
409 if (any) {
410 fprintf(stderr,"\n");
411 any = 0;
74a327ac 412 nothing = 0;
7ef182e7 413 }
2be6f1d1 414#ifdef notdef
ba3dc8b4 415 lpit(LETXACK, "-etxack ");
2be6f1d1 416#endif
ba3dc8b4
SL
417 lpit(LPENDIN, "-pendin ");
418 lpit(LDECCTQ, "-decctlq ");
419 lpit(LNOFLSH, "-noflsh ");
74a327ac 420 if (any || nothing)
16b6b22b
BJ
421 fprintf(stderr,"\n");
422 } else if (!all)
423 fprintf(stderr,"\n");
424 if (all) {
425 switch (ldisc) {
426
427 case 0:
428 fprintf(stderr,"\
429erase kill intr quit stop eof\
430\n");
ba3dc8b4
SL
431 pcol(mode.sg_erase, -1);
432 pcol(mode.sg_kill, -1);
433 pcol(tc.t_intrc, -1);
434 pcol(tc.t_quitc, -1);
435 pcol(tc.t_stopc, tc.t_startc);
436 pcol(tc.t_eofc, tc.t_brkc);
16b6b22b
BJ
437 fprintf(stderr,"\n");
438 break;
439
440 case NTTYDISC:
441 fprintf(stderr,"\
442erase kill werase rprnt flush lnext susp intr quit stop eof\
443\n");
ba3dc8b4
SL
444 pcol(mode.sg_erase, -1);
445 pcol(mode.sg_kill, -1);
446 pcol(ltc.t_werasc, -1);
447 pcol(ltc.t_rprntc, -1);
448 pcol(ltc.t_flushc, -1);
449 pcol(ltc.t_lnextc, -1);
450 pcol(ltc.t_suspc, ltc.t_dsuspc);
451 pcol(tc.t_intrc, -1);
452 pcol(tc.t_quitc, -1);
453 pcol(tc.t_stopc, tc.t_startc);
454 pcol(tc.t_eofc, tc.t_brkc);
16b6b22b
BJ
455 fprintf(stderr,"\n");
456 break;
457 }
458 } else if (ldisc != NETLDISC) {
459 register struct special *sp;
460 int first = 1;
74a327ac 461
16b6b22b
BJ
462 for (sp = special; sp->name; sp++) {
463 if ((*sp->cp&0377) != (sp->def&0377)) {
464 pit(*sp->cp, sp->name, first ? "" : ", ");
465 first = 0;
466 };
ba3dc8b4 467 if (sp->cp == &tc.t_brkc && ldisc == 0)
16b6b22b
BJ
468 break;
469 }
74a327ac 470 if (!first)
ba3dc8b4 471 fprintf(stderr, "\n");
16b6b22b
BJ
472 }
473}
474
475pcol(ch1, ch2)
476 int ch1, ch2;
477{
478 int nout = 0;
479
480 ch1 &= 0377;
481 ch2 &= 0377;
482 if (ch1 == ch2)
483 ch2 = 0377;
484 for (; ch1 != 0377 || ch2 != 0377; ch1 = ch2, ch2 = 0377) {
485 if (ch1 == 0377)
486 continue;
487 if (ch1 & 0200) {
488 fprintf(stderr, "M-");
489 nout += 2;
490 ch1 &= ~ 0200;
491 }
492 if (ch1 == 0177) {
493 fprintf(stderr, "^");
494 nout++;
495 ch1 = '?';
496 } else if (ch1 < ' ') {
497 fprintf(stderr, "^");
498 nout++;
499 ch1 += '@';
500 }
501 fprintf(stderr, "%c", ch1);
502 nout++;
503 if (ch2 != 0377) {
504 fprintf(stderr, "/");
505 nout++;
506 }
507 }
508 while (nout < 7) {
509 fprintf(stderr, " ");
510 nout++;
511 }
512}
513
514pit(what, itsname, sep)
515 unsigned what;
516 char *itsname, *sep;
517{
518
519 what &= 0377;
520 fprintf(stderr, "%s%s", sep, itsname);
521 if (what == 0377) {
522 fprintf(stderr, " <undef>");
523 return;
524 }
525 fprintf(stderr, " = ");
526 if (what & 0200) {
527 fprintf(stderr, "M-");
528 what &= ~ 0200;
529 }
530 if (what == 0177) {
531 fprintf(stderr, "^");
532 what = '?';
533 } else if (what < ' ') {
534 fprintf(stderr, "^");
535 what += '@';
536 }
537 fprintf(stderr, "%c", what);
538}
539
540delay(m, s)
ba3dc8b4 541char *s;
16b6b22b
BJ
542{
543
ba3dc8b4 544 if(m)
16b6b22b
BJ
545 fprintf(stderr,"%s%d ", s, m);
546}
547
548int speed[] = {
6bf7d5d9 549 0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400
16b6b22b
BJ
550};
551
552prspeed(c, s)
553char *c;
554{
555
556 fprintf(stderr,"%s%d baud", c, speed[s]);
557}