config.c revision 1.1 1 /* $NetBSD: config.c,v 1.1 2003/03/04 14:33:55 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.1 2003/03/04 14:33:55 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 block_free(Global);
251 }
252