static int set_servers (struct global *g) { int ret = 0; // count servers size_t num_entries = count_entries(g); // allocate sort array struct dns_sort_entry *sort_entries = BAllocArray(num_entries, sizeof(sort_entries[0])); if (!sort_entries) { goto fail0; } // fill sort array num_entries = 0; for (LinkedList1Node *n = LinkedList1_GetFirst(&g->instances); n; n = LinkedList1Node_Next(n)) { struct instance *o = UPPER_OBJECT(n, struct instance, instances_node); for (LinkedList1Node *en = LinkedList1_GetFirst(&o->entries); en; en = LinkedList1Node_Next(en)) { struct dns_entry *e = UPPER_OBJECT(en, struct dns_entry, list_node); sort_entries[num_entries].line = e->line; sort_entries[num_entries].priority= e->priority; num_entries++; } } // sort by priority // use a custom insertion sort instead of qsort() because we want a stable sort struct dns_sort_entry temp; BInsertionSort(sort_entries, num_entries, sizeof(sort_entries[0]), dns_sort_comparator, &temp); ExpString estr; if (!ExpString_Init(&estr)) { goto fail1; } for (size_t i = 0; i < num_entries; i++) { if (!ExpString_Append(&estr, sort_entries[i].line)) { goto fail2; } } // set servers if (!NCDIfConfig_set_resolv_conf(ExpString_Get(&estr), ExpString_Length(&estr))) { goto fail2; } ret = 1; fail2: ExpString_Free(&estr); fail1: BFree(sort_entries); fail0: return ret; }
static void func_new (NCDModuleInst *i) { // allocate instance struct instance *o = malloc(sizeof(*o)); if (!o) { ModuleLog(i, BLOG_ERROR, "failed to allocate instance"); goto fail0; } NCDModuleInst_Backend_SetUser(i, o); // init arguments o->i = i; // init string ExpString s; if (!ExpString_Init(&s)) { ModuleLog(i, BLOG_ERROR, "ExpString_Init failed"); goto fail1; } // append arguments NCDValue *arg = NCDValue_ListFirst(o->i->args); while (arg) { if (NCDValue_Type(arg) != NCDVALUE_STRING) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail2; } if (!ExpString_Append(&s, NCDValue_StringValue(arg))) { ModuleLog(i, BLOG_ERROR, "ExpString_Append failed"); goto fail2; } arg = NCDValue_ListNext(o->i->args, arg); } // set string o->string = ExpString_Get(&s); // signal up NCDModuleInst_Backend_Up(o->i); return; fail2: ExpString_Free(&s); fail1: free(o); fail0: NCDModuleInst_Backend_SetError(i); NCDModuleInst_Backend_Dead(i); }
static void print_value (NCDValue *v, unsigned int indent) { ExpString estr; if (!ExpString_Init(&estr)) { DEBUG("ExpString_Init failed"); exit(1); } if (!generate_val(v, &estr)) { DEBUG("generate_val failed"); exit(1); } print_indent(indent); printf("%s\n", ExpString_Get(&estr)); ExpString_Free(&estr); }
static void concat_eval (NCDCall call) { ExpString estr; if (!ExpString_Init(&estr)) { FunctionLog(&call, BLOG_ERROR, "ExpString_Init failed"); goto fail0; } size_t count = NCDCall_ArgCount(&call); for (size_t i = 0; i < count; i++) { NCDValRef arg = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call)); if (NCDVal_IsInvalid(arg)) { goto fail1; } if (!concat_recurser(&estr, arg, &call)) { goto fail1; } } NCDCall_SetResult(&call, NCDVal_NewStringBinMr(NCDCall_ResMem(&call), ExpString_GetMr(&estr))); fail1: ExpString_Free(&estr); fail0: return; }
static void replace_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params) { struct replace_instance *o = vo; o->i = i; // read arguments NCDValRef input_arg; NCDValRef regex_arg; NCDValRef replace_arg; if (!NCDVal_ListRead(params->args, 3, &input_arg, ®ex_arg, &replace_arg)) { ModuleLog(i, BLOG_ERROR, "wrong arity"); goto fail1; } if (!NCDVal_IsString(input_arg) || !NCDVal_IsList(regex_arg) || !NCDVal_IsList(replace_arg)) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail1; } // check number of regex/replace if (NCDVal_ListCount(regex_arg) != NCDVal_ListCount(replace_arg)) { ModuleLog(i, BLOG_ERROR, "number of regex's is not the same as number of replacements"); goto fail1; } size_t num_regex = NCDVal_ListCount(regex_arg); // allocate array for compiled regex's regex_t *regs = BAllocArray(num_regex, sizeof(regs[0])); if (!regs) { ModuleLog(i, BLOG_ERROR, "BAllocArray failed"); goto fail1; } size_t num_done_regex = 0; // compile regex's, check arguments while (num_done_regex < num_regex) { NCDValRef regex = NCDVal_ListGet(regex_arg, num_done_regex); NCDValRef replace = NCDVal_ListGet(replace_arg, num_done_regex); if (!NCDVal_IsStringNoNulls(regex) || !NCDVal_IsString(replace)) { ModuleLog(i, BLOG_ERROR, "wrong regex/replace type for pair %zu", num_done_regex); goto fail2; } // null terminate regex NCDValNullTermString regex_nts; if (!NCDVal_StringNullTerminate(regex, ®ex_nts)) { ModuleLog(i, BLOG_ERROR, "NCDVal_StringNullTerminate failed"); goto fail2; } int res = regcomp(®s[num_done_regex], regex_nts.data, REG_EXTENDED); NCDValNullTermString_Free(®ex_nts); if (res != 0) { ModuleLog(i, BLOG_ERROR, "regcomp failed for pair %zu (error=%d)", num_done_regex, res); goto fail2; } num_done_regex++; } // init output string ExpString out; if (!ExpString_Init(&out)) { ModuleLog(i, BLOG_ERROR, "ExpString_Init failed"); goto fail2; } // input state MemRef in = NCDVal_StringMemRef(input_arg); size_t in_pos = 0; // process input while (in_pos < in.len) { // find first match int have_match = 0; size_t match_regex = 0; // to remove warning regmatch_t match = {0, 0}; // to remove warning for (size_t j = 0; j < num_regex; j++) { regmatch_t this_match; this_match.rm_so = 0; this_match.rm_eo = in.len - in_pos; if (regexec(®s[j], in.ptr + in_pos, 1, &this_match, REG_STARTEND) == 0 && (!have_match || this_match.rm_so < match.rm_so)) { have_match = 1; match_regex = j; match = this_match; } } // if no match, append remaining data and finish if (!have_match) { if (!ExpString_AppendBinaryMr(&out, MemRef_SubFrom(in, in_pos))) { ModuleLog(i, BLOG_ERROR, "ExpString_AppendBinaryMr failed"); goto fail3; } break; } // append data before match if (!ExpString_AppendBinaryMr(&out, MemRef_Sub(in, in_pos, match.rm_so))) { ModuleLog(i, BLOG_ERROR, "ExpString_AppendBinaryMr failed"); goto fail3; } // append replacement data NCDValRef replace = NCDVal_ListGet(replace_arg, match_regex); if (!ExpString_AppendBinaryMr(&out, NCDVal_StringMemRef(replace))) { ModuleLog(i, BLOG_ERROR, "ExpString_AppendBinaryMr failed"); goto fail3; } in_pos += match.rm_eo; } // set output o->output = ExpString_GetMr(&out); // free compiled regex's while (num_done_regex-- > 0) { regfree(®s[num_done_regex]); } // free array BFree(regs); // signal up NCDModuleInst_Backend_Up(i); return; fail3: ExpString_Free(&out); fail2: while (num_done_regex-- > 0) { regfree(®s[num_done_regex]); } BFree(regs); fail1: NCDModuleInst_Backend_DeadError(i); }
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params) { struct instance *o = vo; o->i = i; // read arguments NCDValRef glue_arg; NCDValRef pieces_arg; if (!NCDVal_ListRead(params->args, 2, &glue_arg, &pieces_arg)) { ModuleLog(i, BLOG_ERROR, "wrong arity"); goto fail0; } if (!NCDVal_IsString(glue_arg) || !NCDVal_IsList(pieces_arg)) { ModuleLog(i, BLOG_ERROR, "wrong type"); goto fail0; } // init result string ExpString str; if (!ExpString_Init(&str)) { ModuleLog(i, BLOG_ERROR, "ExpString_Init failed"); goto fail0; } size_t count = NCDVal_ListCount(pieces_arg); for (size_t j = 0; j < count; j++) { NCDValRef piece = NCDVal_ListGet(pieces_arg, j); // check piece type if (!NCDVal_IsString(piece)) { ModuleLog(i, BLOG_ERROR, "wrong piece type"); goto fail1; } // append glue if (j > 0) { if (!ExpString_AppendBinary(&str, (const uint8_t *)NCDVal_StringData(glue_arg), NCDVal_StringLength(glue_arg))) { ModuleLog(i, BLOG_ERROR, "ExpString_AppendBinary failed"); goto fail1; } } // append piece if (!ExpString_AppendBinary(&str, (const uint8_t *)NCDVal_StringData(piece), NCDVal_StringLength(piece))) { ModuleLog(i, BLOG_ERROR, "ExpString_AppendBinary failed"); goto fail1; } } // store result o->result = ExpString_Get(&str); o->result_len = ExpString_Length(&str); // signal up NCDModuleInst_Backend_Up(i); return; fail1: ExpString_Free(&str); fail0: NCDModuleInst_Backend_DeadError(i); }
void NCDConfigTokenizer_Tokenize (char *str, size_t left, NCDConfigTokenizer_output output, void *user) { size_t line = 1; size_t line_char = 1; while (left > 0) { size_t l; int error = 0; int token; void *token_val = NULL; size_t token_len = 0; if (*str == '#') { l = 1; while (l < left && str[l] != '\n') { l++; } token = 0; } else if (l = data_begins_with(str, left, "{")) { token = NCD_TOKEN_CURLY_OPEN; } else if (l = data_begins_with(str, left, "}")) { token = NCD_TOKEN_CURLY_CLOSE; } else if (l = data_begins_with(str, left, "(")) { token = NCD_TOKEN_ROUND_OPEN; } else if (l = data_begins_with(str, left, ")")) { token = NCD_TOKEN_ROUND_CLOSE; } else if (l = data_begins_with(str, left, ";")) { token = NCD_TOKEN_SEMICOLON; } else if (l = data_begins_with(str, left, ".")) { token = NCD_TOKEN_DOT; } else if (l = data_begins_with(str, left, ",")) { token = NCD_TOKEN_COMMA; } else if (l = data_begins_with(str, left, ":")) { token = NCD_TOKEN_COLON; } else if (l = data_begins_with(str, left, "[")) { token = NCD_TOKEN_BRACKET_OPEN; } else if (l = data_begins_with(str, left, "]")) { token = NCD_TOKEN_BRACKET_CLOSE; } else if (l = data_begins_with(str, left, "->")) { token = NCD_TOKEN_ARROW; } else if (l = data_begins_with(str, left, "If")) { token = NCD_TOKEN_IF; } else if (l = data_begins_with(str, left, "Elif")) { token = NCD_TOKEN_ELIF; } else if (l = data_begins_with(str, left, "elif")) { token = NCD_TOKEN_ELIF; } else if (l = data_begins_with(str, left, "Else")) { token = NCD_TOKEN_ELSE; } else if (l = data_begins_with(str, left, "else")) { token = NCD_TOKEN_ELSE; } else if (l = data_begins_with(str, left, "Foreach")) { token = NCD_TOKEN_FOREACH; } else if (l = data_begins_with(str, left, "As")) { token = NCD_TOKEN_AS; } else if (l = data_begins_with(str, left, "include_guard")) { token = NCD_TOKEN_INCLUDE_GUARD; } else if (l = data_begins_with(str, left, "include")) { token = NCD_TOKEN_INCLUDE; } else if (is_name_first_char(*str)) { l = 1; while (l < left && is_name_char(str[l])) { l++; } // allocate buffer bsize_t bufsize = bsize_add(bsize_fromsize(l), bsize_fromint(1)); char *buf; if (bufsize.is_overflow || !(buf = malloc(bufsize.value))) { BLog(BLOG_ERROR, "malloc failed"); error = 1; goto out; } // copy and terminate memcpy(buf, str, l); buf[l] = '\0'; if (!strcmp(buf, "process")) { token = NCD_TOKEN_PROCESS; free(buf); } else if (!strcmp(buf, "template")) { token = NCD_TOKEN_TEMPLATE; free(buf); } else { token = NCD_TOKEN_NAME; token_val = buf; token_len = l; } } else if (*str == '"') do { // init string ExpString estr; if (!ExpString_Init(&estr)) { BLog(BLOG_ERROR, "ExpString_Init failed"); goto string_fail0; } // skip start quote l = 1; // decode string while (l < left) { uint8_t dec_ch; // get character if (str[l] == '\\') { if (left - l < 2) { BLog(BLOG_ERROR, "escape character found in string but nothing follows"); goto string_fail1; } size_t extra = 0; switch (str[l + 1]) { case '\'': case '\"': case '\\': case '\?': dec_ch = str[l + 1]; break; case 'a': dec_ch = '\a'; break; case 'b': dec_ch = '\b'; break; case 'f': dec_ch = '\f'; break; case 'n': dec_ch = '\n'; break; case 'r': dec_ch = '\r'; break; case 't': dec_ch = '\t'; break; case 'v': dec_ch = '\v'; break; case '0': dec_ch = 0; break; case 'x': { if (left - l < 4) { BLog(BLOG_ERROR, "hexadecimal escape found in string but too little characters follow"); goto string_fail1; } uintmax_t hex_val; if (!parse_unsigned_hex_integer_bin(&str[l + 2], 2, &hex_val)) { BLog(BLOG_ERROR, "hexadecimal escape found in string but two hex characters don't follow"); goto string_fail1; } dec_ch = hex_val; extra = 2; } break; default: BLog(BLOG_ERROR, "bad escape sequence in string"); goto string_fail1; } l += 2 + extra; } else if (str[l] == '"') { break; } else { dec_ch = str[l]; l++; } // append character to string if (!ExpString_AppendByte(&estr, dec_ch)) { BLog(BLOG_ERROR, "ExpString_AppendChar failed"); goto string_fail1; } } // make sure ending quote was found if (l == left) { BLog(BLOG_ERROR, "missing ending quote for string"); goto string_fail1; } // skip ending quote l++; token = NCD_TOKEN_STRING; token_val = ExpString_Get(&estr); token_len = ExpString_Length(&estr); break; string_fail1: ExpString_Free(&estr); string_fail0: error = 1; } while (0); else if (is_space_char(*str)) { token = 0; l = 1; } else { BLog(BLOG_ERROR, "unrecognized character"); error = 1; } out: // report error if (error) { output(user, NCD_ERROR, NULL, 0, line, line_char); return; } // output token if (token) { if (!output(user, token, token_val, token_len, line, line_char)) { return; } } // update line/char counters for (size_t i = 0; i < l; i++) { if (str[i] == '\n') { line++; line_char = 1; } else { line_char++; } } str += l; left -= l; } output(user, NCD_EOF, NULL, 0, line, line_char); }
void NCDConfigTokenizer_Tokenize (char *str, size_t left, NCDConfigTokenizer_output output, void *user) { size_t line = 1; size_t line_char = 1; while (left > 0) { size_t l; int error = 0; int token; void *token_val = NULL; if (*str == '#') { l = 1; while (l < left && str[l] != '\n') { l++; } token = 0; } else if (l = data_begins_with(str, left, "{")) { token = NCD_TOKEN_CURLY_OPEN; } else if (l = data_begins_with(str, left, "}")) { token = NCD_TOKEN_CURLY_CLOSE; } else if (l = data_begins_with(str, left, "(")) { token = NCD_TOKEN_ROUND_OPEN; } else if (l = data_begins_with(str, left, ")")) { token = NCD_TOKEN_ROUND_CLOSE; } else if (l = data_begins_with(str, left, ";")) { token = NCD_TOKEN_SEMICOLON; } else if (l = data_begins_with(str, left, ".")) { token = NCD_TOKEN_DOT; } else if (l = data_begins_with(str, left, ",")) { token = NCD_TOKEN_COMMA; } else if (l = data_begins_with(str, left, ":")) { token = NCD_TOKEN_COLON; } else if (l = data_begins_with(str, left, "[")) { token = NCD_TOKEN_BRACKET_OPEN; } else if (l = data_begins_with(str, left, "]")) { token = NCD_TOKEN_BRACKET_CLOSE; } else if (l = data_begins_with(str, left, "->")) { token = NCD_TOKEN_ARROW; } else if (is_name_first_char(*str)) { l = 1; while (l < left && is_name_char(str[l])) { l++; } // allocate buffer bsize_t bufsize = bsize_add(bsize_fromsize(l), bsize_fromint(1)); char *buf; if (bufsize.is_overflow || !(buf = malloc(bufsize.value))) { BLog(BLOG_ERROR, "malloc failed"); error = 1; goto out; } // copy and terminate memcpy(buf, str, l); buf[l] = '\0'; if (!strcmp(buf, "process")) { token = NCD_TOKEN_PROCESS; free(buf); } else if (!strcmp(buf, "template")) { token = NCD_TOKEN_TEMPLATE; free(buf); } else { token = NCD_TOKEN_NAME; token_val = buf; } } else if (*str == '"') do { // init string ExpString estr; if (!ExpString_Init(&estr)) { BLog(BLOG_ERROR, "ExpString_Init failed"); goto string_fail0; } // skip start quote l = 1; // decode string while (l < left) { char dec_ch; // get character if (str[l] == '\\') { if (left - l < 2) { BLog(BLOG_ERROR, "escape character found in string but nothing follows"); goto string_fail1; } dec_ch = str[l + 1]; l += 2; } else if (str[l] == '"') { break; } else { dec_ch = str[l]; l++; } // string cannot contain zeros bytes if (dec_ch == '\0') { BLog(BLOG_ERROR, "string contains zero byte"); goto string_fail1; } // append character to string if (!ExpString_AppendChar(&estr, dec_ch)) { BLog(BLOG_ERROR, "ExpString_AppendChar failed"); goto string_fail1; } } // make sure ending quote was found if (l == left) { BLog(BLOG_ERROR, "missing ending quote for string"); goto string_fail1; } // skip ending quote l++; token = NCD_TOKEN_STRING; token_val = ExpString_Get(&estr); break; string_fail1: ExpString_Free(&estr); string_fail0: error = 1; } while (0); else if (is_space_char(*str)) { token = 0; l = 1; } else { BLog(BLOG_ERROR, "unrecognized character"); error = 1; } out: // report error if (error) { output(user, NCD_ERROR, NULL, line, line_char); return; } // output token if (token) { if (!output(user, token, token_val, line, line_char)) { return; } } // update line/char counters for (size_t i = 0; i < l; i++) { if (str[i] == '\n') { line++; line_char = 1; } else { line_char++; } } str += l; left -= l; } output(user, NCD_EOF, NULL, line, line_char); }