2 * SPDX-License-Identifier: BSD-3-Clause
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
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
31 * @(#)from: subr.c 8.1 (Berkeley) 6/4/93
32 * $FreeBSD: head/libexec/getty/subr.c 329724 2018-02-21 15:57:24Z trasz $
38 #include <sys/ioctl.h>
39 #include <sys/param.h>
51 #include "pathnames.h"
58 gettable(const char *name
, char *buf
)
62 struct gettyflags
*fp
;
66 static char path_gettytab
[PATH_MAX
];
69 static int firsttime
= 1;
71 strlcpy(path_gettytab
, _PATH_GETTYTAB
, sizeof(path_gettytab
));
72 dba
[0] = path_gettytab
;
77 * we need to strdup() anything in the strings array
78 * initially in order to simplify things later
80 for (sp
= gettystrs
; sp
->field
; sp
++)
81 if (sp
->value
!= NULL
) {
82 /* handle these ones more carefully */
83 if (sp
>= &gettystrs
[4] && sp
<= &gettystrs
[6])
86 l
= strlen(sp
->value
) + 1;
87 if ((p
= malloc(l
)) != NULL
) {
88 strncpy(p
, sp
->value
, l
);
92 * replace, even if NULL, else we'll
93 * have problems with free()ing static mem
100 switch (cgetent(&buf
, dba
, name
)) {
102 syslog(LOG_ERR
, "getty: couldn't resolve 'tc=' in gettytab '%s'", name
);
107 syslog(LOG_ERR
, "getty: unknown gettytab entry '%s'", name
);
110 syslog(LOG_ERR
, "getty: retrieving gettytab entry '%s': %m", name
);
113 syslog(LOG_ERR
, "getty: recursive 'tc=' reference gettytab entry '%s'", name
);
116 syslog(LOG_ERR
, "getty: unexpected cgetent() error for entry '%s'", name
);
120 for (sp
= gettystrs
; sp
->field
; sp
++) {
121 if ((l
= cgetstr(buf
, sp
->field
, &p
)) >= 0) {
123 /* prefer existing value */
124 if (strcmp(p
, sp
->value
) != 0)
132 } else if (l
== -1) {
138 for (np
= gettynums
; np
->field
; np
++) {
139 if (cgetnum(buf
, np
->field
, &n
) == -1)
147 for (fp
= gettyflags
; fp
->field
; fp
++) {
148 if (cgetcap(buf
, fp
->field
, ':') == NULL
)
152 fp
->value
= 1 ^ fp
->invrt
;
160 struct gettystrs
*sp
;
161 struct gettynums
*np
;
162 struct gettyflags
*fp
;
164 for (sp
= gettystrs
; sp
->field
; sp
++)
166 sp
->defalt
= strdup(sp
->value
);
167 for (np
= gettynums
; np
->field
; np
++)
169 np
->defalt
= np
->value
;
170 for (fp
= gettyflags
; fp
->field
; fp
++)
172 fp
->defalt
= fp
->value
;
174 fp
->defalt
= fp
->invrt
;
180 struct gettystrs
*sp
;
181 struct gettynums
*np
;
182 struct gettyflags
*fp
;
184 for (sp
= gettystrs
; sp
->field
; sp
++)
186 sp
->value
= !sp
->defalt
? sp
->defalt
187 : strdup(sp
->defalt
);
188 for (np
= gettynums
; np
->field
; np
++)
190 np
->value
= np
->defalt
;
191 for (fp
= gettyflags
; fp
->field
; fp
++)
193 fp
->value
= fp
->defalt
;
198 &ER
, &KL
, &IN
, &QU
, &XN
, &XF
, &ET
, &BK
,
199 &SU
, &DS
, &RP
, &FL
, &WE
, &LN
, 0
204 &tmode
.c_cc
[VERASE
], &tmode
.c_cc
[VKILL
], &tmode
.c_cc
[VINTR
],
205 &tmode
.c_cc
[VQUIT
], &tmode
.c_cc
[VSTART
], &tmode
.c_cc
[VSTOP
],
206 &tmode
.c_cc
[VEOF
], &tmode
.c_cc
[VEOL
], &tmode
.c_cc
[VSUSP
],
207 &tmode
.c_cc
[VDSUSP
], &tmode
.c_cc
[VREPRINT
], &tmode
.c_cc
[VDISCARD
],
208 &tmode
.c_cc
[VWERASE
], &tmode
.c_cc
[VLNEXT
], 0
217 for (i
= 0; charnames
[i
]; i
++) {
222 *charvars
[i
] = _POSIX_VDISABLE
;
226 /* Macros to clear/set/test flags. */
227 #define SET(t, f) (t) |= (f)
228 #define CLR(t, f) (t) &= ~(f)
229 #define ISSET(t, f) ((t) & (f))
234 tcflag_t iflag
, oflag
, cflag
, lflag
;
239 if (C0set
&& I0set
&& L0set
&& O0set
) {
248 if (C1set
&& I1set
&& L1set
&& O1set
) {
257 if (C2set
&& I2set
&& L2set
&& O2set
) {
267 iflag
= omode
.c_iflag
;
268 oflag
= omode
.c_oflag
;
269 cflag
= omode
.c_cflag
;
270 lflag
= omode
.c_lflag
;
273 CLR(cflag
, CSIZE
|PARENB
);
275 CLR(iflag
, ISTRIP
|INPCK
|IGNPAR
);
276 } else if (AP
|| EP
|| OP
) {
278 SET(cflag
, CS7
|PARENB
);
281 SET(iflag
, INPCK
|IGNPAR
);
285 } else if (EP
&& !OP
) {
286 SET(iflag
, INPCK
|IGNPAR
);
290 } else if (AP
|| (EP
&& OP
)) {
291 CLR(iflag
, INPCK
|IGNPAR
);
294 } /* else, leave as is */
318 SET(oflag
, ONLCR
|OPOST
);
325 SET(oflag
, OXTABS
|OPOST
);
333 if (n
== 1) { /* read mode flags */
337 CLR(cflag
, CSIZE
|PARENB
);
385 tmode
.c_iflag
= iflag
;
386 tmode
.c_oflag
= oflag
;
387 tmode
.c_cflag
= cflag
;
388 tmode
.c_lflag
= lflag
;
394 unsigned delay
; /* delay in ms */
399 * below are random guesses, I can't be bothered checking
402 struct delayval crdelay
[] = {
411 struct delayval nldelay
[] = {
412 { 1, NL1
}, /* special, calculated */
419 struct delayval bsdelay
[] = {
424 struct delayval ffdelay
[] = {
430 struct delayval tbdelay
[] = {
433 { 3, XTABS
}, /* this is expand tabs */
443 f
= adelay(CD
, crdelay
);
444 f
|= adelay(ND
, nldelay
);
445 f
|= adelay(FD
, ffdelay
);
446 f
|= adelay(TD
, tbdelay
);
447 f
|= adelay(BD
, bsdelay
);
452 adelay(int ms
, struct delayval
*dp
)
456 while (dp
->delay
&& ms
> dp
->delay
)
462 char editedhost
[MAXHOSTNAMELEN
];
465 edithost(const char *pattern
)
471 if (pattern
== NULL
|| *pattern
== '\0')
473 if (regcomp(®ex
, pattern
, REG_EXTENDED
) != 0)
476 match
= calloc(regex
.re_nsub
+ 1, sizeof(*match
));
482 found
= !regexec(®ex
, HN
, regex
.re_nsub
+ 1, match
, 0);
484 size_t subex
, totalsize
;
487 * We found a match. If there were no parenthesized
488 * subexpressions in the pattern, use entire matched
489 * string as ``editedhost''; otherwise use the first
490 * matched subexpression.
492 subex
= !!regex
.re_nsub
;
493 totalsize
= match
[subex
].rm_eo
- match
[subex
].rm_so
+ 1;
494 strlcpy(editedhost
, HN
+ match
[subex
].rm_so
, totalsize
>
495 sizeof(editedhost
) ? sizeof(editedhost
) : totalsize
);
502 * In case of any errors, or if the pattern did not match, pass
503 * the original hostname as is.
506 strlcpy(editedhost
, HN
, sizeof(editedhost
));
509 static struct speedtab
{
527 { 19, EXTA
}, /* for people who say 19.2K */
530 { 7200, EXTB
}, /* alternative */
545 for (sp
= speedtab
; sp
->speed
; sp
++)
546 if (sp
->speed
== val
)
549 return (B300
); /* default in impossible cases */
555 static char termbuf
[128] = "TERM=";
561 strlcat(termbuf
, TT
, sizeof(termbuf
));
566 while ((q
= strchr(q
, ','))) {
578 * This speed select mechanism is written for the Develcon DATASWITCH.
579 * The Develcon sends a string of the form "B{speed}\n" at a predefined
580 * baud rate. This string indicates the user's actual speed.
581 * The routine below returns the terminal type mapped from derived speed.
583 static struct portselect
{
587 { "B110", "std.110" },
588 { "B134", "std.134" },
589 { "B150", "std.150" },
590 { "B300", "std.300" },
591 { "B600", "std.600" },
592 { "B1200", "std.1200" },
593 { "B2400", "std.2400" },
594 { "B4800", "std.4800" },
595 { "B9600", "std.9600" },
596 { "B19200", "std.19200" },
604 const char *type
= "default";
605 struct portselect
*ps
;
609 for (len
= 0; len
< sizeof (baud
) - 1; len
++) {
610 if (read(STDIN_FILENO
, &c
, 1) <= 0)
613 if (c
== '\n' || c
== '\r')
616 len
= 0; /* in case of leading garbage */
620 for (ps
= portspeeds
; ps
->ps_baud
; ps
++)
621 if (strcmp(ps
->ps_baud
, baud
) == 0) {
625 sleep(2); /* wait for connection to complete */
630 * This auto-baud speed select mechanism is written for the Micom 600
631 * portselector. Selection is done by looking at how the character '\r'
632 * is garbled at the different speeds.
637 struct pollfd set
[1];
638 struct timespec timeout
;
640 const char *type
= "9600-baud";
642 (void)tcflush(0, TCIOFLUSH
);
643 set
[0].fd
= STDIN_FILENO
;
644 set
[0].events
= POLLIN
;
645 if (poll(set
, 1, 5000) <= 0)
647 if (read(STDIN_FILENO
, &c
, sizeof(char)) != sizeof(char))
650 timeout
.tv_nsec
= 20000;
651 (void)nanosleep(&timeout
, NULL
);
652 (void)tcflush(0, TCIOFLUSH
);
655 case 0200: /* 300-baud */
659 case 0346: /* 1200-baud */
663 case 015: /* 2400-baud */
668 default: /* 4800-baud */
672 case 0377: /* 9600-baud */