2 #include <stdio.h> /* for NULL, printf, FILE, etc */
3 #include <stdlib.h> /* for malloc */
4 #include <string.h> /* for strdup */
5 #include <ctype.h> /* for isspace */
8 #include "pnd_container.h"
9 #include "pnd_pathiter.h"
11 pnd_conf_filename_t pnd_conf_filenames[] = {
12 { pnd_conf_conf, PND_CONF_FILE },
13 { pnd_conf_apps, "apps" },
14 { pnd_conf_startup, "startup" },
15 { pnd_conf_desktop, "desktop" },
16 { pnd_conf_categories, "categories" },
17 { pnd_conf_evmap, "eventmap" },
18 { pnd_conf_nil, NULL },
21 char *pnd_conf_query_searchpath ( void ) {
25 ch = pnd_conf_fetch_by_id ( pnd_conf_conf, PND_CONF_SEARCHPATH );
28 //printf ( "Couldn't locate base conf file '%s'\n", PND_CONF_FILE );
29 return ( strdup ( PND_CONF_SEARCHPATH ) );
32 // can we find a user-specified config path? if so, use it.. if not, fall back!
36 temp = pnd_conf_get_as_char ( ch, PND_CONF_KEY );
39 searchpath = strdup ( temp );
41 searchpath = strdup ( PND_CONF_SEARCHPATH );
44 return ( searchpath );
47 pnd_conf_handle pnd_conf_fetch_by_id ( pnd_conf_filename_e id, char *searchpath ) {
48 pnd_conf_filename_t *p = pnd_conf_filenames;
50 while ( p -> filename ) {
52 /* found the filename associated to the id? */
53 if ( p -> id == id ) {
54 return ( pnd_conf_fetch_by_name ( p -> filename, searchpath ) );
64 pnd_conf_handle pnd_conf_fetch_by_name ( char *filename, char *searchpath ) {
66 /* the fun part here is that we get to cheat; while we have to search through all the directories
67 * listed in the search path, we can stop at the first matching file. Nothign really fancy going on, and
68 * no need for comprehensive directory crawling. yay!
72 //printf ( "Search path: '%s'\n", searchpath );
77 strncat ( buffer, "/", FILENAME_MAX - 1 );
78 strncat ( buffer, filename, FILENAME_MAX - 1 );
79 conf = pnd_conf_fetch_by_path ( buffer );
91 pnd_conf_handle pnd_conf_fetch_by_path ( char *fullpath ) {
93 char section [ 256 ] = "";
94 char buffer [ FILENAME_MAX ];
95 char inbuffer [ FILENAME_MAX ];
96 char *c, *head, *tail, *mid;
98 //printf ( "Attempt to load config from fullpath '%s'\n", fullpath );
101 * No check yet to verify the directory is actually mounted and readable; either way
102 * this should not block or take up much time, though SD cards might be slow to open over
103 * and over again .. perhaps need some smarts or caching of results or somesuch, since this
104 * call gets spammed over and over...
106 f = fopen ( fullpath, "r" );
112 // damn, we actually found a file, so need to try to parse it. Shucks. Give back a box-handle
113 // so the consumer has some lists to look at
115 h = pnd_box_new ( fullpath );
118 while ( fgets ( inbuffer, FILENAME_MAX, f ) ) {
120 // strip line-endings and DOSisms
121 if ( ( c = strchr ( inbuffer, '\r' ) ) ) {
125 if ( ( c = strchr ( inbuffer, '\n' ) ) ) {
129 //printf ( "config line: '%s'\n", inbuffer );
132 if ( ( c = strchr ( inbuffer, '#' ) ) ) {
136 // strip leading and trailing spaces
138 while ( *head && isspace ( *head ) ) {
142 if ( inbuffer [ 0 ] == '\0' ) {
143 //printf ( " -> discard\n" );
144 continue; // skip, the line was pure comment or blank
147 tail = strchr ( inbuffer, '\0' ) - 1;
148 while ( *tail && isspace ( *tail ) ) {
153 if ( inbuffer [ 0 ] == '\0' ) {
154 //printf ( " -> discard\n" );
155 continue; // skip, the line was pure comment or blank
158 // decorated, ie: a section?
159 if ( *head == '[' && *tail == ']' ) {
160 // note: handle the nil-section
162 memset ( section, '\0', 256 );
164 if ( tail == head + 1 ) {
165 section [ 0 ] = '\0';
167 strncpy ( section, head + 1, tail - head - 1 );
170 //printf ( " -> section '%s'\n", section );
174 // must be a key (and likely a value) .. find the division
176 while ( *mid && ! isspace ( *mid ) ) {
182 // skip past any heading space for the key
183 while ( *mid && isspace ( *mid ) ) {
187 //printf ( "key head: '%s'\n", head );
188 //printf ( "key mid: '%s'\n", mid );
190 // is thjis a key/value pair, or just a key?
195 // form the actual new key
196 if ( section [ 0 ] ) {
197 snprintf ( buffer, FILENAME_MAX - 1, "%s.%s", section, head );
199 strncpy ( buffer, head, FILENAME_MAX - 1 );
202 //printf ( "Found key '%s' in config file\n", buffer );
204 // alloc node into the box
205 v = pnd_box_allocinsert ( h, buffer, strlen ( mid ) + 1 ); // allow for trailing null
210 return ( NULL ); // OOM while reading conf is either sad, or really scary conf (also sad.)
217 // form the actual new key
218 if ( section [ 0 ] ) {
219 snprintf ( buffer, FILENAME_MAX - 1, "%s.%s", section, head );
221 strncpy ( buffer, head, FILENAME_MAX - 1 );
224 //printf ( "Found key with no value '%s' in config file\n", buffer );
226 // alloc node into the box
227 v = pnd_box_allocinsert ( h, buffer, 0 ); // zero b/c of no payload
230 return ( NULL ); // OOM while reading conf is either sad, or really scary conf (also sad.)
233 } // key or key/value?
235 } // section or key/value line?
245 char *pnd_conf_get_as_char ( pnd_conf_handle c, char *key ) {
246 return ( pnd_box_find_by_key ( c, key ) );
249 int pnd_conf_get_as_int ( pnd_conf_handle c, char *key ) {
250 char *t = pnd_box_find_by_key ( c, key );
253 return ( PND_CONF_BADNUM ); // non-existant
261 int pnd_conf_get_as_int_d ( pnd_conf_handle c, char *key, int def ) {
262 char *t = pnd_box_find_by_key ( c, key );
265 return ( def ); // non-existant
273 int *pnd_conf_set_int ( pnd_conf_handle c, char *key, int v ) {
275 // key is already present? if so, delete it
276 void *kv = pnd_box_find_by_key ( c, key );
279 pnd_box_delete_node ( c, kv );
283 int *nv = pnd_box_allocinsert ( c, key, sizeof(int) );
293 char *pnd_conf_set_char ( pnd_conf_handle c, char *key, char *v ) {
295 // key is already present? if so, delete it
296 char *kv = pnd_box_find_by_key ( c, key );
299 pnd_box_delete_node ( c, kv );
303 char *nv = pnd_box_allocinsert ( c, key, strlen ( v ) + 1 );
313 unsigned char pnd_conf_write ( pnd_conf_handle c, char *fullpath ) {
314 char *p = pnd_box_get_head ( c );
316 char lastcategory [ 100 ] = "";
319 return ( 1 ); // nothing to save, so.. success?
322 f = fopen ( fullpath, "w" );
329 char *k = pnd_box_get_key ( p );
330 char *c = strchr ( k, '.' );
333 if ( strncmp ( k, lastcategory, c - k ) == 0 ) {
336 strncpy ( lastcategory, k, c - k );
337 fprintf ( f, "[%s]\n", lastcategory );
339 fprintf ( f, "%s\t%s\n", c + 1, p );
341 if ( lastcategory [ 0 ] ) {
342 fprintf ( f, "[]\n" );
344 lastcategory [ 0 ] = '\0';
345 fprintf ( f, "%s\t%s\n", k, p );
348 p = pnd_box_get_next ( p );