root/src/noit_conf.c

Revision 7192210e4ed02f4546970eb41f6da3a167b4316a, 9.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 11 years ago)

delegate hooking into the configuration system to other modules

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include <stdio.h>
9 #include <assert.h>
10 #include <libxml/parser.h>
11 #include <libxml/tree.h>
12 #include <libxml/xpath.h>
13
14 #include "noit_conf.h"
15 #include "noit_console.h"
16 #include "utils/noit_hash.h"
17 #include "utils/noit_log.h"
18
19 /* tmp hash impl, replace this with something nice */
20 static noit_hash_table _tmp_config = NOIT_HASH_EMPTY;
21 static xmlDocPtr master_config = NULL;
22 static xmlXPathContextPtr xpath_ctxt = NULL;
23
24 static noit_hash_table _compiled_fallback = NOIT_HASH_EMPTY;
25 static struct {
26   const char *key;
27   const char *val;
28 } config_info[] = {
29   /*
30    * These are compile-time fallbacks to be used in the event
31    * that the current running config does not have values for
32    * these config paths.
33    *
34    * PLEASE: keep them alphabetically sorted.
35    */
36   { "/noit/modules/directory", MODULES_DIR },
37
38   { NULL, NULL }
39 };
40
41 void register_console_config_commands();
42
43 void noit_conf_init() {
44   int i;
45   for(i = 0; config_info[i].key != NULL; i++) {
46     noit_hash_store(&_compiled_fallback,
47                     strdup(config_info[i].key), strlen(config_info[i].key),
48                     (void *)strdup(config_info[i].val));
49   }
50   xmlInitParser();
51   xmlXPathInit();
52   register_console_config_commands();
53 }
54
55 int noit_conf_load(const char *path) {
56   xmlDocPtr new_config;
57   new_config = xmlParseFile(path);
58   if(new_config) {
59     if(master_config) xmlFreeDoc(master_config);
60     if(xpath_ctxt) xmlXPathFreeContext(xpath_ctxt);
61
62     master_config = new_config;
63     xpath_ctxt = xmlXPathNewContext(master_config);
64     return 0;
65   }
66   return -1;
67 }
68 int noit_conf_save(const char *path) {
69   return -1;
70 }
71
72 noit_hash_table *noit_conf_get_hash(noit_conf_section_t section,
73                                     const char *path) {
74   int i, cnt;
75   noit_hash_table *table = NULL;
76   xmlXPathObjectPtr pobj;
77   xmlXPathContextPtr current_ctxt;
78   xmlNodePtr current_node = (xmlNodePtr)section;
79   xmlNodePtr node;
80
81   current_ctxt = xpath_ctxt;
82   if(current_node) {
83     current_ctxt = xmlXPathNewContext(master_config);
84     current_ctxt->node = current_node;
85   }
86   pobj = xmlXPathEval((xmlChar *)path, current_ctxt);
87   if(!pobj) goto out;
88   if(pobj->type != XPATH_NODESET) goto out;
89   if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out;
90   table = calloc(1, sizeof(*table));
91   cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
92   for(i=0; i<cnt; i++) {
93     char *value;
94     node = xmlXPathNodeSetItem(pobj->nodesetval, i);
95     value = (char *)xmlXPathCastNodeToString(node);
96     noit_hash_replace(table,
97                       strdup((char *)node->name), strlen((char *)node->name),
98                       strdup(value), free, free);
99   }
100  out:
101   if(current_ctxt && current_ctxt != xpath_ctxt)
102     xmlXPathFreeContext(current_ctxt);
103   return table;
104 }
105 noit_conf_section_t noit_conf_get_section(noit_conf_section_t section,
106                                           const char *path) {
107   noit_conf_section_t subsection = NULL;
108   xmlXPathObjectPtr pobj;
109   xmlXPathContextPtr current_ctxt;
110   xmlNodePtr current_node = (xmlNodePtr)section;
111
112   current_ctxt = xpath_ctxt;
113   if(current_node) {
114     current_ctxt = xmlXPathNewContext(master_config);
115     current_ctxt->node = current_node;
116   }
117   pobj = xmlXPathEval((xmlChar *)path, current_ctxt);
118   if(!pobj) goto out;
119   if(pobj->type != XPATH_NODESET) goto out;
120   if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out;
121   subsection = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0);
122  out:
123   if(current_ctxt && current_ctxt != xpath_ctxt)
124     xmlXPathFreeContext(current_ctxt);
125   return subsection;
126 }
127 noit_conf_section_t *noit_conf_get_sections(noit_conf_section_t section,
128                                             const char *path,
129                                             int *cnt) {
130   int i;
131   noit_conf_section_t *sections = NULL;
132   xmlXPathObjectPtr pobj;
133   xmlXPathContextPtr current_ctxt;
134   xmlNodePtr current_node = (xmlNodePtr)section;
135
136   *cnt = 0;
137   current_ctxt = xpath_ctxt;
138   if(current_node) {
139     current_ctxt = xmlXPathNewContext(master_config);
140     current_ctxt->node = current_node;
141   }
142   pobj = xmlXPathEval((xmlChar *)path, current_ctxt);
143   if(!pobj) goto out;
144   if(pobj->type != XPATH_NODESET) goto out;
145   if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) goto out;
146   *cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
147   sections = calloc(*cnt, sizeof(*sections));
148   for(i=0; i<*cnt; i++)
149     sections[i] = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i);
150  out:
151   if(current_ctxt && current_ctxt != xpath_ctxt)
152     xmlXPathFreeContext(current_ctxt);
153   return sections;
154 }
155 int _noit_conf_get_string(noit_conf_section_t section,
156                           const char *path, char **value) {
157   char *str;
158   int i;
159   xmlXPathObjectPtr pobj;
160   xmlXPathContextPtr current_ctxt;
161   xmlNodePtr current_node = (xmlNodePtr)section;
162
163   current_ctxt = xpath_ctxt;
164   if(current_node) {
165     current_ctxt = xmlXPathNewContext(master_config);
166     current_ctxt->node = current_node;
167   }
168   pobj = xmlXPathEval((xmlChar *)path, current_ctxt);
169   if(pobj) {
170     xmlNodePtr node;
171     switch(pobj->type) {
172       case XPATH_NODESET:
173         if(xmlXPathNodeSetIsEmpty(pobj->nodesetval)) return 0;
174         i = xmlXPathNodeSetGetLength(pobj->nodesetval);
175         node = xmlXPathNodeSetItem(pobj->nodesetval, i-1);
176         *value = (char *)xmlXPathCastNodeToString(node);
177         break;
178       default:
179         *value = (char *)xmlXPathCastToString(pobj);
180     }
181     goto found;
182   }
183   if(noit_hash_retrieve(&_compiled_fallback,
184                         path, strlen(path), (void **)&str)) {
185     *value = str;
186     goto found;
187   }
188   return 0;
189  found:
190   if(current_ctxt && current_ctxt != xpath_ctxt)
191     xmlXPathFreeContext(current_ctxt);
192   return 1;
193 }
194 int noit_conf_get_string(noit_conf_section_t section,
195                          const char *path, char **value) {
196   char *str;
197   if(_noit_conf_get_string(section,path,&str)) {
198     *value = strdup(str);
199     return 1;
200   }
201   return 0;
202 }
203 int noit_conf_get_stringbuf(noit_conf_section_t section,
204                             const char *path, char *buf, int len) {
205   char *str;
206   if(_noit_conf_get_string(section,path,&str)) {
207     strlcpy(buf, str, len);
208     return 1;
209   }
210   return 0;
211 }
212 int noit_conf_set_string(noit_conf_section_t section,
213                          const char *path, const char *value) {
214   noit_hash_replace(&_tmp_config,
215                     strdup(path), strlen(path), (void *)strdup(value),
216                     free, free);
217   return 1;
218 }
219 int noit_conf_get_int(noit_conf_section_t section,
220                       const char *path, int *value) {
221   char *str;
222   long longval;
223   if(noit_conf_get_string(section,path,&str)) {
224     int base = 10;
225     if(str[0] == '0') {
226       if(str[1] == 'x') base = 16;
227       else base = 8;
228     }
229     longval = strtol(str, NULL, base);
230     free(str);
231     *value = (int)longval;
232     return 1;
233   }
234   return 0;
235 }
236 int noit_conf_set_int(noit_conf_section_t section,
237                       const char *path, int value) {
238   char buffer[32];
239   snprintf(buffer, 32, "%d", value);
240   return noit_conf_set_string(section,path,buffer);
241 }
242 int noit_conf_get_float(noit_conf_section_t section,
243                         const char *path, float *value) {
244   char *str;
245   if(noit_conf_get_string(section,path,&str)) {
246     *value = atof(str);
247     free(str);
248     return 1;
249   }
250   return 0;
251 }
252 int noit_conf_set_float(noit_conf_section_t section,
253                         const char *path, float value) {
254   char buffer[32];
255   snprintf(buffer, 32, "%f", value);
256   return noit_conf_set_string(section,path,buffer);
257 }
258 int noit_conf_get_boolean(noit_conf_section_t section,
259                           const char *path, noit_conf_boolean *value) {
260   char *str;
261   if(noit_conf_get_string(section,path,&str)) {
262     if(!strcasecmp(str, "true")) *value = noit_true;
263     else *value = noit_false;
264     free(str);
265     return 1;
266   }
267   return 0;
268 }
269 int noit_conf_set_boolean(noit_conf_section_t section,
270                           const char *path, noit_conf_boolean value) {
271   if(value == noit_true)
272     return noit_conf_set_string(section,path,"true");
273   return noit_conf_set_string(section,path,"false");
274 }
275
276
277 static int
278 noit_console_state_conf_terminal(noit_console_closure_t ncct,
279                                  int argc, char **argv, void *state) {
280   if(argc) {
281     nc_printf(ncct, "extra arguments not expected.\n");
282     return -1;
283   }
284   noit_console_state_push_state(ncct, state);
285   noit_console_state_init(ncct);
286   return 0;
287 }
288
289 static char *
290 conf_t_prompt(EditLine *el) {
291   static char *tl = "noit(conf)# ";
292   return tl;
293 }
294
295 void register_console_config_commands() {
296   noit_console_state_t *tl, *_conf_state, *_conf_t_state;
297
298   tl = noit_console_state_initial();
299
300   _conf_t_state = calloc(1, sizeof(*_conf_t_state));
301   _conf_t_state->console_prompt_function = conf_t_prompt;
302   noit_console_state_add_cmd(_conf_t_state, &console_command_exit);
303
304   _conf_state = calloc(1, sizeof(*_conf_state));
305   noit_console_state_add_cmd(_conf_state,
306     NCSCMD("terminal", noit_console_state_conf_terminal, _conf_t_state));
307
308   noit_console_state_add_cmd(tl,
309     NCSCMD("configure", noit_console_state_delegate, _conf_state));
310 }
Note: See TracBrowser for help on using the browser.