Esempio n. 1
0
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);
}
Esempio n. 2
0
void test_file_read_truncate(void)
{
    char expected_output[FILE_SIZE + 1];

    bool truncated = false;
    Writer *w = FileRead(FILE_NAME, FILE_SIZE - 1, &truncated);
    assert_int_equal(StringWriterLength(w), FILE_SIZE - 1);
    strlcpy(expected_output, FILE_CONTENTS, FILE_SIZE);
    assert_string_equal(StringWriterData(w), expected_output);
    assert_int_equal(truncated, true);
    WriterClose(w);

    bool truncated2 = false;
    Writer *w2 = FileRead(FILE_NAME, 10, &truncated2);
    assert_int_equal(StringWriterLength(w2), 10);
    strlcpy(expected_output, FILE_CONTENTS, 11);
    assert_string_equal(StringWriterData(w2), expected_output);
    assert_int_equal(truncated2, true);
    WriterClose(w2);

    bool truncated3 = false;
    Writer *w3 = FileRead(FILE_NAME, 1, &truncated3);
    assert_int_equal(StringWriterLength(w3), 1);
    strlcpy(expected_output, FILE_CONTENTS, 2);
    assert_string_equal(StringWriterData(w3), expected_output);
    assert_int_equal(truncated3, true);
    WriterClose(w3);
}
Esempio n. 3
0
File: vars.c Progetto: amousset/core
static const char *ReferenceEnd(const char *str, size_t len)
{
    assert(len > 1);
    assert(str[0] == '$');
    assert(str[1] == '{' || str[1] == '(');

#define MAX_VARIABLE_REFERENCE_LEVELS 10
    char stack[MAX_VARIABLE_REFERENCE_LEVELS] = { 0, str[1], 0 };
    int level = 1;

    for (size_t i = 2; i < len; i++)
    {
        switch (str[i])
        {
        case '{':
        case '(':
            if (level < MAX_VARIABLE_REFERENCE_LEVELS - 1)
            {
                level++;
                stack[level] = str[i];
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Stack overflow in variable reference parsing. More than %d levels", MAX_VARIABLE_REFERENCE_LEVELS);
                return NULL;
            }
            break;

        case '}':
            if (stack[level] != '{')
            {
                Writer *w = StringWriter();
                WriterWriteLen(w, str, len);
                Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w));
                WriterClose(w);
                return NULL;
            }
            level--;
            break;
        case ')':
            if (stack[level] != '(')
            {
                Writer *w = StringWriter();
                WriterWriteLen(w, str, len);
                Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w));
                WriterClose(w);
                return NULL;
            }
            level--;
            break;
        }

        if (level == 0)
        {
            return str + i;
        }
    }

    return NULL;
}
Esempio n. 4
0
File: vars.c Progetto: amousset/core
bool ExtractScalarReference(Buffer *out, const char *str, size_t len, bool extract_inner)
{
    if (len <= 1)
    {
        return false;
    }

    const char *dollar_point = memchr(str, '$', len);
    if (!dollar_point || (dollar_point - str) == len)
    {
        return false;
    }
    else
    {
        const char *close_point = NULL;
        {
            size_t remaining = len - (dollar_point - str);
            if (*(dollar_point + 1) == '{' || *(dollar_point + 1) == '(')
            {
                close_point = ReferenceEnd(dollar_point, remaining);
            }
            else
            {
                return ExtractScalarReference(out, dollar_point + 1, remaining - 1, extract_inner);
            }
        }

        if (!close_point)
        {
            Writer *w = StringWriter();
            WriterWriteLen(w, str, len);
            Log(LOG_LEVEL_ERR, "Variable reference close mismatch '%s'", StringWriterData(w));
            WriterClose(w);
            return false;
        }

        size_t outer_len = close_point - dollar_point + 1;
        if (outer_len <= 3)
        {
            Writer *w = StringWriter();
            WriterWriteLen(w, str, len);
            Log(LOG_LEVEL_ERR, "Empty variable reference close mismatch '%s'", StringWriterData(w));
            WriterClose(w);
            return false;
        }

        if (extract_inner)
        {
            BufferAppend(out, dollar_point + 2, outer_len - 3);
        }
        else
        {
            BufferAppend(out, dollar_point, outer_len);
        }
        return true;
    }
}
Esempio n. 5
0
static bool VerifyBundleSequence(EvalContext *ctx, const Policy *policy, const GenericAgentConfig *config)
{
    Rlist *rp;
    char *name;
    Rval retval;
    int ok = true;
    FnCall *fp;

    if (!EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_BUNDLESEQUENCE, &retval))
    {
        Log(LOG_LEVEL_ERR, " No bundlesequence in the common control body");
        return false;
    }

    if (retval.type != RVAL_TYPE_LIST)
    {
        FatalError(ctx, "Promised bundlesequence was not a list");
    }

    for (rp = (Rlist *) retval.item; rp != NULL; rp = rp->next)
    {
        switch (rp->type)
        {
        case RVAL_TYPE_SCALAR:
            name = (char *) rp->item;
            break;

        case RVAL_TYPE_FNCALL:
            fp = (FnCall *) rp->item;
            name = (char *) fp->name;
            break;

        default:
            name = NULL;
            ok = false;
            {
                Writer *w = StringWriter();
                WriterWrite(w, "Illegal item found in bundlesequence '");
                RvalWrite(w, (Rval) {rp->item, rp->type});
                WriterWrite(w, "'");
                Log(LOG_LEVEL_ERR, "%s", StringWriterData(w));
                WriterClose(w);
            }
            break;
        }

        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;
        }
    }

    return ok;
}
Esempio n. 6
0
static void test_show_object_compound(void **state)
{
    JsonElement *json = JsonObjectCreate(10);

    JsonObjectAppendString(json, "first", "one");
    {
        JsonElement *inner = JsonObjectCreate(10);

        JsonObjectAppendString(inner, "third", "three");

        JsonObjectAppendObject(json, "second", inner);
    }
    {
        JsonElement *inner = JsonObjectCreate(10);

        JsonObjectAppendString(inner, "fifth", "five");

        JsonObjectAppendObject(json, "fourth", inner);
    }

    Writer *writer = StringWriter();

    JsonElementPrint(writer, json, 0);

    assert_string_equal(OBJECT_COMPOUND, StringWriterData(writer));

    JsonElementDestroy(json);
}
Esempio n. 7
0
static void LogPromiseContext(const EvalContext *ctx, const Promise *pp)
{
    Rval retval;
    char *v;
    if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_VERSION, &retval))
    {
        v = (char *) retval.item;
    }
    else
    {
        v = "not specified";
    }

    const char *sp = PromiseGetHandle(pp);
    if (sp == NULL)
    {
        sp = PromiseID(pp);
    }
    if (sp == NULL)
    {
        sp = "(unknown)";
    }

    Log(LOG_LEVEL_INFO, "Report relates to a promise with handle '%s'", sp);

    if (PromiseGetBundle(pp)->source_path)
    {
        Log(LOG_LEVEL_INFO, "Made in version '%s' of '%s' near line %zu",
            v, PromiseGetBundle(pp)->source_path, pp->offset.line);
    }
    else
    {
        Log(LOG_LEVEL_INFO, "Promise is made internally by CFEngine");
    }

    switch (pp->promisee.type)
    {
    case RVAL_TYPE_SCALAR:
        Log(LOG_LEVEL_INFO,"The promise was made to '%s'", (char *) pp->promisee.item);
        break;

    case RVAL_TYPE_LIST:
    {
        Writer *w = StringWriter();
        RlistWrite(w, pp->promisee.item);
        Log(LOG_LEVEL_INFO, "The promise was made to (stakeholders) '%s'", StringWriterData(w));
        WriterClose(w);
        break;
    }
    default:
        break;
    }

    if (pp->comment)
    {
        Log(LOG_LEVEL_INFO, "Comment '%s'", pp->comment);
    }
}
Esempio n. 8
0
static void Nova_DumpSlots(void)
{
#define MAX_KEY_FILE_SIZE 16384  /* usually around 4000, cannot grow much */

    char filename[CF_BUFSIZE];
    int i;

    snprintf(filename, CF_BUFSIZE - 1, "%s%cts_key", GetStateDir(), FILE_SEPARATOR);

    char file_contents_new[MAX_KEY_FILE_SIZE] = {0};

    for (i = 0; i < CF_OBSERVABLES; i++)
    {
        char line[CF_MAXVARSIZE];

        if (NovaHasSlot(i))
        {
            snprintf(line, sizeof(line), "%d,%s,%s,%s,%.3lf,%.3lf,%d\n",
                    i,
                    NULLStringToEmpty((char*)NovaGetSlotName(i)),
                    NULLStringToEmpty((char*)NovaGetSlotDescription(i)),
                    NULLStringToEmpty((char*)NovaGetSlotUnits(i)),
                    NovaGetSlotExpectedMinimum(i), NovaGetSlotExpectedMaximum(i), NovaIsSlotConsolidable(i) ? 1 : 0);
        }
        else
        {
            snprintf(line, sizeof(line), "%d,spare,unused\n", i);
        }

        strlcat(file_contents_new, line, sizeof(file_contents_new));
    }

    bool contents_changed = true;

    Writer *w = FileRead(filename, MAX_KEY_FILE_SIZE, NULL);
    if (w)
    {
        if(strcmp(StringWriterData(w), file_contents_new) == 0)
        {
            contents_changed = false;
        }
        WriterClose(w);
    }

    if(contents_changed)
    {
        Log(LOG_LEVEL_VERBOSE, "Updating %s with new slot information", filename);

        if(!FileWriteOver(filename, file_contents_new))
        {
            Log(LOG_LEVEL_ERR, "Nova_DumpSlots: Could not write file '%s'. (FileWriteOver: %s)", filename,
                GetErrorStr());
        }
    }

    chmod(filename, 0600);
}
Esempio n. 9
0
void test_file_read_all(void)
{
    bool truncated;
    Writer *w = FileRead(FILE_NAME, FILE_SIZE, &truncated);
    assert_int_equal(StringWriterLength(w), FILE_SIZE);
    assert_string_equal(StringWriterData(w), FILE_CONTENTS);
    assert_int_equal(truncated, false);
    WriterClose(w);

    Writer *w2 = FileRead(FILE_NAME, FILE_SIZE * 10, &truncated);
    assert_int_equal(StringWriterLength(w2), FILE_SIZE);
    assert_string_equal(StringWriterData(w2), FILE_CONTENTS);
    assert_int_equal(truncated, false);
    WriterClose(w2);

    Writer *w3 = FileRead(FILE_NAME, FILE_SIZE * 10, NULL);
    assert_int_equal(StringWriterLength(w3), FILE_SIZE);
    assert_string_equal(StringWriterData(w3), FILE_CONTENTS);
    WriterClose(w3);
}
Esempio n. 10
0
static void test_show_array_empty(void **state)
{
    JsonElement *array = JsonArrayCreate(10);

    Writer *writer = StringWriter();

    JsonElementPrint(writer, array, 0);

    assert_string_equal("[]", StringWriterData(writer));

    JsonElementDestroy(array);
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
void test_empty_file_buffer(void **p)
{
    global_w = StringWriter();
    global_w_closed = false;
    Writer *w = FileWriter(NULL);

    assert_int_equal(StringWriterLength(global_w), 0);
    assert_string_equal(StringWriterData(global_w), "");

    WriterClose(w);
    WriterClose(global_w);
    assert_int_equal(global_w_closed, true);
}
Esempio n. 13
0
void test_write_file_buffer(void **p)
{
    global_w = StringWriter();
    Writer *w = FileWriter(NULL);

    WriterWrite(w, "123");

    assert_int_equal(StringWriterLength(global_w), 3);
    assert_string_equal(StringWriterData(global_w), "123");

    WriterClose(w);
    WriterClose(global_w);
    assert_int_equal(global_w_closed, true);
}
Esempio n. 14
0
void test_file_read_empty(void)
{
    int creat_fd = creat(FILE_NAME_EMPTY, 0600);
    assert_true(creat_fd > -1);

    int close_res = close(creat_fd);
    assert_int_equal(close_res, 0);

    bool truncated = true;
    Writer *w = FileRead(FILE_NAME_EMPTY, 100, &truncated);
    assert_int_equal(StringWriterLength(w), 0);
    assert_string_equal(StringWriterData(w), "");
    assert_int_equal(truncated, false);
}
Esempio n. 15
0
static void test_show_object_escaped(void **state)
{
    JsonElement *json = JsonObjectCreate(10);

    JsonObjectAppendString(json, "escaped", "quote\"stuff \t \n\n");

    Writer *writer = StringWriter();

    JsonElementPrint(writer, json, 0);

    assert_string_equal(OBJECT_ESCAPED, StringWriterData(writer));

    JsonElementDestroy(json);
}
Esempio n. 16
0
static void test_show_array(void **state)
{
    JsonElement *array = JsonArrayCreate(10);

    JsonArrayAppendString(array, "one");
    JsonArrayAppendString(array, "two");

    Writer *writer = StringWriter();

    JsonElementPrint(writer, array, 0);

    assert_string_equal(ARRAY_SIMPLE, StringWriterData(writer));

    JsonElementDestroy(array);
}
Esempio n. 17
0
static void test_show_object_simple(void **state)
{
    JsonElement *json = JsonObjectCreate(10);

    JsonObjectAppendString(json, "first", "one");
    JsonObjectAppendString(json, "second", "two");

    Writer *writer = StringWriter();

    JsonElementPrint(writer, json, 0);

    assert_string_equal(OBJECT_SIMPLE, StringWriterData(writer));

    JsonElementDestroy(json);
}
Esempio n. 18
0
static void test_show_object_numeric(void **state)
{
    JsonElement *json = JsonObjectCreate(10);

    JsonObjectAppendReal(json, "real", 1234.5678);
    JsonObjectAppendInteger(json, "int", -1234567890);

    Writer *writer = StringWriter();

    JsonElementPrint(writer, json, 0);

    assert_string_equal(OBJECT_NUMERIC, StringWriterData(writer));

    JsonElementDestroy(json);
}
Esempio n. 19
0
static bool RenderVariableContainer(Buffer *out, const JsonElement *container, bool compact)
{
    Writer *w = StringWriter();
    if (compact)
    {
        JsonWriteCompact(w, container);
    }
    else
    {
        JsonWrite(w, container, 0);
    }

    BufferAppendString(out, StringWriterData(w));
    WriterClose(w);
    return true;
}
Esempio n. 20
0
static void test_show_array_object(void **state)
{
    JsonElement *array = JsonArrayCreate(10);
    JsonElement *object = JsonObjectCreate(10);

    JsonObjectAppendString(object, "first", "one");

    JsonArrayAppendObject(array, object);

    Writer *writer = StringWriter();

    JsonElementPrint(writer, array, 0);

    assert_string_equal(ARRAY_OBJECT, StringWriterData(writer));

    JsonElementDestroy(array);
}
Esempio n. 21
0
static void LogPromiseContext(const EvalContext *ctx, const Promise *pp)
{
    Writer *w = StringWriter();
    WriterWrite(w, "Additional promise info:");
    if (PromiseGetHandle(pp))
    {
        WriterWriteF(w, " handle '%s'", PromiseGetHandle(pp));
    }

    {

        Rval retval;
        if (EvalContextVariableControlCommonGet(ctx, COMMON_CONTROL_VERSION, &retval))
        {
            WriterWriteF(w, " version '%s'", RvalScalarValue(retval));
        }
    }

    if (PromiseGetBundle(pp)->source_path)
    {
        WriterWriteF(w, " source path '%s' at line %zu", PromiseGetBundle(pp)->source_path, pp->offset.line);
    }

    switch (pp->promisee.type)
    {
    case RVAL_TYPE_SCALAR:
        WriterWriteF(w, " promisee '%s'", RvalScalarValue(pp->promisee));
        break;

    case RVAL_TYPE_LIST:
        WriterWrite(w, " promisee ");
        RlistWrite(w, pp->promisee.item);
        break;
    default:
        break;
    }

    if (pp->comment)
    {
        WriterWriteF(w, " comment '%s'", pp->comment);
    }

    Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
    WriterClose(w);
}
Esempio n. 22
0
static void test_parse_object_escaped(void **state)
{
    const char *escaped_string = "\\\"/var/cfenigne/bin/cf-know\\\" ";
    const char *key = "json_element_key";

    Writer *writer = StringWriter();
    WriterWriteF(writer, "{ \"%s\" : \"%s\" }", key, escaped_string);

    const char *json_string = StringWriterData(writer);

    JsonElement *obj = JsonParse(&json_string);

    assert_int_not_equal(obj, NULL);
    assert_string_equal(JsonObjectGetAsString(obj, key), escaped_string);

    WriterClose(writer);
    JsonElementDestroy(obj);
}
Esempio n. 23
0
void BannerSubBundle(const Bundle *bp, const Rlist *params)
{
    if (!LEGACY_OUTPUT)
    {
        return;
    }

    Log(LOG_LEVEL_VERBOSE, "      * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
    Log(LOG_LEVEL_VERBOSE, "       BUNDLE %s", bp->name);

    if (params)
    {
        Writer *w = StringWriter();
        RlistWrite(w, params);
        Log(LOG_LEVEL_VERBOSE, "(%s)", StringWriterData(w));
        WriterClose(w);
    }
    Log(LOG_LEVEL_VERBOSE, "      * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
}
Esempio n. 24
0
static void test_show_object_array(void **state)
{
    JsonElement *json = JsonObjectCreate(10);

    JsonElement *array = JsonArrayCreate(10);

    JsonArrayAppendString(array, "one");
    JsonArrayAppendString(array, "two");

    JsonObjectAppendArray(json, "first", array);

    Writer *writer = StringWriter();

    JsonElementPrint(writer, json, 0);

    assert_string_equal(OBJECT_ARRAY, StringWriterData(writer));

    JsonElementDestroy(json);
}
Esempio n. 25
0
static JsonElement *LoadTestFile(const char *filename)
{
    char path[1024];
    sprintf(path, "%s/%s", TESTDATADIR, filename);

    Writer *w = FileRead(path, SIZE_MAX, NULL);
    if (!w)
    {
        return NULL;
    }
    JsonElement *json = NULL;
    const char *data = StringWriterData(w);
    if (JsonParse(&data, &json) != JSON_PARSE_OK)
    {
        WriterClose(w);
        return NULL;
    }

    WriterClose(w);
    return json;
}
Esempio n. 26
0
static void test_parse_object_escaped(void)
{
    const char *decoded = "\"/var/cfenigne/bin/cf-know\" ";

    const char *json_string =  "{\n  \"key\": \"\\\"/var/cfenigne/bin/cf-know\\\" \"\n}";

    JsonElement *obj = NULL;
    const char *data = json_string;
    assert_int_equal(JSON_PARSE_OK, JsonParse(&data, &obj));

    assert_int_not_equal(obj, NULL);
    assert_string_equal(JsonObjectGetAsString(obj, "key"), decoded);

    {
        Writer *w = StringWriter();
        JsonWrite(w, obj, 0);

        assert_string_equal(json_string, StringWriterData(w));

        WriterClose(w);
    }

    JsonDestroy(obj);
}
Esempio n. 27
0
static void ShowContext(EvalContext *ctx)
{
    {
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Hard classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Discovered hard classes:");
        }

        Seq *hard_contexts = SeqNew(1000, NULL);
        SetIterator it = EvalContextHeapIteratorHard(ctx);
        char *context = NULL;
        while ((context = SetIteratorNext(&it)))
        {
            if (!EvalContextHeapContainsNegated(ctx, context))
            {
                SeqAppend(hard_contexts, context);
            }
        }

        SeqSort(hard_contexts, (SeqItemComparator)strcmp, NULL);

        for (size_t i = 0; i < SeqLength(hard_contexts); i++)
        {
            const char *context = SeqAt(hard_contexts, i);

            WriterWriteF(w, " %s", context);
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            WriterClose(w);
        }


        SeqDestroy(hard_contexts);
    }

    {
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Additional classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Additional classes:");
        }

        Seq *soft_contexts = SeqNew(1000, NULL);
        SetIterator it = EvalContextHeapIteratorSoft(ctx);
        char *context = NULL;
        while ((context = SetIteratorNext(&it)))
        {
            if (!EvalContextHeapContainsNegated(ctx, context))
            {
                SeqAppend(soft_contexts, context);
            }
        }

        SeqSort(soft_contexts, (SeqItemComparator)strcmp, NULL);

        for (size_t i = 0; i < SeqLength(soft_contexts); i++)
        {
            const char *context = SeqAt(soft_contexts, i);
            WriterWriteF(w, " %s", context);
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            if (SeqLength(soft_contexts) > 0)
            {
                Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            }
            WriterClose(w);
        }
        SeqDestroy(soft_contexts);
    }

    {
        bool have_negated_classes = false;
        Writer *w = NULL;
        if (LEGACY_OUTPUT)
        {
            w = FileWriter(stdout);
            WriterWriteF(w, "%s>  -> Negated classes = {", VPREFIX);
        }
        else
        {
            w = StringWriter();
            WriterWrite(w, "Negated classes:");
        }

        StringSetIterator it = EvalContextHeapIteratorNegated(ctx);
        const char *context = NULL;
        while ((context = StringSetIteratorNext(&it)))
        {
            WriterWriteF(w, " %s", context);
            have_negated_classes = true;
        }

        if (LEGACY_OUTPUT)
        {
            WriterWrite(w, "}\n");
            FileWriterDetach(w);
        }
        else
        {
            if (have_negated_classes)
            {
                Log(LOG_LEVEL_VERBOSE, "%s", StringWriterData(w));
            }
            WriterClose(w);
        }
    }
}
Esempio n. 28
0
PromiseResult ScheduleEditOperation(EvalContext *ctx, char *filename, Attributes a, Promise *pp)
{
    void *vp;
    FnCall *fp;
    Rlist *args = NULL;
    char edit_bundle_name[CF_BUFSIZE], lockname[CF_BUFSIZE], qualified_edit[CF_BUFSIZE], *method_deref;
    CfLock thislock;

    snprintf(lockname, CF_BUFSIZE - 1, "fileedit-%s", filename);
    thislock = AcquireLock(ctx, lockname, VUQNAME, CFSTARTTIME, a.transaction, pp, false);

    if (thislock.lock == NULL)
    {
        return PROMISE_RESULT_NOOP;
    }

    EditContext *edcontext = NewEditContext(filename, a);

    PromiseResult result = PROMISE_RESULT_NOOP;
    if (edcontext == NULL)
    {
        cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "File '%s' was marked for editing but could not be opened", filename);
        result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
        goto exit;
    }

    Policy *policy = PolicyFromPromise(pp);

    if (a.haveeditline)
    {
        if ((vp = ConstraintGetRvalValue(ctx, "edit_line", pp, RVAL_TYPE_FNCALL)))
        {
            fp = (FnCall *) vp;
            strcpy(edit_bundle_name, fp->name);
            args = fp->args;
        }
        else if ((vp = ConstraintGetRvalValue(ctx, "edit_line", pp, RVAL_TYPE_SCALAR)))
        {
            strcpy(edit_bundle_name, (char *) vp);
            args = NULL;
        }             
        else
        {
            goto exit;
        }

        if (strncmp(edit_bundle_name,"default:",strlen("default:")) == 0) // CF_NS == ':'
        {
            method_deref = strchr(edit_bundle_name, CF_NS) + 1;
        }
        else if ((strchr(edit_bundle_name, CF_NS) == NULL) && (strcmp(PromiseGetNamespace(pp), "default") != 0))
        {
            snprintf(qualified_edit, CF_BUFSIZE, "%s%c%s", PromiseGetNamespace(pp), CF_NS, edit_bundle_name);
            method_deref = qualified_edit;
        }
        else            
        {
            method_deref = edit_bundle_name;
        }        

        Log(LOG_LEVEL_VERBOSE, "Handling file edits in edit_line bundle '%s'", method_deref);

        Bundle *bp = NULL;
        if ((bp = PolicyGetBundle(policy, NULL, "edit_line", method_deref)))
        {
            BannerSubBundle(bp, args);

            EvalContextStackPushBundleFrame(ctx, bp, args, a.edits.inherit);

            BundleResolve(ctx, bp);

            ScheduleEditLineOperations(ctx, bp, a, pp, edcontext);

            EvalContextStackPopFrame(ctx);
        }
        else
        {
            Log(LOG_LEVEL_ERR, "Did not find method '%s' in bundle '%s' for edit operation", method_deref, edit_bundle_name);
        }
    }


    if (a.haveeditxml)
    {
        if ((vp = ConstraintGetRvalValue(ctx, "edit_xml", pp, RVAL_TYPE_FNCALL)))
        {
            fp = (FnCall *) vp;
            strcpy(edit_bundle_name, fp->name);
            args = fp->args;
        }
        else if ((vp = ConstraintGetRvalValue(ctx, "edit_xml", pp, RVAL_TYPE_SCALAR)))
        {
            strcpy(edit_bundle_name, (char *) vp);
            args = NULL;
        }
        else
        {
            goto exit;
        }

        if (strncmp(edit_bundle_name,"default:",strlen("default:")) == 0) // CF_NS == ':'
        {
            method_deref = strchr(edit_bundle_name, CF_NS) + 1;
        }
        else
        {
            method_deref = edit_bundle_name;
        }
        
        Log(LOG_LEVEL_VERBOSE, "Handling file edits in edit_xml bundle '%s'", method_deref);

        Bundle *bp = NULL;
        if ((bp = PolicyGetBundle(policy, NULL, "edit_xml", method_deref)))
        {
            BannerSubBundle(bp, args);

            EvalContextStackPushBundleFrame(ctx, bp, args, a.edits.inherit);
            BundleResolve(ctx, bp);

            ScheduleEditXmlOperations(ctx, bp, a, pp, edcontext);

            EvalContextStackPopFrame(ctx);
        }
    }

    
    if (a.edit_template)
    {
        if (!a.template_method || strcmp("cfengine", a.template_method) == 0)
        {
            Policy *tmp_policy = PolicyNew();
            Bundle *bp = NULL;
            if ((bp = MakeTemporaryBundleFromTemplate(ctx, tmp_policy, a, pp, &result)))
            {
                BannerSubBundle(bp, args);
                a.haveeditline = true;

                EvalContextStackPushBundleFrame(ctx, bp, args, a.edits.inherit);
                BundleResolve(ctx, bp);

                ScheduleEditLineOperations(ctx, bp, a, pp, edcontext);

                EvalContextStackPopFrame(ctx);
            }

            PolicyDestroy(tmp_policy);
        }
        else if (strcmp("mustache", a.template_method) == 0)
        {
            if (!FileCanOpen(a.edit_template, "r"))
            {
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Template file '%s' could not be opened for reading", a.edit_template);
                result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
                goto exit;
            }

            Writer *ouput_writer = NULL;
            {
                FILE *output_file = fopen(pp->promiser, "w");
                if (!output_file)
                {
                    cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Output file '%s' could not be opened for writing", pp->promiser);
                    result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
                    goto exit;
                }

                ouput_writer = FileWriter(output_file);
            }

            Writer *template_writer = FileRead(a.edit_template, SIZE_MAX, NULL);
            if (!template_writer)
            {
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Could not read template file '%s'", a.edit_template);
                result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
                WriterClose(ouput_writer);
                goto exit;
            }

            JsonElement *default_template_data = NULL;
            if (!a.template_data)
            {
                a.template_data = default_template_data = DefaultTemplateData(ctx);
            }

            if (!MustacheRender(ouput_writer, StringWriterData(template_writer), a.template_data))
            {
                cfPS(ctx, LOG_LEVEL_ERR, PROMISE_RESULT_FAIL, pp, a, "Error rendering mustache template '%s'", a.edit_template);
                result = PromiseResultUpdate(result, PROMISE_RESULT_FAIL);
                WriterClose(template_writer);
                WriterClose(ouput_writer);
                goto exit;
            }

            JsonDestroy(default_template_data);
            WriterClose(template_writer);
            WriterClose(ouput_writer);
        }
    }

exit:
    result = PromiseResultUpdate(result, FinishEditContext(ctx, edcontext, a, pp));
    YieldCurrentLock(thislock);
    return result;
}
Esempio n. 29
0
File: fncall.c Progetto: dstam/core
FnCallResult FnCallEvaluate(EvalContext *ctx, const Policy *policy, FnCall *fp, const Promise *caller)
{
    assert(ctx);
    assert(policy);
    assert(fp);
    fp->caller = caller;

    if (!EvalContextGetEvalOption(ctx, EVAL_OPTION_EVAL_FUNCTIONS))
    {
        Log(LOG_LEVEL_VERBOSE, "Skipping function '%s', because evaluation was turned off in the evaluator",
            fp->name);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    const FnCallType *fp_type = FnCallTypeGet(fp->name);

    if (!fp_type)
    {
        if (caller)
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s' in promise '%s' near line %zd",
                  fp->name, PromiseGetBundle(caller)->source_path, caller->offset.line);
        }
        else
        {
            Log(LOG_LEVEL_ERR, "No such FnCall '%s', context info unavailable", fp->name);
        }

        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    Rlist *expargs = NewExpArgs(ctx, policy, fp, fp_type);

    Writer *fncall_writer = NULL;
    const char *fncall_string = "";
    if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
    {
        fncall_writer = StringWriter();
        FnCallWrite(fncall_writer, fp);
        fncall_string = StringWriterData(fncall_writer);
    }

    // Check if arguments are resolved, except for delayed evaluation functions
    if ( ! (fp_type->options & FNCALL_OPTION_DELAYED_EVALUATION) &&
         RlistIsUnresolved(expargs))
    {
        // Special case: ifelse(isvariable("x"), $(x), "default")
        // (the first argument will come down expanded as "!any")
        if (strcmp(fp->name, "ifelse") == 0 &&
            RlistLen(expargs) == 3 &&
            strcmp("!any", RlistScalarValueSafe(expargs)) == 0 &&
            !RlistIsUnresolved(expargs->next->next))
        {
                Log(LOG_LEVEL_DEBUG, "Allowing ifelse() function evaluation even"
                    " though its arguments contain unresolved variables: %s",
                    fncall_string);
        }
        else
        {
            if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
            {
                Log(LOG_LEVEL_DEBUG, "Skipping function evaluation for now,"
                    " arguments contain unresolved variables: %s",
                    fncall_string);
                WriterClose(fncall_writer);
            }
            RlistDestroy(expargs);
            return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
        }
    }

    Rval cached_rval;
    if ((fp_type->options & FNCALL_OPTION_CACHED) && EvalContextFunctionCacheGet(ctx, fp, expargs, &cached_rval))
    {
        if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
        {
            Log(LOG_LEVEL_DEBUG,
                "Using previously cached result for function: %s",
                fncall_string);
            WriterClose(fncall_writer);
        }
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        WriterClose(w);
        RlistDestroy(expargs);

        return (FnCallResult) { FNCALL_SUCCESS, RvalCopy(cached_rval) };
    }

    if (LogGetGlobalLevel() >= LOG_LEVEL_DEBUG)
    {
        Log(LOG_LEVEL_DEBUG, "Evaluating function: %s",
            fncall_string);
        WriterClose(fncall_writer);
    }

    FnCallResult result = CallFunction(ctx, policy, fp, expargs);

    if (result.status == FNCALL_FAILURE)
    {
        RlistDestroy(expargs);
        return (FnCallResult) { FNCALL_FAILURE, { FnCallCopy(fp), RVAL_TYPE_FNCALL } };
    }

    if (fp_type->options & FNCALL_OPTION_CACHED)
    {
        Writer *w = StringWriter();
        FnCallWrite(w, fp);
        Log(LOG_LEVEL_VERBOSE, "Caching result for function '%s'", StringWriterData(w));
        WriterClose(w);

        EvalContextFunctionCachePut(ctx, fp, expargs, &result.rval);
    }

    RlistDestroy(expargs);

    return result;
}
Esempio n. 30
0
File: loading.c Progetto: lra/core
/*
 * The difference between filename and input_input file is that the latter is the file specified by -f or
 * equivalently the file containing body common control. This will hopefully be squashed in later refactoring.
 */
