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