コード例 #1
0
ファイル: cligen_tutorial.c プロジェクト: nkgautam/cligen
/*
 * An example of a callback handling a complex syntax
 */
int
letters(cligen_handle h, cvec *vars, cg_var *arg)
{
    char *str;
    cg_var *cv;

    if ((str = cvec_find_str(vars, "ca")) != NULL)
        printf("%s\n", str);
    if ((cv = cvec_find(vars, "int")) != NULL)
        printf("%d\n", cv_int32_get(cv));
    if ((str = cvec_find_str(vars, "cb")) != NULL)
        printf("%s\n", str);
    if ((str = cvec_find_str(vars, "dd")) != NULL)
        printf("%s\n", str);
    if ((str = cvec_find_str(vars, "ee")) != NULL)
        printf("%s\n", str);
    return 0;
}
コード例 #2
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! set debug level on stderr (not syslog).
 * The level is either what is specified in arg as int argument.
 * _or_ if a 'level' variable is present in vars use that value instead.
 * XXX obsolete. Use cli_debug_cliv or cli_debug_backendv instead
 */
int
cli_debug(clicon_handle h, 
	  cvec         *vars, 
	  cg_var       *arg)
{
    cg_var *cv;
    int     level;

    if ((cv = cvec_find(vars, "level")) == NULL)
	cv = arg;
    level = cv_int32_get(cv);
    /* cli */
    clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */
    /* config daemon */
    if (clicon_rpc_debug(h, level) < 0)
	goto done;
  done:
    return 0;
}
コード例 #3
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! Set debug level on backend daemon (not CLI)
 * @param[in] h     Clicon handle
 * @param[in] vars  If variable "level" exists, its integer value is used
 * @param[in] arg   Else use the integer value of argument
 * @note The level is either what is specified in arg as int argument.
 *       _or_ if a 'level' variable is present in vars use that value instead.
 */
int
cli_debug_backend(clicon_handle h, 
		  cvec         *vars, 
		  cvec         *argv)
{
    int     retval = -1;
    cg_var *cv;
    int     level;

    if ((cv = cvec_find(vars, "level")) == NULL){
	if (cvec_len(argv) != 1){
	    clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
	    goto done;
	}
	cv = cvec_i(argv, 0);
    }
    level = cv_int32_get(cv);
    /* config daemon */
    retval = clicon_rpc_debug(h, level);
 done:
    return retval;
}
コード例 #4
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! Set debug level on CLI client (not backend daemon)
 * @param[in] h     Clicon handle
 * @param[in] vars  If variable "level" exists, its integer value is used
 * @param[in] arg   Else use the integer value of argument
 * @note The level is either what is specified in arg as int argument.
 *       _or_ if a 'level' variable is present in vars use that value instead.
 */
int
cli_debug_cli(clicon_handle h, 
	       cvec         *vars, 
	       cvec         *argv)
{
    int     retval = -1;
    cg_var *cv;
    int     level;

    if ((cv = cvec_find(vars, "level")) == NULL){
	if (cvec_len(argv) != 1){
	    clicon_err(OE_PLUGIN, 0, "Requires either label var or single arg: 0|1");
	    goto done;
	}
	cv = cvec_i(argv, 0);
    }
    level = cv_int32_get(cv);
    /* cli */
    clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */
    retval = 0;
 done:
    return retval;
}
コード例 #5
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! Copy database to local file 
 * Utility function used by cligen spec file
 * @param[in] h     CLICON handle
 * @param[in] cvv  variable vector (containing <varname>)
 * @param[in] argv  a string: "<dbname> <varname>" 
 *   <dbname>  is running, candidate, or startup
 *   <varname> is name of cligen variable in the "cvv" vector containing file name
 * Note that "filename" is local on client filesystem not backend.
 * The function can run without a local database
 * @note The file is saved with dummy top-tag: clicon: <clicon></clicon>
 * @code
 *   save file <name:string>, save_config_file("running name");
 * @endcode
 * @see load_config_file
 */
