scribo

Email-based phlog generator
git clone git://git.z3bra.org/scribo.git
Log | Files | Refs

commit 8c8ef05376c10ddbd4afaff7376a62fbce82e673
parent 2b0a9a4d1f589eb8ec7b814eeda2ae88b28266ba
Author: Willy Goiffon <dev@z3bra.org>
Date:   Mon,  7 Sep 2020 17:29:44 +0200

Rewrite RFC5322 helpers to be independent from headers structure

Diffstat:
Mrfc5322.c | 102++++++++++++++++++++++++++++++-------------------------------------------------
Mrfc5322.h | 17+++--------------
Mscribo.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 98 insertions(+), 85 deletions(-)

diff --git a/rfc5322.c b/rfc5322.c @@ -6,29 +6,53 @@ #include "rfc5322.h" -struct header * -rfc5322_header(char *s) +#define HDRSIZ 997 + +#ifndef strlcpy +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif +#ifndef strlcat +size_t strlcat(char *dst, const char *src, size_t siz); +#endif + +char * +rfc5322_headername(const char *s) +{ + static char n[HDRSIZ]; + char *p; + + strlcpy(n, s, sizeof(n)); + + p = n; + return strsep(&p, ":"); +} + +char * +rfc5322_headerbody(const char *s) { - char *f, *b; - struct header *h; + static char n[BUFSIZ + HDRSIZ + 1]; + char *p; - if (!(f = strsep(&s, ":"))) - return NULL; + strlcpy(n, s, sizeof(n)); - while (isblank(*s)) s++; + p = n + strlen(rfc5322_headername(s)) + 1; + while (isblank(*p)) p++; - if (!(b = strsep(&s, "\r\n"))) - return NULL; + return strsep(&p, "\r\n"); +} - if (!(h = calloc(sizeof(*h), 1))) - return NULL; - h->field = strdup(f); - h->body = strdup(b); +size_t +rfc5322_unfold(char *body, char *line, size_t n) +{ + /* trim leading whitespace when current body is empty */ + if (strnlen(body, n) == 0) + while (isblank(*line)) line++; - return h; + return strlcat(body, strsep(&line, "\r\n"), n); } + time_t rfc5322_date(const char *s) { @@ -41,53 +65,3 @@ rfc5322_date(const char *s) return mktime(&tm); } - -int -rfc5322_unfold(struct header *h, char *buf) -{ - char *l, *p; - size_t len; - - l = strsep(&buf, "\r\n"); - if (!l) - return -1; - - len = strlen(h->body) + strlen(l); - - p = realloc(h->body, len); - if (!p) - return -1; - - strcat(p, l); - - h->body = p; - - return 0; -} - -int -rfc5322_parse(FILE *fp, struct headers *head) -{ - size_t bufsiz; - ssize_t len; - char *buf = NULL; - struct header *p = NULL; - - while ((len = getline(&buf, &bufsiz, fp)) > 0) { - /* done parsin headers */ - if (!strcmp(buf, "\n")) - break; - - if (isblank(*buf)) { - rfc5322_unfold(p, buf); - } else { - p = rfc5322_header(buf); - if (p) - SLIST_INSERT_HEAD(head, p, entries); - } - } - - free(buf); - - return 0; -} diff --git a/rfc5322.h b/rfc5322.h @@ -1,14 +1,3 @@ -#include <sys/queue.h> - -struct header { - char *field; - char *body; - SLIST_ENTRY(header) entries; -}; - -SLIST_HEAD(headers, header); - -time_t rfc5322_date(const char *); -struct header *rfc5322_header(char *); -int rfc5322_unfold(struct header *, char *); -int rfc5322_parse(FILE *, struct headers *); +char *rfc5322_headername(const char *); +char *rfc5322_headerbody(const char *); +size_t rfc5322_unfold(char *, char *, size_t); diff --git a/scribo.c b/scribo.c @@ -11,6 +11,20 @@ #include "config.h" #include "rfc5322.h" +/* header field */ +struct hdr { + char name[BUFSIZ]; + char body[BUFSIZ]; + SLIST_ENTRY(hdr) entries; +}; + +/* header section */ +SLIST_HEAD(headers, hdr); + +#ifndef strlcpy +size_t strlcpy(char *dst, const char *src, size_t siz); +#endif + void usage(char *pgm) { @@ -18,13 +32,48 @@ usage(char *pgm) } int +parseheaders(FILE *fp, struct headers *head) +{ + char *buf = NULL; + size_t bufsiz = 0; + ssize_t len; + struct hdr *h; + + SLIST_INIT(head); + + while ((len = getline(&buf, &bufsiz, fp)) > 0) { + /* a single newline mark the end of header section */ + if (!strncmp(buf, "\r\n", 2)) + break; + + if (isblank(*buf)) { + rfc5322_unfold(h->body, buf, sizeof(h->body)); + continue; + } + + if (!(h = malloc(sizeof(*h)))) + return -1; + + strlcpy(h->name, rfc5322_headername(buf), sizeof(h->name)); + strlcpy(h->body, rfc5322_headerbody(buf), sizeof(h->body)); + SLIST_INSERT_HEAD(head, h, entries); + } + + free(buf); + + if (len < 0) + return -1; + + return 0; +} + +int main(int argc, char *argv[]) { FILE *in = stdin, *out = stdout; - struct header *p = NULL; - struct headers head = SLIST_HEAD_INITIALIZER(headers); char *argv0, *infile, *outfile, buf[BUFSIZ]; size_t len; + struct headers headers; infile = NULL; outfile = NULL; @@ -53,13 +102,14 @@ main(int argc, char *argv[]) if (outfile) out = fopen(outfile, "w"); - if (rfc5322_parse(in, &head) < 0) + if (parseheaders(in, &headers) < 0) return -1; - SLIST_FOREACH(p, &head, entries) { - if (!strcmp(p->field, "Subject")) - fprintf(out, "# %s\n\n", p->body); - } + struct hdr *p; + SLIST_FOREACH(p, &headers, entries) + printf("%s: %s\n", p->name, p->body); + + return 0; while ((len = fread(buf, 1, BUFSIZ, in))) fwrite(buf, 1, len, out);