diff options
Diffstat (limited to 'imap.c')
-rw-r--r-- | imap.c | 107 |
1 files changed, 55 insertions, 52 deletions
diff --git a/imap.c b/imap.c index 54c02bf..8437a2c 100644 --- a/imap.c +++ b/imap.c @@ -81,7 +81,7 @@ static int imapClose(void *_tls) { return error; } -void imapOpen(FILE **read, FILE **write, const char *host, const char *port) { +struct IMAP imapOpen(const char *host, const char *port) { struct tls *client = tls_client(); if (!client) errx(EX_SOFTWARE, "tls_client"); @@ -95,96 +95,99 @@ void imapOpen(FILE **read, FILE **write, const char *host, const char *port) { error = tls_connect(client, host, port); if (error) errx(EX_NOHOST, "tls_connect: %s", tls_error(client)); - *read = funopen(client, imapRead, NULL, NULL, NULL); - *write = funopen(client, NULL, imapWrite, NULL, imapClose); - if (!*read || !*write) err(EX_SOFTWARE, "funopen"); + struct IMAP imap = { + .r = funopen(client, imapRead, NULL, NULL, NULL), + .w = funopen(client, NULL, imapWrite, NULL, imapClose), + }; + if (!imap.r || !imap.w) err(EX_OSERR, "funopen"); - setlinebuf(*write); + setlinebuf(imap.w); + return imap; } -static size_t cap; -static char *buf; -static char *ptr; - -static void imapLine(FILE *imap) { - ssize_t len = getline(&buf, &cap, imap); +static void imapLine(struct IMAP *imap) { + ssize_t len = getline(&imap->buf, &imap->cap, imap->r); if (len < 0) errx(EX_PROTOCOL, "unexpected eof"); - if (len < 1 || buf[len - 1] != '\n') errx(EX_PROTOCOL, "missing LF"); - if (len < 2 || buf[len - 2] != '\r') errx(EX_PROTOCOL, "missing CR"); - buf[len - 2] = '\0'; - ptr = buf; + if (len < 1 || imap->buf[len - 1] != '\n') errx(EX_PROTOCOL, "missing LF"); + if (len < 2 || imap->buf[len - 2] != '\r') errx(EX_PROTOCOL, "missing CR"); + imap->buf[len - 2] = '\0'; + imap->ptr = imap->buf; } -static struct Data parseAtom(void) { - size_t len = (*ptr == '.' ? 1 : strcspn(ptr, " .()[]{\"")); +static struct Data parseAtom(struct IMAP *imap) { + size_t len = (*imap->ptr == '.' ? 1 : strcspn(imap->ptr, " .()[]{\"")); struct Data data = { .type = Atom, - .atom = atomn(ptr, len), + .atom = atomn(imap->ptr, len), }; - ptr += len; + imap->ptr += len; return data; } -static struct Data parseNumber(void) { +static struct Data parseNumber(struct IMAP *imap) { return (struct Data) { .type = Number, - .number = strtoull(ptr, &ptr, 10), + .number = strtoull(imap->ptr, &imap->ptr, 10), }; } -static struct Data parseQuoted(void) { - ptr++; - size_t len = strcspn(ptr, "\""); - if (ptr[len] != '"') errx(EX_PROTOCOL, "missing quoted string delimiter"); +static struct Data parseQuoted(struct IMAP *imap) { + imap->ptr++; + size_t len = strcspn(imap->ptr, "\""); + if (imap->ptr[len] != '"') { + errx(EX_PROTOCOL, "missing quoted string delimiter"); + } struct Data data = { .type = String, - .string = strndup(ptr, len), + .string = strndup(imap->ptr, len), }; if (!data.string) err(EX_OSERR, "strndup"); - ptr += len + 1; + imap->ptr += len + 1; return data; } -static struct Data parseLiteral(FILE *imap) { - ptr++; - size_t len = strtoull(ptr, &ptr, 10); - if (*ptr != '}') errx(EX_PROTOCOL, "missing literal prefix delimiter"); +static struct Data parseLiteral(struct IMAP *imap) { + imap->ptr++; + size_t len = strtoull(imap->ptr, &imap->ptr, 10); + if (*imap->ptr != '}') { + errx(EX_PROTOCOL, "missing literal prefix delimiter"); + } struct Data data = { .type = String, .string = malloc(len + 1), }; if (!data.string) err(EX_OSERR, "malloc"); - size_t n = fread(data.string, len, 1, imap); + size_t n = fread(data.string, len, 1, imap->r); if (!n) errx(EX_PROTOCOL, "truncated literal"); imapLine(imap); data.string[len] = '\0'; return data; } -static struct Data parseData(FILE *imap); +static struct Data parseData(struct IMAP *imap); -static struct Data parseList(FILE *imap, char close) { - if (*ptr) ptr++; +static struct Data parseList(struct IMAP *imap, char close) { + if (*imap->ptr) imap->ptr++; struct Data data = { .type = List }; - while (*ptr != close) { + while (*imap->ptr != close) { listPush(&data.list, parseData(imap)); } - if (*ptr) ptr++; + if (*imap->ptr) imap->ptr++; return data; } -static struct Data parseData(FILE *imap) { - if (*ptr == ' ') ptr++; - if (*ptr == '"') return parseQuoted(); - if (*ptr == '{') return parseLiteral(imap); - if (*ptr == '(') return parseList(imap, ')'); - if (*ptr == '[') return parseList(imap, ']'); - if (*ptr >= '0' && *ptr <= '9') return parseNumber(); - if (*ptr) return parseAtom(); +static struct Data parseData(struct IMAP *imap) { + if (*imap->ptr == ' ') imap->ptr++; + if (*imap->ptr == '"') return parseQuoted(imap); + if (*imap->ptr == '{') return parseLiteral(imap); + if (*imap->ptr == '(') return parseList(imap, ')'); + if (*imap->ptr == '[') return parseList(imap, ']'); + if (*imap->ptr >= '0' && *imap->ptr <= '9') return parseNumber(imap); + if (*imap->ptr) return parseAtom(imap); errx(EX_PROTOCOL, "unexpected eof"); } -struct Resp imapResp(FILE *imap) { +struct Resp imapResp(struct IMAP *imap) { struct Data data; struct Resp resp = {0}; imapLine(imap); @@ -193,8 +196,8 @@ struct Resp imapResp(FILE *imap) { if (data.type != Atom) errx(EX_PROTOCOL, "expected tag atom"); resp.tag = data.atom; if (resp.tag == AtomContinue) { - if (*ptr == ' ') ptr++; - resp.text = ptr; + if (*imap->ptr == ' ') imap->ptr++; + resp.text = imap->ptr; return resp; } @@ -213,13 +216,13 @@ struct Resp imapResp(FILE *imap) { resp.resp == AtomPreauth || resp.resp == AtomBye ) { - if (*ptr == ' ') ptr++; - if (*ptr == '[') { + if (*imap->ptr == ' ') imap->ptr++; + if (*imap->ptr == '[') { data = parseList(imap, ']'); resp.code = data.list; } - if (*ptr == ' ') ptr++; - resp.text = ptr; + if (*imap->ptr == ' ') imap->ptr++; + resp.text = imap->ptr; } else { data = parseList(imap, '\0'); resp.data = data.list; |