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