#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "entity.h"
static EBuf *
expand_homedir (EBuf *str)
{
EBuf *realfile;
char *p;
realfile = ebuf_new ();
/* Expand ~ */
for (p = str->str; *p; p++) {
if (*p == '~') {
ebuf_append_str (realfile, g_get_home_dir());
} else {
ebuf_append_char (realfile, *p);
}
}
return (realfile);
}
void
rend_configfile_sync (ENode *node)
{
EBuf *filename;
EBuf *realfile;
EBuf *xml;
ENode *confignode;
FILE *fp;
if (ebuf_equal_str (enode_type (node), "configfile"))
confignode = node;
else
confignode = enode_parent (node, "configfile");
if (!confignode) {
EDEBUG (("configfilerend",
"Umm, we have no configfile node above us ?"));
return;
}
filename = enode_attrib (confignode, "file", NULL);
EDEBUG (("configfilerend", "file attrib of node %s.%s is %s",
confignode->element->str,
enode_attrib_str (confignode, "name", NULL), filename->str));
realfile = expand_homedir (filename);
EDEBUG (("configfilerend", "Writing out config file to %s",
realfile->str));
/* We just dump stuff to it regardless of whether it exists
* or not */
fp = fopen (realfile->str, "w");
if (!fp) {
/* TODO: Think about how to actually do this.. should we signal an
* error, or ? */
g_warning ("Unable to open configuration file '%s' for writing: %s",
realfile->str, g_strerror (errno));
ebuf_free (realfile);
return;
}
xml = enode_get_child_xml (confignode);
fwrite (xml->str, sizeof (char), xml->len, fp);
fclose (fp);
ebuf_free (realfile);
}
static gint
rend_configfile_file_attr_set (ENode * node, EBuf * attr, EBuf * value)
{
EBuf *realfile;
if (ebuf_not_empty (value)) {
realfile = expand_homedir (value);
if (eutils_file_exists (realfile->str)) {
EDEBUG (("configfilerend",
"Config file %s exists, reading in..",
realfile->str));
/* If the file exists, we clean out whatever is currently there,
* and load up the config file into its place */
enode_destroy_children (node);
xml_parse_file (node, realfile->str);
} else {
EDEBUG (("configfilerend",
"Config file %s does not exists, will write on change",
realfile->str));
}
ebuf_free (realfile);
}
/* At this point, the contents under the node, are sync'd with the
* contents of the config file (if there is one, if not, the contents
* of the node should be in that file anyway).
*
* So, we can safely now setup our callback to start keeping track
* of config changes and writing them to disk when they happen */
enode_event_watch_child_attrib (node,
(EventAttribChange) rend_configfile_sync, NULL);
/* enode_event_watch_child_data (node,
* (EventDataChange) rend_configfile_sync, NULL); */
/* enode_event_watch_child_delete (node,
* (EventDelete) rend_configfile_sync, NULL); */
enode_event_watch_child_new (node,
(EventNewChild) rend_configfile_sync, NULL);
return (TRUE);
}
static void
rend_configfile_render (ENode * node)
{
enode_attribs_sync (node);
}
static void
rend_configfile_parent (ENode * parent_node, ENode * child_node)
{
/* We have to reparent .. */
erend_short_curcuit_parent (parent_node, child_node);
}
void
configfile_renderer_register (void)
{
Element *element;
ElementAttr *e_attr;
element = g_new0 (Element, 1);
element->parent_func = rend_configfile_parent;
element->render_func = rend_configfile_render;
element->tag = "configfile";
element->description =
"Used to store config file information. XML in file is replaced under this node, if the file exists. Any changes to nodes under this are written to that file.";
element_register (element);
e_attr = g_new0 (ElementAttr, 1);
e_attr->attribute = "file";
e_attr->description = "Path to XML configuration file.";
e_attr->value_desc = "string";
e_attr->set_attr_func = rend_configfile_file_attr_set;
element_register_attrib (element, e_attr);
}
syntax highlighted by Code2HTML, v. 0.9.1