xref: /original-bsd/bin/stty/stty.c (revision c43e4352)
1 #ifndef lint
2 static char *sccsid ="@(#)stty.c	4.14 (Berkeley) 07/06/83";
3 #endif
4 /*
5  * set teletype modes
6  */
7 
8 #include <stdio.h>
9 #include <sgtty.h>
10 
11 struct
12 {
13 	char	*string;
14 	int	speed;
15 } speeds[] = {
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,
36 };
37 struct
38 {
39 	char	*string;
40 	int	set;
41 	int	reset;
42 	int	lset;
43 	int	lreset;
44 } modes[] = {
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,
112 #ifdef notdef
113 	"etxack",	0, 0, LETXACK, 0,
114 	"-etxack",	0, 0, 0, LETXACK,
115 #endif
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,
125 };
126 
127 struct tchars tc;
128 struct ltchars ltc;
129 struct sgttyb mode;
130 int	lmode;
131 int	oldisc, ldisc;
132 
133 struct	special {
134 	char	*name;
135 	char	*cp;
136 	char	def;
137 } special[] = {
138 	"erase",	&mode.sg_erase,		CERASE,
139 	"kill",		&mode.sg_kill,		CKILL,
140 	"intr",		&tc.t_intrc,		CINTR,
141 	"quit",		&tc.t_quitc,		CQUIT,
142 	"start",	&tc.t_startc,		CSTART,
143 	"stop",		&tc.t_stopc,		CSTOP,
144 	"eof",		&tc.t_eofc,		CEOF,
145 	"brk",		&tc.t_brkc,		CBRK,
146 	"susp",		&ltc.t_suspc,		CSUSP,
147 	"dsusp",	&ltc.t_dsuspc,		CDSUSP,
148 	"rprnt",	&ltc.t_rprntc,		CRPRNT,
149 	"flush",	&ltc.t_flushc,		CFLUSH,
150 	"werase",	&ltc.t_werasc,		CWERASE,
151 	"lnext",	&ltc.t_lnextc,		CLNEXT,
152 	0
153 };
154 char	*arg;
155 
156 int	argc;
157 char	**argv;
158 main(iargc, iargv)
159 char	**iargv;
160 {
161 	int i;
162 	register struct special *sp;
163 	char obuf[BUFSIZ];
164 
165 	setbuf(stderr, obuf);
166 	argc = iargc;
167 	argv = iargv;
168 	ioctl(1, TIOCGETP, &mode);
169 	ioctl(1, TIOCGETD, &ldisc);
170 	oldisc = ldisc;
171 	ioctl(1, TIOCGETC, &tc);
172 	ioctl(1, TIOCLGET, &lmode);
173 	ioctl(1, TIOCGLTC, &ltc);
174 	if(argc == 1) {
175 		prmodes(0);
176 		exit(0);
177 	}
178 	if (argc == 2 && !strcmp(argv[1], "all")) {
179 		prmodes(1);
180 		exit(0);
181 	}
182 	if (argc == 2 && !strcmp(argv[1], "everything")) {
183 		prmodes(2);
184 		exit(0);
185 	}
186 /*
187 	if (argc == 2 && !strcmp(argv[1], "all")) {
188 		prmodes(2);
189 		exit(0);
190 	}
191 */
192 	while(--argc > 0) {
193 		arg = *++argv;
194 		if (eq("ek")){
195 			mode.sg_erase = '#';
196 			mode.sg_kill = '@';
197 			continue;
198 		}
199 		if (eq("new")){
200 			ldisc = NTTYDISC;
201 			if (ioctl(1, TIOCSETD, &ldisc)<0)
202 				perror("ioctl");
203 			continue;
204 		}
205 		if (eq("newcrt")){
206 			ldisc = NTTYDISC;
207 			lmode &= ~LPRTERA;
208 			lmode |= LCRTBS|LCTLECH;
209 			if (mode.sg_ospeed >= B1200)
210 				lmode |= LCRTERA|LCRTKIL;
211 			if (ioctl(1, TIOCSETD, &ldisc)<0)
212 				perror("ioctl");
213 			continue;
214 		}
215 		if (eq("crt")){
216 			lmode &= ~LPRTERA;
217 			lmode |= LCRTBS|LCTLECH;
218 			if (mode.sg_ospeed >= B1200)
219 				lmode |= LCRTERA|LCRTKIL;
220 			continue;
221 		}
222 		if (eq("old")){
223 			ldisc = 0;
224 			if (ioctl(1, TIOCSETD, &ldisc)<0)
225 				perror("ioctl");
226 			continue;
227 		}
228 		if (eq("dec")){
229 			mode.sg_erase = 0177;
230 			mode.sg_kill = CTRL(u);
231 			tc.t_intrc = CTRL(c);
232 			ldisc = NTTYDISC;
233 			lmode &= ~LPRTERA;
234 			lmode |= LCRTBS|LCTLECH|LDECCTQ;
235 			if (mode.sg_ospeed >= B1200)
236 				lmode |= LCRTERA|LCRTKIL;
237 			if (ioctl(1, TIOCSETD, &ldisc)<0)
238 				perror("ioctl");
239 			continue;
240 		}
241 		for (sp = special; sp->name; sp++)
242 			if (eq(sp->name)) {
243 				if (--argc == 0)
244 					goto done;
245 				if (**++argv == 'u')
246 					*sp->cp = 0377;
247 				else if (**argv == '^')
248 					*sp->cp = ((*argv)[1] == '?') ?
249 					    0177 : (*argv)[1] & 037;
250 				else
251 					*sp->cp = **argv;
252 				goto cont;
253 			}
254 		if (eq("gspeed")) {
255 			mode.sg_ispeed = B300;
256 			mode.sg_ospeed = B9600;
257 			continue;
258 		}
259 		if (eq("hup")) {
260 			ioctl(1, TIOCHPCL, NULL);
261 			continue;
262 		}
263 		for(i=0; speeds[i].string; i++)
264 			if(eq(speeds[i].string)) {
265 				mode.sg_ispeed = mode.sg_ospeed = speeds[i].speed;
266 				goto cont;
267 			}
268 		if (eq("speed")) {
269 			ioctl(open("/dev/tty", 0), TIOCGETP, &mode);
270 			for(i=0; speeds[i].string; i++)
271 				if (mode.sg_ospeed == speeds[i].speed) {
272 					printf("%s\n", speeds[i].string);
273 					exit(0);
274 				}
275 			printf("unknown\n");
276 			exit(1);
277 		}
278 		for(i=0; modes[i].string; i++)
279 			if(eq(modes[i].string)) {
280 				mode.sg_flags &= ~modes[i].reset;
281 				mode.sg_flags |= modes[i].set;
282 				lmode &= ~modes[i].lreset;
283 				lmode |= modes[i].lset;
284 			}
285 		if(arg)
286 			fprintf(stderr,"unknown mode: %s\n", arg);
287 cont:
288 		;
289 	}
290 done:
291 	ioctl(1, TIOCSETN, &mode);
292 	ioctl(1, TIOCSETC, &tc);
293 	ioctl(1, TIOCSLTC, &ltc);
294 	ioctl(1, TIOCLSET, &lmode);
295 }
296 
297 eq(string)
298 char *string;
299 {
300 	int i;
301 
302 	if(!arg)
303 		return(0);
304 	i = 0;
305 loop:
306 	if(arg[i] != string[i])
307 		return(0);
308 	if(arg[i++] != '\0')
309 		goto loop;
310 	arg = 0;
311 	return(1);
312 }
313 
314 prmodes(all)
315 {
316 	register m;
317 	int any;
318 
319 	if(ldisc==NETLDISC)
320 		fprintf(stderr, "net discipline, ");
321 	else if(ldisc==NTTYDISC)
322 		fprintf(stderr, "new tty, ");
323 	else if(all==2)
324 		fprintf(stderr, "old tty, ");
325 	if(mode.sg_ispeed != mode.sg_ospeed) {
326 		prspeed("input speed ", mode.sg_ispeed);
327 		prspeed("output speed ", mode.sg_ospeed);
328 	} else
329 		prspeed("speed ", mode.sg_ispeed);
330 	fprintf(stderr, all==2 ? "\n" : "; ");
331 	m = mode.sg_flags;
332 	if(all==2 || (m&(EVENP|ODDP))!=(EVENP|ODDP)) {
333 		if(m & EVENP)	fprintf(stderr,"even ");
334 		if(m & ODDP)	fprintf(stderr,"odd ");
335 	}
336 	if(all==2 || m&RAW)
337 		fprintf(stderr,"-raw "+((m&RAW)!=0));
338 	if(all==2 || (m&CRMOD)==0)
339 		fprintf(stderr,"-nl "+((m&CRMOD)==0));
340 	if(all==2 || (m&ECHO)==0)
341 		fprintf(stderr,"-echo "+((m&ECHO)!=0));
342 	if(all==2 || (m&LCASE))
343 		fprintf(stderr,"-lcase "+((m&LCASE)!=0));
344 	if(all==2 || (m&TANDEM))
345 		fprintf(stderr,"-tandem "+((m&TANDEM)!=0));
346 	fprintf(stderr,"-tabs "+((m&XTABS)!=XTABS));
347 	if(all==2 || (m&CBREAK))
348 		fprintf(stderr,"-cbreak "+((m&CBREAK)!=0));
349 	if(all==2 || (m&NLDELAY))
350 		delay((m&NLDELAY)/NL1,	"nl");
351 	if ((m&TBDELAY)!=XTABS)
352 		delay((m&TBDELAY)/TAB1,	"tab");
353 	if(all==2 || (m&CRDELAY))
354 		delay((m&CRDELAY)/CR1,	"cr");
355 	if(all==2 || (m&VTDELAY))
356 		delay((m&VTDELAY)/FF1,	"ff");
357 	if(all==2 || (m&BSDELAY))
358 		delay((m&BSDELAY)/BS1,	"bs");
359 	if (all)
360 		fprintf(stderr,"\n");
361 #define	lpit(what,str) \
362 	if (all==2||(lmode&what)) { \
363 		fprintf(stderr,str+((lmode&what)!=0)); any++; \
364 	}
365 	if (ldisc == NTTYDISC) {
366 		int newcrt = (lmode&(LCTLECH|LCRTBS)) == (LCTLECH|LCRTBS) &&
367 		    (lmode&(LCRTERA|LCRTKIL)) ==
368 		      ((mode.sg_ospeed > B300) ? LCRTERA|LCRTKIL : 0);
369 		int nothing = 1;
370 		if (newcrt) {
371 			if (all==2)
372 				fprintf(stderr, "crt: (crtbs crterase crtkill ctlecho) ");
373 			else
374 				fprintf(stderr, "crt ");
375 			any++;
376 		} else {
377 			lpit(LCRTBS, "-crtbs ");
378 			lpit(LCRTERA, "-crterase ");
379 			lpit(LCRTKIL, "-crtkill ");
380 			lpit(LCTLECH, "-ctlecho ");
381 			lpit(LPRTERA, "-prterase ");
382 		}
383 		lpit(LTOSTOP, "-tostop ");
384 		if (all==2) {
385 			fprintf(stderr, "\n");
386 			any = 0;
387 			nothing = 0;
388 		}
389 		lpit(LTILDE, "-tilde ");
390 		lpit(LFLUSHO, "-flusho ");
391 		lpit(LMDMBUF, "-mdmbuf ");
392 		lpit(LLITOUT, "-litout ");
393 		lpit(LNOHANG, "-nohang ");
394 		if (any) {
395 			fprintf(stderr,"\n");
396 			any = 0;
397 			nothing = 0;
398 		}
399 #ifdef notdef
400 		lpit(LETXACK, "-etxack ");
401 #endif
402 		lpit(LPENDIN, "-pendin ");
403 		lpit(LDECCTQ, "-decctlq ");
404 		lpit(LNOFLSH, "-noflsh ");
405 		if (any || nothing)
406 			fprintf(stderr,"\n");
407 	} else if (!all)
408 		fprintf(stderr,"\n");
409 	if (all) {
410 		switch (ldisc) {
411 
412 		case 0:
413 			fprintf(stderr,"\
414 erase  kill   intr   quit   stop   eof\
415 \n");
416 			pcol(mode.sg_erase, -1);
417 			pcol(mode.sg_kill, -1);
418 			pcol(tc.t_intrc, -1);
419 			pcol(tc.t_quitc, -1);
420 			pcol(tc.t_stopc, tc.t_startc);
421 			pcol(tc.t_eofc, tc.t_brkc);
422 			fprintf(stderr,"\n");
423 			break;
424 
425 		case NTTYDISC:
426 			fprintf(stderr,"\
427 erase  kill   werase rprnt  flush  lnext  susp   intr   quit   stop   eof\
428 \n");
429 			pcol(mode.sg_erase, -1);
430 			pcol(mode.sg_kill, -1);
431 			pcol(ltc.t_werasc, -1);
432 			pcol(ltc.t_rprntc, -1);
433 			pcol(ltc.t_flushc, -1);
434 			pcol(ltc.t_lnextc, -1);
435 			pcol(ltc.t_suspc, ltc.t_dsuspc);
436 			pcol(tc.t_intrc, -1);
437 			pcol(tc.t_quitc, -1);
438 			pcol(tc.t_stopc, tc.t_startc);
439 			pcol(tc.t_eofc, tc.t_brkc);
440 			fprintf(stderr,"\n");
441 			break;
442 		}
443 	} else if (ldisc != NETLDISC) {
444 		register struct special *sp;
445 		int first = 1;
446 
447 		for (sp = special; sp->name; sp++) {
448 			if ((*sp->cp&0377) != (sp->def&0377)) {
449 				pit(*sp->cp, sp->name, first ? "" : ", ");
450 				first = 0;
451 			};
452 			if (sp->cp == &tc.t_brkc && ldisc == 0)
453 				break;
454 		}
455 		if (!first)
456 			fprintf(stderr, "\n");
457 	}
458 }
459 
460 pcol(ch1, ch2)
461 	int ch1, ch2;
462 {
463 	int nout = 0;
464 
465 	ch1 &= 0377;
466 	ch2 &= 0377;
467 	if (ch1 == ch2)
468 		ch2 = 0377;
469 	for (; ch1 != 0377 || ch2 != 0377; ch1 = ch2, ch2 = 0377) {
470 		if (ch1 == 0377)
471 			continue;
472 		if (ch1 & 0200) {
473 			fprintf(stderr, "M-");
474 			nout += 2;
475 			ch1 &= ~ 0200;
476 		}
477 		if (ch1 == 0177) {
478 			fprintf(stderr, "^");
479 			nout++;
480 			ch1 = '?';
481 		} else if (ch1 < ' ') {
482 			fprintf(stderr, "^");
483 			nout++;
484 			ch1 += '@';
485 		}
486 		fprintf(stderr, "%c", ch1);
487 		nout++;
488 		if (ch2 != 0377) {
489 			fprintf(stderr, "/");
490 			nout++;
491 		}
492 	}
493 	while (nout < 7) {
494 		fprintf(stderr, " ");
495 		nout++;
496 	}
497 }
498 
499 pit(what, itsname, sep)
500 	unsigned what;
501 	char *itsname, *sep;
502 {
503 
504 	what &= 0377;
505 	fprintf(stderr, "%s%s", sep, itsname);
506 	if (what == 0377) {
507 		fprintf(stderr, " <undef>");
508 		return;
509 	}
510 	fprintf(stderr, " = ");
511 	if (what & 0200) {
512 		fprintf(stderr, "M-");
513 		what &= ~ 0200;
514 	}
515 	if (what == 0177) {
516 		fprintf(stderr, "^");
517 		what = '?';
518 	} else if (what < ' ') {
519 		fprintf(stderr, "^");
520 		what += '@';
521 	}
522 	fprintf(stderr, "%c", what);
523 }
524 
525 delay(m, s)
526 char *s;
527 {
528 
529 	if(m)
530 		fprintf(stderr,"%s%d ", s, m);
531 }
532 
533 int	speed[] = {
534 	0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400
535 };
536 
537 prspeed(c, s)
538 char *c;
539 {
540 
541 	fprintf(stderr,"%s%d baud",  c, speed[s]);
542 }
543