static int choose(struct xml_node *st, struct xml_node *xt, struct xml_node *rt) { struct xml_node *s = NULL; struct xml_node *sc = NULL; int match = 0; /* first try matching 'when' statement */ while ((s = xml_child_each(st, s, XML_ELEMENT)) != NULL) { if (s->xn_namespace && strcmp(s->xn_namespace, "xsl") == 0){ if (strcmp(s->xn_name, "when")==0){ if (choose_test(s, xt, rt, &match) < 0) return -1; if (match) break; } } } if (!match){ /* no match above - find otherwise */ if ((s = xml_xpath(st, "/otherwise")) != NULL && s->xn_namespace && strcmp(s->xn_namespace, "xsl") == 0){ while ((sc = xml_child_each(s, sc, XML_ELEMENT)) != NULL) if (traverse(sc, xt, rt) < 0) return -1; } } return 0; }
/*! Compare two dbs using XML. Write to file and run diff */ static int compare_xmls(cxobj *xc1, cxobj *xc2, int astext) { int fd; FILE *f; char filename1[MAXPATHLEN]; char filename2[MAXPATHLEN]; char cmd[MAXPATHLEN]; int retval = -1; cxobj *xc; snprintf(filename1, sizeof(filename1), "/tmp/cliconXXXXXX"); snprintf(filename2, sizeof(filename2), "/tmp/cliconXXXXXX"); if ((fd = mkstemp(filename1)) < 0){ clicon_err(OE_UNDEF, errno, "tmpfile: %s", strerror (errno)); goto done; } if ((f = fdopen(fd, "w")) == NULL) goto done; xc = NULL; if (astext) while ((xc = xml_child_each(xc1, xc, -1)) != NULL) xml2txt(f, xc, 0); else while ((xc = xml_child_each(xc1, xc, -1)) != NULL) xml_print(f, xc); fclose(f); close(fd); if ((fd = mkstemp(filename2)) < 0){ clicon_err(OE_UNDEF, errno, "mkstemp: %s", strerror (errno)); goto done; } if ((f = fdopen(fd, "w")) == NULL) goto done; xc = NULL; if (astext) while ((xc = xml_child_each(xc2, xc, -1)) != NULL) xml2txt(f, xc, 0); else while ((xc = xml_child_each(xc2, xc, -1)) != NULL) xml_print(f, xc); fclose(f); close(fd); snprintf(cmd, sizeof(cmd), "/usr/bin/diff -dU 1 %s %s | grep -v @@ | sed 1,2d", filename1, filename2); if (system(cmd) < 0) goto done; retval = 0; done: unlink(filename1); unlink(filename2); return retval; }
/*! This is the callback used by cli_setlog to print log message in CLI * param[in] s UNIX socket from backend where message should be read * param[in] arg format: txt, xml, xml2txt, xml2json */ static int cli_notification_cb(int s, void *arg) { struct clicon_msg *reply = NULL; int eof; int retval = -1; cxobj *xt = NULL; cxobj *xe; cxobj *x; enum format_enum format = (enum format_enum)arg; /* get msg (this is the reason this function is called) */ if (clicon_msg_rcv(s, &reply, &eof) < 0) goto done; if (eof){ clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close"); close(s); errno = ESHUTDOWN; event_unreg_fd(s, cli_notification_cb); goto done; } if (clicon_msg_decode(reply, NULL, &xt) < 0) /* XXX pass yang_spec */ goto done; if ((xe = xpath_first(xt, "//event")) != NULL){ x = NULL; while ((x = xml_child_each(xe, x, -1)) != NULL) { switch (format){ case FORMAT_XML: if (clicon_xml2file(stdout, x, 0, 1) < 0) goto done; break; case FORMAT_TEXT: if (xml2txt(stdout, x, 0) < 0) goto done; break; case FORMAT_JSON: if (xml2json(stdout, x, 1) < 0) goto done; break; default: break; } } } retval = 0; done: if (xt) xml_free(xt); if (reply) free(reply); return retval; }
/* * <xsl:if test="expr"/> */ static int ifelement(struct xml_node *st, struct xml_node *xt, struct xml_node *rt) { char *test; struct xml_node *s = NULL; if ((test = xml_get(st, "test")) == NULL) return 0; if (xml_xpath(xt, test) == NULL) return 0; while ((s = xml_child_each(st, s, XML_ELEMENT)) != NULL) if (traverse(s, xt, rt) < 0) return -1; return 0; }
/* * <xsl:choose> * <xsl:when test="expr"/> * <xsl:when test="expr"/> * <xsl:otherwise/> * </xsl:choose> */ static int choose_test(struct xml_node *st, struct xml_node *xt, struct xml_node *rt, int *match) { char *test; struct xml_node *s = NULL; *match = 0; if ((test = xml_get(st, "test")) == NULL) return 0; if (xml_xpath(xt, test) == NULL) return 0; *match = 1; while ((s = xml_child_each(st, s, -1)) != NULL) { if (s->xn_type == XML_ATTRIBUTE) continue; if (traverse(s, xt, rt) < 0) return -1; } return 0; }
/*! Load a configuration file to candidate database * Utility function used by cligen spec file * @param[in] h CLICON handle * @param[in] cvv Vector of variables (where <varname> is found) * @param[in] argv A string: "<varname> (merge|replace)" * <varname> is name of a variable occuring in "cvv" containing filename * @note that "filename" is local on client filesystem not backend. * @note file is assumed to have a dummy top-tag, eg <clicon></clicon> * @code * # cligen spec * load file <name2:string>, load_config_file("name2","merge"); * @endcode * @see save_config_file */ int load_config_file(clicon_handle h, cvec *cvv, cvec *argv) { int ret = -1; struct stat st; char *filename = NULL; int replace; cg_var *cv; char *opstr; char *varstr; int fd = -1; cxobj *xt = NULL; cxobj *x; cbuf *cbxml; if (cvec_len(argv) != 2){ if (cvec_len(argv)==1) clicon_err(OE_PLUGIN, 0, "Got single argument:\"%s\". Expected \"<varname>,<op>\"", cv_string_get(cvec_i(argv,0))); else clicon_err(OE_PLUGIN, 0, "Got %d arguments. Expected: <varname>,<op>", cvec_len(argv)); goto done; } varstr = cv_string_get(cvec_i(argv, 0)); opstr = cv_string_get(cvec_i(argv, 1)); if (strcmp(opstr, "merge") == 0) replace = 0; else if (strcmp(opstr, "replace") == 0) replace = 1; else{ clicon_err(OE_PLUGIN, 0, "No such op: %s, expected merge or replace", opstr); goto done; } if ((cv = cvec_find(cvv, varstr)) == NULL){ clicon_err(OE_PLUGIN, 0, "No such var name: %s", varstr); goto done; } filename = cv_string_get(cv); if (stat(filename, &st) < 0){ clicon_err(OE_UNIX, 0, "load_config: stat(%s): %s", filename, strerror(errno)); goto done; } /* Open and parse local file into xml */ if ((fd = open(filename, O_RDONLY)) < 0){ clicon_err(OE_UNIX, errno, "open(%s)", filename); goto done; } if (xml_parse_file(fd, "</clicon>", NULL, &xt) < 0) goto done; if (xt == NULL) goto done; if ((cbxml = cbuf_new()) == NULL) goto done; x = NULL; while ((x = xml_child_each(xt, x, -1)) != NULL) { /* Ensure top-level is "config", maybe this is too rough? */ xml_name_set(x, "config"); if (clicon_xml2cbuf(cbxml, x, 0, 0) < 0) goto done; } if (clicon_rpc_edit_config(h, "candidate", replace?OP_REPLACE:OP_MERGE, cbuf_get(cbxml)) < 0) goto done; cbuf_free(cbxml); // } ret = 0; done: if (xt) xml_free(xt); if (fd != -1) close(fd); return ret; }