From e864ceb8d062492c1df307e99880511b0eaf73d2 Mon Sep 17 00:00:00 2001 From: "C. McEnroe" Date: Wed, 16 Dec 2020 18:06:48 -0500 Subject: Rewrite main loop linearly --- imap.h | 7 +++ notemap.c | 196 +++++++++++++++++++++++++++----------------------------------- 2 files changed, 93 insertions(+), 110 deletions(-) diff --git a/imap.h b/imap.h index 33dfd33..db4018e 100644 --- a/imap.h +++ b/imap.h @@ -154,6 +154,13 @@ struct Resp { const char *text; }; +static inline struct Resp respOk(struct Resp resp) { + if (resp.resp == AtomNo || resp.resp == AtomBad || resp.resp == AtomBye) { + errx(EX_CONFIG, "%s: %s", Atoms[resp.tag], resp.text); + } + return resp; +} + static inline void respFree(struct Resp resp) { listFree(resp.code); listFree(resp.data); diff --git a/notemap.c b/notemap.c index a1d280c..997a410 100644 --- a/notemap.c +++ b/notemap.c @@ -214,150 +214,126 @@ int main(int argc, char *argv[]) { FILE *map = fopen(path, "r"); if (!map) err(EX_NOINPUT, "%s", path); - size_t cap = 0; - char *entry = NULL; - char *uuid = NULL; - char *note = NULL; - uint32_t seq = 0; - char *message = NULL; - - enum Atom login = 0; - enum Atom next = atom("next"); - enum Atom create = atom("create"); - enum Atom replace = atom("replace"); - + struct Resp resp; struct IMAP imap = imapOpen(host, port); - for ( - struct Resp resp; - resp = imapResp(&imap), resp.resp != AtomBye; - respFree(resp) - ) { - if (resp.resp == AtomNo || resp.resp == AtomBad) { - errx(EX_CONFIG, "%s: %s", Atoms[resp.resp], resp.text); - } + respFree(respOk(imapResp(&imap))); - if (!login) { - login = atom("login"); - fprintf( - imap.w, "%s LOGIN \"%s\" \"%s\"\r\n", - Atoms[login], user, pass - ); - } + enum Atom login = atom("login"); + fprintf(imap.w, "%s LOGIN \"%s\" \"%s\"\r\n", Atoms[login], user, pass); + for (; (resp = respOk(imapResp(&imap))).tag != login; respFree(resp)); + respFree(resp); - if (resp.tag == login) { - fprintf(imap.w, "%s SELECT \"%s\"\r\n", Atoms[next], mailbox); - } + enum Atom select = atom("select"); + fprintf(imap.w, "%s SELECT \"%s\"\r\n", Atoms[select], mailbox); + for (; (resp = respOk(imapResp(&imap))).tag != select; respFree(resp)); + respFree(resp); - ssize_t len; - if (resp.tag == next) { -next: - len = getline(&entry, &cap, map); - if (ferror(map)) err(EX_IOERR, "%s", path); - if (len < 1) { - fprintf(imap.w, "ayy LOGOUT\r\n"); - continue; - } - if (entry[len - 1] == '\n') entry[len - 1] = '\0'; + size_t cap = 0; + char *entry = NULL; + for (ssize_t len; 0 < (len = getline(&entry, &cap, map));) { + if (entry[len - 1] == '\n') entry[len - 1] = '\0'; - note = entry; - uuid = strsep(¬e, " "); - if (!note || !uuid || !uuidCheck(uuid)) { - errx(EX_CONFIG, "invalid map entry: %s", entry); - } + char *note = entry; + char *uuid = strsep(¬e, " "); + if (!note || !uuid || !uuidCheck(uuid)) { + errx(EX_CONFIG, "invalid map entry: %s", entry); + } - if (argc) { - int i; - for (i = 0; i < argc; ++i) { - if (!argv[i]) continue; - if (strcmp(argv[i], note)) continue; - argv[i] = NULL; - break; - } - if (i == argc) goto next; + if (argc) { + int i; + for (i = 0; i < argc; ++i) { + if (!argv[i]) continue; + if (strcmp(argv[i], note)) continue; + argv[i] = NULL; + break; } - - fprintf( - imap.w, - "%s SEARCH HEADER X-Universally-Unique-Identifier \"%s\"\r\n", - Atoms[AtomSearch], uuid - ); - continue; + if (i == argc) continue; } - if (resp.resp == AtomSearch) { + uint32_t seq = 0; + enum Atom search = atom("search"); + fprintf( + imap.w, + "%s SEARCH HEADER X-Universally-Unique-Identifier \"%s\"\r\n", + Atoms[search], uuid + ); + for (; (resp = respOk(imapResp(&imap))).tag != search; respFree(resp)) { + if (resp.resp != AtomSearch) continue; if (resp.data.len > 1) { errx(EX_CONFIG, "multiple messages matching %s", uuid); } if (resp.data.len) { seq = dataCheck(resp.data.ptr[0], Number).number; - fprintf( - imap.w, "%s FETCH %" PRIu32 " ENVELOPE\r\n", - Atoms[AtomFetch], seq - ); - } else { - message = format(user, uuid, note); - fprintf( - imap.w, "%s APPEND %s (\\Seen) {%zu}\r\n", - Atoms[create], mailbox, strlen(message) - ); } } - - if (resp.resp == AtomFetch) { + respFree(resp); + + if (!seq) goto append; + + struct tm date = {0}; + enum Atom fetch = atom("fetch"); + fprintf( + imap.w, "%s FETCH %" PRIu32 " ENVELOPE\r\n", + Atoms[fetch], seq + ); + for (; (resp = respOk(imapResp(&imap))).tag != fetch; respFree(resp)) { + if (resp.resp != AtomFetch) continue; if (!resp.data.len) errx(EX_PROTOCOL, "missing fetch data"); struct List items = dataCheck(resp.data.ptr[0], List).list; if (items.len < 2) errx(EX_PROTOCOL, "missing fetch data items"); enum Atom item = dataCheck(items.ptr[0], Atom).atom; if (item != AtomEnvelope) continue; - struct List envelope = dataCheck(items.ptr[1], List).list; - if (envelope.len < 1) errx(EX_PROTOCOL, "missing envelope date"); - - struct tm date = {0}; - char *rest = strptime( + if (!envelope.len) errx(EX_PROTOCOL, "missing envelope date"); + const char *rest = strptime( dataCheck(envelope.ptr[0], String).string, DATE_FORMAT, &date ); if (!rest) errx(EX_PROTOCOL, "invalid envelope date format"); - - struct stat status; - int error = stat(note, &status); - if (error) err(EX_NOINPUT, "%s", note); - - if (!force && status.st_mtime < mktime(&date)) { - errx( - EX_TEMPFAIL, - "%s: note modified in mailbox; use -f to overwrite", - note - ); - } else if (status.st_mtime == mktime(&date)) { - goto next; - } - - message = format(user, uuid, note); - fprintf( - imap.w, "%s APPEND %s (\\Seen) {%zu}\r\n", - Atoms[replace], mailbox, strlen(message) + } + respFree(resp); + + struct stat status; + int error = stat(note, &status); + if (error) err(EX_NOINPUT, "%s", note); + if (status.st_mtime < mktime(&date) && !force) { + errx( + EX_TEMPFAIL, + "%s: note modified in mailbox; use -f to overwrite", note ); + } else if (status.st_mtime == mktime(&date)) { + continue; } - if (resp.tag == AtomContinue) { - fprintf(imap.w, "%s\r\n", message); - free(message); +append:; + char *message = format(user, uuid, note); + enum Atom append = atom("append"); + fprintf( + imap.w, "%s APPEND %s (\\Seen) {%zu}\r\n", + Atoms[append], mailbox, strlen(message) + ); + for (; (resp = respOk(imapResp(&imap))).tag != append; respFree(resp)) { + if (resp.tag == AtomContinue) fprintf(imap.w, "%s\r\n", message); } + respFree(resp); + free(message); - if (resp.tag == create) { + if (!seq) { printf("+ %s\n", note); - goto next; + continue; } - if (resp.tag == replace) { - printf("~ %s\n", note); - fprintf( - imap.w, "%s STORE %" PRIu32 " +FLAGS (\\Deleted)\r\n", - Atoms[next], seq - ); - } + enum Atom delete = atom("delete"); + fprintf( + imap.w, "%s STORE %" PRIu32 " +FLAGS (\\Deleted)\r\n", + Atoms[delete], seq + ); + for (; (resp = respOk(imapResp(&imap))).tag != delete; respFree(resp)); + respFree(resp); + printf("~ %s\n", note); } + if (ferror(map)) err(EX_IOERR, "%s", path); + + fprintf(imap.w, "ayy LOGOUT\r\n"); fclose(imap.r); fclose(imap.w); -- cgit 1.4.1