root/src/noit_conf.c

Revision 7cdd67a86b56024958cccb41041404e8bfa465a5, 7.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 7 years ago)

inherited options

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