summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--maildrop.c85
-rw-r--r--pop3d.h1
-rw-r--r--session.c53
3 files changed, 53 insertions, 86 deletions
diff --git a/maildrop.c b/maildrop.c
index 634fa3f..ce242f9 100644
--- a/maildrop.c
+++ b/maildrop.c
@@ -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 *);
@@ -188,7 +187,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:
@@ -208,11 +206,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",
@@ -312,16 +307,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
@@ -337,43 +353,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)
{
diff --git a/pop3d.h b/pop3d.h
index 3035795..15b9b09 100644
--- a/pop3d.h
+++ b/pop3d.h
@@ -36,7 +36,6 @@ enum imsg_type {
IMSG_MAILDROP_RSET,
IMSG_MAILDROP_LIST,
IMSG_MAILDROP_LISTALL,
- IMSG_MAILDROP_UIDLALL,
IMSG_MAILDROP_UPDATE
};
diff --git a/session.c b/session.c
index 77402a3..a042f58 100644
--- a/session.c
+++ b/session.c
@@ -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