iics2tsv.c - 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 iics2tsv.c (4611B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 #include Err bitreich.org 70 i 2 #include Err bitreich.org 70 i 3 #include Err bitreich.org 70 i 4 #include Err bitreich.org 70 i 5 #include Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 #include "ical.h" Err bitreich.org 70 i 9 #include "util.h" Err bitreich.org 70 i 10 Err bitreich.org 70 i 11 #ifndef __OpenBSD__ Err bitreich.org 70 i 12 #define pledge(...) 0 Err bitreich.org 70 i 13 #endif Err bitreich.org 70 i 14 Err bitreich.org 70 i 15 #define FIELDS_MAX 128 Err bitreich.org 70 i 16 Err bitreich.org 70 i 17 typedef struct Field Field; Err bitreich.org 70 i 18 typedef struct Block Block; Err bitreich.org 70 i 19 Err bitreich.org 70 i 20 struct Field { Err bitreich.org 70 i 21 char *key; Err bitreich.org 70 i 22 char *value; Err bitreich.org 70 i 23 }; Err bitreich.org 70 i 24 Err bitreich.org 70 i 25 struct Block { Err bitreich.org 70 i 26 time_t beg, end; Err bitreich.org 70 i 27 char *fields[FIELDS_MAX]; Err bitreich.org 70 i 28 }; Err bitreich.org 70 i 29 Err bitreich.org 70 i 30 static int flag_header = 1; Err bitreich.org 70 i 31 static char default_fields[] = "SUMMARY,DESCRIPTION,CATEGORIES,LOCATION"; Err bitreich.org 70 i 32 static char *flag_sep = ","; Err bitreich.org 70 i 33 static char *flag_timefmt = NULL; Err bitreich.org 70 i 34 static char *flag_fields = default_fields; Err bitreich.org 70 i 35 static char *fields[FIELDS_MAX]; Err bitreich.org 70 i 36 static Block block; Err bitreich.org 70 i 37 Err bitreich.org 70 i 38 static int Err bitreich.org 70 i 39 fn_field_name(IcalParser *p, char *name) Err bitreich.org 70 i 40 { Err bitreich.org 70 i 41 (void)p; Err bitreich.org 70 i 42 (void)name; Err bitreich.org 70 i 43 Err bitreich.org 70 i 44 return 0; Err bitreich.org 70 i 45 } Err bitreich.org 70 i 46 Err bitreich.org 70 i 47 static int Err bitreich.org 70 i 48 fn_block_begin(IcalParser *p, char *name) Err bitreich.org 70 i 49 { Err bitreich.org 70 i 50 (void)p; Err bitreich.org 70 i 51 (void)name; Err bitreich.org 70 i 52 Err bitreich.org 70 i 53 if (p->blocktype == ICAL_BLOCK_OTHER) Err bitreich.org 70 i 54 return 0; Err bitreich.org 70 i 55 Err bitreich.org 70 i 56 memset(&block, 0, sizeof block); Err bitreich.org 70 i 57 return 0; Err bitreich.org 70 i 58 } Err bitreich.org 70 i 59 Err bitreich.org 70 i 60 static int Err bitreich.org 70 i 61 fn_block_end(IcalParser *p, char *name) Err bitreich.org 70 i 62 { Err bitreich.org 70 i 63 (void)name; Err bitreich.org 70 i 64 Err bitreich.org 70 i 65 if (p->blocktype == ICAL_BLOCK_OTHER) Err bitreich.org 70 i 66 return 0; Err bitreich.org 70 i 67 fputs(p->current->name, stdout); Err bitreich.org 70 i 68 Err bitreich.org 70 i 69 /* printing dates with %s is much much slower than %lld */ Err bitreich.org 70 i 70 if (flag_timefmt == NULL) { Err bitreich.org 70 i 71 printf("\t%lld\t%lld", block.beg, block.end); Err bitreich.org 70 i 72 } else { Err bitreich.org 70 i 73 char buf[128]; Err bitreich.org 70 i 74 struct tm tm = {0}; Err bitreich.org 70 i 75 Err bitreich.org 70 i 76 localtime_r(&block.beg, &tm); Err bitreich.org 70 i 77 strftime(buf, sizeof buf, flag_timefmt, &tm); Err bitreich.org 70 i 78 printf("\t%s", buf); Err bitreich.org 70 i 79 Err bitreich.org 70 i 80 localtime_r(&block.end, &tm); Err bitreich.org 70 i 81 strftime(buf, sizeof buf, flag_timefmt, &tm); Err bitreich.org 70 i 82 printf("\t%s", buf); Err bitreich.org 70 i 83 } Err bitreich.org 70 i 84 Err bitreich.org 70 i 85 /* reserved for recurring events */ Err bitreich.org 70 i 86 printf("\t%s", "(null)"); Err bitreich.org 70 i 87 Err bitreich.org 70 i 88 for (int i = 0; fields[i] != NULL; i++) { Err bitreich.org 70 i 89 fputc('\t', stdout); Err bitreich.org 70 i 90 if (block.fields[i] != NULL) Err bitreich.org 70 i 91 fputs(block.fields[i], stdout); Err bitreich.org 70 i 92 } Err bitreich.org 70 i 93 printf("\n"); Err bitreich.org 70 i 94 return 0; Err bitreich.org 70 i 95 } Err bitreich.org 70 i 96 Err bitreich.org 70 i 97 static int Err bitreich.org 70 i 98 fn_param_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i 99 { Err bitreich.org 70 i 100 (void)p; Err bitreich.org 70 i 101 (void)name; Err bitreich.org 70 i 102 (void)value; Err bitreich.org 70 i 103 Err bitreich.org 70 i 104 return 0; Err bitreich.org 70 i 105 } Err bitreich.org 70 i 106 Err bitreich.org 70 i 107 static int Err bitreich.org 70 i 108 fn_field_value(IcalParser *p, char *name, char *value) Err bitreich.org 70 i 109 { Err bitreich.org 70 i 110 static char *map[][2] = { Err bitreich.org 70 i 111 [ICAL_BLOCK_VEVENT] = { "DTSTART", "DTEND" }, Err bitreich.org 70 i 112 [ICAL_BLOCK_VTODO] = { NULL, "DUE" }, Err bitreich.org 70 i 113 [ICAL_BLOCK_VJOURNAL] = { "DTSTAMP", NULL }, Err bitreich.org 70 i 114 [ICAL_BLOCK_VFREEBUSY] = { "DTSTART", "DTEND" }, Err bitreich.org 70 i 115 [ICAL_BLOCK_VALARM] = { "DTSTART", NULL }, Err bitreich.org 70 i 116 [ICAL_BLOCK_OTHER] = { NULL, NULL }, Err bitreich.org 70 i 117 }; Err bitreich.org 70 i 118 char *beg, *end; Err bitreich.org 70 i 119 Err bitreich.org 70 i 120 /* fill the date fields */ Err bitreich.org 70 i 121 beg = map[p->blocktype][0]; Err bitreich.org 70 i 122 if (beg != NULL && strcasecmp(name, beg) == 0) Err bitreich.org 70 i 123 if (ical_get_time(p, value, &block.beg) != 0) Err bitreich.org 70 i 124 return -1; Err bitreich.org 70 i 125 end = map[p->blocktype][1]; Err bitreich.org 70 i 126 if (end != NULL && strcasecmp(name, end) == 0) Err bitreich.org 70 i 127 if (ical_get_time(p, value, &block.end) != 0) Err bitreich.org 70 i 128 return -1; Err bitreich.org 70 i 129 Err bitreich.org 70 i 130 /* fill text fields as requested with -o F1,F2... */ Err bitreich.org 70 i 131 for (int i = 0; fields[i] != NULL; i++) { Err bitreich.org 70 i 132 if (strcasecmp(name, fields[i]) == 0) { Err bitreich.org 70 i 133 if (block.fields[i] == NULL) { Err bitreich.org 70 i 134 if ((block.fields[i] = strdup(value)) == NULL) Err bitreich.org 70 i 135 return ical_err(p, strerror(errno)); Err bitreich.org 70 i 136 } else { Err bitreich.org 70 i 137 if (strappend(&block.fields[i], flag_sep) == NULL || Err bitreich.org 70 i 138 strappend(&block.fields[i], value) == NULL) Err bitreich.org 70 i 139 return ical_err(p, strerror(errno)); Err bitreich.org 70 i 140 } Err bitreich.org 70 i 141 } Err bitreich.org 70 i 142 } Err bitreich.org 70 i 143 Err bitreich.org 70 i 144 return 0; Err bitreich.org 70 i 145 } Err bitreich.org 70 i 146 Err bitreich.org 70 i 147 static void Err bitreich.org 70 i 148 usage(void) Err bitreich.org 70 i 149 { Err bitreich.org 70 i 150 fprintf(stderr,"usage: %s [-1] [-f fields] [-s separator] [-t timefmt]" Err bitreich.org 70 i 151 " [file...]\n", arg0); Err bitreich.org 70 i 152 exit(1); Err bitreich.org 70 i 153 } Err bitreich.org 70 i 154 Err bitreich.org 70 i 155 int Err bitreich.org 70 i 156 main(int argc, char **argv) Err bitreich.org 70 i 157 { Err bitreich.org 70 i 158 IcalParser p = {0}; Err bitreich.org 70 i 159 int c; Err bitreich.org 70 i 160 Err bitreich.org 70 i 161 arg0 = *argv; Err bitreich.org 70 i 162 Err bitreich.org 70 i 163 if (pledge("stdio rpath", "") < 0) Err bitreich.org 70 i 164 err(1, "pledge: %s", strerror(errno)); Err bitreich.org 70 i 165 Err bitreich.org 70 i 166 p.fn_field_name = fn_field_name; Err bitreich.org 70 i 167 p.fn_block_begin = fn_block_begin; Err bitreich.org 70 i 168 p.fn_block_end = fn_block_end; Err bitreich.org 70 i 169 p.fn_param_value = fn_param_value; Err bitreich.org 70 i 170 p.fn_field_value = fn_field_value; Err bitreich.org 70 i 171 Err bitreich.org 70 i 172 while ((c = getopt(argc, argv, "01f:s:t:")) != -1) { Err bitreich.org 70 i 173 switch (c) { Err bitreich.org 70 i 174 case '0': Err bitreich.org 70 i 175 flag_header = 0; Err bitreich.org 70 i 176 break; Err bitreich.org 70 i 177 case '1': Err bitreich.org 70 i 178 flag_header = 1; Err bitreich.org 70 i 179 break; Err bitreich.org 70 i 180 case 'f': Err bitreich.org 70 i 181 flag_fields = optarg; Err bitreich.org 70 i 182 break; Err bitreich.org 70 i 183 case 's': Err bitreich.org 70 i 184 flag_sep = optarg; Err bitreich.org 70 i 185 break; Err bitreich.org 70 i 186 case 't': Err bitreich.org 70 i 187 flag_timefmt = optarg; Err bitreich.org 70 i 188 break; Err bitreich.org 70 i 189 case '?': Err bitreich.org 70 i 190 usage(); Err bitreich.org 70 i 191 break; Err bitreich.org 70 i 192 } Err bitreich.org 70 i 193 } Err bitreich.org 70 i 194 argv += optind; Err bitreich.org 70 i 195 argc -= optind; Err bitreich.org 70 i 196 Err bitreich.org 70 i 197 if (strsplit(flag_fields, fields, LEN(fields), ",") < 0) Err bitreich.org 70 i 198 err(1, "too many fields specified with -f flag"); Err bitreich.org 70 i 199 Err bitreich.org 70 i 200 if (flag_header) { Err bitreich.org 70 i 201 printf("%s\t%s\t%s\t%s", "TYPE", "START", "END", "RECUR"); Err bitreich.org 70 i 202 for (size_t i = 0; fields[i] != NULL; i++) Err bitreich.org 70 i 203 printf("\t%s", fields[i]); Err bitreich.org 70 i 204 fputc('\n', stdout); Err bitreich.org 70 i 205 } Err bitreich.org 70 i 206 Err bitreich.org 70 i 207 if (*argv == NULL || strcmp(*argv, "-") == 0) { Err bitreich.org 70 i 208 debug("converting *stdin*"); Err bitreich.org 70 i 209 if (ical_parse(&p, stdin) < 0) Err bitreich.org 70 i 210 err(1, "parsing *stdin*:%d: %s", p.linenum, p.errmsg); Err bitreich.org 70 i 211 } Err bitreich.org 70 i 212 for (; *argv != NULL; argv++, argc--) { Err bitreich.org 70 i 213 FILE *fp; Err bitreich.org 70 i 214 debug("converting \"%s\"", *argv); Err bitreich.org 70 i 215 if ((fp = fopen(*argv, "r")) == NULL) Err bitreich.org 70 i 216 err(1, "opening %s: %s", *argv, strerror(errno)); Err bitreich.org 70 i 217 if (ical_parse(&p, fp) < 0) Err bitreich.org 70 i 218 err(1, "parsing %s:%d: %s", *argv, p.linenum, p.errmsg); Err bitreich.org 70 i 219 fclose(fp); Err bitreich.org 70 i 220 } Err bitreich.org 70 i 221 Err bitreich.org 70 i 222 return 0; Err bitreich.org 70 i 223 } Err bitreich.org 70 .