00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: config.c,v 1.11 2006-01-06 00:53:10 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026
00027 static bind_table_t *BT_config_str = NULL,
00028 *BT_config_int = NULL,
00029 *BT_config_save = NULL;
00030
00031
00032
00033 static int gconfig_level = 0;
00034
00035 typedef struct {
00036 char *handle;
00037 void *root;
00038 } config_handle_t;
00039
00040 static config_handle_t *roots = NULL;
00041 static int nroots = 0;
00042
00043 static void config_delete_var(void *client_data);
00044
00045 int config_init(void)
00046 {
00047 BT_config_str = bind_table_add(BTN_CONFIG_STR, 2, "ss", MATCH_MASK, BIND_STACKABLE);
00048 BT_config_int = bind_table_add(BTN_CONFIG_INT, 2, "si", MATCH_MASK, BIND_STACKABLE);
00049 BT_config_save = bind_table_add(BTN_CONFIG_SAVE, 1, "s", MATCH_MASK, BIND_STACKABLE);
00050 return(0);
00051 }
00052
00053 int config_shutdown(void)
00054 {
00055 int i;
00056
00057 for (i = nroots - 1; i >= 0; i--) {
00058 config_delete_root(roots[i].handle);
00059 }
00060 nroots = 0;
00061
00062 bind_table_del(BT_config_str);
00063 bind_table_del(BT_config_int);
00064 bind_table_del(BT_config_save);
00065 return (0);
00066 }
00067
00068
00069 void *config_get_root(const char *handle)
00070 {
00071 int i;
00072
00073 for (i = 0; i < nroots; i++) {
00074 if (!strcasecmp(handle, roots[i].handle)) return(roots[i].root);
00075 }
00076 return(NULL);
00077 }
00078
00079 int config_set_root(const char *handle, void *config_root)
00080 {
00081 egg_assert_val(handle != NULL, -1);
00082 egg_assert_val(config_root != NULL, -1);
00083
00084 roots = realloc(roots, sizeof(*roots) * (nroots+1));
00085 roots[nroots].handle = strdup(handle);
00086 roots[nroots].root = config_root;
00087 nroots++;
00088 return(0);
00089 }
00090
00091 int config_delete_root(const char *handle)
00092 {
00093 int i;
00094
00095 for (i = 0; i < nroots; i++) {
00096 if (!strcasecmp(handle, roots[i].handle)) {
00097 if (roots[i].handle) free(roots[i].handle);
00098 xml_node_delete_callbacked(roots[i].root, config_delete_var);
00099 memmove(roots+i, roots+i+1, sizeof(*roots) * (nroots-i-1));
00100 if (--nroots == 0) {
00101 free(roots);
00102 roots = NULL;
00103 }
00104 return (0);
00105 }
00106 }
00107
00108
00109 return(-1);
00110 }
00111
00112 void *config_load(const char *fname)
00113 {
00114 xml_node_t *root;
00115
00116 root = xml_parse_file(fname);
00117 if (!root) {
00118
00119 fprintf(stderr, "ERROR\n");
00120 fprintf(stderr, "\tFailed to load config '%s': %s\n\n", fname, xml_last_error());
00121 return NULL;
00122 }
00123
00124 return(root);
00125 }
00126
00127 int config_save(const char *handle, const char *fname)
00128 {
00129 void *root;
00130
00131 root = config_get_root(handle);
00132 if (root) bind_check(BT_config_save, NULL, handle, handle);
00133 if (!fname) fname = "config.xml";
00134
00135 if (xml_save_file(fname, root, XML_INDENT) == 0)
00136 return (0);
00137
00138 putlog(LOG_MISC, "*", _("Failed to save config '%s': %s"), fname, xml_last_error());
00139
00140 return (-1);
00141 }
00142
00143 static void config_delete_var(void *client_data)
00144 {
00145 config_var_t *var = client_data;
00146
00147 switch (var->type) {
00148 case (CONFIG_STRING):
00149 free(*(char **)var->ptr);
00150 *(char **) var->ptr = NULL;
00151 break;
00152 case (CONFIG_INT):
00153 break;
00154 }
00155 }
00156
00157 int config_destroy(void *config_root)
00158 {
00159 xml_node_t *root = config_root;
00160
00161 xml_node_delete_callbacked(root, config_delete_var);
00162
00163 return(0);
00164 }
00165
00166 void *config_lookup_section(void *config_root, ...)
00167 {
00168 va_list args;
00169 xml_node_t *root = config_root;
00170
00171 va_start(args, config_root);
00172 root = xml_node_vlookup(root, args, 1);
00173 va_end(args);
00174
00175 return(root);
00176 }
00177
00178 void *config_exists(void *config_root, ...)
00179 {
00180 va_list args;
00181 xml_node_t *root = config_root;
00182
00183 va_start(args, config_root);
00184 root = xml_node_vlookup(root, args, 0);
00185 va_end(args);
00186 return(root);
00187 }
00188
00189 int config_get_int(int *intptr, void *config_root, ...)
00190 {
00191 va_list args;
00192 xml_node_t *root = config_root;
00193
00194 va_start(args, config_root);
00195 root = xml_node_vlookup(root, args, 0);
00196 va_end(args);
00197
00198 if (!root) {
00199 *intptr = 0;
00200 return(-1);
00201 }
00202 return xml_node_get_int(intptr, root, NULL);
00203 }
00204
00205 int config_get_str(char **strptr, void *config_root, ...)
00206 {
00207 va_list args;
00208 xml_node_t *root = config_root;
00209
00210 va_start(args, config_root);
00211 root = xml_node_vlookup(root, args, 0);
00212 va_end(args);
00213
00214 if (!root) {
00215 *strptr = NULL;
00216 return(-1);
00217 }
00218 return xml_node_get_str(strptr, root, NULL);
00219 }
00220
00221 int config_set_int(int intval, void *config_root, ...)
00222 {
00223 va_list args;
00224 xml_node_t *root = config_root;
00225 config_var_t *var;
00226
00227 va_start(args, config_root);
00228 root = xml_node_vlookup(root, args, 1);
00229 va_end(args);
00230
00231 if (!gconfig_level) {
00232 char *name;
00233 int r;
00234
00235 name = xml_node_fullname(root);
00236 gconfig_level++;
00237 r = bind_check(BT_config_int, NULL, name, name, intval);
00238 gconfig_level--;
00239 free(name);
00240 if (r & BIND_RET_BREAK) return(-1);
00241 }
00242
00243 var = root->client_data;
00244 if (var) {
00245 if (var->type == CONFIG_INT) *(int *)var->ptr = intval;
00246 }
00247 xml_node_set_int(intval, root, NULL);
00248 return(0);
00249 }
00250
00251 int config_set_str(const char *strval, void *config_root, ...)
00252 {
00253 va_list args;
00254 xml_node_t *root = config_root;
00255 config_var_t *var;
00256
00257 va_start(args, config_root);
00258 root = xml_node_vlookup(root, args, 1);
00259 va_end(args);
00260
00261 if (!gconfig_level) {
00262 char *name;
00263 int r;
00264
00265 name = xml_node_fullname(root);
00266 gconfig_level++;
00267 r = bind_check(BT_config_str, NULL, name, name, strval);
00268 gconfig_level--;
00269 free(name);
00270 if (r & BIND_RET_BREAK) return(-1);
00271 }
00272 var = root->client_data;
00273 if (var) {
00274 if (var->type == CONFIG_STRING && *(char **)var->ptr != strval) str_redup(var->ptr, strval);
00275 else if (var->type == CONFIG_INT) *(int *)var->ptr = atoi(strval);
00276 }
00277 xml_node_set_str(strval, root, NULL);
00278 return(0);
00279 }
00280
00281 int config_link_table(config_var_t *table, void *config_root, ...)
00282 {
00283 xml_node_t *node, *root = config_root;
00284 va_list args;
00285
00286 gconfig_level++;
00287
00288 va_start(args, config_root);
00289 root = xml_node_vlookup(root, args, 1);
00290 va_end(args);
00291
00292 if (!root) {
00293 gconfig_level--;
00294 return(-1);
00295 }
00296
00297 while (table->name) {
00298 node = xml_node_lookup(root, 1, table->name, 0, NULL);
00299 node->client_data = table;
00300 if (table->type == CONFIG_INT) config_get_int(table->ptr, root, table->name, 0, NULL);
00301 else if (table->type == CONFIG_STRING) {
00302 char *str;
00303 config_get_str(&str, root, table->name, 0, NULL);
00304 str_redup(table->ptr, str);
00305 }
00306 table++;
00307 }
00308
00309 gconfig_level--;
00310 return(0);
00311 }
00312
00313 int config_update_table(config_var_t *table, void *config_root, ...)
00314 {
00315 xml_node_t *node, *root = config_root;
00316 va_list args;
00317
00318 gconfig_level++;
00319
00320 va_start(args, config_root);
00321 root = xml_node_vlookup(root, args, 1);
00322 va_end(args);
00323
00324 if (!root) {
00325 gconfig_level--;
00326 return(-1);
00327 }
00328
00329 while (table->name) {
00330 node = xml_node_lookup(root, 1, table->name, 0, NULL);
00331 node->client_data = table;
00332
00333 switch (table->type) {
00334
00335 case (CONFIG_INT):
00336 config_set_int(*(int *)table->ptr, root, table->name, 0, NULL);
00337 break;
00338
00339 case (CONFIG_STRING):
00340 config_set_str(*(char **)table->ptr, root, table->name, 0, NULL);
00341 break;
00342 }
00343
00344 table++;
00345 }
00346
00347 gconfig_level--;
00348 return(0);
00349 }
00350
00351 int config_unlink_table(config_var_t *table, void *config_root, ...)
00352 {
00353 xml_node_t *node, *root = config_root;
00354 va_list args;
00355
00356 va_start(args, config_root);
00357 root = xml_node_vlookup(root, args, 1);
00358 va_end(args);
00359
00360 if (!root) return(-1);
00361
00362 while (table->name) {
00363 node = xml_node_lookup(root, 0, table->name, 0, NULL);
00364 if (node)
00365 xml_node_delete_callbacked(node, config_delete_var);
00366 table++;
00367 }
00368 return(0);
00369 }