int variable_append(VarList *list, Instruction *i, int addr) { if (!i) kasm_exit("Null instruction in variable structure.", 0); if (!list) kasm_exit("Invalid variable list for var.", i->page); if (i->list->size < 3) kasm_exit("Variable syntax error.", i->page); int next_addr; StrNode *data_type = i->list->head; StrNode *name = data_type->next; StrNode *value_tok = name->next; verify_variable_name(name->str, i->page); int value = immediate_convert(value_tok->str, i->page); Var *v = NULL; if (!strcmp(".data", data_type->str)) { v = var_create(name->str); v->type = DATA; v->value = value; v->addr = addr; next_addr = addr + 1; } else if (!strcmp(".array", data_type->str)) { v = var_create(name->str); v->type = ARRAY; v->value = value; v->addr = addr; next_addr = addr + value; } else { kasm_exit("Invalid data type.", i->page); } // Hack solution using the link function to check for duplicates if (link_var_name_to_address(list, v->name) != -1) kasm_exit("Duplicate variable name found.", i->page); if (list->size == 0) { list->head = v; list->tail = v; } else { v->prev = list->tail; list->tail->next = v; list->tail = v; } list->size++; return next_addr; }
static var_t * string_tolower(int argc, void **argv) { util_tolower((char *) argv[0]); return var_create(VT_STRING, NULL, argv[0], VF_COPYDATA | VF_EXP_FREE); }
var_t * exp_math_float(int op, var_t *left, var_t *right) { VAR_FLOAT_T *l, *r, x; var_t *v; l = left->v_data; r = right->v_data; if (l == NULL || r == NULL) { log_debug("exp_math_float: empty value"); return EXP_EMPTY; } switch (op) { case '+': x = *l + *r; break; case '-': x = *l - *r; break; case '*': x = *l * *r; break; case '/': x = *l / *r; break; default: log_error("exp_math_float: bad operation"); return NULL; } v = var_create(VT_FLOAT, NULL, &x, VF_COPYDATA | VF_EXP_FREE); if (v == NULL) { log_error("exp_math_float: var_create failed"); } return v; }
static void cf_load_functions(void) { cf_function_t *function; var_t *v; void *data; for(function = cf_functions; function->cf_type; ++function) { if(vtable_get(cf_config, function->cf_name)) { continue; } function->cf_callback(&data); if (data == NULL) { log_die(EX_CONFIG, "cf_load_functions: callback for " "\"%s\" failed", function->cf_name); } v = var_create(function->cf_type, function->cf_name, data, VF_KEEPNAME); if (v == NULL) { log_die(EX_CONFIG, "cf_load_functions: var_create " "failed"); } if(vtable_set(cf_config, v) == -1) { log_die(EX_CONFIG, "cf_load_functions: var_table_set " "failed"); } } return; }
static var_t * string_strlen(int argc, void **argv) { VAR_INT_T len; len = strlen(argv[0]); return var_create(VT_INT, NULL, &len, VF_COPYDATA | VF_EXP_FREE); }
static var_t * string_strcmp(int argc, void **argv) { VAR_INT_T cmp; cmp = strcmp(argv[0], argv[1]); return var_create(VT_INT, NULL, &cmp, VF_COPYDATA | VF_EXP_FREE); }
static var_t * string_mailaddr(int argc, void **argv) { char buffer[BUFLEN]; if (util_strmail(buffer, sizeof buffer, argv[0]) == -1) { log_error("string_mail: util_strmail failed"); return NULL; } return var_create(VT_STRING, NULL, buffer, VF_COPYDATA | VF_EXP_FREE); }
var_t * vlist_create(char *name, int flags) { var_t *list; list = var_create(VT_LIST, name, NULL, flags | VF_CREATE); if (list == NULL) { log_error("vlist_create: var_create failed"); } return list; }
exp_t * exp_constant(var_type_t type, void *data, int flags) { var_t *v = NULL; v = var_create(type, NULL, data, flags); if (v == NULL) { log_die(EX_SOFTWARE, "exp_constant: var_create failed"); } return exp_create(EX_CONSTANT, v); }
var_t * vtable_create(char *name, int flags) { var_t *table; table = var_create(VT_TABLE, name, NULL, flags | VF_CREATE); if (table == NULL) { log_error("vtable_create: var_create failed"); } return table; }
int vtable_set_new(var_t *table, var_type_t type, char *name, void *data, int flags) { var_t *v; v = var_create(type, name, data, flags); if (v == NULL) { log_error("vtable_set_new: var_create failed"); return -1; } return vtable_set(table, v); }
/* set a variable value * ----------------------------------------------------------------------- */ const char *var_setvint(const char *v, int i, int flags) { struct var *var; var = var_create(v, flags); var->flags |= flags; if(var->sa.a == 0) var->sa.s = NULL; stralloc_copyb(&var->sa, v, var->len); stralloc_catc(&var->sa, '='); stralloc_catlong(&var->sa, i); stralloc_nul(&var->sa); var->offset = var->len + 1; return var->sa.s; }
var_t * cf_constant(char *name) { cf_constant_t *cc; for(cc = cf_constants; cc->cc_name; ++cc) { if (strcmp(cc->cc_name, name) == 0) { return var_create(cc->cc_type, NULL, cc->cc_ptr, VF_KEEP); } } parser_error(&cf_parser, "Unknown token %s", name); return NULL; }
cell_t *parse_word(seg_t w, cell_t *module, unsigned int n, cell_t *entry) { cell_t *c; cell_t *data = NULL; csize_t in = 0, out = 1; if(w.s[0] == '?' && w.n == 1) { c = param(T_ANY, entry); } else if(in = 1, out = 1, match_param_word("ap", w, &in, &out)) { c = func(OP_ap, ++in, ++out); } else if(in = 1, out = 1, match_param_word("comp", w, &in, &out)) { in += 2; c = func(OP_compose, in, ++out); } else if(in = 1, out = 1, match_param_word("external", w, &in, &out)) { c = func(OP_external, ++in, out); } else { cell_t *e = lookup_word(w); if(!e) e = module_lookup_compiled(w, &module); if(e) { in = e->entry.in; out = e->entry.out; if(FLAG(*e, entry, PRIMITIVE)) { if(e->op == OP_placeholder) { c = func(OP_placeholder, n + 1, 1); int x = trace_alloc(entry, n + 2); in = n; out = 1; data = var_create(T_LIST, tc_get(entry, x), 0, 0); } else { c = func(e->op, e->entry.in, e->entry.out); } } else { c = func(OP_exec, e->entry.in + 1, e->entry.out); data = e; } } else { return NULL; } } if(in) c->expr.arg[0] = (cell_t *)(intptr_t)(in - 1); TRAVERSE(c, out) { *p = dep(c); }
var_t * exp_math_string(int op, var_t *left, var_t *right) { char *l, *r, x[EXP_STRLEN]; var_t *v; l = left->v_data; r = right->v_data; if (l == NULL) { l = "(null)"; } if (r == NULL) { r = "(null)"; } switch (op) { case '+': break; default: log_error("exp_math_string: bad operation"); return NULL; } if (util_concat(x, sizeof x, l, r, NULL) == -1) { log_error("exp_math_string: util_concat: buffer exhausted"); return NULL; } v = var_create(VT_STRING, NULL, x, VF_COPYDATA | VF_EXP_FREE); if (v == NULL) { log_error("exp_math_string: var_create failed"); } return v; }
/* set a variable * ----------------------------------------------------------------------- */ struct var *var_set(char *v, int flags) { struct var *var; /* find/create the variable */ if((var = var_create(v, flags)) == NULL) return var; /* free if it was a previously allocated string */ if(var->sa.a) stralloc_free(&var->sa); stralloc_init(&var->sa); var->sa.s = v; var->sa.len = str_len(v); var->offset = var->len; if(var->len < var->sa.len) var->offset++; return var; }
int vlist_append_new(var_t *list, var_type_t type, char *name, void *data, int flags) { var_t *v; v = var_create(type, name, data, flags); if (v == NULL) { log_warning("vlist_append_new: var_create failed"); return -1; } if (vlist_append(list, v) == 0) { return 0; } log_error("vlist_append_new: vlist_append failed"); var_delete(v); return -1; }
static var_t * exp_eval_macro(exp_t *exp, var_t *mailspec) { VAR_INT_T *stage; var_t *v; char *value; if (exp->ex_type != EX_MACRO) { log_error("exp_eval_macro: bad type"); return NULL; } stage = vtable_get(mailspec, "stage"); if (stage == NULL) { log_error("exp_eval_macro: milter stage not set"); return NULL; } value = milter_macro_lookup(*stage, exp->ex_data, mailspec); if (value == NULL) { return EXP_EMPTY; } v = var_create(VT_STRING, exp->ex_data, value, VF_KEEPNAME | VF_COPYDATA | VF_EXP_FREE); if (v == NULL) { log_error("exp_eval_macro: var_create failed"); return NULL; } return v; }
/* * Expand an input line and return it. * * Returns: 0 on failure * 1 on success and exp has expanded input */ int variable_expansion(JCR *jcr, char *inp, POOLMEM *&exp) { var_t *var_ctx; var_rc_t status; char *outp; int in_len, out_len; int rtn_stat = 0; in_len = strlen(inp); outp = NULL; out_len = 0; /* * Create context */ if ((status = var_create(&var_ctx)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot create var context: ERR=%s\n"), var_strerror(var_ctx, status)); goto bail_out; } /* * Define callback */ if ((status = var_config(var_ctx, VAR_CONFIG_CB_VALUE, lookup_var, (void *)jcr)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot set var callback: ERR=%s\n"), var_strerror(var_ctx, status)); goto bail_out; } /* * Define special operations */ if ((status = var_config(var_ctx, VAR_CONFIG_CB_OPERATION, operate_var, (void *)jcr)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot set var operate: ERR=%s\n"), var_strerror(var_ctx, status)); goto bail_out; } /* * Unescape in place */ if ((status = var_unescape(var_ctx, inp, in_len, inp, in_len+1, 0)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, status)); goto bail_out; } in_len = strlen(inp); /* * Expand variables */ if ((status = var_expand(var_ctx, inp, in_len, &outp, &out_len, 0)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot expand expression \"%s\": ERR=%s\n"), inp, var_strerror(var_ctx, status)); goto bail_out; } /* * Unescape once more in place */ if ((status = var_unescape(var_ctx, outp, out_len, outp, out_len+1, 1)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot unescape string: ERR=%s\n"), var_strerror(var_ctx, status)); goto bail_out; } pm_strcpy(exp, outp); rtn_stat = 1; bail_out: /* * Destroy expansion context */ if ((status = var_destroy(var_ctx)) != VAR_OK) { Jmsg(jcr, M_ERROR, 0, _("Cannot destroy var context: ERR=%s\n"), var_strerror(var_ctx, status)); } if (outp) { free(outp); } return rtn_stat; }
int spamd_query(milter_stage_t stage, char *name, var_t *attrs) { int sock = 0; var_t *symbols = NULL; int n; char recv_header[BUFLEN]; char buffer[BUFLEN]; char *p, *q; char *message = NULL; VAR_INT_T spam; VAR_FLOAT_T score; VAR_INT_T *message_size; long header_size, size; /* * Build received header */ header_size = spamd_header(attrs, recv_header, sizeof recv_header); if (header_size == -1) { log_error("spamd_query: spamd_header failed"); goto error; } log_debug("spamd_query: received header:\n%s", recv_header); /* * Get message size */ message_size = vtable_get(attrs, "message_size"); if (message_size == NULL) { log_error("spamd_query: vtable_get failed"); goto error; } size = header_size + *message_size; /* * Allocate message buffer */ message = (char *) malloc(size + 1); if (message == NULL) { log_sys_error("spamd_query: malloc"); goto error; } /* * Dump message */ memcpy(message, recv_header, header_size); if (milter_dump_message(message + header_size, size - header_size + 1, attrs) == -1) { log_error("spamd_query: milter_dump_message failed"); goto error; } snprintf(buffer, sizeof(buffer), "SYMBOLS SPAMC/1.2\r\n" "Content-length: %ld\r\n\r\n", size); sock = sock_connect_rr(&spamd_srr); if (sock == -1) { log_error("spamd_query: sock_connect failed"); goto error; } /* * Write spamassassin request */ if (write(sock, buffer, strlen(buffer)) == -1) { log_sys_error("spamd_query: write"); goto error; } /* * Write message */ if (write(sock, message, size) == -1) { log_sys_error("spamd_query: write"); goto error; } /* * Read response */ n = read(sock, buffer, sizeof buffer - 1); if (n == -1) { log_sys_error("spamd_query: read"); goto error; } buffer[n] = 0; /* * No answer. Seen when spamd ran out of mem. */ if (n == 0) { log_error("spamd_query: no data received"); goto error; } /* * Parse response */ p = buffer; if (strncmp(p, SPAMD_SPAMD, SPAMD_SPAMDLEN)) { spamd_printable_buffer(p, SPAMD_SPAMDLEN + 1); log_error("spamd_query: protocol error: expected='%s' " "received='%s'", SPAMD_SPAMD, p); goto error; } p += SPAMD_SPAMDLEN; if (strncmp(p, SPAMD_VERSION, SPAMD_VERSIONLEN)) { spamd_printable_buffer(p, SPAMD_VERSIONLEN + 1); log_notice("spamd_query: protocol version mismtach: " "expected='%s' received='%s'", SPAMD_VERSION, p); } p += SPAMD_VERSIONLEN; p = strstr(p, SPAMD_EX_OK); if(p == NULL) { log_error("spamd_query: spamd returned non EX_OK"); goto error; } /* * Spamd returns 2 lines. Read 2nd line if neccessary. */ p += SPAMD_EX_OKLEN; if(strlen(p) <= 2) { /* '\r\n' */ n = read(sock, buffer, sizeof(buffer)); if (n == -1) { log_sys_error("spamd_query: read"); goto error; } buffer[n] = 0; p = buffer; } else { p += 2; /* '\r\n' */ } /* * Parse results */ if(strncmp(p, SPAMD_SPAM, SPAMD_SPAMLEN)) { spamd_printable_buffer(p, SPAMD_SPAMLEN + 1); log_error("spamd_query: protocol error: expected='%s' " "received='%s'", SPAMD_SPAM, p); goto error; } p += SPAMD_SPAMLEN; if(!strncmp(p, SPAMD_TRUE, SPAMD_TRUELEN)) { spam = 1; p += SPAMD_TRUELEN; } else if(!strncmp(p, SPAMD_FALSE, SPAMD_FALSELEN)) { spam = 0; p += SPAMD_FALSELEN; } else { spamd_printable_buffer(p, (SPAMD_TRUELEN > SPAMD_FALSELEN ? SPAMD_TRUELEN: SPAMD_FALSELEN) + 1); log_error("spamd_query: protocol error: expected: '%s|%s' " "received='%s'", SPAMD_TRUE, SPAMD_FALSE, p); goto error; } /* * Cut score. */ q = strchr(p, ' '); if (q == NULL) { log_error("spamd_query: protocol error: couldn't find the " "next space character"); goto error; } *q++ = 0; score = (VAR_FLOAT_T) strtod(p, NULL); /* * Set SYMBOLS */ p = strchr(q, '\r'); if (p == NULL) { log_error("spamd_query: protocol error: couldn't find the " "start of the spamd symbols"); goto error; } p += 4; /* \r\n\r\n */ q = strchr(p, '\r'); if (q == NULL) { log_error("spamd_query: protocol error: couldn't find the " "end of the spamd symbols"); goto error; } *q = 0; log_message(LOG_ERR, attrs, "spamd: spam=%d score=%.1f symbols=%s", spam, score, p); symbols = var_create(VT_LIST, "spamd_symbols", NULL, VF_KEEPNAME | VF_CREATE); if (symbols == NULL) { log_error("spamd_query: var_create failed"); goto error; } do { q = strchr(p, ','); if (q) { *q = 0; } if (vlist_append_new(symbols, VT_STRING, NULL, p, VF_COPYDATA) == -1) { log_error("spamd_query: vlist_append failed"); goto error; } p = q + 1; } while (q); if (vtable_setv(attrs, VT_INT, "spamd_spam", &spam, VF_KEEPNAME | VF_COPYDATA, VT_FLOAT, "spamd_score", &score, VF_KEEPNAME | VF_COPYDATA, VT_NULL)) { log_error("spamd_query: vtable_setv failed"); goto error; } if (vtable_set(attrs, symbols)) { log_error("spamd_query: vtable_set failed"); goto error; } close(sock); free(message); return 0; error: if (message) { free(message); } if (sock > 0) { close(sock); } if (symbols) { var_delete(symbols); } return -1; }
var_type* var_var_create(var_type* v) { var_type* var = var_create(); var->type = VAR; var->content.var_value = v; return var; }
var_type* int_var_create(int v) { var_type* var = var_create(); var->type = INT; var->content.integer_value = v; return var; }