static Policy *Cf3ParseFile(const GenericAgentConfig *config, const char *input_path)
{
    struct stat statbuf;

    if (stat(input_path, &statbuf) == -1)
    {
        if (config->ignore_missing_inputs)
        {
            return PolicyNew();
        }

        Log(LOG_LEVEL_ERR, "Can't stat file '%s' for parsing. (stat: %s)", input_path, GetErrorStr());
        exit(EXIT_FAILURE);
    }
    else if (S_ISDIR(statbuf.st_mode))
    {
        if (config->ignore_missing_inputs)
        {
            return PolicyNew();
        }

        Log(LOG_LEVEL_ERR, "Can't parse directory '%s'.", input_path);
        exit(EXIT_FAILURE);
    }

#ifndef _WIN32
    if (config->check_not_writable_by_others && (statbuf.st_mode & (S_IWGRP | S_IWOTH)))
    {
        Log(LOG_LEVEL_ERR, "File %s (owner %ju) is writable by others (security exception)", input_path, (uintmax_t)statbuf.st_uid);
        exit(EXIT_FAILURE);
    }
#endif

    Log(LOG_LEVEL_VERBOSE, "Parsing file '%s'", input_path);

    if (!FileCanOpen(input_path, "r"))
    {
        Log(LOG_LEVEL_ERR, "Can't open file '%s' for parsing", input_path);
        exit(EXIT_FAILURE);
    }

    Policy *policy = NULL;
    if (StringEndsWith(input_path, ".json"))
    {
        Writer *contents = FileRead(input_path, SIZE_MAX, NULL);
        if (!contents)
        {
            Log(LOG_LEVEL_ERR, "Error reading JSON input file '%s'", input_path);
            return NULL;
        }
        JsonElement *json_policy = NULL;
        const char *data = StringWriterData(contents);
        if (JsonParse(&data, &json_policy) != JSON_PARSE_OK)
        {
            Log(LOG_LEVEL_ERR, "Error parsing JSON input file '%s'", input_path);
            WriterClose(contents);
            return NULL;
        }

        policy = PolicyFromJson(json_policy);

        JsonDestroy(json_policy);
        WriterClose(contents);
    }
    else
    {
        if (config->agent_type == AGENT_TYPE_COMMON)
        {
            policy = ParserParseFile(config->agent_type, input_path, config->agent_specific.common.parser_warnings, config->agent_specific.common.parser_warnings_error);
        }
        else
        {
            policy = ParserParseFile(config->agent_type, input_path, 0, 0);
        }
    }

    return policy;
}