int
save_config_file(clicon_handle h, 
		 cvec         *cvv, 
		 cvec         *argv)
{
    int        retval = -1;
    char      *filename = NULL;
    cg_var    *cv;
    char      *dbstr;
    char      *varstr;
    cxobj     *xt = NULL;
    cxobj     *xerr;
    FILE      *f = NULL;

    if (cvec_len(argv) != 2){
	if (cvec_len(argv)==1)
	    clicon_err(OE_PLUGIN, 0, "Got single argument:\"%s\". Expected \"<dbname>,<varname>\"",
		       cv_string_get(cvec_i(argv,0)));
	else
	    clicon_err(OE_PLUGIN, 0, " Got %d arguments. Expected: <dbname>,<varname>",
		       cvec_len(argv));

	goto done;
    }
    dbstr = cv_string_get(cvec_i(argv, 0));
    varstr  = cv_string_get(cvec_i(argv, 1));
    if (strcmp(dbstr, "running") != 0 && 
	strcmp(dbstr, "candidate") != 0 &&
	strcmp(dbstr, "startup") != 0) {
	clicon_err(OE_PLUGIN, 0, "No such db name: %s", dbstr);	
	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 (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0)
	goto done;
    if (xt == NULL){
	clicon_err(OE_CFG, 0, "get config: empty tree"); /* Shouldnt happen */
	goto done;
    }
    if ((xerr = xpath_first(xt, "/rpc-error")) != NULL){
	clicon_rpc_generate_error("Get configuration", xerr);
	goto done;
    }
    /* get-config returns a <data> tree. Save as <config> tree so it can be used
     * as data-store.
     */
    if (xml_name_set(xt, "config") < 0)
	goto done;
    if ((f = fopen(filename, "w")) == NULL){
	clicon_err(OE_CFG, errno, "Creating file %s", filename);
	goto done;
    } 
    if (clicon_xml2file(f, xt, 0, 1) < 0)
	goto done;
    retval = 0;
    /* Fall through */
  done:
    if (xt)
	xml_free(xt);
    if (f != NULL)
	fclose(f);
    return retval;
}
コード例 #6
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! 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;
}
コード例 #7
0
ファイル: cli_common.c プロジェクト: clicon/clixon
/*! Copy one configuration object to antother
 *
 * Works for objects that are items ina yang list with a keyname, eg as:
 *   list sender{ 
 *      key name;	
 *	leaf name{...
 *
 * @param[in]  h    CLICON handle
 * @param[in]  cvv  Vector of variables from CLIgen command-line
 * @param[in]  argv Vector: <db>, <xpath>, <field>, <fromvar>, <tovar>
 * Explanation of argv fields:
 *  db:     Database name, eg candidate|tmp|startup
 *  xpath:  XPATH expression with exactly two %s pointing to field and from name
 *  field:  Name of list key, eg name
 *  fromvar:Name of variable containing name of object to copy from (given by xpath)
 *  tovar:  Name of variable containing name of object to copy to.
 * @code
 * cli spec:
 *  copy snd <n1:string> to <n2:string>, cli_copy_config("candidate", "/sender[%s='%s']", "from", "n1", "n2");
 * cli command:
 *  copy snd from to to
 * @endcode
 */
int
cli_copy_config(clicon_handle h, 
		cvec         *cvv, 
		cvec         *argv)
{
    int          retval = -1;
    char        *db;
    cxobj       *x1 = NULL; 
    cxobj       *x2 = NULL; 
    cxobj       *x;
    char        *xpath;
    int          i;
    int          j;
    cbuf        *cb = NULL;
    char        *keyname;
    char        *fromvar;
    cg_var      *fromcv;
    char        *fromname = NULL;
    char        *tovar;
    cg_var      *tocv;
    char        *toname;
    cxobj       *xerr;

    if (cvec_len(argv) != 5){
	clicon_err(OE_PLUGIN, 0, "Requires four elements: <db> <xpath> <keyname> <from> <to>");
	goto done;
    }
    /* First argv argument: Database */
    db = cv_string_get(cvec_i(argv, 0));
    /* Second argv argument: xpath */
    xpath = cv_string_get(cvec_i(argv, 1));
    /* Third argv argument: name of keyname */
    keyname = cv_string_get(cvec_i(argv, 2));
    /* Fourth argv argument: from variable */
    fromvar = cv_string_get(cvec_i(argv, 3));
    /* Fifth argv argument: to variable */
    tovar = cv_string_get(cvec_i(argv, 4));
    
    /* Get from variable -> cv -> from name */
    if ((fromcv = cvec_find(cvv, fromvar)) == NULL){
	clicon_err(OE_PLUGIN, 0, "fromvar '%s' not found in cligen var list", fromvar);	
	goto done;
    }
    /* Get from name from cv */
    fromname = cv_string_get(fromcv);
    /* Create xpath */
    if ((cb = cbuf_new()) == NULL){
	clicon_err(OE_PLUGIN, errno, "cbuf_new");	
	goto done;
    }
    /* Sanity check that xpath contains exactly two %s, ie [%s='%s'] */
    j = 0;
    for (i=0; i<strlen(xpath); i++){
	if (xpath[i] == '%')
	    j++;
    }
    if (j != 2){
	clicon_err(OE_PLUGIN, 0, "xpath '%s' does not have two '%%'", xpath);	
	goto done;
    }
    cprintf(cb, xpath, keyname, fromname);	
    /* Get from object configuration and store in x1 */
    if (clicon_rpc_get_config(h, db, cbuf_get(cb), &x1) < 0)
	goto done;
    if ((xerr = xpath_first(x1, "/rpc-error")) != NULL){
	clicon_rpc_generate_error("Get configuration", xerr);
	goto done;
    }

    /* Get to variable -> cv -> to name */
    if ((tocv = cvec_find(cvv, tovar)) == NULL){
	clicon_err(OE_PLUGIN, 0, "tovar '%s' not found in cligen var list", tovar);
	goto done;
    }
    toname = cv_string_get(tocv);
    /* Create copy xml tree x2 */
    if ((x2 = xml_new("new", NULL, NULL)) == NULL)
	goto done;
    if (xml_copy(x1, x2) < 0)
	goto done;
    xml_name_set(x2, "config");
    cprintf(cb, "/%s", keyname);	
    if ((x = xpath_first(x2, "%s", cbuf_get(cb))) == NULL){
	clicon_err(OE_PLUGIN, 0, "Field %s not found in copy tree", keyname);
	goto done;
    }
    x = xml_find(x, "body");
    xml_value_set(x, toname);
    /* resuse cb */
    cbuf_reset(cb);
    /* create xml copy tree and merge it with database configuration */
    clicon_xml2cbuf(cb, x2, 0, 0);
    if (clicon_rpc_edit_config(h, db, OP_MERGE, cbuf_get(cb)) < 0)
	goto done;
    retval = 0;
 done:
    if (cb)
	cbuf_free(cb);
    if (x1 != NULL)
	xml_free(x1);
    if (x2 != NULL)
	xml_free(x2);
    return retval;
}
コード例 #8
0
ファイル: config_commit.c プロジェクト: andrnils/clicon
/*
 * generic_validate
 *
 * key values are checked for validity independent of user-defined callbacks
 * They are checked as follows:
 * 1. If no value and default value defined, add it.
 * 2. If no value and mandatory flag set in spec, report error.
 * 3. Validate value versus spec, and report error if no match. Currently only int ranges and
 *    string regexp checked.
 */
