Rval ExpandDanglers(EvalContext *ctx, const char *ns, const char *scope, Rval rval, const Promise *pp) { assert(ctx); assert(pp); switch (rval.type) { case RVAL_TYPE_SCALAR: if (IsCf3VarString(RvalScalarValue(rval))) { return EvaluateFinalRval(ctx, PromiseGetPolicy(pp), ns, scope, rval, false, pp); } else { return RvalCopy(rval); } break; case RVAL_TYPE_LIST: { Rlist *result_list = RlistCopy(RvalRlistValue(rval)); RlistFlatten(ctx, &result_list); return RvalNew(result_list, RVAL_TYPE_LIST); } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: return RvalCopy(rval); } ProgrammingError("Unhandled Rval type"); }
static void CopyLocalizedReferencesToBundleScope(EvalContext *ctx, const Bundle *bundle, const Rlist *ref_names) { for (const Rlist *rp = ref_names; rp != NULL; rp = rp->next) { const char *mangled = RlistScalarValue(rp); char *demangled = xstrdup(mangled); DeMangleVarRefString(demangled, strlen(demangled)); if (strchr(RlistScalarValue(rp), CF_MAPPEDLIST)) { VarRef *demangled_ref = VarRefParseFromBundle(demangled, bundle); DataType value_type; const void *value = EvalContextVariableGet(ctx, demangled_ref, &value_type); if (!value) { ProgrammingError("Couldn't find extracted variable '%s'", mangled); } VarRef *mangled_ref = VarRefParseFromBundle(mangled, bundle); switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: { Rlist *list = RlistCopy(value); RlistFlatten(ctx, &list); EvalContextVariablePut(ctx, mangled_ref, list, value_type, "source=agent"); RlistDestroy(list); } break; case RVAL_TYPE_CONTAINER: case RVAL_TYPE_SCALAR: EvalContextVariablePut(ctx, mangled_ref, value, value_type, "source=agent"); break; case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: ProgrammingError("Illegal rval type in switch %d", DataTypeToRvalType(value_type)); } VarRefDestroy(mangled_ref); VarRefDestroy(demangled_ref); } free(demangled); } }
static void ResolvePackageManagerBody(EvalContext *ctx, const Body *pm_body) { PackageModuleBody *new_manager = xcalloc(1, sizeof(PackageModuleBody)); new_manager->name = SafeStringDuplicate(pm_body->name); for (size_t i = 0; i < SeqLength(pm_body->conlist); i++) { Constraint *cp = SeqAt(pm_body->conlist, i); Rval returnval = {0}; if (IsDefinedClass(ctx, cp->classes)) { returnval = ExpandPrivateRval(ctx, NULL, "body", cp->rval.item, cp->rval.type); } if (returnval.item == NULL || returnval.type == RVAL_TYPE_NOPROMISEE) { Log(LOG_LEVEL_VERBOSE, "have invalid constraint while resolving" "package promise body: %s", cp->lval); RvalDestroy(returnval); continue; } if (strcmp(cp->lval, "query_installed_ifelapsed") == 0) { new_manager->installed_ifelapsed = (int)IntFromString(RvalScalarValue(returnval)); } else if (strcmp(cp->lval, "query_updates_ifelapsed") == 0) { new_manager->updates_ifelapsed = (int)IntFromString(RvalScalarValue(returnval)); } else if (strcmp(cp->lval, "default_options") == 0) { new_manager->options = RlistCopy(RvalRlistValue(returnval)); } else { /* This should be handled by the parser. */ assert(0); } RvalDestroy(returnval); } AddPackageModuleToContext(ctx, new_manager); }
static void test_copy(void) { Rlist *list = NULL, *copy = NULL; RlistPrepend(&list, "stuff", RVAL_TYPE_SCALAR); RlistPrepend(&list, "more-stuff", RVAL_TYPE_SCALAR); copy = RlistCopy(list); assert_string_equal(RlistScalarValue(list), RlistScalarValue(copy)); assert_string_equal(RlistScalarValue(list->next), RlistScalarValue(copy->next)); RlistDestroy(list); RlistDestroy(copy); }
static void test_copy(void) { Rlist *list = NULL, *copy = NULL; RlistPrependScalar(&list, "stuff"); RlistPrependScalar(&list, "more-stuff"); copy = RlistCopy(list); assert_string_equal(list->item, copy->item); assert_string_equal(list->next->item, copy->next->item); RlistDestroy(list); RlistDestroy(copy); }
Rval RvalNew(const void *item, RvalType type) { switch (type) { case RVAL_TYPE_SCALAR: return (Rval) { xstrdup(item), RVAL_TYPE_SCALAR }; case RVAL_TYPE_FNCALL: return (Rval) { FnCallCopy(item), RVAL_TYPE_FNCALL }; case RVAL_TYPE_LIST: return (Rval) { RlistCopy(item), RVAL_TYPE_LIST }; case RVAL_TYPE_CONTAINER: return (Rval) { JsonCopy(item), RVAL_TYPE_CONTAINER }; case RVAL_TYPE_NOPROMISEE: return ((Rval) {NULL, type}); } assert(false); return ((Rval) { NULL, RVAL_TYPE_NOPROMISEE }); }
Rlist *NewExpArgs(EvalContext *ctx, const Policy *policy, const FnCall *fp, const FnCallType *fp_type) { // Functions with delayed evaluation will call this themselves later if (fp_type && fp_type->options & FNCALL_OPTION_DELAYED_EVALUATION) { return RlistCopy(fp->args); } const FnCallType *fn = FnCallTypeGet(fp->name); { int len = RlistLen(fp->args); if (!(fn->options & FNCALL_OPTION_VARARG)) { if (len != FnNumArgs(fn)) { Log(LOG_LEVEL_ERR, "Arguments to function '%s' do not tally. Expected %d not %d", fp->name, FnNumArgs(fn), len); PromiseRef(LOG_LEVEL_ERR, fp->caller); exit(EXIT_FAILURE); } } } Rlist *expanded_args = NULL; for (const Rlist *rp = fp->args; rp != NULL; rp = rp->next) { Rval rval; switch (rp->val.type) { case RVAL_TYPE_FNCALL: { FnCall *subfp = RlistFnCallValue(rp); rval = FnCallEvaluate(ctx, policy, subfp, fp->caller).rval; } break; default: rval = ExpandPrivateRval(ctx, NULL, NULL, rp->val.item, rp->val.type); assert(rval.item); break; } /* Collect compound values into containers only if the function supports it. Functions without FNCALL_OPTION_COLLECTING don't collect Rlist elements. So in the policy, you call and(splitstring("a b")) and it ends up as and("a", "b"). This expansion happens once per FnCall, not for all arguments. Functions with FNCALL_OPTION_COLLECTING instead collect all the results of a FnCall into a single JSON array object. It requires functions to expect it, but it's the only reasonable way to preserve backwards compatibility for functions like and() and allow nesting of calls to functions that take and return compound data types. */ RlistAppendAllTypes(&expanded_args, rval.item, rval.type, (fn->options & FNCALL_OPTION_COLLECTING)); RvalDestroy(rval); } return expanded_args; }
void GenericAgentConfigSetBundleSequence(GenericAgentConfig *config, const Rlist *bundlesequence) { RlistDestroy(config->bundlesequence); config->bundlesequence = RlistCopy(bundlesequence); }
FnCall *FnCallCopy(const FnCall *f) { return FnCallNew(f->name, RlistCopy(f->args)); }
FnCall *FnCallCopy(const FnCall *f) { CfDebug("CopyFnCall()\n"); return FnCallNew(f->name, RlistCopy(f->args)); }