--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/brewco/rdrecipes.c Tue Dec 15 23:11:42 2015 +0100 @@ -0,0 +1,655 @@ +/***************************************************************************** + * Copyright (C) 2015 + * + * Michiel Broek <mbroek at mbse dot eu> + * + * This file is part of the mbsePi-apps + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * mbsePi-apps is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ThermFerm; see the file COPYING. If not, write to the Free + * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + *****************************************************************************/ + +#include "brewco.h" +#include "rdrecipes.h" +#include "util.h" +#include "xutil.h" + +extern int debug; + +a_recipe *recipes = NULL; + + +const char SKIPYN[2][4] = { "NO", "YES" }; + + +#define MY_ENCODING "utf-8" + + +int do_wrrecipes(void); +int do_wrrecipes(void) +{ + int i, rc = 0; + FILE *fp; + char *mypath = NULL; + a_recipe *recipe; + xmlTextWriterPtr writer; + xmlBufferPtr buf; + + /* + * Create a new XML buffer, to which the XML document will be written + */ + if ((buf = xmlBufferCreate()) == NULL) { + syslog(LOG_NOTICE, "wrrecipes: error creating the xml buffer"); + return 1; + } + + /* + * Create a new XmlWriter for memory, with no compression. + */ + if ((writer = xmlNewTextWriterMemory(buf, 0)) == NULL) { + syslog(LOG_NOTICE, "wrrecipes: error creating the xml writer"); + return 1; + } + + /* + * Use indentation instead of one long line + */ + if ((rc = xmlTextWriterSetIndent(writer, 2)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error setting Indent"); + return 1; + } + + /* + * Start the document with the xml default for the version, + * encoding ISO 8859-1 and the default for the standalone + * declaration. + */ + if ((rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartDocument"); + return 1; + } + + /* + * Start an element named "BREWCO". Since thist is the first + * element, this will be the root element of the document. + */ + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "BREWCO")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "RECIPES")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + + for (recipe = recipes; recipe; recipe = recipe->next) { + + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "RECIPE")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "UUID", "%s", recipe->uuid)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CODE", "%s", recipe->code)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", recipe->name)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BOILTIME", "%d", recipe->boiltime)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "STARTTIME", "%d", (int)recipe->starttime)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "ENDTIME", "%d", (int)recipe->endtime)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + + /* + * 8 Mash steps + */ + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "MASHSTEPS")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + for (i =0; i < 8; i++) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "MASHSTEP")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", recipe->mash[i].name)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MIN", "%d", recipe->mash[i].min)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MAX", "%d", recipe->mash[i].max)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "CANSKIP", "%s", recipe->mash[i].canskip ? "YES":"NO")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SETPOINT", "%f", recipe->mash[i].setpoint)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SKIP", "%s", recipe->mash[i].skip ? "YES":"NO")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "DURATION", "%d", recipe->mash[i].duration)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + + /* + * 10 Hop additions + */ + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "HOPADDITIONS")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + for (i = 0; i < 10; i++) { + if (recipe->hops[i].name) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "HOPADDITION")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", recipe->hops[i].name)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "BOILTIME", "%d", recipe->hops[i].boiltime)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + } + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + + /* + * 3 Hop stands + */ + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "HOPSTANDS")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + for (i = 0; i < 3; i++) { + if ((rc = xmlTextWriterStartElement(writer, BAD_CAST "HOPSTAND")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterStartElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "NAME", "%s", recipe->hopstand[i].name)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MIN", "%d", recipe->hopstand[i].min)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "MAX", "%d", recipe->hopstand[i].max)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "HOLD", "%s", recipe->hopstand[i].hold ? "YES":"NO")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SETPOINT", "%f", recipe->hopstand[i].setpoint)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "SKIP", "%s", recipe->hopstand[i].skip ? "YES":"NO")) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterWriteFormatElement(writer, BAD_CAST "DURATION", "%d", recipe->hopstand[i].duration)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterWriteFormatElement"); + return 1; + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + } + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + + /* + * Close the element named RECIPE. + */ + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + } + /* + * Close the element named RECIPES. + */ + if ((rc = xmlTextWriterEndElement(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndElement"); + return 1; + } + + /* + * All done, close any open elements + */ + if ((rc = xmlTextWriterEndDocument(writer)) < 0) { + syslog(LOG_NOTICE, "wrrecipes: error at xmlTextWriterEndDocument"); + return 1; + } + xmlFreeTextWriter(writer); + + /* + * Now write the XML recipes + */ + if (getenv((char *)"USER") == NULL) { + mypath = xstrcpy((char *)"/root"); + } else { + mypath = xstrcpy(getenv((char *)"HOME")); + } + mypath = xstrcat(mypath, (char *)"/.brewco/etc/"); + mkdirs(mypath, 0755); + mypath = xstrcat(mypath, (char *)"recipes.xml"); + + if (debug) + fprintf(stdout, "Writing %s\n", mypath); + + if ((fp = fopen(mypath, "w")) == NULL) { + syslog(LOG_NOTICE, "could not rewrite %s", mypath); + free(mypath); + return 1; + } + free(mypath); + + fprintf(fp, "%s", (const char *) buf->content); + fclose(fp); + xmlBufferFree(buf); + + return 0; +} + + + +int wrrecipes(void) +{ + int rc; + + rc = do_wrrecipes(); + syslog(LOG_NOTICE, "Rewritten recipes, rc=%d", rc); + return rc; +} + + + +int parseRecipe(xmlDocPtr doc, xmlNodePtr cur) +{ + xmlChar *key; + xmlNodePtr s1cur, s2cur; + a_recipe *recipe, *tmp; + int i, j, ival; + float fval; + + recipe = (a_recipe *)malloc(sizeof(a_recipe)); + memset(recipe, 0, sizeof(a_recipe)); + recipe->next = NULL; + + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"UUID"))) { + recipe->uuid = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"CODE"))) { + recipe->code = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"NAME"))) { + recipe->name = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"BOILTIME"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->boiltime = ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"STARTTIME"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->starttime = (time_t)ival; + xmlFree(key); + } + if ((!xmlStrcmp(cur->name, (const xmlChar *)"ENDTIME"))) { + key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->endtime = (time_t)ival; + xmlFree(key); + } +fprintf(stdout, "cur %s\n", cur->name); + if ((!xmlStrcmp(cur->name, (const xmlChar *)"MASHSTEPS"))) { + s1cur = cur->xmlChildrenNode; + i = 0; + while (s1cur != NULL) { +fprintf(stdout, " s1cur %s\n", s1cur->name); + + if ((!xmlStrcmp(s1cur->name, (const xmlChar *)"MASHSTEP"))) { + s2cur = s1cur->xmlChildrenNode; + while (s2cur != NULL) { +fprintf(stdout, " s2cur %s\n", s2cur->name); + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"NAME"))) { + recipe->mash[i].name = (char *)xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"MIN"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->mash[i].min = ival; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"MAX"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->mash[i].max = ival; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"CANSKIP"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + for (j = 0; j < 2; j++) { + if (! xmlStrcmp(key, (const xmlChar *)SKIPYN[j])) { + recipe->mash[i].canskip = j; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"SETPOINT"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &fval) == 1) + recipe->mash[i].setpoint = fval; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"SKIP"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + for (j = 0; j < 2; j++) { + if (! xmlStrcmp(key, (const xmlChar *)SKIPYN[j])) { + recipe->mash[i].skip = j; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"DURATION"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->mash[i].duration = ival; + xmlFree(key); + } + s2cur = s2cur->next; + } + i++; + } + s1cur = s1cur->next; + } + } + + if ((!xmlStrcmp(cur->name, (const xmlChar *)"HOPADDITIONS"))) { + s1cur = cur->xmlChildrenNode; + i = 0; + while (s1cur != NULL) { +fprintf(stdout, " s1cur %s\n", s1cur->name); + + if ((!xmlStrcmp(s1cur->name, (const xmlChar *)"HOPADDITION"))) { + s2cur = s1cur->xmlChildrenNode; + while (s2cur != NULL) { +fprintf(stdout, " s2cur %s\n", s2cur->name); + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"NAME"))) { + recipe->hops[i].name = (char *)xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"BOILTIME"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->hops[i].boiltime = ival; + xmlFree(key); + } + s2cur = s2cur->next; + } + i++; + } + s1cur = s1cur->next; + } + } + + if ((!xmlStrcmp(cur->name, (const xmlChar *)"HOPSTANDS"))) { + s1cur = cur->xmlChildrenNode; + i = 0; + while (s1cur != NULL) { +fprintf(stdout, " s1cur %s\n", s1cur->name); + + if ((!xmlStrcmp(s1cur->name, (const xmlChar *)"HOPSTAND"))) { + s2cur = s1cur->xmlChildrenNode; + while (s2cur != NULL) { +fprintf(stdout, " s2cur %s\n", s2cur->name); + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"NAME"))) { + recipe->hopstand[i].name = (char *)xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"MIN"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->hopstand[i].min = ival; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"MAX"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->hopstand[i].max = ival; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"HOLD"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + for (j = 0; j < 2; j++) { + if (! xmlStrcmp(key, (const xmlChar *)SKIPYN[j])) { + recipe->hopstand[i].hold = j; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"SETPOINT"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%f", &fval) == 1) + recipe->hopstand[i].setpoint = fval; + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"SKIP"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + for (j = 0; j < 2; j++) { + if (! xmlStrcmp(key, (const xmlChar *)SKIPYN[j])) { + recipe->hopstand[i].skip = j; + break; + } + } + xmlFree(key); + } + if ((!xmlStrcmp(s2cur->name, (const xmlChar *)"DURATION"))) { + key = xmlNodeListGetString(doc, s2cur->xmlChildrenNode, 1); + if (sscanf((const char *)key, "%d", &ival) == 1) + recipe->hopstand[i].duration = ival; + xmlFree(key); + } + s2cur = s2cur->next; + } + i++; + } + s1cur = s1cur->next; + } + } + cur = cur->next; + } + + if (recipes == NULL) { + recipes = recipe; + } else { + for (tmp = recipes; tmp; tmp = tmp->next) { + if (tmp->next == NULL) { + tmp->next = recipe; + break; + } + } + } + + return 0; +} + + + +int parseRecipes(xmlDocPtr doc, xmlNodePtr cur) +{ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"RECIPE"))) { + parseRecipe(doc, cur); + } + cur = cur->next; + } + return 0; +} + + + +/* + * Returns: + * 0 - All is well, recipes loaded. + * 1 - Something went wrong + */ +int rdrecipes(void) +{ + int i; + char *mypath; + xmlDocPtr doc; + xmlNodePtr cur; + a_recipe *recipe; + + syslog(LOG_NOTICE, "HOME='%s' USER='%s' LOGNAME='%s'", MBSE_SS(getenv((char *)"HOME")), MBSE_SS(getenv((char *)"USER")), MBSE_SS(getenv((char *)"LOGNAME"))); + + /* + * Search config file + */ + if (getenv((char *)"USER") == NULL) { + mypath = xstrcpy((char *)"/root"); + } else { + mypath = xstrcpy(getenv((char *)"HOME")); + } + mypath = xstrcat(mypath, (char *)"/.brewco/etc/"); + mkdirs(mypath, 0755); + mypath = xstrcat(mypath, (char *)"recipes.xml"); + + /* + * Free possible old recipes list + */ + for (recipe = recipes; recipe; recipe = recipe->next) { + if (recipe->uuid) + free(recipe->uuid); + if (recipe->code) + free(recipe->code); + if (recipe->name) + free(recipe->name); + for (i = 0; i < 8; i++) + if (recipe->mash[i].name) + free(recipe->mash[i].name); + for (i = 0; i < 10; i++) + if (recipe->hops[i].name) + free(recipe->hops[i].name); + for (i = 0; i < 3; i++) + if (recipe->hopstand[i].name) + free(recipe->hopstand[i].name); + free(recipe); + } + recipes = NULL; + + /* + * See if we have a recipes file. + */ + if (file_exist(mypath, W_OK)) { + syslog(LOG_NOTICE, "rdrecipes: %s not found, good.", mypath); + free(mypath); + return 0; + } + + if ((doc = xmlParseFile(mypath)) == NULL) { + syslog(LOG_NOTICE, "rdrecipes: %s not found, we may need some.", mypath); + free(mypath); + return 0; + } + syslog(LOG_NOTICE, "rdrecipes: using %s", mypath); + + if ((cur = xmlDocGetRootElement(doc)) == NULL) { + syslog(LOG_NOTICE, "XML file %s empty.", mypath); + xmlFreeDoc(doc); + return 1; + } + if (xmlStrcmp(cur->name, (const xmlChar*)"BREWCO")) { + syslog(LOG_NOTICE, "XML file %s is not a valid configuration file.", mypath); + xmlFreeDoc(doc); + return 1; + } + + /* + * Parse recipes + */ + cur = cur->xmlChildrenNode; + while (cur != NULL) { + if ((!xmlStrcmp(cur->name, (const xmlChar *)"RECIPES"))) { + parseRecipes(doc, cur); + } + cur = cur->next; + } + xmlFreeDoc(doc); + + free(mypath); + mypath = NULL; + + return 0; +} + + +