isupport time zone conversion and date-time parsing - ics2txt - convert icalendar .ics file to plain text Err bitreich.org 70 hgit clone git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt URL:git://bitreich.org/ics2txt git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/ics2txt bitreich.org 70 1Log /scm/ics2txt/log.gph bitreich.org 70 1Files /scm/ics2txt/files.gph bitreich.org 70 1Refs /scm/ics2txt/refs.gph bitreich.org 70 1Tags /scm/ics2txt/tag bitreich.org 70 1README /scm/ics2txt/file/README.md.gph bitreich.org 70 i--- Err bitreich.org 70 1commit 58a1a9df90b5751ae05fba076cd9e664e3d9f3c1 /scm/ics2txt/commit/58a1a9df90b5751ae05fba076cd9e664e3d9f3c1.gph bitreich.org 70 1parent b72092250747c7443e20fee06bee232b236f441e /scm/ics2txt/commit/b72092250747c7443e20fee06bee232b236f441e.gph bitreich.org 70 hAuthor: Josuah Demangeon URL:mailto:me@josuah.net bitreich.org 70 iDate: Mon, 14 Jun 2021 00:08:10 +0200 Err bitreich.org 70 i Err bitreich.org 70 isupport time zone conversion and date-time parsing Err bitreich.org 70 i Err bitreich.org 70 iConvert dates from DT* fields to epoch on sample program. Err bitreich.org 70 i Err bitreich.org 70 iDiffstat: Err bitreich.org 70 i M ical.c | 168 ++++++++++++++++++++++++++------ Err bitreich.org 70 i M ical.h | 19 ++++++++++++++----- Err bitreich.org 70 i M ics2tree.c | 28 +++++++++++++++++++++------- Err bitreich.org 70 i M util.c | 81 ++++++++++++++++++++++--------- Err bitreich.org 70 i M util.h | 21 +++++++++++++-------- Err bitreich.org 70 i Err bitreich.org 70 i5 files changed, 245 insertions(+), 72 deletions(-) Err bitreich.org 70 i--- Err bitreich.org 70 1diff --git a/ical.c b/ical.c /scm/ics2txt/file/ical.c.gph bitreich.org 70 i@@ -11,6 +11,12 @@ Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i #include "base64.h" Err bitreich.org 70 i Err bitreich.org 70 i+#define Xstrlcpy(d, s) (strlcpy((d), (s), sizeof(d)) < sizeof(d)) Err bitreich.org 70 i+#define Xstrlcat(d, s) (strlcat((d), (s), sizeof(d)) < sizeof(d)) Err bitreich.org 70 i+ Err bitreich.org 70 i+/* helpers: common utilities to call within the p->fn() callbacks as Err bitreich.org 70 i+ * well as in the code below */ Err bitreich.org 70 i+ Err bitreich.org 70 i int Err bitreich.org 70 i ical_error(IcalParser *p, char const *msg) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -19,6 +25,12 @@ ical_error(IcalParser *p, char const *msg) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i int Err bitreich.org 70 i+ical_get_level(IcalParser *p) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ return p->current - p->stack; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i ical_get_value(IcalParser *p, char *s, size_t *len) Err bitreich.org 70 i { Err bitreich.org 70 i *len = strlen(s); Err bitreich.org 70 i@@ -31,9 +43,111 @@ ical_get_value(IcalParser *p, char *s, size_t *len) Err bitreich.org 70 i int Err bitreich.org 70 i ical_get_time(IcalParser *p, char *s, time_t *t) Err bitreich.org 70 i { Err bitreich.org 70 i- return -1; Err bitreich.org 70 i+ struct tm tm = {0}; Err bitreich.org 70 i+ char const *tzid; Err bitreich.org 70 i+ Err bitreich.org 70 i+ tzid = (p->tzid) ? p->tzid : Err bitreich.org 70 i+ (p->current && p->current->tzid[0] != '\0') ? p->current->tzid : Err bitreich.org 70 i+ ""; Err bitreich.org 70 i+ Err bitreich.org 70 i+ /* date */ Err bitreich.org 70 i+ for (int i = 0; i < 8; i++) Err bitreich.org 70 i+ if (!isdigit(s[i])) Err bitreich.org 70 i+ return ical_error(p, "invalid date format"); Err bitreich.org 70 i+ tm.tm_year = s[0] * 1000 + s[1] * 100 + s[2] * 10 + s[3]; Err bitreich.org 70 i+ tm.tm_mon = s[4] * 10 + s[5] - 1; Err bitreich.org 70 i+ tm.tm_mday = s[6] * 10 + s[7]; Err bitreich.org 70 i+ s += 8; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (*s == 'T') { Err bitreich.org 70 i+ /* time */ Err bitreich.org 70 i+ s++; Err bitreich.org 70 i+ for (int i = 0; i < 6; i++) Err bitreich.org 70 i+ if (!isdigit(s[i])) Err bitreich.org 70 i+ return ical_error(p, "invalid time format"); Err bitreich.org 70 i+ tm.tm_hour = s[0] * 10 + s[1]; Err bitreich.org 70 i+ tm.tm_min = s[2] * 10 + s[3]; Err bitreich.org 70 i+ tm.tm_sec = s[4] * 10 + s[5]; Err bitreich.org 70 i+ if (s[6] == 'Z') Err bitreich.org 70 i+ tzid = "UTC"; Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i+ if ((*t = tztime(&tm, tzid)) == (time_t)-1) Err bitreich.org 70 i+ return ical_error(p, "could not convert time"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/* hooks: called just before user functions to do extra work such as Err bitreich.org 70 i+ * processing time zones definition or prepare base64 decoding, and Err bitreich.org 70 i+ * permit to only have parsing code left to parsing functions */ Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ (void)p; (void)name; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_param_name(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ (void)p; (void)name; Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (strcasecmp(name, "ENCODING") == 0) Err bitreich.org 70 i+ p->base64 = (strcasecmp(value, "BASE64") == 0); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (strcasecmp(name, "TZID") == 0) Err bitreich.org 70 i+ p->tzid = value; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (strcasecmp(name, "TZID") == 0) Err bitreich.org 70 i+ if (!Xstrlcpy(p->current->tzid, value)) Err bitreich.org 70 i+ return ical_error(p, "TZID: name too large"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ p->tzid = NULL; Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ p->current++; Err bitreich.org 70 i+ memset(p->current, 0, sizeof(*p->current)); Err bitreich.org 70 i+ if (ical_get_level(p) >= ICAL_STACK_SIZE) Err bitreich.org 70 i+ return ical_error(p, "max recurion reached"); Err bitreich.org 70 i+ if (!Xstrlcpy(p->current->name, name)) Err bitreich.org 70 i+ return ical_error(p, "value too large"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+int Err bitreich.org 70 i+hook_block_end(IcalParser *p, char *name) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ if (strcasecmp(p->current->name, name) != 0) Err bitreich.org 70 i+ return ical_error(p, "mismatching BEGIN: and END:"); Err bitreich.org 70 i+ p->current--; Err bitreich.org 70 i+ if (p->current < p->stack) Err bitreich.org 70 i+ return ical_error(p, "more END: than BEGIN:"); Err bitreich.org 70 i+ Err bitreich.org 70 i+ return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+/* parsers: in charge of reading from `fp`, splitting text into Err bitreich.org 70 i+ * fields, and call hooks and user functions. */ Err bitreich.org 70 i+ Err bitreich.org 70 i #define CALL(p, fn, ...) ((p)->fn ? (p)->fn((p), __VA_ARGS__) : 0) Err bitreich.org 70 i Err bitreich.org 70 i static int Err bitreich.org 70 i@@ -43,24 +157,23 @@ ical_parse_value(IcalParser *p, char **sp, char *name) Err bitreich.org 70 i char *s, c, *val; Err bitreich.org 70 i Err bitreich.org 70 i s = *sp; Err bitreich.org 70 i- Err bitreich.org 70 i if (*s == '"') { Err bitreich.org 70 i- ++s; Err bitreich.org 70 i- for (val = s; !iscntrl(*s) && !strchr(",;:\"", *s); s++); Err bitreich.org 70 i+ val = ++s; Err bitreich.org 70 i+ while (!iscntrl(*s) && *s != '"') Err bitreich.org 70 i+ s++; Err bitreich.org 70 i if (*s != '"') Err bitreich.org 70 i return ical_error(p, "missing '\"'"); Err bitreich.org 70 i *s++ = '\0'; Err bitreich.org 70 i } else { Err bitreich.org 70 i- for (val = s; !iscntrl(*s) && !strchr(",;:'\"", *s); s++); Err bitreich.org 70 i+ val = s; Err bitreich.org 70 i+ while (!iscntrl(*s) && !strchr(",;:'\"", *s)) Err bitreich.org 70 i+ s++; Err bitreich.org 70 i } Err bitreich.org 70 i- Err bitreich.org 70 i c = *s, *s = '\0'; Err bitreich.org 70 i- if ((err = CALL(p, fn_param_value, name, val)) != 0) Err bitreich.org 70 i+ if ((err = hook_param_value(p, name, val)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_param_value, name, val)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i- if (strcasecmp(name, "ENCODING") == 0) Err bitreich.org 70 i- p->base64 = (strcasecmp(val, "BASE64") == 0); Err bitreich.org 70 i *s = c; Err bitreich.org 70 i- Err bitreich.org 70 i *sp = s; Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -72,42 +185,39 @@ ical_parse_param(IcalParser *p, char **sp) Err bitreich.org 70 i char *s, *name; Err bitreich.org 70 i Err bitreich.org 70 i s = *sp; Err bitreich.org 70 i- Err bitreich.org 70 i do { Err bitreich.org 70 i for (name = s; isalnum(*s) || *s == '-'; s++); Err bitreich.org 70 i if (s == name || (*s != '=')) Err bitreich.org 70 i return ical_error(p, "invalid parameter name"); Err bitreich.org 70 i *s++ = '\0'; Err bitreich.org 70 i- if ((err = CALL(p, fn_param_name, name)) != 0) Err bitreich.org 70 i+ if ((err = hook_param_name(p, name)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_param_name, name)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i- Err bitreich.org 70 i do { Err bitreich.org 70 i if ((err = ical_parse_value(p, &s, name)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i } while (*s == ',' && s++); Err bitreich.org 70 i } while (*s == ';' && s++); Err bitreich.org 70 i- Err bitreich.org 70 i *sp = s; Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i static int Err bitreich.org 70 i-ical_parse_contentline(IcalParser *p, char *line) Err bitreich.org 70 i+ical_parse_contentline(IcalParser *p, char *s) Err bitreich.org 70 i { Err bitreich.org 70 i int err; Err bitreich.org 70 i- char *s, c, *name, *end; Err bitreich.org 70 i- Err bitreich.org 70 i- s = line; Err bitreich.org 70 i+ char c, *name, *sep; Err bitreich.org 70 i Err bitreich.org 70 i for (name = s; isalnum(*s) || *s == '-'; s++); Err bitreich.org 70 i if (s == name || (*s != ';' && *s != ':')) Err bitreich.org 70 i return ical_error(p, "invalid entry name"); Err bitreich.org 70 i c = *s, *s = '\0'; Err bitreich.org 70 i if (strcasecmp(name, "BEGIN") != 0 && strcasecmp(name, "END") != 0) Err bitreich.org 70 i- if ((err = CALL(p, fn_entry_name, name)) != 0) Err bitreich.org 70 i+ if ((err = hook_entry_name(p, name)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_entry_name, name)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i *s = c; Err bitreich.org 70 i- end = s; Err bitreich.org 70 i+ sep = s; Err bitreich.org 70 i Err bitreich.org 70 i p->base64 = 0; Err bitreich.org 70 i while (*s == ';') { Err bitreich.org 70 i@@ -120,20 +230,20 @@ ical_parse_contentline(IcalParser *p, char *line) Err bitreich.org 70 i return ical_error(p, "expected ':' delimiter"); Err bitreich.org 70 i s++; Err bitreich.org 70 i Err bitreich.org 70 i- *end = '\0'; Err bitreich.org 70 i+ *sep = '\0'; Err bitreich.org 70 i if (strcasecmp(name, "BEGIN") == 0) { Err bitreich.org 70 i- if ((err = CALL(p, fn_block_begin, s)) != 0) Err bitreich.org 70 i+ if ((err = hook_block_begin(p, s)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_block_begin, s)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i- p->level++; Err bitreich.org 70 i } else if (strcasecmp(name, "END") == 0) { Err bitreich.org 70 i- if ((err = CALL(p, fn_block_end, s)) != 0) Err bitreich.org 70 i+ if ((err = hook_block_end(p, s)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_block_end, s)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i- p->level--; Err bitreich.org 70 i } else { Err bitreich.org 70 i- if ((err = CALL(p, fn_entry_value, name, s)) != 0) Err bitreich.org 70 i+ if ((err = hook_entry_value(p, name, s)) != 0 || Err bitreich.org 70 i+ (err = CALL(p, fn_entry_value, name, s)) != 0) Err bitreich.org 70 i return err; Err bitreich.org 70 i } Err bitreich.org 70 i- Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -144,6 +254,8 @@ ical_parse(IcalParser *p, FILE *fp) Err bitreich.org 70 i size_t sz = 0; Err bitreich.org 70 i int err, c; Err bitreich.org 70 i Err bitreich.org 70 i+ p->current = p->stack; Err bitreich.org 70 i+ Err bitreich.org 70 i while (!feof(fp)) { Err bitreich.org 70 i if ((contentline = realloc(contentline, 1)) == NULL) Err bitreich.org 70 i return -1; Err bitreich.org 70 i@@ -151,7 +263,7 @@ ical_parse(IcalParser *p, FILE *fp) Err bitreich.org 70 i Err bitreich.org 70 i do { Err bitreich.org 70 i do { Err bitreich.org 70 i- p->line++; Err bitreich.org 70 i+ p->linenum++; Err bitreich.org 70 i if (getline(&ln, &sz, fp) <= 0) Err bitreich.org 70 i return -1; Err bitreich.org 70 i strchomp(ln); Err bitreich.org 70 1diff --git a/ical.h b/ical.h /scm/ics2txt/file/ical.h.gph bitreich.org 70 i@@ -4,9 +4,18 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i Err bitreich.org 70 i+#define ICAL_STACK_SIZE 10 Err bitreich.org 70 i+ Err bitreich.org 70 i typedef struct IcalParser IcalParser; Err bitreich.org 70 i+typedef struct IcalStack IcalStack; Err bitreich.org 70 i+ Err bitreich.org 70 i+struct IcalStack { Err bitreich.org 70 i+ char name[32]; Err bitreich.org 70 i+ char tzid[32]; Err bitreich.org 70 i+}; Err bitreich.org 70 i+ Err bitreich.org 70 i struct IcalParser { Err bitreich.org 70 i- /* function called on content */ Err bitreich.org 70 i+ /* function called while parsing in this order */ Err bitreich.org 70 i int (*fn_entry_name)(IcalParser *, char *); Err bitreich.org 70 i int (*fn_param_name)(IcalParser *, char *); Err bitreich.org 70 i int (*fn_param_value)(IcalParser *, char *, char *); Err bitreich.org 70 i@@ -17,14 +26,14 @@ struct IcalParser { Err bitreich.org 70 i Err bitreich.org 70 i int base64; Err bitreich.org 70 i char const *errmsg; Err bitreich.org 70 i- size_t line; Err bitreich.org 70 i+ size_t linenum; Err bitreich.org 70 i+ char *tzid; Err bitreich.org 70 i Err bitreich.org 70 i- /* stack of blocks names: "name1\0name2\0...nameN\0\0" */ Err bitreich.org 70 i- int level; Err bitreich.org 70 i- char stack[1024]; Err bitreich.org 70 i+ IcalStack stack[ICAL_STACK_SIZE], *current; Err bitreich.org 70 i }; Err bitreich.org 70 i Err bitreich.org 70 i int ical_parse(IcalParser *, FILE *); Err bitreich.org 70 i+int ical_get_level(IcalParser *); Err bitreich.org 70 i int ical_get_time(IcalParser *, char *, time_t *); Err bitreich.org 70 i int ical_get_value(IcalParser *, char *, size_t *); Err bitreich.org 70 i int ical_error(IcalParser *, char const *); Err bitreich.org 70 1diff --git a/ics2tree.c b/ics2tree.c /scm/ics2txt/file/ics2tree.c.gph bitreich.org 70 i@@ -1,6 +1,7 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i Err bitreich.org 70 i #include "ical.h" Err bitreich.org 70 i #include "util.h" Err bitreich.org 70 i@@ -15,7 +16,7 @@ print_ruler(int level) Err bitreich.org 70 i static int Err bitreich.org 70 i fn_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i- print_ruler(p->level); Err bitreich.org 70 i+ print_ruler(ical_get_level(p)); Err bitreich.org 70 i printf("name %s\n", name); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -23,7 +24,7 @@ fn_entry_name(IcalParser *p, char *name) Err bitreich.org 70 i static int Err bitreich.org 70 i fn_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i { Err bitreich.org 70 i- print_ruler(p->level); Err bitreich.org 70 i+ print_ruler(ical_get_level(p) - 1); Err bitreich.org 70 i printf("begin %s\n", name); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -31,7 +32,7 @@ fn_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i static int Err bitreich.org 70 i fn_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i { Err bitreich.org 70 i- print_ruler(p->level + 1); Err bitreich.org 70 i+ print_ruler(ical_get_level(p) + 1); Err bitreich.org 70 i printf("param %s=%s\n", name, value); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i@@ -44,8 +45,21 @@ fn_entry_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i Err bitreich.org 70 i if (ical_get_value(p, value, &len) < 0) Err bitreich.org 70 i return -1; Err bitreich.org 70 i- print_ruler(p->level + 1); Err bitreich.org 70 i- printf("value %s\n", value); Err bitreich.org 70 i+ Err bitreich.org 70 i+ print_ruler(ical_get_level(p) + 1); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (strcasecmp(name, "DTSTART") == 0 || Err bitreich.org 70 i+ strcasecmp(name, "DTSTAMP") == 0 || Err bitreich.org 70 i+ strcasecmp(name, "DTEND") == 0) { Err bitreich.org 70 i+ time_t t; Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (ical_get_time(p, value, &t) != 0) Err bitreich.org 70 i+ warn("%s: %s", p->errmsg, value); Err bitreich.org 70 i+ printf("epoch %ld\n", t); Err bitreich.org 70 i+ } else { Err bitreich.org 70 i+ printf("value %s\n", value); Err bitreich.org 70 i+ } Err bitreich.org 70 i+ Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -62,7 +76,7 @@ main(int argc, char **argv) Err bitreich.org 70 i Err bitreich.org 70 i if (*argv == NULL) { Err bitreich.org 70 i if (ical_parse(&p, stdin) < 0) Err bitreich.org 70 i- err("parsing stdin:%d: %s", p.line, p.errmsg); Err bitreich.org 70 i+ err("parsing stdin:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70 i@@ -72,7 +86,7 @@ main(int argc, char **argv) Err bitreich.org 70 i if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70 i err("opening %s", *argv); Err bitreich.org 70 i if (ical_parse(&p, fp) < 0) Err bitreich.org 70 i- err("parsing %s:%d: %s", *argv, p.line, p.errmsg); Err bitreich.org 70 i+ err("parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i fclose(fp); Err bitreich.org 70 i } Err bitreich.org 70 i return 0; Err bitreich.org 70 1diff --git a/util.c b/util.c /scm/ics2txt/file/util.c.gph bitreich.org 70 i@@ -5,20 +5,18 @@ Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i Err bitreich.org 70 i char *arg0; Err bitreich.org 70 i Err bitreich.org 70 i-/* logging */ Err bitreich.org 70 i+/** logging **/ Err bitreich.org 70 i Err bitreich.org 70 i static void Err bitreich.org 70 i-_log(char const *tag, char const *fmt, va_list va) Err bitreich.org 70 i+_log(char const *fmt, va_list va) Err bitreich.org 70 i { Err bitreich.org 70 i if (arg0 != NULL) Err bitreich.org 70 i fprintf(stderr, "%s: ", arg0); Err bitreich.org 70 i- fprintf(stderr, "%s: ", tag); Err bitreich.org 70 i vfprintf(stderr, fmt, va); Err bitreich.org 70 i- if (errno != 0) Err bitreich.org 70 i- fprintf(stderr, ": %s", strerror(errno)); Err bitreich.org 70 i fprintf(stderr, "\n"); Err bitreich.org 70 i fflush(stderr); Err bitreich.org 70 i } Err bitreich.org 70 i@@ -29,7 +27,7 @@ err(char const *fmt, ...) Err bitreich.org 70 i va_list va; Err bitreich.org 70 i Err bitreich.org 70 i va_start(va, fmt); Err bitreich.org 70 i- _log("error", fmt, va); Err bitreich.org 70 i+ _log( fmt, va); Err bitreich.org 70 i exit(1); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i@@ -39,7 +37,7 @@ warn(char const *fmt, ...) Err bitreich.org 70 i va_list va; Err bitreich.org 70 i Err bitreich.org 70 i va_start(va, fmt); Err bitreich.org 70 i- _log("warning", fmt, va); Err bitreich.org 70 i+ _log(fmt, va); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i void Err bitreich.org 70 i@@ -53,23 +51,34 @@ debug(char const *fmt, ...) Err bitreich.org 70 i if (!verbose) Err bitreich.org 70 i return; Err bitreich.org 70 i va_start(va, fmt); Err bitreich.org 70 i- _log("debug", fmt, va); Err bitreich.org 70 i+ _log(fmt, va); Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* strings */ Err bitreich.org 70 i+/** strings **/ Err bitreich.org 70 i Err bitreich.org 70 i size_t Err bitreich.org 70 i-strlcpy(char *buf, char const *str, size_t sz) Err bitreich.org 70 i+strlcpy(char *d, char const *s, size_t sz) Err bitreich.org 70 i { Err bitreich.org 70 i size_t len, cpy; Err bitreich.org 70 i Err bitreich.org 70 i- len = strlen(str); Err bitreich.org 70 i+ len = strlen(s); Err bitreich.org 70 i cpy = (len > sz) ? (sz) : (len); Err bitreich.org 70 i- memcpy(buf, str, cpy + 1); Err bitreich.org 70 i- buf[sz - 1] = '\0'; Err bitreich.org 70 i+ memcpy(d, s, cpy + 1); Err bitreich.org 70 i+ d[sz - 1] = '\0'; Err bitreich.org 70 i return len; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i+size_t Err bitreich.org 70 i+strlcat(char *d, char const *s, size_t dsz) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ size_t dlen; Err bitreich.org 70 i+ Err bitreich.org 70 i+ dlen = strlen(d); Err bitreich.org 70 i+ if (dlen >= dsz) Err bitreich.org 70 i+ return dlen + strlen(s); Err bitreich.org 70 i+ return dlen + strlcpy(d + dlen, s, dsz - dlen); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i char * Err bitreich.org 70 i strsep(char **sp, char const *sep) Err bitreich.org 70 i { Err bitreich.org 70 i@@ -102,28 +111,52 @@ strchomp(char *line) Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i int Err bitreich.org 70 i-strappend(char **dstp, char const *src) Err bitreich.org 70 i+strappend(char **dp, char const *s) Err bitreich.org 70 i { Err bitreich.org 70 i- size_t dstlen, srclen; Err bitreich.org 70 i+ size_t dlen, slen; Err bitreich.org 70 i void *mem; Err bitreich.org 70 i Err bitreich.org 70 i- dstlen = (*dstp == NULL) ? 0 : strlen(*dstp); Err bitreich.org 70 i- srclen = strlen(src); Err bitreich.org 70 i+ dlen = (*dp == NULL) ? 0 : strlen(*dp); Err bitreich.org 70 i+ slen = strlen(s); Err bitreich.org 70 i Err bitreich.org 70 i- if ((mem = realloc(*dstp, dstlen + srclen + 1)) == NULL) Err bitreich.org 70 i+ if ((mem = realloc(*dp, dlen + slen + 1)) == NULL) Err bitreich.org 70 i return -1; Err bitreich.org 70 i- *dstp = mem; Err bitreich.org 70 i+ *dp = mem; Err bitreich.org 70 i Err bitreich.org 70 i- memcpy(*dstp + dstlen, src, srclen + 1); Err bitreich.org 70 i+ memcpy(*dp + dlen, s, slen + 1); Err bitreich.org 70 i return 0; Err bitreich.org 70 i } Err bitreich.org 70 i Err bitreich.org 70 i-/* memory */ Err bitreich.org 70 i+/** memory **/ Err bitreich.org 70 i Err bitreich.org 70 i void * Err bitreich.org 70 i-reallocarray(void *buf, size_t len, size_t sz) Err bitreich.org 70 i+reallocarray(void *mem, size_t n, size_t sz) Err bitreich.org 70 i { Err bitreich.org 70 i- if (SIZE_MAX / len < sz) Err bitreich.org 70 i+ if (SIZE_MAX / n < sz) Err bitreich.org 70 i return errno=ERANGE, NULL; Err bitreich.org 70 i- return realloc(buf, len * sz); Err bitreich.org 70 i+ return realloc(mem, n * sz); Err bitreich.org 70 i+} Err bitreich.org 70 i+ Err bitreich.org 70 i+/** time **/ Err bitreich.org 70 i+ Err bitreich.org 70 i+time_t Err bitreich.org 70 i+tztime(struct tm *tm, char const *tz) Err bitreich.org 70 i+{ Err bitreich.org 70 i+ char *env, old[32]; Err bitreich.org 70 i+ time_t t; Err bitreich.org 70 i+ Err bitreich.org 70 i+ env = getenv("TZ"); Err bitreich.org 70 i+ if (strlcpy(old, env ? env : "", sizeof old) >= sizeof old) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ if (setenv("TZ", tz, 1) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ Err bitreich.org 70 i+ tzset(); Err bitreich.org 70 i+ t = mktime(tm); Err bitreich.org 70 i+ Err bitreich.org 70 i+ if (env == NULL) Err bitreich.org 70 i+ unsetenv("TZ"); Err bitreich.org 70 i+ else if (setenv("TZ", old, 1) < 0) Err bitreich.org 70 i+ return -1; Err bitreich.org 70 i+ return t; Err bitreich.org 70 i } Err bitreich.org 70 1diff --git a/util.h b/util.h /scm/ics2txt/file/util.h.gph bitreich.org 70 i@@ -3,20 +3,25 @@ Err bitreich.org 70 i Err bitreich.org 70 i #include Err bitreich.org 70 i #include Err bitreich.org 70 i+#include Err bitreich.org 70 i Err bitreich.org 70 i-/* logging */ Err bitreich.org 70 i+/** logging **/ Err bitreich.org 70 i extern char *arg0; Err bitreich.org 70 i void err(char const *fmt, ...); Err bitreich.org 70 i void warn(char const *fmt, ...); Err bitreich.org 70 i void debug(char const *fmt, ...); Err bitreich.org 70 i Err bitreich.org 70 i-/* strings */ Err bitreich.org 70 i-size_t strlcpy(char *buf, char const *str, size_t sz); Err bitreich.org 70 i-char *strsep(char **str_p, char const *sep); Err bitreich.org 70 i-void strchomp(char *line); Err bitreich.org 70 i-int strappend(char **base_p, char const *s); Err bitreich.org 70 i+/** strings **/ Err bitreich.org 70 i+size_t strlcpy(char *, char const *, size_t); Err bitreich.org 70 i+char *strsep(char **, char const *); Err bitreich.org 70 i+void strchomp(char *); Err bitreich.org 70 i+int strappend(char **, char const *); Err bitreich.org 70 i+size_t strlcat(char *, char const *, size_t); Err bitreich.org 70 i Err bitreich.org 70 i-/* memory */ Err bitreich.org 70 i-void *reallocarray(void *buf, size_t len, size_t sz); Err bitreich.org 70 i+/** memory **/ Err bitreich.org 70 i+void *reallocarray(void *, size_t, size_t); Err bitreich.org 70 i+ Err bitreich.org 70 i+/** time **/ Err bitreich.org 70 i+time_t tztime(struct tm *, char const *); Err bitreich.org 70 i Err bitreich.org 70 i #endif Err bitreich.org 70 .