commit 30f0686fb2d332cdc0ced15ac2c04094a127783a Author: Leah Neukirchen Date: Sun Jul 10 20:27:27 2016 +0200 various code that may end up as a mail client diff --git a/blaze822.c b/blaze822.c new file mode 100644 index 0000000..11b5285 --- /dev/null +++ b/blaze822.c @@ -0,0 +1,373 @@ +// memmem +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// WSP = SP / HTAB +#define iswsp(c) (((c) == ' ' || (c) == '\t')) + +#define bufsiz 4096 + +static long +parse_posint(char **s, size_t minn, size_t maxn) +{ + long n; + char *end; + + errno = 0; + n = strtol(*s, &end, 10); + if (errno) { +// perror("strtol"); + return -1; + } + if (n < (long)minn || n > (long)maxn) { +// fprintf(stderr, "number outside %zd <= n < %zd\n", minn, maxn); + return -1; + } + *s = end; + return n; +} + +time_t +parse_date(char *s) { + struct tm tm; + int c; + +#if 0 +#define i4(m) (s[0] && (s[0]|0x20) == m[0] && \ + s[1] && (s[1]|0x20) == m[1] && \ + s[2] && (s[2]|0x20) == m[2] && \ + s[3] && (s[3]|0x20) == m[3] && (s = s+4) ) + +#define i3(m) (s[0] && (s[0]|0x20) == m[0] && \ + s[1] && (s[1]|0x20) == m[1] && \ + s[2] && (s[2]|0x20) == m[2] && (s = s+3) ) +#endif + +#define i4(m) (((uint32_t) m[0]<<24 | m[1]<<16 | m[2]<<8 | m[3]) == \ + ((uint32_t) s[0]<<24 | s[1]<<16 | s[2]<<8 | s[3] | 0x20202020) \ + && (s += 4)) + +#define i3(m) (((uint32_t) m[0]<<24 | m[1]<<16 | m[2]<<8) == \ + ((uint32_t) s[0]<<24 | s[1]<<16 | s[2]<<8 | 0x20202000) \ + && (s += 3)) + + while (iswsp(*s)) + s++; + if (i4("mon,") || i4("tue,") || i4("wed,") || i4("thu,") || + i4("fri,") || i4("sat,") || i4("sun,")) + while (iswsp(*s)) + s++; + + if ((c = parse_posint(&s, 1, 31)) < 0) goto fail; + tm.tm_mday = c; + + while (iswsp(*s)) + s++; + + if (i3("jan")) tm.tm_mon = 0; + else if (i3("feb")) tm.tm_mon = 1; + else if (i3("mar")) tm.tm_mon = 2; + else if (i3("apr")) tm.tm_mon = 3; + else if (i3("may")) tm.tm_mon = 4; + else if (i3("jul")) tm.tm_mon = 5; + else if (i3("jun")) tm.tm_mon = 6; + else if (i3("aug")) tm.tm_mon = 7; + else if (i3("sep")) tm.tm_mon = 8; + else if (i3("oct")) tm.tm_mon = 9; + else if (i3("nov")) tm.tm_mon = 10; + else if (i3("dec")) tm.tm_mon = 11; + else goto fail; + + while (iswsp(*s)) + s++; + + if ((c = parse_posint(&s, 1000, 9999)) > 0) { + tm.tm_year = c - 1900; + } else if ((c = parse_posint(&s, 0, 49)) > 0) { + tm.tm_year = c + 100; + } else if ((c = parse_posint(&s, 50, 99)) > 0) { + tm.tm_year = c; + } else goto fail; + + while (iswsp(*s)) + s++; + + if ((c = parse_posint(&s, 0, 24)) < 0) goto fail; + tm.tm_hour = c; + if (*s++ != ':') goto fail; + if ((c = parse_posint(&s, 0, 59)) < 0) goto fail; + tm.tm_min = c; + if (*s++ == ':') { + if ((c = parse_posint(&s, 0, 61)) < 0) goto fail; + tm.tm_sec = c; + } + + while (iswsp(*s)) + s++; + + if (*s == '+' || *s == '-') { + int neg = (*s == '-'); + s++; + if ((c = parse_posint(&s, 0, 10000)) < 0) goto fail; + if (neg) { + tm.tm_hour += c / 100; + tm.tm_min += c % 100; + } else { + tm.tm_hour -= c / 100; + tm.tm_min -= c % 100; + } + } + + tm.tm_isdst = -1; + + time_t r = mktime(&tm); + return r; + +fail: + return -1; +} + +char * +parse_addr(char *s, char **dispo, char **addro) +{ + static char disp[1024]; + static char addr[1024]; +// char *disp = disp+sizeof disp; +// char *addr = addr+sizeof addr; + char *c, *e; + + printf("RAW : |%s|\n", s); + + while (iswsp(*s)) + s++; + + c = disp; + e = disp + sizeof disp; + + *disp = 0; + *addr = 0; + + while (*s) { + if (*s == '<') { + char *c = addr; + char *e = addr + sizeof addr; + + s++; + while (*s && c < e && *s != '>') + *c++ = *s++; + if (*s == '>') + s++; + *c = 0; + } else if (*s == '"') { + s++; + while (*s && c < e && *s != '"') + *c++ = *s++; + if (*s == '"') + s++; + } else if (*s == '(') { + s++; + + if (!*addr) { // assume: user@host (name) + *c-- = 0; + while (c > disp && iswsp(*c)) + *c-- = 0; + strcpy(addr, disp); + c = disp; + *c = 0; + } + + while (*s && c < e && *s != ')') + *c++ = *s++; + if (*s == ')') + s++; + } else if (*s == ',') { + s++; + break; + } else { + *c++ = *s++; + } + } + + *c-- = 0; + // strip trailing ws + while (c > disp && iswsp(*c)) + *c-- = 0; + + if (*disp && !*addr && strchr(disp, '@')) { + // just mail address was given + strcpy(addr, disp); + *disp = 0; + } + + printf("DISP :: |%s|\n", disp); + printf("ADDR :: |%s|\n", addr); + + if (dispo) *dispo = disp; + if (addro) *addro = addr; + + return s; +} + +void +blaze822(char *file) +{ + int fd; + ssize_t rd; + char *buf; + ssize_t bufalloc; + ssize_t used; + char *end; + + fd = open(file, O_RDONLY); + if (fd < 0) { + perror("open"); + return; + } + + buf = malloc(3); + buf[0] = '\n'; + buf[1] = '\n'; + buf[2] = '\n'; + bufalloc = 3; + used = 3; + + while (1) { + bufalloc += bufsiz; + buf = realloc(buf, bufalloc); + + rd = read(fd, buf+used, bufalloc-used); + if (rd == 0) { + end = buf+used; + break; + } + if (rd < 0) + exit(-1); + + if ((end = memmem(buf-1+used, rd+1, "\n\n", 2)) || + (end = memmem(buf-3+used, rd+3, "\r\n\r\n", 4))) { + used += rd; + break; + } + + used += rd; + } + close(fd); + + end++; + *end = 0; // dereferencing *end is safe + + char *s; + for (s = buf; s < end; s++) { + if (*s == 0) // sanitize nul bytes in headers + *s = ' '; + + if (*s == '\r') { + if (*(s+1) == '\n') { + *s++ = '\n'; + } else { + *s = ' '; + } + } + + if (iswsp(*s)) { + // change prior \n to spaces + int j; + for (j = 1; s - j >= buf && *(s-j) == '\n'; j++) + *(s-j) = ' '; + } + + if (*s == '\n') { + s++; + if (iswsp(*s)) { + *(s-1) = ' '; + } else { + *(s-1) = 0; + if (*(s-2) == '\n') // ex-crlf + *(s-2) = 0; + while (s < end && *s != ':') { + *s = tolower(*s); + s++; + } + } + } + } + + buf[0] = 0; + +/* + for (s = buf; s < end; ) { + printf("%s\n", s); + s += strlen(s) + 1; + } +*/ + char *v; + if ((v = memmem(buf, end-buf, "\0from:", 6))) { + printf("FROM : %s\n", v+6); + parse_addr(v+6, 0, 0); + } + if ((v = memmem(buf, end-buf, "\0to:", 4))) { + printf("TO : %s\n", v+4); + char *a = v+4; + char *disp, *addr; + do { + a = parse_addr(a, &disp, &addr); + printf("DISP: |%s| ADDR: |%s|\n", disp, addr); + } while (*a); + } + if ((v = memmem(buf, end-buf, "\0date:", 6))) { + printf("DATE : %s\n", v+6); + time_t t = parse_date(v+6); + if (t != -1) + printf("DATE :: %s", ctime(&t)); + else + fprintf(stderr, "invalid date: %s\n", v+6); + } + if ((v = memmem(buf, end-buf, "\0subject:", 9))) { + printf("SUBJECT : %s\n", v+9); + } + + free(buf); + + printf("used: %d %d\n", used, end-buf); +} + +int +main(int argc, char *argv[]) { + char *s; + + char *line = 0; + size_t linelen = 0; + int read; + + int i = 0; + + if (argc == 1 || (argc == 2 && strcmp(argv[1], "-") == 0)) { + while ((read = getdelim(&line, &linelen, '\n', stdin)) != -1) { + if (line[read-1] == '\n') line[read-1] = 0; + fprintf(stderr, "%s\n", line); + blaze822(line); + i++; + } + } else { + for (i = 1; i < argc; i++) { + fprintf(stderr, "%s\n", argv[i]); + blaze822(argv[i]); + } + i--; + } + + printf("%d mails scanned\n", i); + + return 0; +} diff --git a/fastls.c b/fastls.c new file mode 100644 index 0000000..c1111c3 --- /dev/null +++ b/fastls.c @@ -0,0 +1,97 @@ +#define _GNU_SOURCE +#include /* Defines DT_* constants */ +#include +#include +#include +#include +#include +#include +#include + +#define handle_error(msg) \ + do { perror(msg); exit(EXIT_FAILURE); } while (0) + +struct linux_dirent64 { + ino64_t d_ino; /* 64-bit inode number */ + off64_t d_off; /* 64-bit offset to next structure */ + unsigned short d_reclen; /* Size of this dirent */ + unsigned char d_type; /* File type */ + char d_name[]; /* Filename (null-terminated) */ +}; + + +#define BUF_SIZE 1024000 + +void flagsort(char *s) { + int i, j; + if (!s[0]) + return; + // adapted insertion sort from http://stackoverflow.com/a/2789530 + for (i = 1; s[i]; i++) { + char t = s[i]; + for (j = i; j >= 1 && t < s[j-1]; j--) + s[j] = s[j-1]; + s[j] = t; + } +} + +int +main(int argc, char *argv[]) +{ + int fd, nread; + char buf[BUF_SIZE]; + struct linux_dirent64 *d; + int bpos; + char d_type; + + fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY); + if (fd == -1) + handle_error("open"); + + while (1) { + nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE); + if (nread == -1) + handle_error("getdents64"); + + if (nread == 0) + break; + + printf("--------------- nread=%d ---------------\n", nread); + printf("inode# file type d_reclen d_off d_name\n"); + for (bpos = 0; bpos < nread;) { + d = (struct linux_dirent64 *) (buf + bpos); + if (d->d_type != DT_REG) + goto next; + if (d->d_name[0] == '.') + goto next; + char *flags = strstr(d->d_name, ":2,"); + if (!flags) + goto next; +// if (strncmp(d->d_name, "1467836925_0.1439.juno,U=87588,FMD5=7e33429f656f1", strlen("1467836925_0.1439.juno,U=87588,FMD5=7e33429f656f1")-1)) +// goto next; +// printf("%s\n", d->d_name); + flagsort(flags+3); + printf("%s\n", d->d_name); +// if (!strchr(flags, 'S')) +// printf("%s\n", d->d_name); + +// goto next; + +/* + printf("%-10s ", (d_type == DT_REG) ? "regular" : + (d_type == DT_DIR) ? "directory" : + (d_type == DT_FIFO) ? "FIFO" : + (d_type == DT_SOCK) ? "socket" : + (d_type == DT_LNK) ? "symlink" : + (d_type == DT_BLK) ? "block dev" : + (d_type == DT_CHR) ? "char dev" : "???"); + printf("%4d %10lld %s\n", d->d_reclen, + (long long) d->d_off, d->d_name); +*/ +next: + bpos += d->d_reclen; + } + } + + exit(EXIT_SUCCESS); +} diff --git a/flags.c b/flags.c new file mode 100644 index 0000000..fd66951 --- /dev/null +++ b/flags.c @@ -0,0 +1,48 @@ +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int i; + unsigned int j; + char *f, *e; + + int8_t flagmod[255] = { 0 }; + + for (i = 1; i < argc; i++) { + if (*argv[i] == '+') { + f = argv[i] + 1; + while (*f) + flagmod[(int)*f++]++; + continue; + } else if (*argv[i] == '-') { + f = argv[i] + 1; + while (*f) + flagmod[(int)*f++]--; + continue; + } + + int8_t flags[255] = { 0 }; + char flagstr[255]; + f = e = strstr(argv[i], ":2,"); + + if (!f) + continue; + f += 3; + while (*f) + flags[(int)*f++] = 1; + + *e = 0; + f = flagstr; + for (j = 0; j < sizeof flags; j++) + if (flags[j] + flagmod[j]) + *f++ = j; + *f = 0; + + printf("%s:2,%s\n", argv[i], flagstr); + } + + return 0; +} diff --git a/foo822.c b/foo822.c new file mode 100644 index 0000000..0db82dd --- /dev/null +++ b/foo822.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include + +#undef getc +#define getc getc_unlocked + +#ifndef __GLIBC__ +#include "/home/chris/src/musl/src/internal/stdio_impl.h" +#endif + +FILE *input; + +enum { + EOL = -2, + EOH = -3 +}; + + +// WSP = SP / HTAB +#define iswsp(c) (((c) == ' ' || (c) == '\t')) + +// CRLF is \n, LF is \n, just CR is ' ', +// end of file is EOF, end of line is EOL, end of header is EOH, +// CRLFCR is EOH, CRLFCRLF is EOH, CRCR is EOH +int +mgetch() +{ + int c, d; + + switch(c = getc(input)) { + case EOF: + return EOF; + case '\r': + d = getc(input); + if (d != '\n') { + // stray CR + ungetc(d, input); + return ' '; + } + /* fallthru */ + case '\n': + d = getc(input); + if (d == '\r') { + d = getc(input); + if (d != '\n' && d != '\r') + return d; + } + if (d == '\n' || d == '\r') { + return EOH; + } else if (iswsp(d)) { + // line continuation + return ' '; + } else { + // end of line + ungetc(d, input); + return EOL; + } + default: + return c; + } +} + +char * +strip(char *t) +{ + char *b, *e; + for (b = t; *b && iswsp(*b); b++); + for (e = b; *e && !iswsp(*e); e++); + *e = 0; + return b; +} + +void skipws() { + int c; + do { + c = getc(input); + } while (c != EOF && iswsp(c)); + ungetc(c, input); +} + +char * +parse_header() +{ + static char hdr[1024]; + static const char *hdrend = hdr + sizeof hdr; + int c; + + char *s = hdr; + *s = 0; + while ((c = mgetch()) > 0 && s < hdrend) { + if (c < 0) + return 0; + if (c == ':') { + *s = 0; + skipws(); + return strip(hdr); + } + *s++ = tolower(c); + } + return 0; +} + +char * +parse_value() +{ + static char value[1024]; + static const char *valend = value + sizeof value; + + int c; + char *s = value; + + *s = 0; + + while ((c = mgetch()) != EOF && s < valend) { + if (c == EOH) { + ungetc('\n', input); + return value; + } + if (c == EOL) { + *s = 0; + return value; + } + *s++ = c; + } + return value; +} + +int +parse_tok(char **t) +{ + static char tok[16]; + static const char *tokend = tok + sizeof tok; + + int c; + + char *s = tok; + *s = 0; + *t = 0; + + c = mgetch(); + while (iswsp(c)) + c = mgetch(); + while (c > 0 && s < tokend) { +// printf("%c/%d ", c, c); + if (iswsp(c)) { + skipws(); + *s = 0; + *t = tok; + break; + } + else + *s++ = c; + c = mgetch(); + } + if (c == EOL) { + *s = 0; + *t = tok; + } + if (t) + *t = strip(tok); + +// printf("TOK |%s|", tok); + if (c < 0) + return c; + else { + return 1; + } +} + +static long +parse_posint(char *s, size_t minn, size_t maxn) +{ + long n; + char *end; + + errno = 0; + n = strtol(s, &end, 10); + if (errno || *end || n < (long)minn || n > (long)maxn) + return -1; + return n; +} + +int +parse_date(time_t *r) +{ + char *t; + int c; + + struct tm tm; + + if ((c = parse_tok(&t)) < 0) goto fail; + if (strlen(t) == 4 && t[3] == ',') // ignore day of week + if ((c = parse_tok(&t)) < 0) goto fail; + + if ((c = parse_posint(t, 1, 31)) < 0) goto fail; + tm.tm_mday = c; + + if ((c = parse_tok(&t)) < 0) goto fail; + // convert to switch + if (strcmp("Jan", t) == 0) tm.tm_mon = 0; + else if (strcmp("Feb", t) == 0) tm.tm_mon = 1; + else if (strcmp("Mar", t) == 0) tm.tm_mon = 2; + else if (strcmp("Apr", t) == 0) tm.tm_mon = 3; + else if (strcmp("May", t) == 0) tm.tm_mon = 4; + else if (strcmp("Jun", t) == 0) tm.tm_mon = 5; + else if (strcmp("Jul", t) == 0) tm.tm_mon = 6; + else if (strcmp("Aug", t) == 0) tm.tm_mon = 7; + else if (strcmp("Sep", t) == 0) tm.tm_mon = 8; + else if (strcmp("Oct", t) == 0) tm.tm_mon = 9; + else if (strcmp("Nov", t) == 0) tm.tm_mon = 10; + else if (strcmp("Dec", t) == 0) tm.tm_mon = 11; + else goto fail; + + if ((c = parse_tok(&t)) < 0) goto fail; + if ((c = parse_posint(t, 1000, 9999)) > 0) { + tm.tm_year = c - 1900; + } else if ((c = parse_posint(t, 0, 49)) > 0) { + tm.tm_year = c + 100; + } else if ((c = parse_posint(t, 50, 99)) > 0) { + tm.tm_year = c; + } else goto fail; + + if ((c = parse_tok(&t)) < 0) + if (!t) goto fail; + if (strlen(t) == 8 && t[2] == ':' && t[5] == ':') { + t[2] = t[5] = 0; + if ((c = parse_posint(t, 0, 24)) < 0) goto fail; + tm.tm_hour = c; + if ((c = parse_posint(t+3, 0, 59)) < 0) goto fail; + tm.tm_min = c; + if ((c = parse_posint(t+6, 0, 61)) < 0) goto fail; + tm.tm_sec = c; + } else if (strlen(t) == 5 && t[2] == ':') { + t[2] = 0; + if ((c = parse_posint(t, 0, 24)) < 0) goto fail; + tm.tm_hour = c; + if ((c = parse_posint(t+3, 0, 59)) < 0) goto fail; + tm.tm_min = c; + tm.tm_sec = 0; + } else { + goto fail; + } + +// if ((c = parse_tok(&t)) > 0) goto fail; // expect EOL, EOH, EOF + c = parse_tok(&t); + if (t && strlen(t) == 5 && (t[0] == '+' || t[0] == '-')) { + if ((c = parse_posint(t+1, 0, 10000)) < 0) goto fail; + if (t[0] == '+') { + tm.tm_hour -= c / 100; + tm.tm_min -= c % 100; + } else { + tm.tm_hour += c / 100; + tm.tm_min += c % 100; + } + } + // TODO: parse obs-zone? + + tm.tm_isdst = -1; + + *r = timegm(&tm); + return 0; + +fail: + *r = -1; + /* slurp rest of line and leave it */ + while ((c = mgetch()) > 0) + ; + return c; +} + +int decode_rfc2047 (char *str, char *dst, size_t dstlen); + + +int catmain() { + int c; + + input = stdin; + while ((c = mgetch())) { + if (c > 0) + putchar(c); + else + printf("[%d]\n", c); + } + + return 0; +} + +int tmain() { + char *s; + + input = stdin; + while ((s = parse_header())) { + if (strcmp(s, "date") == 0) { + time_t t; + if (parse_date(&t) >= 0) + printf("%s :: (%ld) %s", s, t, ctime(&t)); + else + printf("date : OOPS\n"); + } else if (strcmp(s, "subject") == 0) { + char *v = parse_value(); + char buf[2048]; + decode_rfc2047(v, buf, sizeof buf); + printf("%s : %s\n", s, v); + printf("%s :: %s\n", s, buf); + } else { + char *v = parse_value(); + printf("%s : %s\n", s, v); + } + } + + return 0; +} + +int main() { + char *s; + + char *line = 0; + size_t linelen = 0; + int read; + + int i = 0; + + static char buf[50000]; /* buf must survive until stdout is closed */ + + while ((read = getdelim(&line, &linelen, '\n', stdin)) != -1) { + if (line[read-1] == '\n') line[read-1] = 0; + + printf("%s\n", line); + + FILE *f = fopen(line, "r"); + if (!f) { + perror("fopen"); + continue; + } + setvbuf ( f , buf , _IOFBF , sizeof(buf) ); + i++; + + input = f; + while ((s = parse_header())) { + if (strcmp(s, "date") == 0) { + time_t t; + if (parse_date(&t) >= 0) + printf("%s :: (%ld) %s", s, t, ctime(&t)); + else + printf("date : OOPS\n"); + } else if (strcmp(s, "subject") == 0 || + strcmp(s, "from") == 0 || + strcmp(s, "to") == 0) { + char *v = parse_value(); + char buf[2048]; + if (decode_rfc2047(v, buf, sizeof buf)) + printf("%s :: %s\n", s, buf); + else + printf("%s : %s\n", s, v); + } else + parse_value(); // and ignore it + } + fclose(f); + } + + printf("%d mails scanned\n", i); + + return 0; +} diff --git a/next.c b/next.c new file mode 100644 index 0000000..f82e437 --- /dev/null +++ b/next.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int argc, char *argv[]) +{ + int fd; + struct stat st; + + fd = open("map", O_RDONLY); + if (!fd) + exit(101); + + fstat(fd, &st); + char *map = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (!map) + exit(102); + + char *s = strstr(map, argv[1]); + if (!argv[1][0] || !s) { + // default to first line + s = map; + } else { + while (*s && *s != '\n') + s++; + s++; + } + char *t = s; + while (*t && *t != '\n') + t++; + if (!*t) + exit(1); + t++; + write(1, s, t-s); + + return 0; +}