#include #include #include #include #include #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); }