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