Exemple #1
0
PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp, PromiseActuator *ActOnPromise, void *param)
{
    Rlist *lists = NULL;
    Rlist *scalars = NULL;
    Rlist *containers = NULL;

    Promise *pcopy = DeRefCopyPromise(ctx, pp);

    MapIteratorsFromRval(ctx, PromiseGetBundle(pp), (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp), pp->promisee, &scalars, &lists, &containers);
    }

    for (size_t i = 0; i < SeqLength(pcopy->conlist); i++)
    {
        Constraint *cp = SeqAt(pcopy->conlist, i);
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp), cp->rval, &scalars, &lists, &containers);
    }

    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), lists);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), scalars);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), containers);

    PromiseResult result = ExpandPromiseAndDo(ctx, pcopy, lists, containers, ActOnPromise, param);

    PromiseDestroy(pcopy);

    RlistDestroy(lists);
    RlistDestroy(scalars);
    RlistDestroy(containers);

    return result;
}
void TestExpandVariables()
{
    Promise pp = { 0 }, *pcopy;
    Rlist *args, *listvars = NULL, *scalarvars = NULL;
    Constraint *cp;
    FnCall *fp;

    strcpy(CFWORKDIR, GetWorkDir());
    MapName(CFWORKDIR);

/* Still have diagnostic scope */
    NewScope("control_common");

    printf("%d. Testing variable expansion\n", ++NR);
    pp.promiser = "the originator";
    pp.promisee = (Rval) {"the recipient with $(two)", CF_SCALAR};
    pp.classes = "proletariat";
    pp.offset.line = 12;
    pp.audit = NULL;
    pp.conlist = NULL;
    pp.agentsubtype = "none";

    pp.bundletype = "bundle_type";
    pp.bundle = "test_bundle";
    pp.ref = "commentary";
    pp.agentsubtype = xstrdup("files");
    pp.done = false;
    pp.next = NULL;
    pp.cache = NULL;
    pp.inode_cache = NULL;
    pp.this_server = NULL;
    pp.donep = &(pp.done);
    pp.conn = NULL;

    args = SplitStringAsRList("$(administrator)", ',');
    fp = NewFnCall("getuid", args);

    AppendConstraint(&(pp.conlist), "lval1", (Rval) {xstrdup("@(one)"), CF_SCALAR}, "lower classes1", false);
    AppendConstraint(&(pp.conlist), "lval2", (Rval) {xstrdup("$(four)"), CF_SCALAR}, "upper classes1", false);
    AppendConstraint(&(pp.conlist), "lval3", (Rval) {fp, CF_FNCALL}, "upper classes2", false);

/* Now copy promise and delete */

    pcopy = DeRefCopyPromise("diagnostic", &pp);

    MapIteratorsFromRval("diagnostic", &scalarvars, &listvars, (Rval) {pcopy->promiser, CF_SCALAR}, NULL);

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval("diagnostic", &scalarvars, &listvars, pp.promisee, NULL);
    }

    for (cp = pcopy->conlist; cp != NULL; cp = cp->next)
    {
        MapIteratorsFromRval("diagnostic", &scalarvars, &listvars, cp->rval, NULL);
    }

    ExpandPromiseAndDo(cf_common, "diagnostic", pcopy, scalarvars, listvars, NULL);
/* No cleanup */
}
Exemple #3
0
/**
 * Recursively go down the #rval and run PromiseIteratorPrepare() to take note
 * of all iterables and mangle all rvals than need to be mangled before
 * iterating.
 */
