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