static void ShowVariablesFormatted(EvalContext *ctx) { VariableTableIterator *iter = EvalContextVariableTableIteratorNew(ctx, NULL, NULL, NULL); Variable *v = NULL; Seq *seq = SeqNew(2000, free); while ((v = VariableTableIteratorNext(iter))) { char *varname = VarRefToString(v->ref, true); Writer *w = StringWriter(); switch (DataTypeToRvalType(v->type)) { case RVAL_TYPE_CONTAINER: JsonWriteCompact(w, RvalContainerValue(v->rval)); break; default: RvalWrite(w, v->rval); } const char *var_value; if (StringIsPrintable(StringWriterData(w))) { var_value = StringWriterData(w); } else { var_value = "<non-printable>"; } StringSet *tagset = EvalContextVariableTags(ctx, v->ref); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; xasprintf(&line, "%-40s %-60s %-40s", varname, var_value, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); WriterClose(w); free(varname); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-40s %-60s %-40s\n", "Variable name", "Variable value", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *variable = SeqAt(seq, i); printf("%s\n", variable); } SeqDestroy(seq); VariableTableIteratorDestroy(iter); }
void SeqAppendSeq(Seq *seq, const Seq *items) { for (size_t i = 0; i < SeqLength(items); i++) { SeqAppend(seq, SeqAt(items, i)); } }
static bool RenderVariable(Writer *out, const char *content, size_t content_len, bool escaped, Seq *hash_stack) { JsonElement *var = NULL; if (strncmp(content, ".", content_len) == 0) { var = SeqAt(hash_stack, SeqLength(hash_stack) - 1); } else { var = LookupVariable(hash_stack, content, content_len); } if (!var) { return true; } switch (JsonGetElementType(var)) { case JSON_ELEMENT_TYPE_PRIMITIVE: return RenderVariablePrimitive(out, var, escaped); case JSON_ELEMENT_TYPE_CONTAINER: assert(false); return false; } assert(false); return false; }
static void ResolveCommonClassPromises(EvalContext *ctx, PromiseType *pt) { assert(strcmp("classes", pt->name) == 0); assert(strcmp(pt->parent_bundle->type, "common") == 0); EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); char *sp = NULL; if (VarClassExcluded(ctx, pp, &sp)) { if (LEGACY_OUTPUT) { Log(LOG_LEVEL_VERBOSE, "\n"); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); Log(LOG_LEVEL_VERBOSE, "Skipping whole next promise (%s), as var-context %s is not relevant", pp->promiser, sp); Log(LOG_LEVEL_VERBOSE, ". . . . . . . . . . . . . . . . . . . . . . . . . . . . "); } else { Log(LOG_LEVEL_VERBOSE, "Skipping next promise '%s', as var-context '%s' is not relevant", pp->promiser, sp); } continue; } ExpandPromise(ctx, pp, VerifyClassPromise, NULL); } EvalContextStackPopFrame(ctx); }
void DeleteMountInfo(Seq *list) { for (size_t i = 0; i < SeqLength(list); i++) { Mount *entry = SeqAt(list, i); if (entry->host) { free(entry->host); } if (entry->source) { free(entry->source); } if (entry->mounton) { free(entry->mounton); } if (entry->options) { free(entry->options); } } SeqClear(list); }
void PromiseIteratorUpdateVariable(EvalContext *ctx, const PromiseIterator *iter) { for (size_t i = 0; i < SeqLength(iter->vars); i++) { CfAssoc *iter_var = SeqAt(iter->vars, i); const Rlist *state = SeqAt(iter->var_states, i); if (!state || state->val.type == RVAL_TYPE_FNCALL) { continue; } assert(state->val.type == RVAL_TYPE_SCALAR); switch (iter_var->dtype) { case CF_DATA_TYPE_STRING_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_STRING, "source=promise"); break; case CF_DATA_TYPE_INT_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_INT, "source=promise"); break; case CF_DATA_TYPE_REAL_LIST: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, iter_var->lval, RlistScalarValue(state), CF_DATA_TYPE_REAL, "source=promise"); break; default: assert(false); break; } } }
static bool MethodsParseTreeCheck(const Promise *pp, Seq *errors) { bool success = true; for (size_t i = 0; i < SeqLength(pp->conlist); i++) { const Constraint *cp = SeqAt(pp->conlist, i); // ensure: if call and callee are resolved, then they have matching arity if (StringSafeEqual(cp->lval, "usebundle")) { if (cp->rval.type == RVAL_TYPE_FNCALL) { const FnCall *call = (const FnCall *)cp->rval.item; const Bundle *callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", call->name); if (!callee) { callee = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", call->name); } if (callee) { if (RlistLen(call->args) != RlistLen(callee->args)) { SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_CONSTRAINT, cp, POLICY_ERROR_METHODS_BUNDLE_ARITY, call->name, RlistLen(callee->args), RlistLen(call->args))); success = false; } } } } } return success; }
static bool VariableStateIncrement(PromiseIterator *iter, size_t index) { assert(index < SeqLength(iter->var_states)); CfAssoc *var = SeqAt(iter->vars, index); switch (var->rval.type) { case RVAL_TYPE_LIST: { Rlist *state = SeqAt(iter->var_states, index); assert(state); // find the next valid value, return false if there is none state = FirstRealEntry(state->next); SeqSet(iter->var_states, index, state); return state != NULL; } break; default: ProgrammingError("Unhandled case in switch"); } return false; }
static void ShowContextsFormatted(EvalContext *ctx) { ClassTableIterator *iter = EvalContextClassTableIteratorNewGlobal(ctx, NULL, true, true); Class *cls = NULL; Seq *seq = SeqNew(1000, free); while ((cls = ClassTableIteratorNext(iter))) { char *class_name = ClassRefToString(cls->ns, cls->name); StringSet *tagset = EvalContextClassTags(ctx, cls->ns, cls->name); Buffer *tagbuf = StringSetToBuffer(tagset, ','); char *line; xasprintf(&line, "%-60s %-40s", class_name, BufferData(tagbuf)); SeqAppend(seq, line); BufferDestroy(tagbuf); free(class_name); } SeqSort(seq, (SeqItemComparator)strcmp, NULL); printf("%-60s %-40s\n", "Class name", "Meta tags"); for (size_t i = 0; i < SeqLength(seq); i++) { const char *context = SeqAt(seq, i); printf("%s\n", context); } SeqDestroy(seq); ClassTableIteratorDestroy(iter); }
static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ CleanReportBookFilterSet(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); bool server_bundle = strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0; bool common_bundle = strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0; if (server_bundle || common_bundle) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } } if (server_bundle) { EvaluateBundle(ctx, bp, SERVER_TYPESEQUENCE); } else if (common_bundle) { EvaluateBundle(ctx, bp, COMMON_TYPESEQUENCE); } } }
static Body *IsBody(Seq *bodies, const char *ns, const char *key) { char fqname[CF_BUFSIZE]; for (size_t i = 0; i < SeqLength(bodies); i++) { Body *bp = SeqAt(bodies, i); // bp->namespace is where the body belongs, namespace is where we are now if (strchr(key, CF_NS) || strcmp(ns,"default") == 0) { if (strncmp(key,"default:",strlen("default:")) == 0) // CF_NS == ':' { strcpy(fqname,strchr(key,CF_NS)+1); } else { strcpy(fqname,key); } } else { snprintf(fqname,CF_BUFSIZE-1, "%s%c%s", ns, CF_NS, key); } if (strcmp(bp->name, fqname) == 0) { return bp; } } return NULL; }
size_t EvalContextStackFrameMatchCountSoft(const EvalContext *ctx, const char *context_regex) { if (SeqLength(ctx->stack) == 0) { return 0; } return StringSetMatchCount(EvalContextStackFrame(ctx)->contexts, context_regex); }
static bool EvalContextStackFrameContainsNegated(const EvalContext *ctx, const char *context) { if (SeqLength(ctx->stack) == 0) { return false; } return StringSetContains(EvalContextStackFrame(ctx)->contexts_negated, context); }
StringSet *EvalContextStackFrameAddMatchingSoft(const EvalContext *ctx, StringSet* base, const char *context_regex) { if (SeqLength(ctx->stack) == 0) { return base; } return StringSetAddAllMatchingIterator(base, EvalContextStackFrameIteratorSoft(ctx), context_regex); }
void BundleResolvePromiseType(EvalContext *ctx, const Bundle *bundle, const char *type, PromiseActuator *actuator) { for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, type) == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, actuator, NULL); } EvalContextStackPopFrame(ctx); } } }
static void KeepPromiseBundles(EvalContext *ctx, const Policy *policy) { /* Dial up the generic promise expansion with a callback */ CleanReportBookFilterSet(); for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { Log(LOG_LEVEL_WARNING, "Cannot implicitly evaluate bundle '%s %s', as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "access") != 0) && (strcmp(sp->name, "roles") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushPromiseTypeFrame(ctx, sp); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, NULL); } EvalContextStackPopFrame(ctx); } EvalContextStackPopFrame(ctx); } } }
Policy *GenericAgentLoadPolicy(EvalContext *ctx, GenericAgentConfig *config) { config->policy_last_read_attempt = time(NULL); StringSet *parsed_files = StringSetNew(); StringSet *failed_files = StringSetNew(); Policy *policy = LoadPolicyFile(ctx, config, config->input_file, parsed_files, failed_files); if (StringSetSize(failed_files) > 0) { Log(LOG_LEVEL_ERR, "There are syntax errors in policy files"); exit(EXIT_FAILURE); } StringSetDestroy(parsed_files); StringSetDestroy(failed_files); { Seq *errors = SeqNew(100, PolicyErrorDestroy); if (PolicyCheckPartial(policy, errors)) { if (!config->bundlesequence && (PolicyIsRunnable(policy) || config->check_runnable)) { Log(LOG_LEVEL_VERBOSE, "Running full policy integrity checks"); PolicyCheckRunnable(ctx, policy, errors, config->ignore_missing_bundles); } } if (SeqLength(errors) > 0) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); exit(EXIT_FAILURE); // TODO: do not exit } SeqDestroy(errors); } if (LogGetGlobalLevel() >= LOG_LEVEL_VERBOSE) { ShowContext(ctx); } if (policy) { VerifyPromises(ctx, policy, config); } return policy; }
static void KeepPromiseBundles(EvalContext *ctx, Policy *policy, const ReportContext *report_context) { /* Dial up the generic promise expansion with a callback */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); if ((strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_SERVER]) == 0) || (strcmp(bp->type, CF_AGENTTYPES[AGENT_TYPE_COMMON]) == 0)) { if (RlistLen(bp->args) > 0) { CfOut(OUTPUT_LEVEL_ERROR, "", "Cannot implicitly evaluate bundle %s %s, as this bundle takes arguments.", bp->type, bp->name); continue; } BannerBundle(bp, NULL); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); if ((strcmp(sp->name, "access") != 0) && (strcmp(sp->name, "roles") != 0)) { continue; } BannerPromiseType(bp->name, sp->name, 0); EvalContextStackPushBundleFrame(ctx, bp, false); ScopeAugment(ctx, bp, NULL); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, KeepServerPromise, report_context); } EvalContextStackPopFrame(ctx); } } } }
/** * The "roles" access promise is for remote class activation by means of * cf-runagent -D: * * pp->promiser is a regex to match classes. * pp->conlist is an slist of usernames. */ static void KeepServerRolePromise(EvalContext *ctx, const Promise *pp) { size_t pos = acl_SortedInsert(&roles_acl, pp->promiser); if (pos == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "acl_Insert: %s", GetErrorStr()); exit(255); } size_t i = SeqLength(pp->conlist); while (i > 0) { i--; Constraint *cp = SeqAt(pp->conlist, i); char const * const authorizer = CF_REMROLE_BODIES[REMOTE_ROLE_AUTHORIZE].lval; if (strcmp(cp->lval, authorizer) == 0) { if (cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_ERR, "Right-hand side of authorize promise for '%s' should be a list", pp->promiser); } else if (IsDefinedClass(ctx, cp->classes)) { for (const Rlist *rp = cp->rval.item; rp != NULL; rp = rp->next) { /* The "roles" access promise currently only supports * listing usernames to admit access to, nothing more. */ struct resource_acl *racl = &roles_acl->acls[pos]; size_t zret = StrList_Append(&racl->admit.usernames, RlistScalarValue(rp)); if (zret == (size_t) -1) { /* Should never happen, besides when allocation fails. */ Log(LOG_LEVEL_CRIT, "StrList_Append: %s", GetErrorStr()); exit(255); } } } } else if (strcmp(cp->lval, "comment") != 0 && strcmp(cp->lval, "handle") != 0 && /* Are there other known list constraints ? if not, skip this: */ cp->rval.type != RVAL_TYPE_LIST) { Log(LOG_LEVEL_WARNING, "Unrecognised promise '%s' for %s", cp->lval, pp->promiser); } } }
Promise *ExpandDeRefPromise(EvalContext *ctx, const char *scopeid, const Promise *pp) { Promise *pcopy; Rval returnval, final; CfDebug("ExpandDerefPromise()\n"); pcopy = xcalloc(1, sizeof(Promise)); returnval = ExpandPrivateRval(ctx, "this", (Rval) {pp->promiser, RVAL_TYPE_SCALAR }); pcopy->promiser = (char *) returnval.item; if (pp->promisee.item) { pcopy->promisee = EvaluateFinalRval(ctx, scopeid, pp->promisee, true, pp); } else { pcopy->promisee = (Rval) {NULL, RVAL_TYPE_NOPROMISEE }; } if (pp->classes) { pcopy->classes = xstrdup(pp->classes); } else { pcopy->classes = xstrdup("any"); } if (pcopy->promiser == NULL) { ProgrammingError("ExpandPromise returned NULL"); } pcopy->parent_promise_type = pp->parent_promise_type; pcopy->offset.line = pp->offset.line; pcopy->comment = pp->comment ? xstrdup(pp->comment) : NULL; pcopy->conlist = SeqNew(10, ConstraintDestroy); pcopy->org_pp = pp->org_pp; /* No further type checking should be necessary here, already done by CheckConstraintTypeMatch */ for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); Rval returnval; if (ExpectedDataType(cp->lval) == DATA_TYPE_BUNDLE) { final = ExpandBundleReference(ctx, scopeid, cp->rval); } else {
static void SavePackages(const char *database_filename, Seq *package_entries) { FILE *packages_file = fopen(database_filename, "w"); for (size_t i = 0; i < SeqLength(package_entries); i++) { fprintf(packages_file, "%s\n", SerializePackage(SeqAt(package_entries, i))); } fclose(packages_file); }
static void DumpErrors(Seq *errs) { if (SeqLength(errs) > 0) { Writer *writer = FileWriter(stdout); for (size_t i = 0; i < errs->length; i++) { PolicyErrorWrite(writer, errs->data[i]); } FileWriterDetach(writer); } }
size_t EvalContextStackFrameMatchCountSoft(const EvalContext *ctx, const char *context_regex) { if (SeqLength(ctx->stack) == 0) { return 0; } const StackFrame *frame = LastStackFrameBundle(ctx); assert(frame); return StringSetMatchCount(frame->data.bundle.contexts, context_regex); }
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; }
static void VerifyPromises(EvalContext *ctx, Policy *policy, GenericAgentConfig *config) { /* Now look once through ALL the bundles themselves */ for (size_t i = 0; i < SeqLength(policy->bundles); i++) { Bundle *bp = SeqAt(policy->bundles, i); EvalContextStackPushBundleFrame(ctx, bp, NULL, false); for (size_t j = 0; j < SeqLength(bp->promise_types); j++) { PromiseType *sp = SeqAt(bp->promise_types, j); for (size_t ppi = 0; ppi < SeqLength(sp->promises); ppi++) { Promise *pp = SeqAt(sp->promises, ppi); ExpandPromise(ctx, pp, CommonEvalPromise, NULL); } } EvalContextStackPopFrame(ctx); } PolicyResolve(ctx, policy, config); // TODO: need to move this inside PolicyCheckRunnable eventually. if (!config->bundlesequence && config->check_runnable) { // only verify policy-defined bundlesequence for cf-agent, cf-promises if ((config->agent_type == AGENT_TYPE_AGENT) || (config->agent_type == AGENT_TYPE_COMMON)) { if (!VerifyBundleSequence(ctx, policy, config)) { FatalError(ctx, "Errors in promise bundles"); } } } }
static void KeepServerRolePromise(EvalContext *ctx, Promise *pp) { Rlist *rp; Auth *ap; if (!GetAuthPath(pp->promiser, SV.roles)) { InstallServerAuthPath(pp->promiser, &SV.roles, &SV.rolestop); } ap = GetAuthPath(pp->promiser, SV.roles); for (size_t i = 0; i < SeqLength(pp->conlist); i++) { Constraint *cp = SeqAt(pp->conlist, i); if (!IsDefinedClass(ctx, cp->classes, PromiseGetNamespace(pp))) { continue; } switch (cp->rval.type) { case RVAL_TYPE_LIST: for (rp = (Rlist *) cp->rval.item; rp != NULL; rp = rp->next) { if (strcmp(cp->lval, CF_REMROLE_BODIES[REMOTE_ROLE_AUTHORIZE].lval) == 0) { PrependItem(&(ap->accesslist), rp->item, NULL); continue; } } break; case RVAL_TYPE_FNCALL: /* Shouldn't happen */ break; default: if ((strcmp(cp->lval, "comment") == 0) || (strcmp(cp->lval, "handle") == 0)) { } else { Log(LOG_LEVEL_ERR, "Right-hand side of authorize promise for '%s' should be a list", pp->promiser); } break; } } }
void BundleResolve(EvalContext *ctx, const Bundle *bundle) { Log(LOG_LEVEL_DEBUG, "Resolving variables in bundle '%s' '%s'", bundle->type, bundle->name); if (strcmp(bundle->type, "common") == 0) { for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, "classes") == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, VerifyClassPromise, NULL); } EvalContextStackPopFrame(ctx); } } } for (size_t j = 0; j < SeqLength(bundle->promise_types); j++) { PromiseType *pt = SeqAt(bundle->promise_types, j); if (strcmp(pt->name, "vars") == 0) { EvalContextStackPushPromiseTypeFrame(ctx, pt); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); ExpandPromise(ctx, pp, (PromiseActuator*)VerifyVarPromise, NULL); } EvalContextStackPopFrame(ctx); } } }
static void AddPackage(PackagePattern *pattern) { fprintf(stderr, "Trying to install all packages matching pattern %s\n", SerializePackagePattern(pattern)); Seq *matching_available = FindPackages(AVAILABLE_PACKAGES_FILE_NAME, pattern); if (SeqLength(matching_available) == 0) { fprintf(stderr, "Unable to find any package matching %s\n", SerializePackagePattern(pattern)); exit(EXIT_FAILURE); } for (size_t i = 0; i < SeqLength(matching_available); i++) { Package *p = SeqAt(matching_available, i); PackagePattern *pat = MatchAllVersions(p); if (SeqLength(FindPackages(INSTALLED_PACKAGES_FILE_NAME, pat)) > 0) { fprintf(stderr, "Package %s is already installed.\n", SerializePackage(p)); exit(EXIT_FAILURE); } } Seq *installed_packages = ReadPackageEntries(INSTALLED_PACKAGES_FILE_NAME); for (size_t i = 0; i < SeqLength(matching_available); i++) { Package *p = SeqAt(matching_available, i); SeqAppend(installed_packages, p); fprintf(stderr, "Successfully installed package %s\n", SerializePackage(p)); } SavePackages(INSTALLED_PACKAGES_FILE_NAME, installed_packages); exit(EXIT_SUCCESS); }
static void SeqMailFilterFill(const Seq *input, Seq **output, Seq **output_regex, const char *filter_type) { int len = SeqLength(input); *output = SeqNew(len, &free); *output_regex = SeqNew(len, &RegexFree); for (int i = 0; i < len; i++) { MailFilterFill(SeqAt(input, i), output, output_regex, filter_type); } }
static void ResolveVariablesPromises(EvalContext *ctx, PromiseType *pt) { assert(strcmp("vars", pt->name) == 0); for (size_t i = 0; i < SeqLength(pt->promises); i++) { Promise *pp = SeqAt(pt->promises, i); EvalContextStackPushPromiseFrame(ctx, pp, false); EvalContextStackPushPromiseIterationFrame(ctx, 0, NULL); VerifyVarPromise(ctx, pp, false); EvalContextStackPopFrame(ctx); EvalContextStackPopFrame(ctx); } }