int vlist_dereference(var_t *list, ...) { va_list ap; var_t *v; void **p; ll_t *ll; ll_entry_t *pos; va_start(ap, list); ll = list->v_data; pos = LL_START(ll); while ((v = ll_next(ll, &pos))) { p = va_arg(ap, void **); /* * Skip NULL Pointers. */ if (p == NULL) { continue; } *p = v->v_data; } va_end(ap); return 0; }
var_t * vlist_record_from_table(var_t *scheme, var_t *table) { var_t *record = NULL, *vs, *vt; ll_t *ll; ll_entry_t *pos; void *data; var_type_t type; char *name; record = vlist_create(scheme->v_name, VF_KEEPNAME); if (record == NULL) { log_warning("vlist_record: vlist_create failed"); return NULL; } ll = scheme->v_data; pos = LL_START(ll); while ((vs = ll_next(ll, &pos))) { name = vs->v_name; vt = vtable_lookup(table, name); if (vt == NULL && vs->v_flags & VF_KEY) { log_error("vlist_record_from_table: \"%s\" is missing " "in vtable and declared as key", name); goto error; } data = vt == NULL ? NULL : vt->v_data; type = vt == NULL ? VT_NULL : vt->v_type; if (vlist_append_new(record, type, name, data, VF_COPY | vs->v_flags) == -1) { log_warning("vlist_record_from_table: vlist_append_new" " failed"); goto error; } } return record; error: if(record) { var_delete(record); } return NULL; }
int cf_load_list(ll_t *list, char *key, var_type_t type) { var_t *v, *item; ll_entry_t *pos; v = vtable_lookup(cf_config, key); if (v == NULL) { log_error("cf_load_list: %s not found", key); return -1; } // Scalar if (v->v_type == type) { if (LL_INSERT(list, v->v_data) == -1) { log_error("cf_load_list: LL_INSERT failed"); return -1; } return 0; } // Unexpected type if (v->v_type != VT_LIST) { log_error("config error: unexpected value for %s", key); return -1; } pos = LL_START((ll_t *) v->v_data); while ((item = ll_next(v->v_data, &pos))) { if (item->v_type != type) { log_error("config error: unexpected value in %s", key); return -1; } if (LL_INSERT(list, item->v_data) == -1) { log_error("cf_load_list: LL_INSERT failed"); return -1; } } return 0; }
var_t * vlist_record(var_t *scheme, ...) { va_list ap; var_t *record = NULL, *v; int flags; void *data; ll_t *ll; ll_entry_t *pos; va_start(ap, scheme); record = vlist_create(scheme->v_name, VF_KEEPNAME); if (record == NULL) { log_warning("vlist_record: vlist_create failed"); return NULL; } ll = scheme->v_data; pos = LL_START(ll); while ((v = ll_next(ll, &pos))) { flags = v->v_flags; flags |= VF_KEEPDATA | VF_KEEPNAME; flags &= ~(VF_COPYNAME | VF_COPYDATA); data = va_arg(ap, void *); if (vlist_append_new(record, v->v_type, v->v_name, data, flags) == -1) { log_warning("vlist_record: vlist_append_new failed"); var_delete(record); return NULL; } } va_end(ap); return record; }
var_t * exp_eval_in(var_t *needle, var_t *haystack) { var_t *v; ll_t *list; ll_entry_t *pos; int cmp; if (needle == NULL || haystack == NULL) { return EXP_EMPTY; } if (needle->v_data == NULL || haystack->v_data == NULL) { log_debug("exp_eval_in: empty value"); return EXP_EMPTY; } if (haystack->v_type != VT_LIST) { log_error("exp_eval_in: in operator only works on lists"); return NULL; } list = haystack->v_data; pos = LL_START(list); while ((v = ll_next(list, &pos))) { if (var_compare(&cmp, needle, v)) { log_error("exp_eval_in: var_compare failed"); } if (cmp == 0) { return EXP_TRUE; } } return EXP_FALSE; }
var_t * vlist_record_lookup(var_t *record, char *key) { ll_t *list = record->v_data; ll_entry_t *pos; var_t *item; /* * Bad search: but records usually only have less than 10 values. */ pos = LL_START(list); while ((item = ll_next(list, &pos))) { if (strcmp(item->v_name, key) == 0) { return item; } } return NULL; }
static var_t * exp_eval_list(exp_t *exp, var_t *mailspec) { ll_t *exp_list = exp->ex_data; ll_entry_t *pos; exp_t *exp_item; var_t *var_item, *var_list = NULL; var_list = vlist_create(NULL, VF_EXP_FREE); if (var_list == NULL) { log_sys_error("exp_eval_list: malloc"); goto error; } pos = LL_START(exp_list); while ((exp_item = ll_next(exp_list, &pos))) { var_item = exp_eval(exp_item, mailspec); if (vlist_append(var_list, var_item)) { log_sys_error("exp_eval_list: malloc"); goto error; } } return var_list; error: if (var_list) { var_delete(var_list); } return NULL; }
int vlist_record_keys_missing(var_t *record, var_t *table) { ll_t *list = record->v_data; ll_entry_t *pos; var_t *item; pos = LL_START(list); while ((item = ll_next(list, &pos))) { if ((item->v_flags & VF_KEY) == 0) { continue; } if (vtable_lookup(table, item->v_name) == NULL) { return -1; } } return 0; }
static var_t * exp_eval_function_simple(char *name, acl_function_t *af, ll_t *args) { ll_t garbage; ll_entry_t *pos; void **argv = NULL; var_t *v = NULL; int argc; int size; int i; var_t *arg; /* * Initialize garbage */ ll_init(&garbage); /* * Check argc */ argc = args->ll_size; if (argc != af->af_argc) { log_error("exp_eval_function_simple: function \"%s\" requires " "%d arguments", name, af->af_argc); return NULL; } size = (argc + 1) * sizeof (void *); argv = (void **) malloc(size); if (argv == NULL) { log_sys_error("exp_eval_function_simple: malloc"); return NULL; } memset(argv, 0, size); /* * Prepare argv */ pos = LL_START(args); for (i = 0; (arg = ll_next(args, &pos)); ++i) { if (af->af_types[i] == arg->v_type) { argv[i] = arg->v_data; continue; } /* * Type casting required. Don't care about the remains of arg * (freed with args!). */ arg = var_cast_copy(af->af_types[i], arg); if (arg == NULL) { log_error("exp_eval_function_simple: var_cast_copy " "failed"); goto error; } /* * Need to free copy later */ if (LL_INSERT(&garbage, arg) == -1) { log_error("exp_eval_function_simlpe: LL_INSERT " "failed"); var_delete(arg); goto error; } argv[i] = arg->v_data; } v = af->af_callback.fc_simple(argc, argv); error: ll_clear(&garbage, (ll_delete_t) var_delete); if (argv) { free(argv); } return v; }
static var_t * hitlist_record(hitlist_t *hl, var_t *attrs, int load_data) { ll_entry_t *pos; var_t *key; char *keystr; var_t *v; var_t *schema = NULL; VAR_INT_T zero = 0; char *name; name = hl->hl_table? hl->hl_table: hl->hl_name; schema = vlist_create(name, VF_KEEPNAME); if (schema == NULL) { log_error("hitlist_schema: vlist_create failed"); goto error; } pos = LL_START(hl->hl_keys); while ((key = ll_next(hl->hl_keys, &pos))) { // Impossible if (key->v_data == NULL) { log_error("hitlist_schema: key is NULL"); goto error; } // Bad configured if (key->v_type != VT_STRING) { log_error("hitlist_scheme: bad configuration %s:" " hitlist keys must be strings.", hl->hl_name); goto error; } keystr = key->v_data; // Variables if (keystr[0] == '$') { v = acl_variable_get(attrs, keystr); } // Regular symbol else { v = acl_symbol_get(attrs, keystr); } if (v == NULL) { log_error("hitlist_scheme: %s: lookup %s failed", hl->hl_name, keystr); goto error; } if (load_data && v->v_data == NULL) { log_error("hitlist_scheme: %s: key %s is NULL", hl->hl_name, keystr); goto error; } if (vlist_append_new(schema, v->v_type, keystr, load_data? v->v_data: NULL, VF_COPY | VF_KEY)) { log_error("hitlist_schema: %s: vlist_append_new" " failed", hl->hl_name); goto error; } } // Add value if (vlist_append_new(schema, VT_INT, hl->hl_value_field, load_data? &zero: NULL, VF_COPY)) { log_error("hitlist_schema: %s: vlist_append_new failed for %s", hl->hl_name, hl->hl_value_field); goto error; } if (vlist_append_new(schema, VT_INT, hl->hl_expire_field, load_data? &zero: NULL, VF_COPY)) { log_error("hitlist_schema: %s: vlist_append_new failed for %s", hl->hl_name, hl->hl_expire_field); goto error; } return schema; error: if (schema != NULL) { var_delete(schema); } return NULL; }
acl_action_type_t msgmod(milter_stage_t stage, char *stagename, var_t *mailspec, void *data, int depth) { msgmod_t *mm = data; void *ctx; acl_action_type_t action = ACL_ERROR; var_t **args = NULL; int argc; int size; var_t *v, *copy; int i; exp_t *exp; ll_t *ll; ll_entry_t *pos; /* * Get milter ctx pointer */ ctx = vtable_get(mailspec, "milter_ctx"); if (ctx == NULL) { log_error("msgmod: ctx not set"); goto error; } /* * Evaluate arguments */ argc = mm->mm_args->ll_size; size = (argc + 1) * sizeof (var_t *); args = (var_t **) malloc(size); if (args == NULL) { log_sys_error("msgmod: malloc"); goto error; } memset(args, 0, size); ll = mm->mm_args; pos = LL_START(ll); for (i = 0; i < argc; ++i) { exp = ll_next(ll, &pos); if (exp == NULL) { log_die(EX_SOFTWARE, "msgmod: empty argument"); } v = exp_eval(exp, mailspec); if (v == NULL) { log_error("msgmod: exp_eval failed"); goto error; } // Cast all aruments to VT_STRING if (v->v_type != VT_STRING) { copy = var_cast_copy(VT_STRING, v); if (copy == NULL) { log_error("msgmod: var_cast_copy failed"); goto error; } exp_free(v); /* * args are freed using exp_free. Set VF_EXP_FREE to * free copy. */ copy->v_flags |= VF_EXP_FREE; v = copy; } args[i] = v; } if (mm->mm_callback(ctx, argc, args)) { log_error("msgmod: mm_callback failed"); goto error; } action = ACL_NONE; error: /* * Free args */ for (i = 0; args[i]; ++i) { exp_free(args[i]); } if (args) { free(args); } return action; }