Example #1
0
/*! CLI generic callback printing the variable vector and argument
 */
int
callback(cligen_handle handle, cvec *cvv, cvec *argv)
{
    int     i = 1;
    cg_var *cv;
    char    buf[64];

    fprintf(stderr, "function: %s\n", cligen_fn_str_get(handle));
    fprintf(stderr, "variables:\n");
    cv = NULL;
    while ((cv = cvec_each1(cvv, cv)) != NULL) {
	cv2str(cv, buf, sizeof(buf)-1);
	fprintf(stderr, "\t%d name:%s type:%s value:%s\n", 
		i++, 
		cv_name_get(cv),
		cv_type2str(cv_type_get(cv)),
		buf
	    );
    }
    if (argv){
	    cv = NULL;
	    i=0;
	    while ((cv = cvec_each(argv, cv)) != NULL) {
		cv2str(cv, buf, sizeof(buf)-1);
		fprintf(stderr, "arg %d: %s\n", i++, buf);
	    }
	}
    return 0;
}
Example #2
0
/*! Delete a cv variable from a cvec. Note: cv is not reset & cv may be stale!
 *
 * @param[in]  cvv   Cligen variable vector
 * @param[in]  del   variable to delete
 *
 * @note This is a dangerous command since the cv it deletes (such as created by 
 * cvec_add) may have been modified with realloc (eg cvec_add/delete) and 
 * therefore can not be used as a reference.  Safer methods are to use 
 * cvec_find/cvec_i to find a cv and then to immediately remove it. 
 */
int
cvec_del(cvec   *cvv, 
	 cg_var *del)
{
    int i;
    cg_var *cv;

    if (cvec_len(cvv) == 0)
	return 0;
    
    i = 0;
    cv = NULL;
    while ((cv = cvec_each(cvv, cv)) != NULL) {
	if (cv == del)
	    break;
	i++;
    }
    if (i >= cvec_len(cvv)) /* Not found !?! */
	return cvec_len(cvv);

    if (i != cvec_len(cvv)-1) /* If not last entry, move the remaining cv's */
	memmove(&cvv->vr_vec[i], &cvv->vr_vec[i+1],
		(cvv->vr_len-i-1) * sizeof(cvv->vr_vec[0]));
    
    cvv->vr_len--;
    cvv->vr_vec = realloc(cvv->vr_vec, cvv->vr_len*sizeof(cvv->vr_vec[0])); /* Shrink should not fail? */

    return cvec_len(cvv);
}
Example #3
0
/*! Call expand callback and insert expanded commands in place of variable
 * variable argument callback variant
 * @see pt_expand_fn
 */
static int
pt_expand_fnv(cligen_handle h, 
	      cg_obj       *co,     
	      cvec         *cvv,
	      parse_tree   *ptn,
	      cg_obj       *parent)
{
    int     retval = -1;
    cvec   *commands = cvec_new(0);
    cvec   *helptexts = cvec_new(0);
    cg_var *cv = NULL;
    char   *helpstr;
    cg_obj *con;
    int     i;

    if ((*co->co_expandv_fn)(
			     cligen_userhandle(h)?cligen_userhandle(h):h, 
			     co->co_expand_fn_str, 
			     cvv,
			     co->co_expand_fn_vec,
			     commands, 
			     helptexts) < 0)
	goto done;
    i = 0;
    while ((cv = cvec_each(commands, cv)) != NULL) {
	if (i < cvec_len(helptexts)){
	    helpstr = strdup(cv_string_get(cvec_i(helptexts, i)));
	}
	else
	    helpstr = NULL;
	i++;
	pt_realloc(ptn);
	if (co_expand_sub(co, parent, 
			  &ptn->pt_vec[ptn->pt_len-1]) < 0)
	    goto done;
	con = ptn->pt_vec[ptn->pt_len-1];
	if (transform_var_to_cmd(con, 
				 strdup(cv_string_get(cv)),
				 helpstr) < 0)
	    goto done;
    }
    if (commands)
	cvec_free(commands);
    if (helptexts)
	cvec_free(helptexts);
    retval = 0;
 done:
    return retval;

}
Example #4
0
/*! Reset cligen variable vector resetting it to an initial state as returned by cvec_new
 *
 * @param[in]  cvv   Cligen variable vector
 * @see also cvec_free. But this function does not actually free the cvec.
 */
int
cvec_reset(cvec *cvv)
{
    cg_var *cv = NULL;
    
    while ((cv = cvec_each(cvv, cv)) != NULL)  
	cv_reset(cv);
    if (cvv->vr_vec)
	free(cvv->vr_vec);
    if (cvv->vr_name)
	free(cvv->vr_name);
    memset(cvv, 0, sizeof(*cvv));
    return 0;
}
Example #5
0
/*! Recursively copy callback structure to all terminal nodes in the parse-tree.
 * XXX: Actually copies to every node, even if not terminal
 * Problem is that the argument is modified according to reference rule
 * @param[in]  pt   Parse-tree
 * @param[in]  cc0  This is the parameter (calling) callback. eg fn in @sub,fn().
 *
 * The function installs the calling callback in all executable non-terminal nodes.
 * That is, it only install callbacks in non-terminal with NULL child which is 
 * where a ';' is in the syntax, eg:
 *	   a ;{} # Here a is executable
 *	   b {}  # But b is not
 * Somewhat strange semantics though:
 * - Always replace (or add if empty) original callback in co0
 * - Use local argument-list _unless_ there is none, then use callback list from cc0
 */
static int
pt_callback_reference(parse_tree          pt, 
		      struct cg_callback *cc0)
{
    int                 i;
    cg_obj             *co;
    parse_tree         *ptc;
    int                 retval = -1;
    struct cg_callback *cc;
    cg_var             *cv;
		    
    for (i=0; i<pt.pt_len; i++){    
	if ((co = pt.pt_vec[i]) == NULL)
	    continue;
	ptc = &co->co_pt;
	/* Filter out non-executable non-terminals. */
	if (ptc->pt_len && ptc->pt_vec[0] == NULL){
	    /* Copy the callback from top */
	    if ((cc = co->co_callbacks) == NULL){
		if (co_callback_copy(cc0, &co->co_callbacks) < 0)
		    return -1;
	    }
	    else {
#ifdef CALLBACK_SINGLEARG
		cc->cc_fn = cc0->cc_fn; /* iterate */
#endif
		cc->cc_fn_vec = cc0->cc_fn_vec; /*  */
		if (cc0->cc_fn_str){
		    if (cc->cc_fn_str)
			free (cc->cc_fn_str);
		    cc->cc_fn_str = strdup(cc0->cc_fn_str);
		}
		/* Append original parameters to end of call */
		if (cc0->cc_cvec){
		    cv = NULL;
		    while ((cv = cvec_each(cc0->cc_cvec, cv)) != NULL)
			cvec_append_var(cc->cc_cvec, cv);
		}
		
	    }
	}
	if (pt_callback_reference(co->co_pt, cc0) < 0)
	    goto done;
    }
    retval = 0;
  done:
    return retval;
}
Example #6
0
/*
 * 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;
}