xref: /original-bsd/bin/stty/stty.c (revision f0fd5f8a)
1 static char *sccsid ="@(#)stty.c	4.10 (Berkeley) 12/19/82";
2 /*
3  * set teletype modes
4  */
5 
6 #include <stdio.h>
7 #include <sgtty.h>
8 
9 struct {
10 	char	*string;
11 	int	speed;
12 } speeds[] = {
13 	{ "0",		B0 },
14 	{ "50",		B50 },
15 	{ "75",		B75 },
16 	{ "110",	B110 },
17 	{ "134",	B134 },
18 	{ "134.5",	B134 },
19 	{ "150",	B150 },
20 	{ "200",	B200 },
21 	{ "300",	B300 },
22 	{ "600",	B600 },
23 	{ "1200",	B1200 },
24 	{ "1800",	B1800 },
25 	{ "2400",	B2400 },
26 	{ "4800",	B4800 },
27 	{ "9600",	B9600 },
28 	{ "exta",	EXTA },
29 	{ "19200",	EXTA },
30 	{ "extb",	EXTB },
31 	{ "38400",	EXTB },
32 	{ 0 },
33 };
34 
35 struct {
36 	char	*string;
37 	long	set;
38 	long	reset;
39 } modes[] = {
40 	{ "even",	EVENP,		0 },
41 	{ "-even",	0,		EVENP },
42 	{ "odd",	ODDP,		0 },
43 	{ "-odd",	0,		ODDP },
44 	{ "raw",	RAW,		0 },
45 	{ "-raw",	0,		RAW },
46 	{ "cooked",	0,		RAW },
47 	{ "-nl",	CRMOD,		0 },
48 	{ "nl",		0,		CRMOD },
49 	{ "echo",	ECHO,		0 },
50 	{ "-echo",	0,		ECHO },
51 	{ "LCASE",	LCASE,		0 },
52 	{ "lcase",	LCASE,		0 },
53 	{ "-LCASE",	0,		LCASE },
54 	{ "-lcase",	0,		LCASE },
55 	{ "-tabs",	XTABS,		0 },
56 	{ "tabs",	0,		XTABS },
57 	{ "tandem",	TANDEM,		0 },
58 	{ "-tandem",	0,		TANDEM },
59 	{ "cbreak",	CBREAK,		0 },
60 	{ "-cbreak",	0,		CBREAK },
61 	{ "cr0",	CR0,		CR3 },
62 	{ "cr1",	CR1,		CR3 },
63 	{ "cr2",	CR2,		CR3 },
64 	{ "cr3",	CR3,		CR3 },
65 	{ "tab0",	TAB0,		XTABS },
66 	{ "tab1",	TAB1,		XTABS },
67 	{ "tab2",	TAB2,		XTABS },
68 	{ "nl0",	NL0,		NL3 },
69 	{ "nl1",	NL1,		NL3 },
70 	{ "nl2",	NL2,		NL3 },
71 	{ "nl3",	NL3,		NL3 },
72 	{ "ff0",	FF0,		FF1 },
73 	{ "ff1",	FF1,		FF1 },
74 	{ "bs0",	BS0,		BS1 },
75 	{ "bs1",	BS1,		BS1 },
76 	{ "33",		CR1,		ALLDELAY },
77 	{ "tty33",	CR1,		ALLDELAY },
78 	{ "37",		FF1+CR2+TAB1+NL1, ALLDELAY },
79 	{ "tty37",	FF1+CR2+TAB1+NL1, ALLDELAY },
80 	{ "05",		NL2,		ALLDELAY },
81 	{ "vt05",	NL2,		ALLDELAY },
82 	{ "tn",		CR1,		ALLDELAY },
83 	{ "tn300",	CR1,		ALLDELAY },
84 	{ "ti",		CR2,		ALLDELAY },
85 	{ "ti700",	CR2,		ALLDELAY },
86 	{ "tek",	FF1,		ALLDELAY },
87 	{ "crtbs",	CRTBS,		PRTERA },
88 	{ "-crtbs",	0,		CRTBS },
89 	{ "prterase",	PRTERA,		CRTBS+CRTKIL+CRTERA },
90 	{ "-prterase",	0,		PRTERA },
91 	{ "crterase",	CRTERA,		PRTERA },
92 	{ "-crterase",	0,		CRTERA },
93 	{ "crtkill",	CRTKIL,		PRTERA },
94 	{ "-crtkill",	0,		CRTKIL },
95 	{ "tilde",	TILDE,		0 },
96 	{ "-tilde",	0,		TILDE },
97 	{ "mdmbuf",	MDMBUF,		0 },
98 	{ "-mdmbuf",	0,		MDMBUF },
99 	{ "litout",	LITOUT,		0 },
100 	{ "-litout",	0,		LITOUT },
101 	{ "tostop",	TOSTOP,		0 },
102 	{ "-tostop",	0,		TOSTOP },
103 	{ "flusho",	FLUSHO,		0 },
104 	{ "-flusho",	0,		FLUSHO },
105 	{ "nohang",	NOHANG,		0 },
106 	{ "-nohang",	0,		NOHANG },
107 #ifdef notdef
108 	{ "etxack",	ETXACK,		0 },
109 	{ "-etxack",	0,		ETXACK },
110 #endif
111 	{ "ctlecho",	CTLECH,		0 },
112 	{ "-ctlecho",	0,		CTLECH },
113 	{ "pendin",	PENDIN,		0 },
114 	{ "-pendin",	0,		PENDIN },
115 	{ "decctlq",	DECCTQ,		0 },
116 	{ "-decctlq",	0,		DECCTQ },
117 	{ "noflsh",	NOFLSH,		0 },
118 	{ "-noflsh",	0,		NOFLSH },
119 	{ 0 },
120 };
121 
122 struct ttychars tc;
123 struct sgttyb sb;
124 long	flags;
125 int	oldisc, ldisc;
126 
127 struct	special {
128 	char	*name;
129 	char	*cp;
130 	char	def;
131 } special[] = {
132 	{ "erase",	&tc.tc_erase,		CERASE },
133 	{ "kill",	&tc.tc_kill,		CKILL },
134 	{ "intr",	&tc.tc_intrc,		CINTR },
135 	{ "quit",	&tc.tc_quitc,		CQUIT },
136 	{ "start",	&tc.tc_startc,		CSTART },
137 	{ "stop",	&tc.tc_stopc,		CSTOP },
138 	{ "eof",	&tc.tc_eofc,		CEOF },
139 	{ "brk",	&tc.tc_brkc,		CBRK },
140 	{ "susp",	&tc.tc_suspc,		CSUSP },
141 	{ "dsusp",	&tc.tc_dsuspc,		CDSUSP },
142 	{ "rprnt",	&tc.tc_rprntc,		CRPRNT },
143 	{ "flush",	&tc.tc_flushc,		CFLUSH },
144 	{ "werase",	&tc.tc_werasc,		CWERASE },
145 	{ "lnext",	&tc.tc_lnextc,		CLNEXT },
146 	0
147 };
148 char	*arg;
149 
150 int	argc;
151 char	**argv;
152 
153 main(iargc, iargv)
154 	int iargc;
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 	ioctl(1, TIOCCGET, (char *)&tc);
165 	ioctl(1, TIOCGET, (char *)&flags);
166 	ioctl(1, TIOCGETD, &ldisc);
167 #ifndef notdef
168 	ioctl(1, TIOCGETP, (char *)&sb);
169 #endif
170 	oldisc = ldisc;
171 	if (argc == 1) {
172 		prmodes(0);
173 		exit(0);
174 	}
175 	if (argc == 2 && !strcmp(argv[1], "all")) {
176 		prmodes(1);
177 		exit(0);
178 	}
179 	if (argc == 2 && !strcmp(argv[1], "everything")) {
180 		prmodes(2);
181 		exit(0);
182 	}
183 	while (--argc > 0) {
184 		arg = *++argv;
185 		if (eq("ek")) {
186 			tc.tc_erase = '#';
187 			tc.tc_kill = '@';
188 			continue;
189 		}
190 		if (eq("new")) {
191 			ldisc = NTTYDISC;
192 			if (ioctl(1, TIOCSETD, &ldisc) < 0)
193 				perror("ioctl");
194 			continue;
195 		}
196 		if (eq("newcrt")) {
197 			ldisc = NTTYDISC;
198 			flags &= ~PRTERA;
199 			flags |= CRTBS|CTLECH;
200 			if (sb.sg_ospeed >= B1200)
201 				flags |= CRTERA|CRTKIL;
202 			if (ioctl(1, TIOCSETD, &ldisc) < 0)
203 				perror("ioctl");
204 			continue;
205 		}
206 		if (eq("crt")) {
207 			flags &= ~PRTERA;
208 			flags |= CRTBS|CTLECH;
209 			if (sb.sg_ospeed >= B1200)
210 				flags |= CRTERA|CRTKIL;
211 			continue;
212 		}
213 		if (eq("old")) {
214 			ldisc = OTTYDISC;
215 			if (ioctl(1, TIOCSETD, &ldisc) < 0)
216 				perror("ioctl");
217 			continue;
218 		}
219 		if (eq("dec")) {
220 			tc.tc_erase = 0177;
221 			tc.tc_kill = CTRL(u);
222 			tc.tc_intrc = CTRL(c);
223 			ldisc = NTTYDISC;
224 			flags &= ~PRTERA;
225 			flags |= CRTBS|CTLECH|DECCTQ;
226 			if (sb.sg_ospeed >= B1200)
227 				flags |= CRTERA|CRTKIL;
228 			if (ioctl(1, TIOCSETD, &ldisc) < 0)
229 				perror("ioctl");
230 			continue;
231 		}
232 		for (sp = special; sp->name; sp++)
233 			if (eq(sp->name)) {
234 				if (--argc == 0)
235 					goto done;
236 				if (**++argv == 'u')
237 					*sp->cp = 0377;
238 				else if (**argv == '^')
239 					*sp->cp = ((*argv)[1] == '?') ?
240 					    0177 : (*argv)[1] & 037;
241 				else
242 					*sp->cp = **argv;
243 				goto cont;
244 			}
245 		if (eq("gspeed")) {
246 			sb.sg_ispeed = B300;
247 			sb.sg_ospeed = B9600;
248 			continue;
249 		}
250 		if (eq("hup")) {
251 			if (ioctl(1, TIOCHPCL, NULL) < 0)
252 				perror("ioctl");
253 			continue;
254 		}
255 		for (i = 0; speeds[i].string; i++)
256 			if (eq(speeds[i].string)) {
257 				sb.sg_ispeed = sb.sg_ospeed = speeds[i].speed;
258 				goto cont;
259 			}
260 		if (eq("speed")) {
261 			int fd = open("/dev/tty", 0);
262 
263 			if (fd < 0) {
264 				perror("open");
265 				exit(1);
266 			}
267 			ioctl(fd, TIOCGETP, &sb);
268 			for (i = 0; speeds[i].string; i++)
269 				if (sb.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 				flags &= ~modes[i].reset;
279 				flags |= modes[i].set;
280 			}
281 		if (arg)
282 			fprintf(stderr,"unknown mode: %s\n", arg);
283 cont:
284 		;
285 	}
286 done:
287 #ifndef notdef
288 	ioctl(1, TIOCSETN, &sb);
289 #endif
290 	ioctl(1, TIOCSET, &flags);
291 	ioctl(1, TIOCCSET, &tc);
292 }
293 
294 eq(string)
295 	char *string;
296 {
297 	int i;
298 
299 	if (!arg)
300 		return (0);
301 	i = 0;
302 loop:
303 	if (arg[i] != string[i])
304 		return(0);
305 	if (arg[i++] != '\0')
306 		goto loop;
307 	arg = 0;
308 	return (1);
309 }
310 
311 prmodes(all)
312 	int 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(sb.sg_ispeed != sb.sg_ospeed) {
324 		prspeed("input speed ", sb.sg_ispeed);
325 		prspeed("output speed ", sb.sg_ospeed);
326 	} else
327 		prspeed("speed ", sb.sg_ispeed);
328 	fprintf(stderr, all == 2 ? "\n" : "; ");
329 	m = flags;
330 	if (all == 2 || (m&(EVENP|ODDP)) != (EVENP|ODDP)) {
331 		if (m & EVENP)
332 			fprintf(stderr,"even ");
333 		if (m & ODDP)
334 			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 || flags&what) { \
363 		fprintf(stderr,str + ((flags&what) != 0)); any++; \
364 	}
365 	if (ldisc == NTTYDISC) {
366 		int newcrt = (flags&(CTLECH|CRTBS)) == (CTLECH|CRTBS) &&
367 		    (flags&(CRTERA|CRTKIL)) ==
368 		      ((sb.sg_ospeed > B300) ? CRTERA|CRTKIL : 0);
369 		if (newcrt) {
370 			fprintf(stderr, all != 2 ? "crt" :
371 				 "crt: (crtbs crterase crtkill ctlecho) ");
372 			any++;
373 		} else {
374 			lpit(CRTBS, "-crtbs ");
375 			lpit(CRTERA, "-crterase ");
376 			lpit(CRTKIL, "-crtkill ");
377 			lpit(CTLECH, "-ctlecho ");
378 			lpit(PRTERA, "-prterase ");
379 		}
380 		lpit(TOSTOP, "-tostop ");
381 		if (all == 2) {
382 			fprintf(stderr, "\n");
383 			any = 0;
384 		}
385 		lpit(TILDE, "-tilde ");
386 		lpit(FLUSHO, "-flusho ");
387 		lpit(MDMBUF, "-mdmbuf ");
388 		lpit(LITOUT, "-litout ");
389 		lpit(NOHANG, "-nohang ");
390 		if (any) {
391 			fprintf(stderr,"\n");
392 			any = 0;
393 		}
394 #ifdef notdef
395 		lpit(ETXACK, "-etxack ");
396 #endif
397 		lpit(PENDIN, "-pendin ");
398 		lpit(DECCTQ, "-decctlq ");
399 		lpit(NOFLSH, "-noflsh ");
400 		if (any)
401 			fprintf(stderr,"\n");
402 	} else if (!all)
403 		fprintf(stderr,"\n");
404 	if (all) {
405 		switch (ldisc) {
406 
407 		case 0:
408 			fprintf(stderr,"\
409 erase  kill   intr   quit   stop   eof\
410 \n");
411 			pcol(tc.tc_erase, -1);
412 			pcol(tc.tc_kill, -1);
413 			pcol(tc.tc_intrc, -1);
414 			pcol(tc.tc_quitc, -1);
415 			pcol(tc.tc_stopc, tc.tc_startc);
416 			pcol(tc.tc_eofc, tc.tc_brkc);
417 			fprintf(stderr,"\n");
418 			break;
419 
420 		case NTTYDISC:
421 			fprintf(stderr,"\
422 erase  kill   werase rprnt  flush  lnext  susp   intr   quit   stop   eof\
423 \n");
424 			pcol(tc.tc_erase, -1);
425 			pcol(tc.tc_kill, -1);
426 			pcol(tc.tc_werasc, -1);
427 			pcol(tc.tc_rprntc, -1);
428 			pcol(tc.tc_flushc, -1);
429 			pcol(tc.tc_lnextc, -1);
430 			pcol(tc.tc_suspc, tc.tc_dsuspc);
431 			pcol(tc.tc_intrc, -1);
432 			pcol(tc.tc_quitc, -1);
433 			pcol(tc.tc_stopc, tc.tc_startc);
434 			pcol(tc.tc_eofc, tc.tc_brkc);
435 			fprintf(stderr,"\n");
436 			break;
437 		}
438 	} else if (ldisc != NETLDISC) {
439 		register struct special *sp;
440 		int first = 1;
441 
442 		for (sp = special; sp->name; sp++) {
443 			if ((*sp->cp&0377) != (sp->def&0377)) {
444 				pit(*sp->cp, sp->name, first ? "" : ", ");
445 				first = 0;
446 			};
447 			if (sp->cp == &tc.tc_brkc && ldisc == 0)
448 				break;
449 		}
450 		if (first == 0)
451 			fprintf(stderr, "\n");
452 	}
453 }
454 
455 pcol(ch1, ch2)
456 	int ch1, ch2;
457 {
458 	int nout = 0;
459 
460 	ch1 &= 0377;
461 	ch2 &= 0377;
462 	if (ch1 == ch2)
463 		ch2 = 0377;
464 	for (; ch1 != 0377 || ch2 != 0377; ch1 = ch2, ch2 = 0377) {
465 		if (ch1 == 0377)
466 			continue;
467 		if (ch1 & 0200) {
468 			fprintf(stderr, "M-");
469 			nout += 2;
470 			ch1 &= ~ 0200;
471 		}
472 		if (ch1 == 0177) {
473 			fprintf(stderr, "^");
474 			nout++;
475 			ch1 = '?';
476 		} else if (ch1 < ' ') {
477 			fprintf(stderr, "^");
478 			nout++;
479 			ch1 += '@';
480 		}
481 		fprintf(stderr, "%c", ch1);
482 		nout++;
483 		if (ch2 != 0377) {
484 			fprintf(stderr, "/");
485 			nout++;
486 		}
487 	}
488 	while (nout < 7) {
489 		fprintf(stderr, " ");
490 		nout++;
491 	}
492 }
493 
494 pit(what, itsname, sep)
495 	unsigned what;
496 	char *itsname, *sep;
497 {
498 
499 	what &= 0377;
500 	fprintf(stderr, "%s%s", sep, itsname);
501 	if (what == 0377) {
502 		fprintf(stderr, " <undef>");
503 		return;
504 	}
505 	fprintf(stderr, " = ");
506 	if (what & 0200) {
507 		fprintf(stderr, "M-");
508 		what &= ~ 0200;
509 	}
510 	if (what == 0177) {
511 		fprintf(stderr, "^");
512 		what = '?';
513 	} else if (what < ' ') {
514 		fprintf(stderr, "^");
515 		what += '@';
516 	}
517 	fprintf(stderr, "%c", what);
518 }
519 
520 delay(m, s)
521 	char *s;
522 {
523 
524 	if (m)
525 		fprintf(stderr,"%s%d ", s, m);
526 }
527 
528 int	speed[] = {
529 	0,50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,19200,38400
530 };
531 
532 prspeed(c, s)
533 char *c;
534 {
535 
536 	fprintf(stderr,"%s%d baud",  c, speed[s]);
537 }
538