xref: /netbsd-src/usr.sbin/wsmoused/config.c (revision 1ffa7b76c40339c17a0fb2a09fac93f287cfc046)
1 /* $NetBSD: config.c,v 1.2 2003/03/04 19:28:59 jmmv Exp $ */
2 
3 /*
4  * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Julio Merino.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. The name authors may not be used to endorse or promote products
16  *    derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
20  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 
34 #ifndef lint
35 __RCSID("$NetBSD: config.c,v 1.2 2003/03/04 19:28:59 jmmv Exp $");
36 #endif /* not lint */
37 
38 #include <sys/time.h>
39 #include <dev/wscons/wsconsio.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <err.h>
43 #include <errno.h>
44 #include <string.h>
45 
46 #include "pathnames.h"
47 #include "wsmoused.h"
48 
49 static struct block *Global = NULL;
50 
51 /* Prototypes for config_yacc.y (only used here) */
52 struct block *config_parse(FILE *);
53 
54 /*
55  * Creates a new, empty property.  Returns a pointer to it.
56  */
57 struct prop *
58 prop_new(void)
59 {
60 	struct prop *p;
61 
62 	p = (struct prop *) calloc(1, sizeof(struct prop));
63 	if (p == NULL)
64 		err(EXIT_FAILURE, "calloc");
65 	return p;
66 }
67 
68 /*
69  * Frees a property created with prop_new.  All data stored in the property
70  * is also destroyed.
71  */
72 void
73 prop_free(struct prop *p)
74 {
75 	free(p->p_name);
76 	free(p->p_value);
77 	free(p);
78 }
79 
80 /*
81  * Creates a new, empty block, with the specified type (see BLOCK_* macros).
82  * Returns a pointer to it.
83  */
84 struct block *
85 block_new(int type)
86 {
87 	struct block *b;
88 
89 	b = (struct block *) calloc(1, sizeof(struct block));
90 	if (b == NULL)
91 		err(EXIT_FAILURE, "calloc");
92 	b->b_type = type;
93 	return b;
94 }
95 
96 /*
97  * Frees a block created with block_new.  All data contained inside the block
98  * is also destroyed.
99  */
100 void
101 block_free(struct block *b)
102 {
103 	int i;
104 
105 	if (b->b_name != NULL)
106 		free(b->b_name);
107 
108 	for (i = 0; i < b->b_prop_count; i++)
109 		prop_free(b->b_prop[i]);
110 	for (i = 0; i < b->b_child_count; i++)
111 		block_free(b->b_child[i]);
112 
113 	free(b);
114 }
115 
116 /*
117  * Add a property to a block.
118  */
119 void
120 block_add_prop(struct block *b, struct prop *p)
121 {
122 	if (p == NULL)
123 		return;
124 
125 	if (b->b_prop_count >= MAX_PROPS)
126 		errx(EXIT_FAILURE, "too many properties for current block");
127 	else {
128 		b->b_prop[b->b_prop_count] = p;
129 		b->b_prop_count++;
130 	}
131 }
132 
133 /*
134  * Add a child (block) to a block.
135  */
136 void
137 block_add_child(struct block *b, struct block *c)
138 {
139 	if (c == NULL)
140 		return;
141 
142 	if (b->b_child_count >= MAX_BLOCKS)
143 		errx(EXIT_FAILURE, "too many childs for current block");
144 	else {
145 		c->b_parent = b;
146 		b->b_child[b->b_child_count] = c;
147 		b->b_child_count++;
148 	}
149 }
150 
151 /*
152  * Get the value of a property in the specified block (or in its parents).
153  * If not found, return the value given in def.
154  */
155 char *
156 block_get_propval(struct block *b, char *pname, char *def)
157 {
158 	int pc;
159 
160 	if (b == NULL)
161 		return def;
162 
163 	while (b != NULL) {
164 		for (pc = 0; pc < b->b_prop_count; pc++)
165 			if (strcmp(b->b_prop[pc]->p_name, pname) == 0)
166 				return b->b_prop[pc]->p_value;
167 		b = b->b_parent;
168 	}
169 
170 	return def;
171 }
172 
173 /*
174  * Get the value of a property in the specified block converting it to an
175  * integer, if possible.  If the property cannot be found in the given
176  * block, all its parents are tried.  If after all not found (or conversion
177  * not possible), return the value given in def.
178  */
179 int
180 block_get_propval_int(struct block *b, char *pname, int def)
181 {
182 	int pc, ret;
183 	char *ptr;
184 
185 	if (b == NULL)
186 		return def;
187 
188 	while (b != NULL) {
189 		for (pc = 0; pc < b->b_prop_count; pc++)
190 			if (strcmp(b->b_prop[pc]->p_name, pname) == 0) {
191 				ret = (int) strtol(b->b_prop[pc]->p_value,
192 				    &ptr, 10);
193 				if (b->b_prop[pc]->p_value == ptr) {
194 					warnx("expected integer in `%s' "
195 					    "property", pname);
196 					return def;
197 				}
198 				return ret;
199 			}
200 		b = b->b_parent;
201 	}
202 
203 	return def;
204 }
205 
206 /*
207  * Get a mode block (childs of the global scope), which matches the specified
208  * name.
209  */
210 struct block *
211 config_get_mode(char *modename)
212 {
213 	struct block *b = Global;
214 	int bc;
215 
216 	if (b != NULL)
217 		for (bc = 0; bc < b->b_child_count; bc++)
218 			if (strcmp(b->b_child[bc]->b_name, modename) == 0)
219 				return b->b_child[bc];
220 
221 	return NULL;
222 }
223 
224 /*
225  * Read the configuration file.
226  */
227 void
228 config_read(char *conffile, int opt)
229 {
230 	FILE *f;
231 
232 	errno = 0;
233 	f = fopen(conffile, "r");
234 	if (f != NULL) {
235 		Global = config_parse(f);
236 		if (Global == NULL)
237 			errx(EXIT_FAILURE, "%s contains fatal errors",
238 			     conffile);
239 	} else if (errno != ENOENT || opt) {
240 		err(EXIT_FAILURE, "cannot open %s", conffile);
241 	}
242 }
243 
244 /*
245  * Destroy all the configuration data.
246  */
247 void
248 config_free(void)
249 {
250 	if (Global != NULL)
251 		block_free(Global);
252 }
253