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 */
313 SET(oflag
, ONLCR
|OPOST
);
320 SET(oflag
, OXTABS
|OPOST
);
328 if (n
== 1) { /* read mode flags */
332 CLR(cflag
, CSIZE
|PARENB
);
380 tmode
.c_iflag
= iflag
;
381 tmode
.c_oflag
= oflag
;
382 tmode
.c_cflag
= cflag
;
383 tmode
.c_lflag
= lflag
;
389 unsigned delay
; /* delay in ms */
394 * below are random guesses, I can't be bothered checking
397 struct delayval crdelay
[] = {
406 struct delayval nldelay
[] = {
407 { 1, NL1
}, /* special, calculated */
414 struct delayval bsdelay
[] = {
419 struct delayval ffdelay
[] = {
425 struct delayval tbdelay
[] = {
428 { 3, XTABS
}, /* this is expand tabs */
438 f
= adelay(CD
, crdelay
);
439 f
|= adelay(ND
, nldelay
);
440 f
|= adelay(FD
, ffdelay
);
441 f
|= adelay(TD
, tbdelay
);
442 f
|= adelay(BD
, bsdelay
);
447 adelay(int ms
, struct delayval
*dp
)
451 while (dp
->delay
&& ms
> dp
->delay
)
457 char editedhost
[MAXHOSTNAMELEN
];
460 edithost(const char *pattern
)
466 if (pattern
== NULL
|| *pattern
== '\0')
468 if (regcomp(®ex
, pattern
, REG_EXTENDED
) != 0)
471 match
= calloc(regex
.re_nsub
+ 1, sizeof(*match
));
477 found
= !regexec(®ex
, HN
, regex
.re_nsub
+ 1, match
, 0);
479 size_t subex
, totalsize
;
482 * We found a match. If there were no parenthesized
483 * subexpressions in the pattern, use entire matched
484 * string as ``editedhost''; otherwise use the first
485 * matched subexpression.
487 subex
= !!regex
.re_nsub
;
488 totalsize
= match
[subex
].rm_eo
- match
[subex
].rm_so
+ 1;
489 strlcpy(editedhost
, HN
+ match
[subex
].rm_so
, totalsize
>
490 sizeof(editedhost
) ? sizeof(editedhost
) : totalsize
);
497 * In case of any errors, or if the pattern did not match, pass
498 * the original hostname as is.
501 strlcpy(editedhost
, HN
, sizeof(editedhost
));
504 static struct speedtab
{
522 { 19, EXTA
}, /* for people who say 19.2K */
525 { 7200, EXTB
}, /* alternative */
540 for (sp
= speedtab
; sp
->speed
; sp
++)
541 if (sp
->speed
== val
)
544 return (B300
); /* default in impossible cases */
550 static char termbuf
[128] = "TERM=";
556 strlcat(termbuf
, TT
, sizeof(termbuf
));
561 while ((q
= strchr(q
, ','))) {
573 * This speed select mechanism is written for the Develcon DATASWITCH.
574 * The Develcon sends a string of the form "B{speed}\n" at a predefined
575 * baud rate. This string indicates the user's actual speed.
576 * The routine below returns the terminal type mapped from derived speed.
578 static struct portselect
{
582 { "B110", "std.110" },
583 { "B134", "std.134" },
584 { "B150", "std.150" },
585 { "B300", "std.300" },
586 { "B600", "std.600" },
587 { "B1200", "std.1200" },
588 { "B2400", "std.2400" },
589 { "B4800", "std.4800" },
590 { "B9600", "std.9600" },
591 { "B19200", "std.19200" },
592 { "B38400", "std.38400" },
593 { "B57600", "std.57600" },
594 { "B115200", "std.115200" },
595 { "B230400", "std.230400" },
603 const char *type
= "default";
604 struct portselect
*ps
;
608 for (len
= 0; len
< sizeof (baud
) - 1; len
++) {
609 if (read(STDIN_FILENO
, &c
, 1) <= 0)
612 if (c
== '\n' || c
== '\r')
615 len
= 0; /* in case of leading garbage */
619 for (ps
= portspeeds
; ps
->ps_baud
; ps
++)
620 if (strcmp(ps
->ps_baud
, baud
) == 0) {
624 sleep(2); /* wait for connection to complete */
629 * This auto-baud speed select mechanism is written for the Micom 600
630 * portselector. Selection is done by looking at how the character '\r'
631 * is garbled at the different speeds.
636 struct pollfd set
[1];
637 struct timespec timeout
;
639 const char *type
= "9600-baud";
641 (void)tcflush(0, TCIOFLUSH
);
642 set
[0].fd
= STDIN_FILENO
;
643 set
[0].events
= POLLIN
;
644 if (poll(set
, 1, 5000) <= 0)
646 if (read(STDIN_FILENO
, &c
, sizeof(char)) != sizeof(char))
649 timeout
.tv_nsec
= 20000;
650 (void)nanosleep(&timeout
, NULL
);
651 (void)tcflush(0, TCIOFLUSH
);
654 case 0200: /* 300-baud */
658 case 0346: /* 1200-baud */
662 case 015: /* 2400-baud */
667 default: /* 4800-baud */
671 case 0377: /* 9600-baud */