From 78653936498babc06894526bd1fde36fc672f9ed Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Tue, 27 Oct 2020 19:47:07 -0400 Subject: Refactor IMAP struct --- imap.c | 107 ++++++++++++++++++++++++++++++++------------------------------ imap.h | 13 ++++++-- notemap.c | 27 ++++++++-------- 3 files changed, 79 insertions(+), 68 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; diff --git a/imap.h b/imap.h index 186cc55..7cd52e6 100644 --- a/imap.h +++ b/imap.h @@ -160,7 +160,16 @@ static inline void respFree(struct Resp resp) { } extern bool imapVerbose; -void imapOpen(FILE **read, FILE **write, const char *host, const char *port); -struct Resp imapResp(FILE *imapRead); + +struct IMAP { + FILE *r; + FILE *w; + size_t cap; + char *buf; + char *ptr; +}; + +struct IMAP imapOpen(const char *host, const char *port); +struct Resp imapResp(struct IMAP *imap); #endif /* IMAP_H */ diff --git a/notemap.c b/notemap.c index 8cdde70..8612493 100644 --- a/notemap.c +++ b/notemap.c @@ -295,11 +295,10 @@ int main(int argc, char *argv[]) { enum Atom create = atom("create"); enum Atom replace = atom("replace"); - FILE *imapRead, *imap; - imapOpen(&imapRead, &imap, host, port); + struct IMAP imap = imapOpen(host, port); for ( struct Resp resp; - resp = imapResp(imapRead), resp.resp != AtomBye; + resp = imapResp(&imap), resp.resp != AtomBye; respFree(resp) ) { if (resp.resp == AtomNo || resp.resp == AtomBad) { @@ -309,13 +308,13 @@ int main(int argc, char *argv[]) { if (!login) { login = atom("login"); fprintf( - imap, "%s LOGIN \"%s\" \"%s\"\r\n", + imap.w, "%s LOGIN \"%s\" \"%s\"\r\n", Atoms[login], user, pass ); } if (resp.tag == login) { - fprintf(imap, "%s SELECT \"%s\"\r\n", Atoms[next], mailbox); + fprintf(imap.w, "%s SELECT \"%s\"\r\n", Atoms[next], mailbox); } ssize_t len; @@ -324,7 +323,7 @@ next: len = getline(&entry, &cap, map); if (ferror(map)) err(EX_IOERR, "%s", path); if (len < 1) { - fprintf(imap, "ayy LOGOUT\r\n"); + fprintf(imap.w, "ayy LOGOUT\r\n"); continue; } if (entry[len - 1] == '\n') entry[len - 1] = '\0'; @@ -347,7 +346,7 @@ next: } fprintf( - imap, + imap.w, "%s SEARCH HEADER X-Universally-Unique-Identifier \"%s\"\r\n", Atoms[AtomSearch], uuid ); @@ -361,13 +360,13 @@ next: if (resp.data.len) { seq = dataCheck(resp.data.ptr[0], Number).number; fprintf( - imap, "%s FETCH %" PRIu32 " ENVELOPE\r\n", + imap.w, "%s FETCH %" PRIu32 " ENVELOPE\r\n", Atoms[AtomFetch], seq ); } else { message = format(user, uuid, note); fprintf( - imap, "%s APPEND %s (\\Seen) {%zu}\r\n", + imap.w, "%s APPEND %s (\\Seen) {%zu}\r\n", Atoms[create], mailbox, strlen(message) ); } @@ -405,13 +404,13 @@ next: message = format(user, uuid, note); fprintf( - imap, "%s APPEND %s (\\Seen) {%zu}\r\n", + imap.w, "%s APPEND %s (\\Seen) {%zu}\r\n", Atoms[replace], mailbox, strlen(message) ); } if (resp.tag == AtomContinue) { - fprintf(imap, "%s\r\n", message); + fprintf(imap.w, "%s\r\n", message); free(message); } @@ -423,13 +422,13 @@ next: if (resp.tag == replace) { printf("~ %s\n", note); fprintf( - imap, "%s STORE %" PRIu32 " +FLAGS (\\Deleted)\r\n", + imap.w, "%s STORE %" PRIu32 " +FLAGS (\\Deleted)\r\n", Atoms[next], seq ); } } - fclose(imapRead); - fclose(imap); + fclose(imap.r); + fclose(imap.w); int ret = EX_OK; for (int i = 0; i < argc; ++i) { -- cgit 1.4.1