void strb_vadd(struct strb **sbp, const char *key, const char *value, va_list ap) { struct strb *sb = *sbp; size_t size, keylen, valuelen; u_int n; struct strbent sbe, *sbep; va_list aq; keylen = strlen(key) + 1; va_copy(aq, ap); valuelen = xvsnprintf(NULL, 0, value, aq) + 1; va_end(aq); size = sb->str_size; while (sb->str_size - sb->str_used < keylen + valuelen) { if (STRB_SIZE(sb) > SIZE_MAX / 2) fatalx("size too large"); sb->str_size *= 2; } if (size != sb->str_size) { sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb)); memmove( STRB_ENTBASE(sb), STRB_BASE(sb) + size, STRB_ENTSIZE(sb)); memset(STRB_BASE(sb) + size, 0, sb->str_size - size); } sbep = strb_address(sb, key); if (sbep == NULL) { if (sb->ent_used > sb->ent_max) { /* Allocate some more entries. */ n = sb->ent_max; size = STRB_SIZE(sb); if (sb->ent_max > UINT_MAX / 2) fatalx("ent_max too large"); sb->ent_max *= 2; if (STRB_SIZE(sb) < size) fatalx("size too large"); sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb)); memset(STRB_ENTRY(sb, n), 0, STRB_ENTSIZE(sb) / 2); } sbep = STRB_ENTRY(sb, sb->ent_used); sb->ent_used++; sbe.key = sb->str_used; memcpy(STRB_KEY(sb, &sbe), key, keylen); sb->str_used += keylen; } else memcpy(&sbe, sbep, sizeof sbe); sbe.value = sb->str_used; xvsnprintf(STRB_VALUE(sb, &sbe), valuelen, value, ap); sb->str_used += valuelen; memcpy(sbep, &sbe, sizeof sbe); }
int match_command_match(struct mail_ctx *mctx, struct expritem *ei) { struct match_command_data *data = ei->data; struct account *a = mctx->account; struct mail *m = mctx->mail; struct io *io = mctx->io; struct msg msg; struct msgbuf msgbuf; struct userdata *ud; char *user; set_wrapped(m, '\n'); /* * We are called as the child so to change uid this needs to be done * largely in the parent. */ memset(&msg, 0, sizeof msg); msg.type = MSG_COMMAND; msg.id = m->idx; msg.data.account = a; msg.data.cmddata = data; user = conf.cmd_user; if (data->user.str != NULL) user = replacestr(&data->user, m->tags, m, &m->rml); if ((ud = user_lookup(user, conf.user_order)) == NULL) { log_warnx("%s: bad user: %s", a->name, user); return (MATCH_ERROR); } if (data->user.str != NULL) xfree(user); msg.data.uid = ud->uid; msg.data.gid = ud->gid; update_tags(&m->tags, ud); user_free(ud); msgbuf.buf = m->tags; msgbuf.len = STRB_SIZE(m->tags); mail_send(m, &msg); if (privsep_send(io, &msg, &msgbuf) != 0) fatalx("privsep_send error"); reset_tags(&m->tags); mctx->msgid = msg.id; return (MATCH_PARENT); }
void strb_clear(struct strb **sbp) { struct strb *sb = *sbp; sb->ent_used = 0; sb->ent_max = STRBENTRIES; sb->str_size = STRBBLOCK; sb->str_used = 0; sb = *sbp = xrealloc(sb, 1, STRB_SIZE(sb)); memset(STRB_BASE(sb), 0, sb->str_size + STRB_ENTSIZE(sb)); }
int child_deliver(struct child *child, struct io *pio) { struct child_deliver_data *data = child->data; struct account *a = data->account; struct mail *m = data->mail; struct msg msg; struct msgbuf msgbuf; int error = 0; #ifdef DEBUG xmalloc_clear(); COUNTFDS(a->name); #endif log_debug2("%s: deliver started, pid %ld", a->name, (long) getpid()); #ifdef HAVE_SETPROCTITLE setproctitle("%s[%lu]", data->name, (u_long) geteuid()); #endif /* Call the hook. */ memset(&msg, 0, sizeof msg); data->hook(0, a, &msg, data, &msg.data.error); /* Inform parent we're done. */ msg.type = MSG_DONE; msg.id = 0; msgbuf.buf = m->tags; msgbuf.len = STRB_SIZE(m->tags); if (privsep_send(pio, &msg, &msgbuf) != 0) fatalx("privsep_send error"); do { if (privsep_recv(pio, &msg, NULL) != 0) fatalx("privsep_recv error"); } while (msg.type != MSG_EXIT); #ifdef DEBUG COUNTFDS(a->name); xmalloc_report(getpid(), a->name); #endif return (error); }