static void MapIteratorsFromRval(EvalContext *ctx,
                                 PromiseIterator *iterctx,
                                 Rval rval)
{
    switch (rval.type)
    {

    case RVAL_TYPE_SCALAR:
        PromiseIteratorPrepare(iterctx, ctx, RvalScalarValue(rval));
        break;

    case RVAL_TYPE_LIST:
        for (const Rlist *rp = RvalRlistValue(rval);
             rp != NULL; rp = rp->next)
        {
            MapIteratorsFromRval(ctx, iterctx, rp->val);
        }
        break;

    case RVAL_TYPE_FNCALL:
    {
        char *fn_name = RvalFnCallValue(rval)->name;

        /* Check function name. */
        PromiseIteratorPrepare(iterctx, ctx, fn_name);

        /* Check each of the function arguments. */
        /* EXCEPT on functions that use special variables: the mangled
         * variables would never be resolved if they contain inner special
         * variables (for example "$(bundle.A[$(this.k)])" and the returned
         * slist would contained mangled vars like "bundle#A[1]" which would
         * never resolve in future iterations. By skipping the iteration
         * engine for now, the function returns an slist with unmangled
         * entries, and the iteration engine works correctly on the next
         * pass! */
        if (strcmp(fn_name, "maplist") != 0 &&
            strcmp(fn_name, "mapdata") != 0 &&
            strcmp(fn_name, "maparray")!= 0)
        {
            for (Rlist *rp = RvalFnCallValue(rval)->args;
                 rp != NULL;  rp = rp->next)
            {
                MapIteratorsFromRval(ctx, iterctx, rp->val);
            }
        }
        break;
    }

    case RVAL_TYPE_CONTAINER:
    case RVAL_TYPE_NOPROMISEE:
        break;
    }
}
Exemple #4
0
PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp,
                            PromiseActuator *ActOnPromise, void *param)
{
    Log(LOG_LEVEL_VERBOSE, "Evaluating promise '%s'", pp->promiser);
    if (!IsDefinedClass(ctx, pp->classes))
    {
        if (LEGACY_OUTPUT)
        {
            Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . ");
            Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as context %s is not relevant", pp->promiser,
                  pp->classes);
            Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . ");
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as context '%s' is not relevant", pp->promiser, pp->classes);
        }
        return PROMISE_RESULT_SKIPPED;
    }

    Rlist *lists = NULL;
    Rlist *scalars = NULL;
    Rlist *containers = NULL;

    Promise *pcopy = DeRefCopyPromise(ctx, pp);

    MapIteratorsFromRval(ctx, PromiseGetBundle(pp), (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp), pp->promisee, &scalars, &lists, &containers);
    }

    for (size_t i = 0; i < SeqLength(pcopy->conlist); i++)
    {
        Constraint *cp = SeqAt(pcopy->conlist, i);
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp), cp->rval, &scalars, &lists, &containers);
    }

    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), lists);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), scalars);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), containers);

    PromiseResult result = ExpandPromiseAndDo(ctx, pcopy, lists, containers, ActOnPromise, param);

    PromiseDestroy(pcopy);

    RlistDestroy(lists);
    RlistDestroy(scalars);
    RlistDestroy(containers);

    return result;
}
Exemple #5
0
PromiseResult ExpandPromise(EvalContext *ctx, const Promise *pp,
                            PromiseActuator *act_on_promise, void *param)
{
    if (!IsDefinedClass(ctx, pp->classes))
    {
        return PROMISE_RESULT_SKIPPED;
    }

    /* 1. Copy the promise while expanding '@' slists and body arguments
     *    (including body inheritance). */
    Promise *pcopy = DeRefCopyPromise(ctx, pp);

    EvalContextStackPushPromiseFrame(ctx, pcopy, true);
    PromiseIterator *iterctx = PromiseIteratorNew(pcopy);

    /* 2. Parse all strings (promiser-promisee-constraints), find all
          unexpanded variables, mangle them if needed (if they are
          namespaced/scoped), and start the iteration engine (iterctx) to
          iterate over slists and containers. */

    MapIteratorsFromRval(ctx, iterctx,
    (Rval) {
        pcopy->promiser, RVAL_TYPE_SCALAR
    });

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval(ctx, iterctx, pcopy->promisee);
    }

    for (size_t i = 0; i < SeqLength(pcopy->conlist); i++)
    {
        Constraint *cp = SeqAt(pcopy->conlist, i);
        MapIteratorsFromRval(ctx, iterctx, cp->rval);
    }

    /* 3. GO! */
    PutHandleVariable(ctx, pcopy);
    PromiseResult result = ExpandPromiseAndDo(ctx, iterctx,
                           act_on_promise, param);

    EvalContextStackPopFrame(ctx);
    PromiseIteratorDestroy(iterctx);
    PromiseDestroy(pcopy);

    return result;
}
Exemple #6
0
void ExpandPromise(EvalContext *ctx, Promise *pp, PromiseActuator *ActOnPromise, void *param)
{
    Rlist *listvars = NULL;
    Rlist *scalars = NULL;
    Promise *pcopy;

    // Set a default for packages here...general defaults that need to come before
    //fix me wth a general function SetMissingDefaults
    SetAnyMissingDefaults(ctx, pp);

    ScopeClear("match");       /* in case we expand something expired accidentially */

    EvalContextStackPushPromiseFrame(ctx, pp);

    pcopy = DeRefCopyPromise(ctx, pp);

    MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, &listvars, &scalars, (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR });

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, &listvars, &scalars, pp->promisee);
    }

    for (size_t i = 0; i < SeqLength(pcopy->conlist); i++)
    {
        Constraint *cp = SeqAt(pcopy->conlist, i);
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, &listvars, &scalars, cp->rval);
    }

    CopyLocalizedIteratorsToThisScope(ctx, PromiseGetBundle(pp)->name, listvars);
    CopyLocalizedScalarsToThisScope(ctx, PromiseGetBundle(pp)->name, scalars);

    ScopePushThis();
    ExpandPromiseAndDo(ctx, pcopy, listvars, ActOnPromise, param);
    ScopePopThis();

    PromiseDestroy(pcopy);
    RlistDestroy(listvars);
    RlistDestroy(scalars);

    EvalContextStackPopFrame(ctx);
}
Exemple #7
0
void MapIteratorsFromRval(EvalContext *ctx, const Bundle *bundle, Rval rval,
                          Rlist **scalars, Rlist **lists, Rlist **containers)
{
    assert(rval.item);
    if (rval.item == NULL)
    {
        return;
    }

    switch (rval.type)
    {
    case RVAL_TYPE_SCALAR:
        {
            char *val = RvalScalarValue(rval);
            size_t val_len = strlen(val);
            ExpandAndMapIteratorsFromScalar(ctx, bundle, val, val_len, 0, scalars, lists, containers, NULL);
        }
        break;

    case RVAL_TYPE_LIST:
        for (const Rlist *rp = RvalRlistValue(rval); rp; rp = rp->next)
        {
            MapIteratorsFromRval(ctx, bundle, rp->val, scalars, lists, containers);
        }
        break;

    case RVAL_TYPE_FNCALL:
        ExpandAndMapIteratorsFromScalar(ctx, bundle, RvalFnCallValue(rval)->name,
                                        strlen(RvalFnCallValue(rval)->name), 0, scalars, lists, containers, NULL);
        for (const Rlist *rp = RvalFnCallValue(rval)->args; rp; rp = rp->next)
        {
            Log(LOG_LEVEL_DEBUG, "Looking at arg for function-like object '%s'", RvalFnCallValue(rval)->name);
            MapIteratorsFromRval(ctx, bundle, rp->val, scalars, lists, containers);
        }
        break;

    case RVAL_TYPE_CONTAINER:
    case RVAL_TYPE_NOPROMISEE:
        Log(LOG_LEVEL_DEBUG, "Unknown Rval type for scope '%s'", bundle->name);
        break;
    }
}
Exemple #8
0
void ExpandPromise(EvalContext *ctx, Promise *pp, PromiseActuator *ActOnPromise, void *param)
{
    Rlist *lists = NULL;
    Rlist *scalars = NULL;
    Rlist *containers = NULL;

    // Set a default for packages here...general defaults that need to come before
    //fix me wth a general function SetMissingDefaults
    SetAnyMissingDefaults(ctx, pp);

    Promise *pcopy = DeRefCopyPromise(ctx, pp);

    MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, (Rval) { pcopy->promiser, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

    if (pcopy->promisee.item != NULL)
    {
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, pp->promisee, &scalars, &lists, &containers);
    }

    for (size_t i = 0; i < SeqLength(pcopy->conlist); i++)
    {
        Constraint *cp = SeqAt(pcopy->conlist, i);
        MapIteratorsFromRval(ctx, PromiseGetBundle(pp)->name, cp->rval,&scalars, &lists, &containers);
    }

    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), lists);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), scalars);
    CopyLocalizedReferencesToBundleScope(ctx, PromiseGetBundle(pp), containers);

    ExpandPromiseAndDo(ctx, pcopy, lists, containers, ActOnPromise, param);

    PromiseDestroy(pcopy);

    RlistDestroy(lists);
    RlistDestroy(scalars);
    RlistDestroy(containers);
}
Exemple #9
0
void TestVariableScan()
{
    int i;
    char *list_text1 = "$(administrator),a,b,c,d,e,f";
    char *list_text2 = "1,2,3,4,@(one)";
    Rlist *varlist1, *varlist2, *listoflists = NULL, *scalars = NULL;

    static char *varstrings[] =
    {
        "alpha $(one) beta $(two) gamma",
        "alpha $(five) beta $(none) gamma $(array[$(four)])",
        "alpha $(none) beta $(two) gamma",
        "alpha $(four) beta $(two) gamma $(array[$(diagnostic.three)])",
        NULL
    };

    printf("%d. Test variable scanning\n", ++NR);
    SetNewScope("diagnostic");

    varlist1 = SplitStringAsRList(list_text1, ',');
    varlist2 = SplitStringAsRList(list_text2, ',');

    NewList("diagnostic", "one", varlist1, cf_slist);
    NewScalar("diagnostic", "two", "secondary skills", cf_str);
    NewScalar("diagnostic", "administrator", "root", cf_str);
    NewList("diagnostic", "three", varlist2, cf_slist);
    NewList("diagnostic", "four", varlist2, cf_slist);
    NewList("diagnostic", "five", varlist2, cf_slist);

    for (i = 0; varstrings[i] != NULL; i++)
    {
        if (VERBOSE || DEBUG)
        {
            printf("-----------------------------------------------------------\n");
            printf("Scanning: [%s]\n", varstrings[i]);
            MapIteratorsFromRval("diagnostic", &scalars, &listoflists, (Rval) {
                varstrings[i], CF_SCALAR
            }, NULL);
            printf("Cumulative scan produced:\n");
            printf("   Scalar variables: ");
            ShowRlist(stdout, scalars);
            printf("\n");
            printf("   Lists variables: ");
            ShowRlist(stdout, listoflists);
            printf("\n");
        }
    }
}
Exemple #10
0
static void test_map_iterators_from_rval_literal(void **state)
{
    EvalContext *ctx = *state;
    Policy *p = PolicyNew();
    Bundle *bp = PolicyAppendBundle(p, "default", "none", "agent", NULL, NULL);

    Rlist *lists = NULL;
    Rlist *scalars = NULL;
    Rlist *containers = NULL;
    MapIteratorsFromRval(ctx, bp, (Rval) { "snookie", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

    assert_int_equal(0, RlistLen(lists));
    assert_int_equal(0, RlistLen(scalars));
    assert_int_equal(0, RlistLen(containers));

    PolicyDestroy(p);
}
Exemple #11
0
bool EvalContextVariablePut(EvalContext *ctx, VarRef lval, Rval rval, DataType type)
{
    Scope *ptr;
    const Rlist *rp;
    CfAssoc *assoc;

    if (rval.type == RVAL_TYPE_SCALAR)
    {
        CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", lval.scope, lval.lval, (const char *) rval.item, CF_DATATYPES[type],
                rval.type);
    }
    else
    {
        CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", lval.scope, lval.lval, CF_DATATYPES[type], rval.type);
    }

    if (lval.lval == NULL || lval.scope == NULL)
    {
        CfOut(OUTPUT_LEVEL_ERROR, "", "scope.value = %s.%s", lval.scope, lval.lval);
        ProgrammingError("Bad variable or scope in a variable assignment, should not happen - forgotten to register a function call in fncall.c?");
    }

    if (rval.item == NULL)
    {
        CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n");
        return false;
    }

    if (strlen(lval.lval) > CF_MAXVARSIZE)
    {
        char *lval_str = VarRefToString(lval);
        CfOut(OUTPUT_LEVEL_ERROR, "", "Variable %s cannot be added because its length exceeds the maximum length allowed: %d", lval_str, CF_MAXVARSIZE);
        free(lval_str);
        return false;
    }

/* If we are not expanding a body template, check for recursive singularities */

    if (strcmp(lval.scope, "body") != 0)
    {
        switch (rval.type)
        {
        case RVAL_TYPE_SCALAR:

            if (StringContainsVar((char *) rval.item, lval.lval))
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", "Scalar variable %s.%s contains itself (non-convergent): %s", lval.scope, lval.lval,
                      (char *) rval.item);
                return false;
            }
            break;

        case RVAL_TYPE_LIST:

            for (rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (StringContainsVar((char *) rp->item, lval.lval))
                {
                    CfOut(OUTPUT_LEVEL_ERROR, "", "List variable %s contains itself (non-convergent)", lval.lval);
                    return false;
                }
            }
            break;

        default:
            break;
        }
    }

    ptr = ScopeGet(lval.scope);
    if (!ptr)
    {
        ptr = ScopeNew(lval.scope);
        if (!ptr)
        {
            return false;
        }
    }

