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