static int
generic_validate(clicon_handle h, char *dbname, const struct dbdiff *dd)
{
    int             i, j;
    char           *key;
    cvec           *cvec = NULL;
    cg_var         *cv;
    cg_varspec     *cs;
    int             retval = -1;
    cg_obj         *co;
    cg_obj         *cov;
    parse_tree     *dbspec_co;
    char           *reason = NULL;
    parse_tree     *pt;

    if ((dbspec_co = clicon_dbspec_pt(h)) == NULL)
	goto done;
    /* dd->df_ents[].dfe_key1 (running),  
       dd->df_ents[].dfe_key2 (candidate) */
    for (i = 0; i < dd->df_nr; i++) {
	if ((key = dd->df_ents[i].dfe_key2) == NULL)
	    continue;
	if ((co = key2spec_co(dbspec_co, key)) == NULL)
	    continue;
	/* read variable list from db */
	if ((cvec = dbkey2cvec(dbname, key)) == NULL) 
	    goto done;
	/* Loop over all co:s children (spec) and check if actual values
	   in db(cv) satisfies them */
	pt = &co->co_pt;
	for (j=0; j<pt->pt_len; j++){
	    if ((cov = pt->pt_vec[j]) == NULL)
		continue;
	    if (cov->co_type == CO_VARIABLE){

		/* There is no db-value, but dbspec has default value */
		if ((cv = dbspec_default_get(cov)) != NULL &&
		    cvec_find(cvec, cov->co_command) == NULL){
		    cv_flag_set(cv, V_DEFAULT); /* mark it as default XXX not survive DB */
		    /* add default value to cvec */
		    if (cvec_add_cv(cvec, cv) < 0){
			clicon_err(OE_CFG, 0, "cvec_add_cv");
			goto done;
		    }
		    /* Write to database */
		    if (cvec2dbkey(dbname, key, cvec) < 0)
			goto done;
		}
		else
		if (!dbspec_optional_get(cov) && cvec_find(cvec, cov->co_command) == NULL){
		    clicon_err(OE_CFG, 0, 
			       "key %s: Missing mandatory variable: %s\n",
			       key, cov->co_command);
		    goto done;
		}
	    }
	}
	cv = NULL;
	/* Loop over all actual db/cv:s och check their validity */	
	while ((cv = cvec_each(cvec, cv))) {
	    if ((cov = co_find_one(*pt, cv_name_get(cv))) == NULL){
		clicon_err(OE_CFG, 0, "key %s: variable %s not found in co-spec", 
			   key, cv_name_get(cv));
		goto done;
	    }
	    if ((cs = co2varspec(cov)) == NULL)
		continue;
	    if (cv_validate(cv, cs, &reason) != 1){ /* We ignore errors */
		clicon_err(OE_DB, 0, 
			   "key %s: validation of %s failed\n",
			   key, cov->co_command);
		goto done;
	    }

	}
	if (cvec){
	    cvec_free(cvec);
	    cvec = NULL;
	}
    } /* for */
    retval = 0;
  done:
    if (cvec)
	cvec_free(cvec);
    if (reason)
	free(reason);
    return retval;
}