// Look for outstanding lists in variable rvals

    if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON)
    {
        Rlist *listvars = NULL;

        if (ScopeGetCurrent() && strcmp(ScopeGetCurrent()->scope, "this") != 0)
        {
            MapIteratorsFromRval(ScopeGetCurrent()->scope, &listvars, rval);

            if (listvars != NULL)
            {
                CfOut(OUTPUT_LEVEL_ERROR, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"",
                      lval.lval, ScopeGetCurrent()->scope);
            }

            RlistDestroy(listvars);
        }
    }

    assoc = HashLookupElement(ptr->hashtable, lval.lval);

    if (assoc)
    {
        if (CompareVariableValue(rval, assoc) == 0)
        {
            /* Identical value, keep as is */
        }
        else
        {
            /* Different value, bark and replace */
            if (!UnresolvedVariables(assoc, rval.type))
            {
                CfOut(OUTPUT_LEVEL_INFORM, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval.lval, ptr->scope);
            }
            RvalDestroy(assoc->rval);
            assoc->rval = RvalCopy(rval);
            assoc->dtype = type;
            CfDebug("Stored \"%s\" in context %s\n", lval.lval, lval.scope);
        }
    }
    else
    {
        if (!HashInsertElement(ptr->hashtable, lval.lval, rval, type))
        {
            ProgrammingError("Hash table is full");
        }
    }

    CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval.lval, lval.scope);
    return true;
}
Exemple #12
0
bool EvalContextVariablePut(EvalContext *ctx, VarRef lval, Rval rval, DataType type)
{
    assert(type != DATA_TYPE_NONE);

    if (lval.lval == NULL || lval.scope == NULL)
    {
        ProgrammingError("Bad variable or scope in a variable assignment. scope.value = %s.%s", lval.scope, lval.lval);
    }

    if (rval.item == NULL)
    {
        return false;
    }

    if (strlen(lval.lval) > CF_MAXVARSIZE)
    {
        char *lval_str = VarRefToString(lval, true);
        Log(LOG_LEVEL_ERR, "Variable '%s'' cannot be added because its length exceeds the maximum length allowed '%d' characters", lval_str, CF_MAXVARSIZE);
        free(lval_str);
        return false;
    }

    // If we are not expanding a body template, check for recursive singularities
    if (strcmp(lval.scope, "body") != 0)
    {
        switch (rval.type)
        {
        case RVAL_TYPE_SCALAR:
            if (StringContainsVar((char *) rval.item, lval.lval))
            {
                Log(LOG_LEVEL_ERR, "Scalar variable '%s.%s' contains itself (non-convergent), value '%s'", lval.scope, lval.lval,
                      (char *) rval.item);
                return false;
            }
            break;

        case RVAL_TYPE_LIST:
            for (const Rlist *rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (StringContainsVar(rp->item, lval.lval))
                {
                    Log(LOG_LEVEL_ERR, "List variable '%s' contains itself (non-convergent)", lval.lval);
                    return false;
                }
            }
            break;

        default:
            break;
        }
    }
    else
    {
        assert(STACK_FRAME_TYPE_BODY == LastStackFrame(ctx, 0)->type);
    }

    Scope *put_scope = ScopeGet(lval.scope);
    if (!put_scope)
    {
        put_scope = ScopeNew(lval.scope);
        if (!put_scope)
        {
            return false;
        }
    }

// Look for outstanding lists in variable rvals

    if (THIS_AGENT_TYPE == AGENT_TYPE_COMMON)
    {
        Rlist *listvars = NULL;
        Rlist *scalars = NULL; // TODO what do we do with scalars?

        if (ScopeGetCurrent() && strcmp(ScopeGetCurrent()->scope, "this") != 0)
        {
            MapIteratorsFromRval(ctx, ScopeGetCurrent()->scope, &listvars, &scalars, rval);

            if (listvars != NULL)
            {
                Log(LOG_LEVEL_ERR, "Redefinition of variable '%s' (embedded list in RHS) in context '%s'",
                      lval.lval, ScopeGetCurrent()->scope);
            }

            RlistDestroy(listvars);
            RlistDestroy(scalars);
        }
    }

    // FIX: lval is stored with array params as part of the lval for legacy reasons.
    char *final_lval = VarRefToString(lval, false);

    CfAssoc *assoc = HashLookupElement(put_scope->hashtable, final_lval);
    if (assoc)
    {
        if (CompareVariableValue(rval, assoc) != 0)
        {
            /* Different value, bark and replace */
            if (!UnresolvedVariables(assoc, rval.type))
            {
                Log(LOG_LEVEL_INFO, "Replaced value of variable '%s' in scope '%s'", lval.lval, put_scope->scope);
            }
            RvalDestroy(assoc->rval);
            assoc->rval = RvalCopy(rval);
            assoc->dtype = type;
        }
    }
    else
    {
        if (!HashInsertElement(put_scope->hashtable, final_lval, rval, type))
        {
            ProgrammingError("Hash table is full");
        }
    }

    free(final_lval);
    return true;
}
Exemple #13
0
int AddVariableHash(const char *scope, const char *lval, Rval rval, enum cfdatatype dtype, const char *fname,
                    int lineno)
{
    Scope *ptr;
    const Rlist *rp;
    CfAssoc *assoc;

    if (rval.rtype == CF_SCALAR)
    {
        CfDebug("AddVariableHash(%s.%s=%s (%s) rtype=%c)\n", scope, lval, (const char *) rval.item, CF_DATATYPES[dtype],
                rval.rtype);
    }
    else
    {
        CfDebug("AddVariableHash(%s.%s=(list) (%s) rtype=%c)\n", scope, lval, CF_DATATYPES[dtype], rval.rtype);
    }

    if (lval == NULL || scope == NULL)
    {
        CfOut(cf_error, "", "scope.value = %s.%s", scope, lval);
        ReportError("Bad variable or scope in a variable assignment");
        FatalError("Should not happen - forgotten to register a function call in fncall.c?");
    }

    if (rval.item == NULL)
    {
        CfDebug("No value to assignment - probably a parameter in an unused bundle/body\n");
        return false;
    }

    if (strlen(lval) > CF_MAXVARSIZE)
    {
        ReportError("variable lval too long");
        return false;
    }

/* If we are not expanding a body template, check for recursive singularities */

    if (strcmp(scope, "body") != 0)
    {
        switch (rval.rtype)
        {
        case CF_SCALAR:

            if (StringContainsVar((char *) rval.item, lval))
            {
                CfOut(cf_error, "", "Scalar variable %s.%s contains itself (non-convergent): %s", scope, lval,
                      (char *) rval.item);
                return false;
            }
            break;

        case CF_LIST:

            for (rp = rval.item; rp != NULL; rp = rp->next)
            {
                if (StringContainsVar((char *) rp->item, lval))
                {
                    CfOut(cf_error, "", "List variable %s contains itself (non-convergent)", lval);
                    return false;
                }
            }
            break;

        }
    }

    ptr = GetScope(scope);

    if (ptr == NULL)
    {
        return false;
    }

// Look for outstanding lists in variable rvals

    if (THIS_AGENT_TYPE == cf_common)
    {
        Rlist *listvars = NULL, *scalarvars = NULL;

        if (strcmp(CONTEXTID, "this") != 0)
        {
            MapIteratorsFromRval(CONTEXTID, &scalarvars, &listvars, rval, NULL);

            if (listvars != NULL)
            {
                CfOut(cf_error, "", " !! Redefinition of variable \"%s\" (embedded list in RHS) in context \"%s\"",
                      lval, CONTEXTID);
            }

            DeleteRlist(scalarvars);
            DeleteRlist(listvars);
        }
    }

    assoc = HashLookupElement(ptr->hashtable, lval);

    if (assoc)
    {
        if (CompareVariableValue(rval, assoc) == 0)
        {
            /* Identical value, keep as is */
        }
        else
        {
            /* Different value, bark and replace */
            if (!UnresolvedVariables(assoc, rval.rtype))
            {
                CfOut(cf_inform, "", " !! Duplicate selection of value for variable \"%s\" in scope %s", lval,
                      ptr->scope);
                if (fname)
                {
                    CfOut(cf_inform, "", " !! Rule from %s at/before line %d\n", fname, lineno);
                }
                else
                {
                    CfOut(cf_inform, "", " !! in bundle parameterization\n");
                }
            }
            DeleteRvalItem(assoc->rval);
            assoc->rval = CopyRvalItem(rval);
            assoc->dtype = dtype;
            CfDebug("Stored \"%s\" in context %s\n", lval, scope);
        }
    }
    else
    {
        if (!HashInsertElement(ptr->hashtable, lval, rval, dtype))
        {
            FatalError("Hash table is full");
        }
    }

    CfDebug("Added Variable %s in scope %s with value (omitted)\n", lval, scope);
    return true;
}
Exemple #14
0
static void test_map_iterators_from_rval_naked_list_var_namespace(void **state)
{
    EvalContext *ctx = *state;
    Policy *p = PolicyNew();
    Bundle *bp = PolicyAppendBundle(p, "ns", "scope", "agent", NULL, NULL);

    {
        Rlist *list = NULL;
        RlistAppend(&list, "jersey", RVAL_TYPE_SCALAR);
        VarRef *lval = VarRefParse("ns:scope.jwow");

        EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL);

        VarRefDestroy(lval);
        RlistDestroy(list);
    }

    EvalContextStackPushBundleFrame(ctx, bp, NULL, false);

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        MapIteratorsFromRval(ctx, bp, (Rval) { "${jwow}", RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        char *str = xstrdup("${scope.jwow}");
        MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_string_equal("${scope#jwow}", str);
        free(str);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("scope#jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    {
        Rlist *lists = NULL;
        Rlist *scalars = NULL;
        Rlist *containers = NULL;
        char *str = xstrdup("${ns:scope.jwow}");
        MapIteratorsFromRval(ctx, bp, (Rval) { str, RVAL_TYPE_SCALAR }, &scalars, &lists, &containers);

        assert_string_equal("${ns*scope#jwow}", str);
        free(str);

        assert_int_equal(1, RlistLen(lists));
        assert_string_equal("ns*scope#jwow", RlistScalarValue(lists));
        assert_int_equal(0, RlistLen(scalars));
        assert_int_equal(0, RlistLen(containers));

        RlistDestroy(lists);
    }

    EvalContextStackPopFrame(ctx);
    PolicyDestroy(p);
}