1 /* $NetBSD: config.c,v 1.3 2003/08/06 18:07:53 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 M. Merino Vidal.
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.3 2003/08/06 18:07:53 jmmv Exp $");
36 #endif /* not lint */
37
38 #include <sys/time.h>
39 #include <dev/wscons/wsconsio.h>
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <err.h>
44 #include <errno.h>
45 #include <string.h>
46
47 #include "pathnames.h"
48 #include "wsmoused.h"
49
50 /* --------------------------------------------------------------------- */
51
52 /*
53 * Global variables.
54 */
55
56 static struct block *Global = NULL;
57
58 /* --------------------------------------------------------------------- */
59
60 /* Prototypes for config_yacc.y (only used here) */
61 struct block *config_parse(FILE *);
62
63 /* --------------------------------------------------------------------- */
64
65 /* Creates a new, empty property. Returns a pointer to it. */
66 struct prop *
prop_new(void)67 prop_new(void)
68 {
69 struct prop *p;
70
71 p = (struct prop *) calloc(1, sizeof(struct prop));
72 if (p == NULL)
73 err(EXIT_FAILURE, "calloc");
74 return p;
75 }
76
77 /* --------------------------------------------------------------------- */
78
79 /* Frees a property created with prop_new. All data stored in the property
80 * is also destroyed. */
81 void
prop_free(struct prop * p)82 prop_free(struct prop *p)
83 {
84
85 free(p->p_name);
86 free(p->p_value);
87 free(p);
88 }
89
90 /* --------------------------------------------------------------------- */
91
92 /* Creates a new, empty block, with the specified type (see BLOCK_* macros).
93 * Returns a pointer to it. */
94 struct block *
block_new(int type)95 block_new(int type)
96 {
97 struct block *b;
98
99 b = (struct block *) calloc(1, sizeof(struct block));
100 if (b == NULL)
101 err(EXIT_FAILURE, "calloc");
102 b->b_type = type;
103 return b;
104 }
105
106 /* --------------------------------------------------------------------- */
107
108 /* Frees a block created with block_new. All data contained inside the block
109 * is also destroyed. */
110 void
block_free(struct block * b)111 block_free(struct block *b)
112 {
113 int i;
114
115 if (b->b_name != NULL)
116 free(b->b_name);
117
118 for (i = 0; i < b->b_prop_count; i++)
119 prop_free(b->b_prop[i]);
120 for (i = 0; i < b->b_child_count; i++)
121 block_free(b->b_child[i]);
122
123 free(b);
124 }
125
126 /* --------------------------------------------------------------------- */
127
128 /* Adds a property to a block. */
129 void
block_add_prop(struct block * b,struct prop * p)130 block_add_prop(struct block *b, struct prop *p)
131 {
132
133 if (p == NULL)
134 return;
135
136 if (b->b_prop_count >= MAX_PROPS)
137 errx(EXIT_FAILURE, "too many properties for current block");
138 else {
139 b->b_prop[b->b_prop_count] = p;
140 b->b_prop_count++;
141 }
142 }
143
144 /* --------------------------------------------------------------------- */
145
146 /* Adds a child (block) to a block. */
147 void
block_add_child(struct block * b,struct block * c)148 block_add_child(struct block *b, struct block *c)
149 {
150
151 if (c == NULL)
152 return;
153
154 if (b->b_child_count >= MAX_BLOCKS)
155 errx(EXIT_FAILURE, "too many childs for current block");
156 else {
157 c->b_parent = b;
158 b->b_child[b->b_child_count] = c;
159 b->b_child_count++;
160 }
161 }
162
163 /* --------------------------------------------------------------------- */
164
165 /* Get the value of a property in the specified block (or in its parents).
166 * If not found, return the value given in def. */
167 char *
block_get_propval(struct block * b,const char * pname,char * def)168 block_get_propval(struct block *b, const char *pname, char *def)
169 {
170 int pc;
171
172 if (b == NULL)
173 return def;
174
175 while (b != NULL) {
176 for (pc = 0; pc < b->b_prop_count; pc++)
177 if (strcmp(b->b_prop[pc]->p_name, pname) == 0)
178 return b->b_prop[pc]->p_value;
179 b = b->b_parent;
180 }
181
182 return def;
183 }
184
185 /* --------------------------------------------------------------------- */
186
187 /* Get the value of a property in the specified block converting it to an
188 * integer, if possible. If the property cannot be found in the given
189 * block, all its parents are tried. If after all not found (or conversion
190 * not possible), return the value given in def. */
191 int
block_get_propval_int(struct block * b,const char * pname,int def)192 block_get_propval_int(struct block *b, const char *pname, int def)
193 {
194 char *ptr;
195 int pc, ret;
196
197 if (b == NULL)
198 return def;
199
200 while (b != NULL) {
201 for (pc = 0; pc < b->b_prop_count; pc++)
202 if (strcmp(b->b_prop[pc]->p_name, pname) == 0) {
203 ret = (int) strtol(b->b_prop[pc]->p_value,
204 &ptr, 10);
205 if (b->b_prop[pc]->p_value == ptr) {
206 warnx("expected integer in `%s' "
207 "property", pname);
208 return def;
209 }
210 return ret;
211 }
212 b = b->b_parent;
213 }
214
215 return def;
216 }
217
218 /* --------------------------------------------------------------------- */
219
220 /* Gets a mode block (childs of the global scope), which matches the
221 * specified name. */
222 struct block *
config_get_mode(const char * modename)223 config_get_mode(const char *modename)
224 {
225 int bc;
226 struct block *b;
227
228 b = Global;
229
230 if (strcmp(modename, "Global") == 0)
231 return Global;
232
233 if (b != NULL)
234 for (bc = 0; bc < b->b_child_count; bc++)
235 if (strcmp(b->b_child[bc]->b_name, modename) == 0)
236 return b->b_child[bc];
237
238 return NULL;
239 }
240
241 /* --------------------------------------------------------------------- */
242
243 /* Reads the configuration file. */
244 void
config_read(const char * conffile,int opt)245 config_read(const char *conffile, int opt)
246 {
247 FILE *f;
248
249 errno = 0;
250 f = fopen(conffile, "r");
251 if (f != NULL) {
252 Global = config_parse(f);
253 if (Global == NULL)
254 errx(EXIT_FAILURE, "%s contains fatal errors",
255 conffile);
256 } else if (errno != ENOENT || opt) {
257 err(EXIT_FAILURE, "cannot open %s", conffile);
258 }
259 }
260
261 /* --------------------------------------------------------------------- */
262
263 /* Destroys all the configuration data. */
264 void
config_free(void)265 config_free(void)
266 {
267
268 if (Global != NULL)
269 block_free(Global);
270 }
271