subr.c revision 1.8 1 /*
2 * Copyright (c) 1983 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 /*static char sccsid[] = "from: @(#)subr.c 5.10 (Berkeley) 2/26/91";*/
36 static char rcsid[] = "$Id: subr.c,v 1.8 1994/08/15 15:46:44 pk Exp $";
37 #endif /* not lint */
38
39 /*
40 * Melbourne getty.
41 */
42 #define COMPAT_43
43 #include <stdlib.h>
44 #include <unistd.h>
45 #include <string.h>
46 #include <termios.h>
47 #include <sys/ioctl.h>
48
49 #include "gettytab.h"
50 #include "pathnames.h"
51
52 extern struct termios tmode;
53
54 static void compatflags __P((long));
55 /*
56 * Get a table entry.
57 */
58 gettable(name, buf)
59 char *name, *buf;
60 {
61 register struct gettystrs *sp;
62 register struct gettynums *np;
63 register struct gettyflags *fp;
64 long n;
65 char *dba[2];
66 dba[0] = _PATH_GETTYTAB;
67 dba[1] = 0;
68
69 if (cgetent(&buf, dba, name) != 0)
70 return;
71
72 for (sp = gettystrs; sp->field; sp++)
73 cgetstr(buf, sp->field, &sp->value);
74 for (np = gettynums; np->field; np++) {
75 if (cgetnum(buf, np->field, &n) == -1)
76 np->set = 0;
77 else {
78 np->set = 1;
79 np->value = n;
80 }
81 }
82 for (fp = gettyflags; fp->field; fp++) {
83 if (cgetcap(buf, fp->field, ':') == NULL)
84 fp->set = 0;
85 else {
86 fp->set = 1;
87 fp->value = 1 ^ fp->invrt;
88 }
89 }
90 #ifdef DEBUG
91 printf("name=\"%s\", buf=\"%s\"\n", name, buf);
92 for (sp = gettystrs; sp->field; sp++)
93 printf("cgetstr: %s=%s\n", sp->field, sp->value);
94 for (np = gettynums; np->field; np++)
95 printf("cgetnum: %s=%d\n", np->field, np->value);
96 for (fp = gettyflags; fp->field; fp++)
97 printf("cgetflags: %s='%c' set='%c'\n", fp->field,
98 fp->value + '0', fp->set + '0');
99 exit(1);
100 #endif /* DEBUG */
101 }
102
103 gendefaults()
104 {
105 register struct gettystrs *sp;
106 register struct gettynums *np;
107 register struct gettyflags *fp;
108
109 for (sp = gettystrs; sp->field; sp++)
110 if (sp->value)
111 sp->defalt = sp->value;
112 for (np = gettynums; np->field; np++)
113 if (np->set)
114 np->defalt = np->value;
115 for (fp = gettyflags; fp->field; fp++)
116 if (fp->set)
117 fp->defalt = fp->value;
118 else
119 fp->defalt = fp->invrt;
120 }
121
122 setdefaults()
123 {
124 register struct gettystrs *sp;
125 register struct gettynums *np;
126 register struct gettyflags *fp;
127
128 for (sp = gettystrs; sp->field; sp++)
129 if (!sp->value)
130 sp->value = sp->defalt;
131 for (np = gettynums; np->field; np++)
132 if (!np->set)
133 np->value = np->defalt;
134 for (fp = gettyflags; fp->field; fp++)
135 if (!fp->set)
136 fp->value = fp->defalt;
137 }
138
139 static char **
140 charnames[] = {
141 &ER, &KL, &IN, &QU, &XN, &XF, &ET, &BK,
142 &SU, &DS, &RP, &FL, &WE, &LN, 0
143 };
144
145 static char *
146 charvars[] = {
147 &tmode.c_cc[VERASE], &tmode.c_cc[VKILL], &tmode.c_cc[VINTR],
148 &tmode.c_cc[VQUIT], &tmode.c_cc[VSTART], &tmode.c_cc[VSTOP],
149 &tmode.c_cc[VEOF], &tmode.c_cc[VEOL], &tmode.c_cc[VSUSP],
150 &tmode.c_cc[VDSUSP], &tmode.c_cc[VREPRINT], &tmode.c_cc[VDISCARD],
151 &tmode.c_cc[VWERASE], &tmode.c_cc[VLNEXT], 0
152 };
153
154 setchars()
155 {
156 register int i;
157 register char *p;
158
159 for (i = 0; charnames[i]; i++) {
160 p = *charnames[i];
161 if (p && *p)
162 *charvars[i] = *p;
163 else
164 *charvars[i] = '\377';
165 }
166 }
167
168 void
169 setflags(n)
170 {
171 register tcflag_t iflag, oflag, cflag, lflag;
172
173 #ifdef COMPAT_43
174 switch (n) {
175 case 0:
176 if (F0set) {
177 compatflags(F0);
178 return;
179 }
180 break;
181 case 1:
182 if (F1set) {
183 compatflags(F1);
184 return;
185 }
186 break;
187 default:
188 if (F2set) {
189 compatflags(F2);
190 return;
191 }
192 break;
193 }
194 #endif
195
196 switch (n) {
197 case 0:
198 if (C0set && I0set && L0set && O0set) {
199 tmode.c_cflag = C0;
200 tmode.c_iflag = I0;
201 tmode.c_lflag = L0;
202 tmode.c_oflag = O0;
203 return;
204 }
205 break;
206 case 1:
207 if (C1set && I1set && L1set && O1set) {
208 tmode.c_cflag = C1;
209 tmode.c_iflag = I1;
210 tmode.c_lflag = L1;
211 tmode.c_oflag = O1;
212 return;
213 }
214 break;
215 default:
216 if (C2set && I2set && L2set && O2set) {
217 tmode.c_cflag = C2;
218 tmode.c_iflag = I2;
219 tmode.c_lflag = L2;
220 tmode.c_oflag = O2;
221 return;
222 }
223 break;
224 }
225
226 iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
227 oflag = (OPOST|ONLCR|OXTABS);
228 cflag = (CREAD);
229 lflag = (ICANON|ISIG|IEXTEN);
230
231 if (NP) {
232 iflag |= IGNPAR;
233 cflag |= CS8;
234 } else if (OP && !EP) {
235 iflag |= INPCK|ISTRIP;
236 cflag |= PARENB|PARODD|CS7;
237 } else if (EP && !OP) {
238 iflag |= INPCK|ISTRIP;
239 cflag |= PARENB|CS7;
240 } else {
241 /* Other combinations, including `AP' and `EP && OP' */
242 iflag |= IGNPAR|ISTRIP;
243 cflag |= CS7;
244 }
245
246 #if 0
247 if (UC)
248 f |= LCASE;
249 #endif
250
251 if (HC)
252 cflag |= HUPCL;
253
254 if (NL) {
255 iflag |= ICRNL;
256 oflag |= ONLCR;
257 }
258
259 #ifdef XXX_DELAY
260 f |= delaybits();
261 #endif
262
263 if (n == 1) { /* read mode flags */
264 if (RW) {
265 iflag = 0;
266 oflag = 0;
267 cflag = CREAD|CS8;
268 lflag = 0;
269 } else {
270 lflag &= ~ICANON;
271 }
272 goto out;
273 }
274
275 if (!HT)
276 oflag |= OXTABS;
277
278 if (n == 0)
279 goto out;
280
281 #if 0
282 if (CB)
283 f |= CRTBS;
284 #endif
285
286 if (CE)
287 lflag |= ECHOE;
288
289 if (CK)
290 lflag |= ECHOKE;
291
292 if (PE)
293 lflag |= ECHOPRT;
294
295 if (EC)
296 lflag |= ECHO;
297
298 if (XC)
299 lflag |= ECHOCTL;
300
301 if (DX)
302 lflag |= IXANY;
303
304 if (MB)
305 cflag |= MDMBUF;
306
307 out:
308 tmode.c_iflag = iflag;
309 tmode.c_oflag = oflag;
310 tmode.c_cflag = cflag;
311 tmode.c_lflag = lflag;
312 }
313
314 #ifdef COMPAT_43
315 /*
316 * Old TTY => termios, snatched from <sys/kern/tty_compat.c>
317 */
318 void
319 compatflags(flags)
320 register long flags;
321 {
322 register tcflag_t iflag, oflag, cflag, lflag;
323
324 iflag = (BRKINT|ICRNL|IMAXBEL|IXON|IXANY);
325 oflag = (OPOST|ONLCR|OXTABS);
326 cflag = (CREAD);
327 lflag = (ICANON|ISIG|IEXTEN);
328
329 if (flags & TANDEM)
330 iflag |= IXOFF;
331 else
332 iflag &= ~IXOFF;
333 if (flags & ECHO)
334 lflag |= ECHO;
335 else
336 lflag &= ~ECHO;
337 if (flags & CRMOD) {
338 iflag |= ICRNL;
339 oflag |= ONLCR;
340 } else {
341 iflag &= ~ICRNL;
342 oflag &= ~ONLCR;
343 }
344 if (flags & XTABS)
345 oflag |= OXTABS;
346 else
347 oflag &= ~OXTABS;
348
349 if (flags & RAW) {
350 iflag &= IXOFF;
351 lflag &= ~(ISIG|ICANON|IEXTEN);
352 } else {
353 iflag |= BRKINT|IXON|IMAXBEL;
354 lflag |= ISIG|IEXTEN;
355 if (flags & CBREAK)
356 lflag &= ~ICANON;
357 else
358 lflag |= ICANON;
359 }
360
361 switch (flags & ANYP) {
362 case EVENP:
363 iflag |= INPCK;
364 cflag &= ~PARODD;
365 break;
366 case ODDP:
367 iflag |= INPCK;
368 cflag |= PARODD;
369 break;
370 default:
371 iflag &= ~INPCK;
372 break;
373 }
374
375 if (flags & (RAW|LITOUT|PASS8)) {
376 cflag &= ~(CSIZE|PARENB);
377 cflag |= CS8;
378 if ((flags & (RAW|PASS8)) == 0)
379 iflag |= ISTRIP;
380 else
381 iflag &= ~ISTRIP;
382 if ((flags & (RAW|LITOUT)) == 0)
383 oflag |= OPOST;
384 else
385 oflag &= ~OPOST;
386 } else {
387 cflag &= ~CSIZE;
388 cflag |= CS7|PARENB;
389 iflag |= ISTRIP;
390 oflag |= OPOST;
391 }
392
393 if (flags & PRTERA)
394 lflag |= ECHOPRT;
395 else
396 lflag &= ~ECHOPRT;
397 if (flags & CRTERA)
398 lflag |= ECHOE;
399 else
400 lflag &= ~ECHOE;
401 if (flags & MDMBUF)
402 cflag |= MDMBUF;
403 else
404 cflag &= ~MDMBUF;
405 if (flags & NOHANG)
406 cflag &= ~HUPCL;
407 else
408 cflag |= HUPCL;
409 if (flags & CRTKIL)
410 lflag |= ECHOKE;
411 else
412 lflag &= ~ECHOKE;
413 if (flags & CTLECH)
414 lflag |= ECHOCTL;
415 else
416 lflag &= ~ECHOCTL;
417 if ((flags & DECCTQ) == 0)
418 lflag |= IXANY;
419 else
420 lflag &= ~IXANY;
421 lflag &= ~(TOSTOP|FLUSHO|PENDIN|NOFLSH);
422 lflag |= flags & (TOSTOP|FLUSHO|PENDIN|NOFLSH);
423
424 if (flags & (RAW|LITOUT|PASS8)) {
425 cflag &= ~(CSIZE|PARENB);
426 cflag |= CS8;
427 if ((flags & (RAW|PASS8)) == 0)
428 iflag |= ISTRIP;
429 else
430 iflag &= ~ISTRIP;
431 if ((flags & (RAW|LITOUT)) == 0)
432 oflag |= OPOST;
433 else
434 oflag &= ~OPOST;
435 } else {
436 cflag &= ~CSIZE;
437 cflag |= CS7|PARENB;
438 iflag |= ISTRIP;
439 oflag |= OPOST;
440 }
441
442 tmode.c_iflag = iflag;
443 tmode.c_oflag = oflag;
444 tmode.c_cflag = cflag;
445 tmode.c_lflag = lflag;
446 }
447 #endif
448
449 #ifdef XXX_DELAY
450 struct delayval {
451 unsigned delay; /* delay in ms */
452 int bits;
453 };
454
455 /*
456 * below are random guesses, I can't be bothered checking
457 */
458
459 struct delayval crdelay[] = {
460 1, CR1,
461 2, CR2,
462 3, CR3,
463 83, CR1,
464 166, CR2,
465 0, CR3,
466 };
467
468 struct delayval nldelay[] = {
469 1, NL1, /* special, calculated */
470 2, NL2,
471 3, NL3,
472 100, NL2,
473 0, NL3,
474 };
475
476 struct delayval bsdelay[] = {
477 1, BS1,
478 0, 0,
479 };
480
481 struct delayval ffdelay[] = {
482 1, FF1,
483 1750, FF1,
484 0, FF1,
485 };
486
487 struct delayval tbdelay[] = {
488 1, TAB1,
489 2, TAB2,
490 3, XTABS, /* this is expand tabs */
491 100, TAB1,
492 0, TAB2,
493 };
494
495 delaybits()
496 {
497 register f;
498
499 f = adelay(CD, crdelay);
500 f |= adelay(ND, nldelay);
501 f |= adelay(FD, ffdelay);
502 f |= adelay(TD, tbdelay);
503 f |= adelay(BD, bsdelay);
504 return (f);
505 }
506
507 adelay(ms, dp)
508 register ms;
509 register struct delayval *dp;
510 {
511 if (ms == 0)
512 return (0);
513 while (dp->delay && ms > dp->delay)
514 dp++;
515 return (dp->bits);
516 }
517 #endif
518
519 char editedhost[32];
520
521 edithost(pat)
522 register char *pat;
523 {
524 register char *host = HN;
525 register char *res = editedhost;
526
527 if (!pat)
528 pat = "";
529 while (*pat) {
530 switch (*pat) {
531
532 case '#':
533 if (*host)
534 host++;
535 break;
536
537 case '@':
538 if (*host)
539 *res++ = *host++;
540 break;
541
542 default:
543 *res++ = *pat;
544 break;
545
546 }
547 if (res == &editedhost[sizeof editedhost - 1]) {
548 *res = '\0';
549 return;
550 }
551 pat++;
552 }
553 if (*host)
554 strncpy(res, host, sizeof editedhost - (res - editedhost) - 1);
555 else
556 *res = '\0';
557 editedhost[sizeof editedhost - 1] = '\0';
558 }
559
560 struct speedtab {
561 int speed;
562 int uxname;
563 } speedtab[] = {
564 50, B50,
565 75, B75,
566 110, B110,
567 134, B134,
568 150, B150,
569 200, B200,
570 300, B300,
571 600, B600,
572 1200, B1200,
573 1800, B1800,
574 2400, B2400,
575 4800, B4800,
576 9600, B9600,
577 19200, EXTA,
578 19, EXTA, /* for people who say 19.2K */
579 38400, EXTB,
580 38, EXTB,
581 7200, EXTB, /* alternative */
582 57600, B57600,
583 115200, B115200,
584 0
585 };
586
587 speed(val)
588 {
589 register struct speedtab *sp;
590
591 if (val <= 15)
592 return (val);
593
594 for (sp = speedtab; sp->speed; sp++)
595 if (sp->speed == val)
596 return (sp->uxname);
597
598 return (B300); /* default in impossible cases */
599 }
600
601 makeenv(env)
602 char *env[];
603 {
604 static char termbuf[128] = "TERM=";
605 register char *p, *q;
606 register char **ep;
607 char *index();
608
609 ep = env;
610 if (TT && *TT) {
611 strcat(termbuf, TT);
612 *ep++ = termbuf;
613 }
614 if (p = EV) {
615 q = p;
616 while (q = index(q, ',')) {
617 *q++ = '\0';
618 *ep++ = p;
619 p = q;
620 }
621 if (*p)
622 *ep++ = p;
623 }
624 *ep = (char *)0;
625 }
626
627 /*
628 * This speed select mechanism is written for the Develcon DATASWITCH.
629 * The Develcon sends a string of the form "B{speed}\n" at a predefined
630 * baud rate. This string indicates the user's actual speed.
631 * The routine below returns the terminal type mapped from derived speed.
632 */
633 struct portselect {
634 char *ps_baud;
635 char *ps_type;
636 } portspeeds[] = {
637 { "B110", "std.110" },
638 { "B134", "std.134" },
639 { "B150", "std.150" },
640 { "B300", "std.300" },
641 { "B600", "std.600" },
642 { "B1200", "std.1200" },
643 { "B2400", "std.2400" },
644 { "B4800", "std.4800" },
645 { "B9600", "std.9600" },
646 { "B19200", "std.19200" },
647 { 0 }
648 };
649
650 char *
651 portselector()
652 {
653 char c, baud[20], *type = "default";
654 register struct portselect *ps;
655 int len;
656
657 alarm(5*60);
658 for (len = 0; len < sizeof (baud) - 1; len++) {
659 if (read(STDIN_FILENO, &c, 1) <= 0)
660 break;
661 c &= 0177;
662 if (c == '\n' || c == '\r')
663 break;
664 if (c == 'B')
665 len = 0; /* in case of leading garbage */
666 baud[len] = c;
667 }
668 baud[len] = '\0';
669 for (ps = portspeeds; ps->ps_baud; ps++)
670 if (strcmp(ps->ps_baud, baud) == 0) {
671 type = ps->ps_type;
672 break;
673 }
674 sleep(2); /* wait for connection to complete */
675 return (type);
676 }
677
678 /*
679 * This auto-baud speed select mechanism is written for the Micom 600
680 * portselector. Selection is done by looking at how the character '\r'
681 * is garbled at the different speeds.
682 */
683 #include <sys/time.h>
684
685 char *
686 autobaud()
687 {
688 int rfds;
689 struct timeval timeout;
690 char c, *type = "9600-baud";
691 int null = 0;
692
693 ioctl(0, TIOCFLUSH, &null);
694 rfds = 1 << 0;
695 timeout.tv_sec = 5;
696 timeout.tv_usec = 0;
697 if (select(32, (fd_set *)&rfds, (fd_set *)NULL,
698 (fd_set *)NULL, &timeout) <= 0)
699 return (type);
700 if (read(STDIN_FILENO, &c, sizeof(char)) != sizeof(char))
701 return (type);
702 timeout.tv_sec = 0;
703 timeout.tv_usec = 20;
704 (void) select(32, (fd_set *)NULL, (fd_set *)NULL,
705 (fd_set *)NULL, &timeout);
706 ioctl(0, TIOCFLUSH, &null);
707 switch (c & 0377) {
708
709 case 0200: /* 300-baud */
710 type = "300-baud";
711 break;
712
713 case 0346: /* 1200-baud */
714 type = "1200-baud";
715 break;
716
717 case 015: /* 2400-baud */
718 case 0215:
719 type = "2400-baud";
720 break;
721
722 default: /* 4800-baud */
723 type = "4800-baud";
724 break;
725
726 case 0377: /* 9600-baud */
727 type = "9600-baud";
728 break;
729 }
730 return (type);
731 }
732