diff options
-rw-r--r-- | maildrop.c | 85 | ||||
-rw-r--r-- | pop3d.h | 1 | ||||
-rw-r--r-- | session.c | 53 |
3 files changed, 53 insertions, 86 deletions
@@ -38,9 +38,8 @@ static void retr(struct imsgev *, struct imsg *, struct m_backend *); static void dele(struct imsgev *, struct imsg *, struct m_backend *); static void rset(struct imsgev *, struct imsg *, struct m_backend *); static void list(struct imsgev *, struct imsg *, struct m_backend *); -static void list_all(struct imsgev *, struct imsg *, struct m_backend *, int); +static void list_all(struct imsgev *, struct imsg *, struct m_backend *); static void do_list(unsigned int, size_t *, char *, size_t); -static void *do_list_all(int, size_t *); static struct m_backend *m_backend_lookup(enum m_type); static void sig_handler(int, short, void *); static void needfd(struct imsgev *); @@ -173,7 +172,6 @@ static void session_imsgev(struct imsgev *iev, int code, struct imsg *imsg) { struct m_backend *mb = iev->data; - int uidl = 0; switch (code) { case IMSGEV_IMSG: @@ -193,11 +191,8 @@ session_imsgev(struct imsgev *iev, int code, struct imsg *imsg) case IMSG_MAILDROP_LIST: list(iev, imsg, mb); break; - case IMSG_MAILDROP_UIDLALL: - uidl = 1; - /* FALLTHROUGH */ case IMSG_MAILDROP_LISTALL: - list_all(iev, imsg, mb, uidl); + list_all(iev, imsg, mb); break; default: logit(LOG_DEBUG, "%s: unexpected imsg %u", @@ -297,16 +292,37 @@ list(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb) } static void -list_all(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb, int uidl) +list_all(struct imsgev *iev, struct imsg *imsg, struct m_backend *mb) { - void *res; - size_t sz; - - res = do_list_all(uidl, &sz); - /* XXX watchout for sz > MAX_IMSGSIZE */ - imsgev_xcompose(iev, - (uidl) ? IMSG_MAILDROP_UIDLALL : IMSG_MAILDROP_LISTALL, - imsg->hdr.peerid, 0, -1, res, sz, "maildrop_list"); + struct list_res res; + size_t i; + int *uidl = imsg->data; + + for (i = 0; i < m.nmsgs; i++) { + if (m.msgs_index[i]->flags & F_DELE) + continue; + + res.idx = i; + res.uidl = *uidl; + if (*uidl) { + strlcpy(res.u.hash, m.msgs_index[i]->hash, + sizeof(res.u.hash)); + } else + res.u.sz = m.msgs_index[i]->sz; + + imsgev_xcompose(iev, IMSG_MAILDROP_LISTALL, + imsg->hdr.peerid, 0, -1, &res, sizeof(res), + "maildrop_list"); + } + + /* terminal sentinel: hash = "" and sz = 0 */ + if (*uidl) + strlcpy(res.u.hash, "", sizeof(res.u.hash)); + else + res.u.sz = 0; + + imsgev_xcompose(iev, IMSG_MAILDROP_LISTALL, imsg->hdr.peerid, + 0, -1, &res, sizeof(res), "maildrop_list"); } static void @@ -322,43 +338,6 @@ do_list(unsigned int idx, size_t *sz, char *hash, size_t hash_sz) strlcpy(hash, m.msgs_index[idx]->hash, hash_sz); } -static void * -do_list_all(int uidl, size_t *sz) -{ - size_t i, j, *nsz = NULL; - char *nhash = NULL; - - if (uidl) { - nhash = xcalloc(m.nmsgs, SHA1_DIGEST_STRING_LENGTH, "list_all"); - } else - nsz = xcalloc(m.nmsgs, sizeof(size_t), "list_all"); - - for (i = 0; i < m.nmsgs; i++) { - - if (uidl) { - j = i * SHA1_DIGEST_STRING_LENGTH; - if (m.msgs_index[i]->flags & F_DELE) - nhash[j] = '\0'; - else - strlcpy(nhash + j, m.msgs_index[i]->hash, - SHA1_DIGEST_STRING_LENGTH); - } else { - if (m.msgs_index[i]->flags & F_DELE) - nsz[i] = 0; - else - nsz[i] = m.msgs_index[i]->sz; - } - } - - if (uidl) { - *sz = m.nmsgs * SHA1_DIGEST_STRING_LENGTH; - return (nhash); - } else { - *sz = m.nmsgs * sizeof(size_t); - return (nsz); - } -} - static void needfd(struct imsgev *iev) { @@ -36,7 +36,6 @@ enum imsg_type { IMSG_MAILDROP_RSET, IMSG_MAILDROP_LIST, IMSG_MAILDROP_LISTALL, - IMSG_MAILDROP_UIDLALL, IMSG_MAILDROP_UPDATE }; @@ -85,7 +85,7 @@ static void handle_init(struct session *, struct imsg *); static void handle_retr(struct session *, struct imsg *); static void handle_dele(struct session *, struct imsg *); static void handle_list(struct session *, struct imsg *); -static void handle_list_all(struct session *, struct imsg *, int); +static void handle_list_all(struct session *, struct imsg *); static void handle_update(struct session *, struct imsg *); static void needfd(struct imsgev *); static void pop3_debug(char *, ...); @@ -417,9 +417,10 @@ trans_command(struct session *s, int cmd, char *args) static void get_list_all(struct session *s, int uidl) { - imsgev_xcompose(&s->iev_maildrop, - (uidl) ? IMSG_MAILDROP_UIDLALL : IMSG_MAILDROP_LISTALL, - s->id, 0, -1, NULL, 0, "list_all"); + io_pause(&s->io, IO_PAUSE_IN); + session_reply(s, "+OK"); + imsgev_xcompose(&s->iev_maildrop, IMSG_MAILDROP_LISTALL, + s->id, 0, -1, &uidl, sizeof(uidl), "list_all"); } static void @@ -443,7 +444,6 @@ static void maildrop_imsgev(struct imsgev *iev, int code, struct imsg *imsg) { struct session key, *r; - int uidl = 0; switch (code) { case IMSGEV_IMSG: @@ -470,11 +470,8 @@ maildrop_imsgev(struct imsgev *iev, int code, struct imsg *imsg) case IMSG_MAILDROP_LIST: handle_list(r, imsg); break; - case IMSG_MAILDROP_UIDLALL: - uidl = 1; - /* FALLTHROUGH */ case IMSG_MAILDROP_LISTALL: - handle_list_all(r, imsg, uidl); + handle_list_all(r, imsg); break; case IMSG_MAILDROP_UPDATE: handle_update(r, imsg); @@ -602,36 +599,28 @@ handle_list(struct session *s, struct imsg *imsg) io_set_write(&s->io); } -/* DELEted msg's hash and sz will be zero, ignore them */ +/* List terminal is indicated by hash being empty string or sz = 0 */ static void -handle_list_all(struct session *s, struct imsg *imsg, int uidl) +handle_list_all(struct session *s, struct imsg *imsg) { - char *nhash = NULL; - size_t datalen, i, item_sz, j, nitems, *nsz = NULL; + struct list_res *res = imsg->data; - datalen = imsg->hdr.len - sizeof(imsg->hdr); - item_sz = (uidl) ? SHA1_DIGEST_STRING_LENGTH : sizeof(size_t); - nitems = datalen / item_sz; - if (uidl) - nhash = imsg->data; + if (res->uidl) + if (strlen(res->u.hash)) + session_reply(s, "%s", res->u.hash); + else + goto end; else - nsz = imsg->data; - - session_reply(s, "+OK"); - for (i = 0; i < nitems; i++) { - if (uidl) { - j = i * SHA1_DIGEST_STRING_LENGTH; - if (nhash[j]) - session_reply(s, "%zu %s", i + 1, nhash + j); - } else { - if (nsz[i]) - session_reply(s, "%zu %zu", i + 1, nsz[i]); - } - } + if (res->u.sz) + session_reply(s, "%zu", res->u.sz); + else + goto end; + return; +end: session_reply(s, "."); io_set_write(&s->io); - + io_resume(&s->io, IO_PAUSE_IN); } static void |