xref: /netbsd-src/lib/libc/gen/getttyent.c (revision 6caac9d0e71f77de08c10d80dc2c38f30e32baeb)
1*6caac9d0Smartin /*	$NetBSD: getttyent.c,v 1.26 2013/06/30 10:07:43 martin Exp $	*/
2b585e843Scgd 
361f28255Scgd /*
4b585e843Scgd  * Copyright (c) 1989, 1993
5b585e843Scgd  *	The Regents of the University of California.  All rights reserved.
661f28255Scgd  *
761f28255Scgd  * Redistribution and use in source and binary forms, with or without
861f28255Scgd  * modification, are permitted provided that the following conditions
961f28255Scgd  * are met:
1061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
1261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
1461f28255Scgd  *    documentation and/or other materials provided with the distribution.
15eb7c1594Sagc  * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd  *    may be used to endorse or promote products derived from this software
1761f28255Scgd  *    without specific prior written permission.
1861f28255Scgd  *
1961f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd  * SUCH DAMAGE.
3061f28255Scgd  */
3161f28255Scgd 
32052e43e4Schristos #include <sys/cdefs.h>
3361f28255Scgd #if defined(LIBC_SCCS) && !defined(lint)
34b585e843Scgd #if 0
35b585e843Scgd static char sccsid[] = "@(#)getttyent.c	8.1 (Berkeley) 6/4/93";
36b585e843Scgd #else
37*6caac9d0Smartin __RCSID("$NetBSD: getttyent.c,v 1.26 2013/06/30 10:07:43 martin Exp $");
38b585e843Scgd #endif
3961f28255Scgd #endif /* LIBC_SCCS and not lint */
4061f28255Scgd 
4143fa6fe3Sjtc #include "namespace.h"
42b48252f3Slukem 
43b48252f3Slukem #include <assert.h>
4461f28255Scgd #include <ctype.h>
45b48252f3Slukem #include <stdio.h>
4661f28255Scgd #include <string.h>
47b48252f3Slukem #include <ttyent.h>
48622e897fSchristos #include <errno.h>
49622e897fSchristos #include <err.h>
50622e897fSchristos #include <stdlib.h>
5161f28255Scgd 
52138bf8b9Smatt #include <sys/sysctl.h>
53138bf8b9Smatt #include <sys/utsname.h>
54138bf8b9Smatt 
5543fa6fe3Sjtc #ifdef __weak_alias
5660549036Smycroft __weak_alias(endttyent,_endttyent)
5760549036Smycroft __weak_alias(getttyent,_getttyent)
5860549036Smycroft __weak_alias(getttynam,_getttynam)
5960549036Smycroft __weak_alias(setttyent,_setttyent)
602118fde3Ssalo __weak_alias(setttyentpath,_setttyentpath)
6143fa6fe3Sjtc #endif
6243fa6fe3Sjtc 
6361f28255Scgd static FILE *tf;
64622e897fSchristos static size_t lineno = 0;
65ba984735Schristos static char *skip(char *, char *);
66ba984735Schristos static char *value(char *);
6761f28255Scgd 
6861f28255Scgd struct ttyent *
getttynam(const char * tty)69ba984735Schristos getttynam(const char *tty)
7061f28255Scgd {
714146d586Sperry 	struct ttyent *t;
7261f28255Scgd 
73b48252f3Slukem 	_DIAGASSERT(tty != NULL);
74b48252f3Slukem 
7561f28255Scgd 	setttyent();
76052e43e4Schristos 	while ((t = getttyent()) != NULL)
7761f28255Scgd 		if (!strcmp(tty, t->ty_name))
7861f28255Scgd 			break;
7961f28255Scgd 	endttyent();
8061f28255Scgd 	return (t);
8161f28255Scgd }
8261f28255Scgd 
8361f28255Scgd struct ttyent *
getttyent(void)84ba984735Schristos getttyent(void)
8561f28255Scgd {
8661f28255Scgd 	static struct ttyent tty;
874146d586Sperry 	int c;
884146d586Sperry 	char *p;
89622e897fSchristos 	size_t len;
90622e897fSchristos 	static char *line = NULL;
91ba984735Schristos 	char zapchar;
9261f28255Scgd 
93622e897fSchristos 	if (line)
94622e897fSchristos 		free(line);
95ba984735Schristos 
96ba984735Schristos 	if (!tf && !setttyent())
97ba984735Schristos 		return NULL;
98ba984735Schristos 
9961f28255Scgd 	for (;;) {
100622e897fSchristos 		errno = 0;
101622e897fSchristos 		line = fparseln(tf, &len, &lineno, NULL, FPARSELN_UNESCALL);
102622e897fSchristos 		if (line == NULL) {
103622e897fSchristos 			if (errno != 0)
104ba984735Schristos 				warn(__func__);
105622e897fSchristos 			return NULL;
10661f28255Scgd 		}
107622e897fSchristos 		for (p = line; *p && isspace((unsigned char)*p); p++)
108622e897fSchristos 			continue;
10961f28255Scgd 		if (*p && *p != '#')
11061f28255Scgd 			break;
111622e897fSchristos 		free(line);
11261f28255Scgd 	}
11361f28255Scgd 
11461f28255Scgd 	tty.ty_name = p;
115ba984735Schristos 	p = skip(p, &zapchar);
116ba984735Schristos 	if (*(tty.ty_getty = p) == '\0')
11761f28255Scgd 		tty.ty_getty = tty.ty_type = NULL;
11861f28255Scgd 	else {
119ba984735Schristos 		p = skip(p, &zapchar);
120ba984735Schristos 		if (*(tty.ty_type = p) == '\0')
12161f28255Scgd 			tty.ty_type = NULL;
12261f28255Scgd 		else
123ba984735Schristos 			p = skip(p, &zapchar);
12461f28255Scgd 	}
12561f28255Scgd 	tty.ty_status = 0;
12661f28255Scgd 	tty.ty_window = NULL;
127d1ca0533Schristos 	tty.ty_class = NULL;
12861f28255Scgd 
129622e897fSchristos #define	scmp(e)	!strncmp(p, e, sizeof(e) - 1) && (isspace((unsigned char) p[sizeof(e) - 1]) || p[sizeof(e) - 1] == '\0')
13061f28255Scgd #define	vcmp(e)	!strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
131ba984735Schristos 	for (; *p; p = skip(p, &zapchar)) {
13261f28255Scgd 		if (scmp(_TTYS_OFF))
13361f28255Scgd 			tty.ty_status &= ~TTY_ON;
13461f28255Scgd 		else if (scmp(_TTYS_ON))
13561f28255Scgd 			tty.ty_status |= TTY_ON;
13661f28255Scgd 		else if (scmp(_TTYS_SECURE))
13761f28255Scgd 			tty.ty_status |= TTY_SECURE;
138a1fcdedbScgd 		else if (scmp(_TTYS_LOCAL))
139a1fcdedbScgd 			tty.ty_status |= TTY_LOCAL;
140a1fcdedbScgd 		else if (scmp(_TTYS_RTSCTS))
141a1fcdedbScgd 			tty.ty_status |= TTY_RTSCTS;
14294cf4332Sscottr 		else if (scmp(_TTYS_DTRCTS))
14394cf4332Sscottr 			tty.ty_status |= TTY_DTRCTS;
144a1fcdedbScgd 		else if (scmp(_TTYS_SOFTCAR))
145a1fcdedbScgd 			tty.ty_status |= TTY_SOFTCAR;
146a1fcdedbScgd 		else if (scmp(_TTYS_MDMBUF))
147a1fcdedbScgd 			tty.ty_status |= TTY_MDMBUF;
14861f28255Scgd 		else if (vcmp(_TTYS_WINDOW))
14961f28255Scgd 			tty.ty_window = value(p);
150531aeb7cStsarna 		else if (vcmp(_TTYS_CLASS))
151531aeb7cStsarna 			tty.ty_class = value(p);
15261f28255Scgd 		else
153ba984735Schristos 			warnx("%s: %s, %lu: unknown option `%s'",
154ba984735Schristos 			    __func__, _PATH_TTYS, (unsigned long)lineno, p);
15561f28255Scgd 	}
15661f28255Scgd 
15761f28255Scgd 	if (zapchar == '#' || *p == '#')
15861f28255Scgd 		while ((c = *++p) == ' ' || c == '\t')
159ba984735Schristos 			continue;
16061f28255Scgd 	tty.ty_comment = p;
161ba984735Schristos 	if (*p == '\0')
162ba984735Schristos 		tty.ty_comment = NULL;
163052e43e4Schristos 	if ((p = strchr(p, '\n')) != NULL)
16461f28255Scgd 		*p = '\0';
165ba984735Schristos 	return &tty;
16661f28255Scgd }
16761f28255Scgd 
16861f28255Scgd #define	QUOTED	1
16961f28255Scgd 
17061f28255Scgd /*
17161f28255Scgd  * Skip over the current field, removing quotes, and return a pointer to
17261f28255Scgd  * the next field.
17361f28255Scgd  */
17461f28255Scgd static char *
skip(char * p,char * zapchar)175ba984735Schristos skip(char *p, char *zapchar)
17661f28255Scgd {
1774146d586Sperry 	char *t;
1784146d586Sperry 	int c, q;
17961f28255Scgd 
180b48252f3Slukem 	_DIAGASSERT(p != NULL);
181ba984735Schristos 	*zapchar = '\0';
182b48252f3Slukem 
18361f28255Scgd 	for (q = 0, t = p; (c = *p) != '\0'; p++) {
18461f28255Scgd 		if (c == '"') {
18561f28255Scgd 			q ^= QUOTED;	/* obscure, but nice */
18661f28255Scgd 			continue;
18761f28255Scgd 		}
18861f28255Scgd 		if (q == QUOTED && *p == '\\' && *(p+1) == '"')
18961f28255Scgd 			p++;
19061f28255Scgd 		*t++ = *p;
19161f28255Scgd 		if (q == QUOTED)
19261f28255Scgd 			continue;
19361f28255Scgd 		if (c == '#') {
194ba984735Schristos 			*zapchar = c;
195ba984735Schristos 			*p = '\0';
196ba984735Schristos 			*--t = '\0';
197ba984735Schristos 			return p;
19861f28255Scgd 		}
19961f28255Scgd 		if (c == '\t' || c == ' ' || c == '\n') {
200ba984735Schristos 			*zapchar = c;
201ba984735Schristos 			*p++ = '\0';
20261f28255Scgd 			while ((c = *p) == '\t' || c == ' ' || c == '\n')
20361f28255Scgd 				p++;
20461f28255Scgd 			*--t = '\0';
205ba984735Schristos 			return p;
206ba984735Schristos 		}
207ba984735Schristos 	}
208ba984735Schristos 	if (t != p)
209ba984735Schristos 		*t = '\0';
210ba984735Schristos 	return p;
21161f28255Scgd }
21261f28255Scgd 
21361f28255Scgd static char *
value(char * p)214ba984735Schristos value(char *p)
21561f28255Scgd {
21661f28255Scgd 
217b48252f3Slukem 	_DIAGASSERT(p != NULL);
218b48252f3Slukem 
219ba984735Schristos 	return (p = strchr(p, '=')) != NULL ? ++p : NULL;
22061f28255Scgd }
22161f28255Scgd 
22261f28255Scgd int
setttyentpath(const char * path)2232118fde3Ssalo setttyentpath(const char *path)
22461f28255Scgd {
225622e897fSchristos 	lineno = 0;
22661f28255Scgd 	if (tf) {
227915b76ddSjtc 		rewind(tf);
228ba984735Schristos 		return 1;
229138bf8b9Smatt 	}
230138bf8b9Smatt 
231138bf8b9Smatt 	/*
232138bf8b9Smatt 	 * Try <path>.$MACHINE (e.g. etc/ttys.amd64)
233138bf8b9Smatt 	 */
234*6caac9d0Smartin 	{
235138bf8b9Smatt 		char machine[_SYS_NMLN];
236138bf8b9Smatt 		const int mib[] = { [0] = CTL_HW, [1] = HW_MACHINE, };
237138bf8b9Smatt 		size_t len = sizeof(machine);
238138bf8b9Smatt 
239*6caac9d0Smartin 		if (sysctl(mib, (u_int)__arraycount(mib), machine, &len,
240*6caac9d0Smartin 		     NULL, 0) != -1) {
241138bf8b9Smatt 			char npath[PATH_MAX];
242*6caac9d0Smartin 			(void)snprintf(npath, sizeof(npath), "%s.%s", path,
243*6caac9d0Smartin 			    machine);
244138bf8b9Smatt 			if ((tf = fopen(npath, "re")) != NULL)
245138bf8b9Smatt 				return 1;
246138bf8b9Smatt 		}
247*6caac9d0Smartin 	}
248138bf8b9Smatt 
249138bf8b9Smatt 	if ((tf = fopen(path, "re")) != NULL)
250ba984735Schristos 		return 1;
251ba984735Schristos 	return 0;
25261f28255Scgd }
25361f28255Scgd 
25461f28255Scgd int
setttyent(void)2552118fde3Ssalo setttyent(void)
2562118fde3Ssalo {
2572118fde3Ssalo 	return setttyentpath(_PATH_TTYS);
2582118fde3Ssalo }
2592118fde3Ssalo 
2602118fde3Ssalo int
endttyent(void)261ba984735Schristos endttyent(void)
26261f28255Scgd {
26361f28255Scgd 	int rval;
26461f28255Scgd 
26561f28255Scgd 	if (tf) {
26661f28255Scgd 		rval = !(fclose(tf) == EOF);
26761f28255Scgd 		tf = NULL;
268ba984735Schristos 		return rval;
26961f28255Scgd 	}
270ba984735Schristos 	return 1;
27161f28255Scgd }
272