static void ParsePackageVersion(char *version, Rlist **num, Rlist **sep) { char *sp, numeral[30], separator[2]; if (version == NULL) { return; } for (sp = version; *sp != '\0'; sp++) { memset(numeral, 0, 30); memset(separator, 0, 2); /* Split in 2's complement */ sscanf(sp, "%29[0-9a-zA-Z]", numeral); sp += strlen(numeral); /* Append to end up with left->right (major->minor) comparison */ RlistAppendScalar(num, numeral); if (*sp == '\0') { return; } sscanf(sp, "%1[^0-9a-zA-Z]", separator); RlistAppendScalar(sep, separator); } }
static void test_expand_list_nested(void **state) { EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.i"); EvalContextVariablePut(ctx, lval, "one", CF_DATA_TYPE_STRING, NULL); VarRefDestroy(lval); } { VarRef *lval = VarRefParse("default:bundle.inner[one]"); Rlist *list = NULL; RlistAppendScalar(&list, "foo"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); RlistDestroy(list); VarRefDestroy(lval); } Rlist *outer = NULL; RlistAppendScalar(&outer, "@{inner[$(i)]}"); Rlist *expanded = ExpandList(ctx, "default", "bundle", outer, true); assert_int_equal(1, RlistLen(expanded)); assert_string_equal("foo", RlistScalarValue(expanded)); RlistDestroy(outer); RlistDestroy(expanded); }
static void RlistAppendContainerPrimitive(Rlist **list, const JsonElement *primitive) { assert(JsonGetElementType(primitive) == JSON_ELEMENT_TYPE_PRIMITIVE); switch (JsonGetPrimitiveType(primitive)) { case JSON_PRIMITIVE_TYPE_BOOL: RlistAppendScalar(list, JsonPrimitiveGetAsBool(primitive) ? "true" : "false"); break; case JSON_PRIMITIVE_TYPE_INTEGER: { char *str = StringFromLong(JsonPrimitiveGetAsInteger(primitive)); RlistAppendScalar(list, str); free(str); } break; case JSON_PRIMITIVE_TYPE_REAL: { char *str = StringFromDouble(JsonPrimitiveGetAsReal(primitive)); RlistAppendScalar(list, str); free(str); } break; case JSON_PRIMITIVE_TYPE_STRING: RlistAppendScalar(list, JsonPrimitiveGetAsString(primitive)); break; case JSON_PRIMITIVE_TYPE_NULL: break; } }
static void test_expand_promise_slist(void **state) { actuator_state = 0; EvalContext *ctx = *state; { VarRef *lval = VarRefParse("default:bundle.foo"); Rlist *list = NULL; RlistAppendScalar(&list, "a"); RlistAppendScalar(&list, "b"); EvalContextVariablePut(ctx, lval, list, CF_DATA_TYPE_STRING_LIST, NULL); RlistDestroy(list); VarRefDestroy(lval); } Policy *policy = PolicyNew(); Bundle *bundle = PolicyAppendBundle(policy, NamespaceDefault(), "bundle", "agent", NULL, NULL); PromiseType *promise_type = BundleAppendPromiseType(bundle, "dummy"); Promise *promise = PromiseTypeAppendPromise(promise_type, "$(foo)", (Rval) { NULL, RVAL_TYPE_NOPROMISEE }, "any", NULL); EvalContextStackPushBundleFrame(ctx, bundle, NULL, false); EvalContextStackPushPromiseTypeFrame(ctx, promise_type); ExpandPromise(ctx, promise, actuator_expand_promise_slist, NULL); EvalContextStackPopFrame(ctx); EvalContextStackPopFrame(ctx); assert_int_equal(2, actuator_state); PolicyDestroy(policy); }
Rlist *RlistFromSplitRegex(const char *string, const char *regex, size_t max_entries, bool allow_blanks) { assert(string); if (!string) { return NULL; } const char *sp = string; size_t entry_count = 0; int start = 0; int end = 0; Rlist *result = NULL; Buffer *buffer = BufferNewWithCapacity(CF_MAXVARSIZE); pcre *rx = CompileRegex(regex); if (rx) { while ((entry_count < max_entries) && StringMatchWithPrecompiledRegex(rx, sp, &start, &end)) { if (end == 0) { break; } BufferClear(buffer); BufferAppend(buffer, sp, start); if (allow_blanks || BufferSize(buffer) > 0) { RlistAppendScalar(&result, BufferData(buffer)); entry_count++; } sp += end; } pcre_free(rx); } if (entry_count < max_entries) { BufferClear(buffer); size_t remaining = strlen(sp); BufferAppend(buffer, sp, remaining); if ((allow_blanks && sp != string) || BufferSize(buffer) > 0) { RlistAppendScalar(&result, BufferData(buffer)); } } BufferDestroy(buffer); return result; }
static void test_last(void) { Rlist *l = NULL; assert_true(RlistLast(l) == NULL); RlistAppendScalar(&l, "a"); assert_string_equal("a", RlistScalarValue(RlistLast(l))); RlistAppendScalar(&l, "b"); assert_string_equal("b", RlistScalarValue(RlistLast(l))); RlistDestroy(l); }
Rlist *RlistFromSplitRegex(const char *string, const char *regex, int max, int blanks) /* Splits a string containing a separator like "," into a linked list of separate items, */ // NOTE: this has a bad side-effect of creating scope match and variables, // see RegExMatchSubString in matching.c - could leak memory { Rlist *liststart = NULL; char node[CF_MAXVARSIZE]; int start, end; int count = 0; if (string == NULL) { return NULL; } CfDebug("\n\nSplit \"%s\" with regex \"%s\" (up to maxent %d)\n\n", string, regex, max); const char *sp = string; while ((count < max) && BlockTextMatch(regex, sp, &start, &end)) { if (end == 0) { break; } memset(node, 0, CF_MAXVARSIZE); strncpy(node, sp, start); if (blanks || strlen(node) > 0) { RlistAppendScalar(&liststart, node); count++; } sp += end; } if (count < max) { memset(node, 0, CF_MAXVARSIZE); strncpy(node, sp, CF_MAXVARSIZE - 1); if ((blanks && sp != string) || strlen(node) > 0) { RlistAppendScalar(&liststart, node); } } return liststart; }
void test_sort_rlist(void) { Rlist *list = NULL; RlistAppendScalar(&list, "bbb"); RlistAppendScalar(&list, "cc"); RlistAppendScalar(&list, "a"); Rlist *sorted = SortRlist(list, &FirstItemShorter); assert_string_equal(RlistScalarValue(sorted), "a"); assert_string_equal(RlistScalarValue(sorted->next), "cc"); assert_string_equal(RlistScalarValue(sorted->next->next), "bbb"); assert_int_equal(sorted->next->next->next, NULL); RlistDestroy(sorted); }
void test_alpha_sort_rlist_names(void) { Rlist *list = NULL; RlistAppendScalar(&list, "c"); RlistAppendScalar(&list, "a"); RlistAppendScalar(&list, "b"); Rlist *sorted = AlphaSortRListNames(list); assert_string_equal(RlistScalarValue(sorted), "a"); assert_string_equal(RlistScalarValue(sorted->next), "b"); assert_string_equal(RlistScalarValue(sorted->next->next), "c"); assert_int_equal(sorted->next->next->next, NULL); RlistDestroy(sorted); }
Rlist *RlistAppend(Rlist **start, const void *item, RvalType type) { Rlist *rp, *lp = *start; switch (type) { case RVAL_TYPE_SCALAR: return RlistAppendScalar(start, item); case RVAL_TYPE_FNCALL: break; case RVAL_TYPE_LIST: for (rp = (Rlist *) item; rp != NULL; rp = rp->next) { lp = RlistAppend(start, rp->item, rp->type); } return lp; default: Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item); return NULL; } rp = xmalloc(sizeof(Rlist)); if (*start == NULL) { *start = rp; } else { for (lp = *start; lp->next != NULL; lp = lp->next) { } lp->next = rp; } rp->item = RvalCopy((Rval) {(void *) item, type}).item; rp->type = type; /* scalar, builtin function */ ThreadLock(cft_lock); if (type == RVAL_TYPE_LIST) { rp->state_ptr = rp->item; } else { rp->state_ptr = NULL; } rp->next = NULL; ThreadUnlock(cft_lock); return rp; }
Rlist *RlistFromSplitString(const char *string, char sep) /* Splits a string containing a separator like "," into a linked list of separate items, supports escaping separators, e.g. \, */ { if (string == NULL) { return NULL; } Rlist *liststart = NULL; char node[CF_MAXVARSIZE]; int maxlen = strlen(string); CfDebug("SplitStringAsRList(%s)\n", string); for (const char *sp = string; *sp != '\0'; sp++) { if (*sp == '\0' || sp > string + maxlen) { break; } memset(node, 0, CF_MAXVARSIZE); sp += SubStrnCopyChr(node, sp, CF_MAXVARSIZE, sep); RlistAppendScalar(&liststart, node); } return liststart; }
Rlist *RlistAppendScalarIdemp(Rlist **start, const char *scalar) { if (RlistKeyIn(*start, scalar)) { return NULL; } return RlistAppendScalar(start, scalar); }
static bool VerifyBundleSequence(EvalContext *ctx, const Policy *policy, const GenericAgentConfig *config) { Rlist *fallback = NULL; const Rlist *bundlesequence = EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE); if (!bundlesequence) { RlistAppendScalar(&fallback, "main"); bundlesequence = fallback; } const char *name; int ok = true; for (const Rlist *rp = bundlesequence; rp != NULL; rp = rp->next) { switch (rp->val.type) { case RVAL_TYPE_SCALAR: name = RlistScalarValue(rp); break; case RVAL_TYPE_FNCALL: name = RlistFnCallValue(rp)->name; break; default: name = NULL; ok = false; { Writer *w = StringWriter(); WriterWrite(w, "Illegal item found in bundlesequence '"); RvalWrite(w, rp->val); WriterWrite(w, "'"); Log(LOG_LEVEL_ERR, "%s", StringWriterData(w)); WriterClose(w); } continue; } if (strcmp(name, CF_NULL_VALUE) == 0) { continue; } if (!config->ignore_missing_bundles && !PolicyGetBundle(policy, NULL, NULL, name)) { Log(LOG_LEVEL_ERR, "Bundle '%s' listed in the bundlesequence is not a defined bundle", name); ok = false; } } RlistDestroy(fallback); return ok; }
/* * Splits string on regex, returns a list of (at most max) fragments. * * NOTE: in contrast with RlistFromSplitRegex() this one will produce at most max number of elements; * last element will contain everything that lefts from original string (we use everything after * the (max-1)-th separator as the final list element, including any separators that may be embedded in it) */ Rlist *RlistFromRegexSplitNoOverflow(const char *string, const char *regex, int max) { Rlist *liststart = NULL; char node[CF_MAXVARSIZE]; int start, end; int count = 0; assert(max > 0); // ensured by FnCallStringSplit() before calling us assert(string != NULL); // ensured by FnCallStringSplit() before calling us const char *sp = string; // We will avoid compiling regex multiple times. pcre *pattern = CompileRegex(regex); if (pattern == NULL) { Log(LOG_LEVEL_DEBUG, "Error compiling regex from '%s'", regex); return NULL; } while (count < max - 1 && StringMatchWithPrecompiledRegex(pattern, sp, &start, &end)) { assert(start < CF_MAXVARSIZE); memcpy(node, sp, start); node[start] = '\0'; RlistAppendScalar(&liststart, node); count++; sp += end; } assert(count < max); RlistAppendScalar(&liststart, sp); pcre_free(pattern); return liststart; }
Rlist *RlistAppend(Rlist **start, const void *item, RvalType type) { Rlist *lp = *start; switch (type) { case RVAL_TYPE_SCALAR: return RlistAppendScalar(start, item); case RVAL_TYPE_FNCALL: break; case RVAL_TYPE_LIST: for (const Rlist *rp = item; rp; rp = rp->next) { lp = RlistAppendRval(start, RvalCopy(rp->val)); } return lp; default: Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item); return NULL; } Rlist *rp = xmalloc(sizeof(Rlist)); if (*start == NULL) { *start = rp; } else { for (lp = *start; lp->next != NULL; lp = lp->next) { } lp->next = rp; } rp->val = RvalCopy((Rval) {(void *) item, type}); ThreadLock(cft_lock); rp->next = NULL; ThreadUnlock(cft_lock); return rp; }
Rlist *RlistParseShown(const char *string) { Rlist *newlist = NULL, *splitlist, *rp; /* Parse a string representation generated by ShowList and turn back into Rlist */ splitlist = RlistFromSplitString(string, ','); for (rp = splitlist; rp != NULL; rp = rp->next) { char value[CF_MAXVARSIZE] = { 0 }; sscanf(RlistScalarValue(rp), "%*[{ '\"]%255[^'\"}]", value); RlistAppendScalar(&newlist, value); } RlistDestroy(splitlist); return newlist; }
static Policy *LoadPolicyFile(EvalContext *ctx, GenericAgentConfig *config, const char *policy_file, StringSet *parsed_files_and_checksums, StringSet *failed_files) { unsigned char digest[EVP_MAX_MD_SIZE + 1] = { 0 }; char hashbuffer[CF_HOSTKEY_STRING_SIZE] = { 0 }; char hashprintbuffer[CF_BUFSIZE] = { 0 }; HashFile(policy_file, digest, CF_DEFAULT_DIGEST); snprintf(hashprintbuffer, CF_BUFSIZE - 1, "{checksum}%s", HashPrintSafe(hashbuffer, sizeof(hashbuffer), digest, CF_DEFAULT_DIGEST, true)); Log(LOG_LEVEL_DEBUG, "Hashed policy file %s to %s", policy_file, hashprintbuffer); if (StringSetContains(parsed_files_and_checksums, policy_file)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate policy file %s", policy_file); return NULL; } else if (StringSetContains(parsed_files_and_checksums, hashprintbuffer)) { Log(LOG_LEVEL_VERBOSE, "Skipping loading of duplicate (detected by hash) policy file %s", policy_file); return NULL; } else { Log(LOG_LEVEL_DEBUG, "Loading policy file %s", policy_file); } Policy *policy = Cf3ParseFile(config, policy_file); // we keep the checksum and the policy file name to help debugging StringSetAdd(parsed_files_and_checksums, xstrdup(policy_file)); StringSetAdd(parsed_files_and_checksums, xstrdup(hashprintbuffer)); if (policy) { Seq *errors = SeqNew(10, free); if (!PolicyCheckPartial(policy, errors)) { Writer *writer = FileWriter(stderr); for (size_t i = 0; i < errors->length; i++) { PolicyErrorWrite(writer, errors->data[i]); } WriterClose(writer); SeqDestroy(errors); StringSetAdd(failed_files, xstrdup(policy_file)); PolicyDestroy(policy); return NULL; } SeqDestroy(errors); } else { StringSetAdd(failed_files, xstrdup(policy_file)); return NULL; } PolicyResolve(ctx, policy, config); DataType def_inputs_type = CF_DATA_TYPE_NONE; VarRef *inputs_ref = VarRefParse("def.augment_inputs"); const void *def_inputs = EvalContextVariableGet(ctx, inputs_ref, &def_inputs_type); VarRefDestroy(inputs_ref); if (RVAL_TYPE_CONTAINER == DataTypeToRvalType(def_inputs_type) && NULL != def_inputs) { const JsonElement *el; JsonIterator iter = JsonIteratorInit((JsonElement*) def_inputs); while ((el = JsonIteratorNextValueByType(&iter, JSON_ELEMENT_TYPE_PRIMITIVE, true))) { char *input = JsonPrimitiveToString(el); Log(LOG_LEVEL_VERBOSE, "Loading augments from def.augment_inputs: %s", input); Rlist* inputs_rlist = NULL; RlistAppendScalar(&inputs_rlist, input); Policy *aux_policy = LoadPolicyInputFiles(ctx, config, inputs_rlist, parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } RlistDestroy(inputs_rlist); free(input); } } Body *body_common_control = PolicyGetBody(policy, NULL, "common", "control"); Body *body_file_control = PolicyGetBody(policy, NULL, "file", "control"); if (body_common_control) { Seq *potential_inputs = BodyGetConstraint(body_common_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } if (body_file_control) { Seq *potential_inputs = BodyGetConstraint(body_file_control, "inputs"); Constraint *cp = EffectiveConstraint(ctx, potential_inputs); SeqDestroy(potential_inputs); if (cp) { Policy *aux_policy = LoadPolicyInputFiles(ctx, config, RvalRlistValue(cp->rval), parsed_files_and_checksums, failed_files); if (aux_policy) { policy = PolicyMerge(policy, aux_policy); } } } return policy; }
static Rlist *RlistParseStringBounded(char *left, char *right, int *n) { Rlist *newlist = NULL; char str2[CF_MAXVARSIZE]; char *s = left; char *s2 = str2; bool precede = false; //set if we just encountred escaping character bool ignore = true; //set if we're outside quotation marks bool skipped = true; //set if a separating comma is behind us char *extract = NULL; if (n!=NULL) { *n = 0; } memset(str2, 0, CF_MAXVARSIZE); while (*s && s < right) { if (*s != '\\') { if (precede) { if (*s != '\\' && *s != '"') { Log(LOG_LEVEL_ERR, "Presence of illegal %c after escaping character", *s); goto clean; } else { *s2++ = *s; } precede = false; } else { if (*s == '"') { if (ignore) { if (skipped != true) { Log(LOG_LEVEL_ERR, "Quotation marks \" should follow commas"); goto clean; } ignore = false; extract = s2; } else { *s2='\0'; Log(LOG_LEVEL_VERBOSE, "Extracted string [%s] of length (%d)", extract, (size_t) (s2 - extract)); RlistAppendScalar(&newlist, extract); ignore = true; extract = NULL; if (n != NULL) { *n += 1; } } skipped = false; } else if (*s == ',') { if (ignore) { if (skipped == false) { skipped = true; } else { Log(LOG_LEVEL_ERR, "Only one comma should separate different list elements"); goto clean; } } else { *s2++ = *s; } } else { if (ignore == true && *s != ' ') { Log(LOG_LEVEL_ERR, "Only white characters are permitted outside of list elements. Character %c is illegal.", *s); goto clean; } *s2++ = *s; } } } else { if (precede) { *s2++ = '\\'; precede = false; } else { precede = true; } } s++; } if (ignore) { return newlist; } else { goto clean; } clean: if (newlist) { RlistDestroy(newlist); } return NULL; }
Rlist *RlistAppend(Rlist **start, const void *item, RvalType type) /* Allocates new memory for objects - careful, could leak! */ { Rlist *rp, *lp = *start; FnCall *fp; switch (type) { case RVAL_TYPE_SCALAR: return RlistAppendScalar(start, item); case RVAL_TYPE_FNCALL: CfDebug("Appending function to rval-list function call: "); fp = (FnCall *) item; if (DEBUG) { FnCallShow(stdout, fp); } CfDebug("\n"); break; case RVAL_TYPE_LIST: CfDebug("Expanding and appending list object\n"); for (rp = (Rlist *) item; rp != NULL; rp = rp->next) { lp = RlistAppend(start, rp->item, rp->type); } return lp; default: CfDebug("Cannot append %c to rval-list [%s]\n", type, (char *) item); return NULL; } rp = xmalloc(sizeof(Rlist)); if (*start == NULL) { *start = rp; } else { for (lp = *start; lp->next != NULL; lp = lp->next) { } lp->next = rp; } rp->item = RvalCopy((Rval) {(void *) item, type}).item; rp->type = type; /* scalar, builtin function */ ThreadLock(cft_lock); if (type == RVAL_TYPE_LIST) { rp->state_ptr = rp->item; } else { rp->state_ptr = NULL; } rp->next = NULL; ThreadUnlock(cft_lock); return rp; }
// See fncall.c for the usage of allow_all_types. Rlist *RlistAppendAllTypes(Rlist **start, const void *item, RvalType type, bool allow_all_types) { Rlist *lp = *start; switch (type) { case RVAL_TYPE_SCALAR: return RlistAppendScalar(start, item); case RVAL_TYPE_FNCALL: break; case RVAL_TYPE_LIST: if (allow_all_types) { JsonElement* store = JsonArrayCreate(RlistLen(item)); for (const Rlist *rp = item; rp; rp = rp->next) { JsonArrayAppendElement(store, RvalToJson(rp->val)); } return RlistAppendRval(start, (Rval) { store, RVAL_TYPE_CONTAINER }); } for (const Rlist *rp = item; rp; rp = rp->next) { lp = RlistAppendRval(start, RvalCopy(rp->val)); } return lp; case RVAL_TYPE_CONTAINER: if (allow_all_types) { return RlistAppendRval(start, (Rval) { JsonCopy((JsonElement*) item), RVAL_TYPE_CONTAINER }); } // note falls through! default: Log(LOG_LEVEL_DEBUG, "Cannot append %c to rval-list '%s'", type, (char *) item); return NULL; } Rlist *rp = xmalloc(sizeof(Rlist)); rp->val = RvalNew(item, type); rp->next = NULL; if (*start == NULL) { *start = rp; } else { for (lp = *start; lp->next != NULL; lp = lp->next) { } lp->next = rp; } return rp; }
static void DoVerifyServices(EvalContext *ctx, Attributes a, Promise *pp, const ReportContext *report_context) { FnCall *default_bundle = NULL; Rlist *args = NULL; // Need to set up the default service pack to eliminate syntax if (ConstraintGetRvalValue(ctx, "service_bundle", pp, RVAL_TYPE_SCALAR) == NULL) { switch (a.service.service_policy) { case SERVICE_POLICY_START: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "start"); break; case SERVICE_POLICY_RESTART: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "restart"); break; case SERVICE_POLICY_RELOAD: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "restart"); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "stop"); break; } default_bundle = FnCallNew("default:standard_services", args); PromiseAppendConstraint(pp, "service_bundle", (Rval) {default_bundle, RVAL_TYPE_FNCALL }, "any", false); a.havebundle = true; } // Set $(this.service_policy) for flexible bundle adaptation switch (a.service.service_policy) { case SERVICE_POLICY_START: ScopeNewScalar("this", "service_policy", "start", DATA_TYPE_STRING); break; case SERVICE_POLICY_RESTART: ScopeNewScalar("this", "service_policy", "restart", DATA_TYPE_STRING); break; case SERVICE_POLICY_RELOAD: ScopeNewScalar("this", "service_policy", "reload", DATA_TYPE_STRING); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: ScopeNewScalar("this", "service_policy", "stop", DATA_TYPE_STRING); break; } const Bundle *bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", default_bundle->name); if (!bp) { bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", default_bundle->name); } if (default_bundle && bp == NULL) { cfPS(ctx, OUTPUT_LEVEL_INFORM, CF_FAIL, "", pp, a, " !! Service %s could not be invoked successfully\n", pp->promiser); } if (!DONTDO) { VerifyMethod(ctx, "service_bundle", a, pp, report_context); // Send list of classes to set privately? } }
static PromiseResult DoVerifyServices(EvalContext *ctx, Attributes a, Promise *pp) { FnCall *default_bundle = NULL; Rlist *args = NULL; // Need to set up the default service pack to eliminate syntax if (ConstraintGetRvalValue(ctx, "service_bundle", pp, RVAL_TYPE_SCALAR) == NULL) { switch (a.service.service_policy) { case SERVICE_POLICY_START: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "start"); break; case SERVICE_POLICY_RESTART: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "restart"); break; case SERVICE_POLICY_RELOAD: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "reload"); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: RlistAppendScalar(&args, pp->promiser); RlistAppendScalar(&args, "stop"); break; } default_bundle = FnCallNew("standard_services", args); PromiseAppendConstraint(pp, "service_bundle", (Rval) {default_bundle, RVAL_TYPE_FNCALL }, "any", false); a.havebundle = true; } // Set $(this.service_policy) for flexible bundle adaptation switch (a.service.service_policy) { case SERVICE_POLICY_START: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "start", DATA_TYPE_STRING, "goal=state,source=promise"); break; case SERVICE_POLICY_RESTART: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "restart", DATA_TYPE_STRING, "goal=state,source=promise"); break; case SERVICE_POLICY_RELOAD: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "reload", DATA_TYPE_STRING, "goal=state,source=promise"); break; case SERVICE_POLICY_STOP: case SERVICE_POLICY_DISABLE: default: EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "service_policy", "stop", DATA_TYPE_STRING, "goal=state,source=promise"); break; } const Bundle *bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "agent", default_bundle->name); if (!bp) { bp = PolicyGetBundle(PolicyFromPromise(pp), NULL, "common", default_bundle->name); } PromiseResult result = PROMISE_RESULT_NOOP; if (default_bundle && bp == NULL) { cfPS(ctx, LOG_LEVEL_INFO, PROMISE_RESULT_FAIL, pp, a, "Service '%s' could not be invoked successfully", pp->promiser); result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL); } if (!DONTDO) { result = PromiseResultUpdate(result, VerifyMethod(ctx, "service_bundle", a, pp)); // Send list of classes to set privately? } return result; }
/** @brief parse elements in a list passed through use_module @param[in] str: is the string to parse @param[out] newlist: rlist of elements found @retval 0: successful > 0: failed */ static int LaunchParsingMachine(const char *str, Rlist **newlist) { const char *s = str; state current_state = ST_OPENED; int ret; Buffer *buf = BufferNewWithCapacity(CF_MAXVARSIZE); assert(newlist); while (current_state != ST_CLOSED && *s) { switch(current_state) { case ST_ERROR: Log(LOG_LEVEL_ERR, "Parsing error : Malformed string"); ret = 1; goto clean; case ST_OPENED: if (CLASS_BLANK(*s)) { current_state = ST_OPENED; } else if (CLASS_BRA1(*s)) { current_state = ST_IO; } else if (CLASS_ANY0(*s)) { current_state = ST_ERROR; } s++; break; case ST_IO: if (CLASS_BLANK(*s)) { current_state = ST_IO; } else if (CLASS_START1(*s)) { BufferClear(buf); current_state = ST_ELM1; } else if (CLASS_START2(*s)) { BufferClear(buf); current_state = ST_ELM2; } else if (CLASS_ANY1(*s)) { current_state = ST_ERROR; } s++; break; case ST_ELM1: if (CLASS_END1(*s)) { RlistAppendScalar(newlist, BufferData(buf)); BufferClear(buf); current_state = ST_END1; } else if (CLASS_ANY2(*s)) { BufferAppendChar(buf, *s); current_state = ST_ELM1; } s++; break; case ST_ELM2: if (CLASS_END2(*s)) { RlistAppendScalar(newlist, BufferData(buf)); BufferClear(buf); current_state = ST_END2; } else if (CLASS_ANY3(*s)) { BufferAppendChar(buf, *s); current_state = ST_ELM2; } s++; break; case ST_END1: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END1; } else if (CLASS_ANY4(*s)) { current_state = ST_ERROR; } s++; break; case ST_END2: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END2; } else if (CLASS_ANY5(*s)) { current_state = ST_ERROR; } s++; break; case ST_SEP: if (CLASS_BLANK(*s)) { current_state = ST_SEP; } else if (CLASS_START1(*s)) { current_state = ST_ELM1; } else if (CLASS_START2(*s)) { current_state = ST_ELM2; } else if (CLASS_ANY6(*s)) { current_state = ST_ERROR; } s++; break; case ST_PRECLOSED: if (CLASS_BLANK(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_EOL(*s)) { current_state = ST_CLOSED; } else if (CLASS_ANY7(*s)) { current_state = ST_ERROR; } s++; break; default: Log(LOG_LEVEL_ERR, "Parsing logic error: unknown state"); ret = 2; goto clean; break; } } if (current_state != ST_CLOSED && current_state != ST_PRECLOSED ) { Log(LOG_LEVEL_ERR, "Parsing error : Malformed string (unexpected end of input)"); ret = 3; goto clean; } BufferDestroy(buf); return 0; clean: BufferDestroy(buf); RlistDestroy(*newlist); assert(ret != 0); return ret; }
/** @brief parse elements in a list passed through use_module @param[in] str: is the string to parse @param[out] newlist: rlist of elements found @retval 0: successful >0: failed */ static int LaunchParsingMachine(const char *str, Rlist **newlist) { const char *s = str; state current_state = ST_OPENED; int ret; char snatched[CF_MAXVARSIZE]; snatched[0]='\0'; char *sn = NULL; while (current_state != ST_CLOSED && *s) { switch(current_state) { case ST_ERROR: Log(LOG_LEVEL_ERR, "Parsing error : Malformed string"); ret = 1; goto clean; case ST_OPENED: if (CLASS_BLANK(*s)) { current_state = ST_OPENED; } else if (CLASS_BRA1(*s)) { current_state = ST_IO; } else if (CLASS_ANY0(*s)) { current_state = ST_ERROR; } s++; break; case ST_IO: if (CLASS_BLANK(*s)) { current_state = ST_IO; } else if (CLASS_START1(*s)) { sn=snatched; current_state = ST_ELM1; } else if (CLASS_START2(*s)) { sn=snatched; current_state = ST_ELM2; } else if (CLASS_ANY1(*s)) { current_state = ST_ERROR; } s++; break; case ST_ELM1: if (CLASS_END1(*s)) { if (sn==NULL) { sn=snatched; } *sn='\0'; RlistAppendScalar(newlist, snatched); sn=NULL; current_state = ST_END1; } else if (CLASS_ANY2(*s)) { if (sn==NULL) { sn=snatched; } *sn=*s; sn++; current_state = ST_ELM1; } s++; break; case ST_ELM2: if (CLASS_END2(*s)) { if (sn==NULL) { sn=snatched; } *sn='\0'; RlistAppendScalar(newlist, snatched); sn=NULL; current_state = ST_END2; } else if (CLASS_ANY3(*s)) { if (sn==NULL) { sn=snatched; } *sn=*s; sn++; current_state = ST_ELM2; } s++; break; case ST_END1: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END1; } else if (CLASS_ANY4(*s)) { current_state = ST_ERROR; } s++; break; case ST_END2: if (CLASS_SEP(*s)) { current_state = ST_SEP; } else if (CLASS_BRA2(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_BLANK(*s)) { current_state = ST_END2; } else if (CLASS_ANY5(*s)) { current_state = ST_ERROR; } s++; break; case ST_SEP: if (CLASS_BLANK(*s)) { current_state = ST_SEP; } else if (CLASS_START1(*s)) { current_state = ST_ELM1; } else if (CLASS_START2(*s)) { current_state = ST_ELM2; } else if (CLASS_ANY6(*s)) { current_state = ST_ERROR; } s++; break; case ST_PRECLOSED: if (CLASS_BLANK(*s)) { current_state = ST_PRECLOSED; } else if (CLASS_EOL(*s)) { current_state = ST_CLOSED; } else if (CLASS_ANY7(*s)) { current_state = ST_ERROR; } s++; break; default: Log(LOG_LEVEL_ERR, "Parsing logic error: unknown state"); ret = 2; goto clean; break; } } if (current_state != ST_CLOSED && current_state != ST_PRECLOSED ) { Log(LOG_LEVEL_ERR, "Parsing error : Malformed string (unexpected end of input)"); ret = 3; goto clean; } return 0; clean: if (newlist) { RlistDestroy(*newlist); } return ret; }