Home | History | Annotate | Line # | Download | only in gen
getttyent.c revision 1.25
      1 /*	$NetBSD: getttyent.c,v 1.25 2013/06/30 07:50:54 matt Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1989, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      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.
     18  *
     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.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #if defined(LIBC_SCCS) && !defined(lint)
     34 #if 0
     35 static char sccsid[] = "@(#)getttyent.c	8.1 (Berkeley) 6/4/93";
     36 #else
     37 __RCSID("$NetBSD: getttyent.c,v 1.25 2013/06/30 07:50:54 matt Exp $");
     38 #endif
     39 #endif /* LIBC_SCCS and not lint */
     40 
     41 #include "namespace.h"
     42 
     43 #include <assert.h>
     44 #include <ctype.h>
     45 #include <stdio.h>
     46 #include <string.h>
     47 #include <ttyent.h>
     48 #include <errno.h>
     49 #include <err.h>
     50 #include <stdlib.h>
     51 
     52 #include <sys/sysctl.h>
     53 #include <sys/utsname.h>
     54 
     55 #ifdef __weak_alias
     56 __weak_alias(endttyent,_endttyent)
     57 __weak_alias(getttyent,_getttyent)
     58 __weak_alias(getttynam,_getttynam)
     59 __weak_alias(setttyent,_setttyent)
     60 __weak_alias(setttyentpath,_setttyentpath)
     61 #endif
     62 
     63 static FILE *tf;
     64 static size_t lineno = 0;
     65 static char *skip(char *, char *);
     66 static char *value(char *);
     67 
     68 struct ttyent *
     69 getttynam(const char *tty)
     70 {
     71 	struct ttyent *t;
     72 
     73 	_DIAGASSERT(tty != NULL);
     74 
     75 	setttyent();
     76 	while ((t = getttyent()) != NULL)
     77 		if (!strcmp(tty, t->ty_name))
     78 			break;
     79 	endttyent();
     80 	return (t);
     81 }
     82 
     83 struct ttyent *
     84 getttyent(void)
     85 {
     86 	static struct ttyent tty;
     87 	int c;
     88 	char *p;
     89 	size_t len;
     90 	static char *line = NULL;
     91 	char zapchar;
     92 
     93 	if (line)
     94 		free(line);
     95 
     96 	if (!tf && !setttyent())
     97 		return NULL;
     98 
     99 	for (;;) {
    100 		errno = 0;
    101 		line = fparseln(tf, &len, &lineno, NULL, FPARSELN_UNESCALL);
    102 		if (line == NULL) {
    103 			if (errno != 0)
    104 				warn(__func__);
    105 			return NULL;
    106 		}
    107 		for (p = line; *p && isspace((unsigned char)*p); p++)
    108 			continue;
    109 		if (*p && *p != '#')
    110 			break;
    111 		free(line);
    112 	}
    113 
    114 	tty.ty_name = p;
    115 	p = skip(p, &zapchar);
    116 	if (*(tty.ty_getty = p) == '\0')
    117 		tty.ty_getty = tty.ty_type = NULL;
    118 	else {
    119 		p = skip(p, &zapchar);
    120 		if (*(tty.ty_type = p) == '\0')
    121 			tty.ty_type = NULL;
    122 		else
    123 			p = skip(p, &zapchar);
    124 	}
    125 	tty.ty_status = 0;
    126 	tty.ty_window = NULL;
    127 	tty.ty_class = NULL;
    128 
    129 #define	scmp(e)	!strncmp(p, e, sizeof(e) - 1) && (isspace((unsigned char) p[sizeof(e) - 1]) || p[sizeof(e) - 1] == '\0')
    130 #define	vcmp(e)	!strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
    131 	for (; *p; p = skip(p, &zapchar)) {
    132 		if (scmp(_TTYS_OFF))
    133 			tty.ty_status &= ~TTY_ON;
    134 		else if (scmp(_TTYS_ON))
    135 			tty.ty_status |= TTY_ON;
    136 		else if (scmp(_TTYS_SECURE))
    137 			tty.ty_status |= TTY_SECURE;
    138 		else if (scmp(_TTYS_LOCAL))
    139 			tty.ty_status |= TTY_LOCAL;
    140 		else if (scmp(_TTYS_RTSCTS))
    141 			tty.ty_status |= TTY_RTSCTS;
    142 		else if (scmp(_TTYS_DTRCTS))
    143 			tty.ty_status |= TTY_DTRCTS;
    144 		else if (scmp(_TTYS_SOFTCAR))
    145 			tty.ty_status |= TTY_SOFTCAR;
    146 		else if (scmp(_TTYS_MDMBUF))
    147 			tty.ty_status |= TTY_MDMBUF;
    148 		else if (vcmp(_TTYS_WINDOW))
    149 			tty.ty_window = value(p);
    150 		else if (vcmp(_TTYS_CLASS))
    151 			tty.ty_class = value(p);
    152 		else
    153 			warnx("%s: %s, %lu: unknown option `%s'",
    154 			    __func__, _PATH_TTYS, (unsigned long)lineno, p);
    155 	}
    156 
    157 	if (zapchar == '#' || *p == '#')
    158 		while ((c = *++p) == ' ' || c == '\t')
    159 			continue;
    160 	tty.ty_comment = p;
    161 	if (*p == '\0')
    162 		tty.ty_comment = NULL;
    163 	if ((p = strchr(p, '\n')) != NULL)
    164 		*p = '\0';
    165 	return &tty;
    166 }
    167 
    168 #define	QUOTED	1
    169 
    170 /*
    171  * Skip over the current field, removing quotes, and return a pointer to
    172  * the next field.
    173  */
    174 static char *
    175 skip(char *p, char *zapchar)
    176 {
    177 	char *t;
    178 	int c, q;
    179 
    180 	_DIAGASSERT(p != NULL);
    181 	*zapchar = '\0';
    182 
    183 	for (q = 0, t = p; (c = *p) != '\0'; p++) {
    184 		if (c == '"') {
    185 			q ^= QUOTED;	/* obscure, but nice */
    186 			continue;
    187 		}
    188 		if (q == QUOTED && *p == '\\' && *(p+1) == '"')
    189 			p++;
    190 		*t++ = *p;
    191 		if (q == QUOTED)
    192 			continue;
    193 		if (c == '#') {
    194 			*zapchar = c;
    195 			*p = '\0';
    196 			*--t = '\0';
    197 			return p;
    198 		}
    199 		if (c == '\t' || c == ' ' || c == '\n') {
    200 			*zapchar = c;
    201 			*p++ = '\0';
    202 			while ((c = *p) == '\t' || c == ' ' || c == '\n')
    203 				p++;
    204 			*--t = '\0';
    205 			return p;
    206 		}
    207 	}
    208 	if (t != p)
    209 		*t = '\0';
    210 	return p;
    211 }
    212 
    213 static char *
    214 value(char *p)
    215 {
    216 
    217 	_DIAGASSERT(p != NULL);
    218 
    219 	return (p = strchr(p, '=')) != NULL ? ++p : NULL;
    220 }
    221 
    222 int
    223 setttyentpath(const char *path)
    224 {
    225 	lineno = 0;
    226 	if (tf) {
    227 		rewind(tf);
    228 		return 1;
    229 	}
    230 
    231 	/*
    232 	 * Try <path>.$MACHINE (e.g. etc/ttys.amd64)
    233 	 */
    234 	char machine[_SYS_NMLN];
    235 	const int mib[] = { [0] = CTL_HW, [1] = HW_MACHINE, };
    236 	size_t len = sizeof(machine);
    237 
    238         if (sysctl(mib, __arraycount(mib), machine, &len, NULL, 0) != -1) {
    239 		char npath[PATH_MAX];
    240 		(void)snprintf(npath, sizeof(npath), "%s.%s", path, machine);
    241 		if ((tf = fopen(npath, "re")) != NULL)
    242 			return 1;
    243 	}
    244 
    245 	if ((tf = fopen(path, "re")) != NULL)
    246 		return 1;
    247 	return 0;
    248 }
    249 
    250 int
    251 setttyent(void)
    252 {
    253 	return setttyentpath(_PATH_TTYS);
    254 }
    255 
    256 int
    257 endttyent(void)
    258 {
    259 	int rval;
    260 
    261 	if (tf) {
    262 		rval = !(fclose(tf) == EOF);
    263 		tf = NULL;
    264 		return rval;
    265 	}
    266 	return 1;
    267 }
    268