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