/* * Add an item onto the tail of the stack, freeing the bottom if at limit. Note * that the caller is responsible for allocating data. */ void paste_add_tail(struct paste_stack *ps, char *data, size_t size, u_int limit) { struct paste_buffer *pb; if (size == 0) return; while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); xfree(pb->data); xfree(pb); ARRAY_TRUNC(ps, 1); } pb = xmalloc(sizeof *pb); if (ARRAY_LENGTH(ps) > 0) { ARRAY_ADD(ps, ARRAY_FIRST(ps)); ARRAY_SET(ps, 0, pb); } else { ARRAY_ADD(ps, pb); } // ARRAY_INSERT(ps, 0, pb); pb->data = data; pb->size = size; }
int include_finish(void) { if (ARRAY_EMPTY(&parse_filestack)) return (1); log_debug2("finished file %s", parse_file->path); xfree(parse_file); parse_file = ARRAY_LAST(&parse_filestack); ARRAY_TRUNC(&parse_filestack, 1); return (0); }
void paste_add(struct paste_stack *ps, char *data, u_int limit) { struct paste_buffer *pb; while (ARRAY_LENGTH(ps) >= limit) ARRAY_TRUNC(ps, 1); pb = xmalloc(sizeof *pb); ARRAY_INSERT(ps, 0, pb); pb->data = data; if (gettimeofday(&pb->tv, NULL) != 0) fatal("gettimeofday"); }
/* * Add an item onto the top of the stack, freeing the bottom if at limit. Note * that the caller is responsible for allocating data. */ void paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit) { struct paste_buffer *pb; if (size == 0) return; while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); free(pb->data); free(pb); ARRAY_TRUNC(ps, 1); } pb = xmalloc(sizeof *pb); ARRAY_INSERT(ps, 0, pb); pb->data = data; pb->size = size; }
void paste_add(struct paste_stack *ps, u_char *data, size_t size, u_int limit) { struct paste_buffer *pb; if (*data == '\0') return; while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); xfree(pb->data); xfree(pb); ARRAY_TRUNC(ps, 1); } pb = xmalloc(sizeof *pb); ARRAY_INSERT(ps, 0, pb); pb->data = data; pb->size = size; if (gettimeofday(&pb->tv, NULL) != 0) fatal("gettimeofday"); }
/* Check mail against next rule or part of expression. */ int mail_match(struct mail_ctx *mctx, struct msg *msg, struct msgbuf *msgbuf) { struct account *a = mctx->account; struct mail *m = mctx->mail; struct expritem *ei; struct replstrs *users; int should_free, this = -1, error = MAIL_CONTINUE; char desc[DESCBUFSIZE]; set_wrapped(m, ' '); /* If blocked, check for msgs from parent. */ if (mctx->msgid != 0) { if (msg == NULL || msg->id != mctx->msgid) return (MAIL_BLOCKED); mctx->msgid = 0; if (msg->type != MSG_DONE) fatalx("unexpected message"); if (msgbuf->buf != NULL && msgbuf->len != 0) { strb_destroy(&m->tags); m->tags = msgbuf->buf; reset_tags(&m->tags); } ei = mctx->expritem; switch (msg->data.error) { case MATCH_ERROR: return (MAIL_ERROR); case MATCH_TRUE: this = 1; break; case MATCH_FALSE: this = 0; break; default: fatalx("unexpected response"); } apply_result(ei, &mctx->result, this); goto next_expritem; } /* Check for completion and end of ruleset. */ if (mctx->done) return (MAIL_DONE); if (mctx->rule == NULL) { switch (conf.impl_act) { case DECISION_NONE: log_warnx("%s: reached end of ruleset. no " "unmatched-mail option; keeping mail", a->name); m->decision = DECISION_KEEP; break; case DECISION_KEEP: log_debug2("%s: reached end of ruleset. keeping mail", a->name); m->decision = DECISION_KEEP; break; case DECISION_DROP: log_debug2("%s: reached end of ruleset. dropping mail", a->name); m->decision = DECISION_DROP; break; } return (MAIL_DONE); } /* Expression not started. Start it. */ if (mctx->expritem == NULL) { /* Start the expression. */ mctx->result = 0; mctx->expritem = TAILQ_FIRST(mctx->rule->expr); } /* Check this expression item and adjust the result. */ ei = mctx->expritem; /* Handle short-circuit evaluation. */ switch (ei->op) { case OP_NONE: break; case OP_AND: /* And and the result is already false. */ if (!mctx->result) goto next_expritem; break; case OP_OR: /* Or and the result is already true. */ if (mctx->result) goto next_expritem; break; } switch (ei->match->match(mctx, ei)) { case MATCH_ERROR: return (MAIL_ERROR); case MATCH_PARENT: return (MAIL_BLOCKED); case MATCH_TRUE: this = 1; break; case MATCH_FALSE: this = 0; break; default: fatalx("unexpected op"); } apply_result(ei, &mctx->result, this); ei->match->desc(ei, desc, sizeof desc); log_debug3("%s: tried %s, result now %d", a->name, desc, mctx->result); next_expritem: /* Move to the next item. If there is one, then return. */ mctx->expritem = TAILQ_NEXT(mctx->expritem, entry); if (mctx->expritem != NULL) return (MAIL_CONTINUE); log_debug3("%s: finished rule %u, result %d", a->name, mctx->rule->idx, mctx->result); /* If the result was false, skip to find the next rule. */ if (!mctx->result) goto next_rule; log_debug2("%s: matched to rule %u", a->name, mctx->rule->idx); /* * If this rule is stop, mark the context so when we get back after * delivery we know to stop. */ if (mctx->rule->stop) mctx->done = 1; /* Handle nested rules. */ if (!TAILQ_EMPTY(&mctx->rule->rules)) { log_debug2("%s: entering nested rules", a->name); /* * Stack the current rule (we are at the end of it so the * the expritem must be NULL already). */ ARRAY_ADD(&mctx->stack, mctx->rule); /* Continue with the first rule of the nested list. */ mctx->rule = TAILQ_FIRST(&mctx->rule->rules); return (MAIL_CONTINUE); } mctx->matched = 1; /* Handle lambda actions. */ if (mctx->rule->lambda != NULL) { users = find_delivery_users(mctx, NULL, &should_free); chained = MAXACTIONCHAIN; if (fill_from_action(mctx, mctx->rule, mctx->rule->lambda, users) != 0) { if (should_free) ARRAY_FREEALL(users); return (MAIL_ERROR); } if (should_free) ARRAY_FREEALL(users); error = MAIL_DELIVER; } /* Fill the delivery action queue. */ if (!ARRAY_EMPTY(mctx->rule->actions)) { chained = MAXACTIONCHAIN; if (fill_from_strings(mctx, mctx->rule, mctx->rule->actions) != 0) return (MAIL_ERROR); error = MAIL_DELIVER; } next_rule: /* Move to the next rule. */ mctx->ruleidx = mctx->rule->idx; /* save last index */ mctx->rule = TAILQ_NEXT(mctx->rule, entry); /* If no more rules, try to move up the stack. */ while (mctx->rule == NULL) { if (ARRAY_EMPTY(&mctx->stack)) break; log_debug2("%s: exiting nested rules", a->name); mctx->rule = ARRAY_LAST(&mctx->stack); mctx->rule = TAILQ_NEXT(mctx->rule, entry); ARRAY_TRUNC(&mctx->stack, 1); } return (error); }