diff options
author | Hiltjo Posthuma <hiltjo@codemadness.org> | 2020-01-18 19:19:41 +0100 |
---|---|---|
committer | Hiltjo Posthuma <hiltjo@codemadness.org> | 2020-01-18 20:09:42 +0100 |
commit | 009f6e1affd8c8501f66526f100bfa273307e640 (patch) | |
tree | 9e1d5ad41be849f24a09f8080bb27dcfda46c552 /sfeed_gopher.c | |
parent | 018278e40b6794b23f98f57f154bfa1a30d56672 (diff) |
add sfeed_gopher: generic gopher formatting program, remove sfeed_gph
Diffstat (limited to 'sfeed_gopher.c')
-rw-r--r-- | sfeed_gopher.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/sfeed_gopher.c b/sfeed_gopher.c new file mode 100644 index 0000000..4100c62 --- /dev/null +++ b/sfeed_gopher.c @@ -0,0 +1,159 @@ +#include <sys/stat.h> +#include <sys/types.h> + +#include <ctype.h> +#include <err.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include "util.h" + +static struct feed f; +static char *prefixpath = "/", *host = "127.0.0.1", *port = "70"; /* default */ +static char *line; +static size_t linesize; +static time_t comparetime; + +/* Escape characters in gopher, CR and LF are ignored */ +void +gophertext(FILE *fp, const char *s) +{ + for (; *s; s++) { + switch (*s) { + case '\r': /* ignore CR */ + case '\n': /* ignore LF */ + break; + case '\t': + fputs(" ", fp); + break; + default: + fputc(*s, fp); + break; + } + } +} + +static void +printfeed(FILE *fpitems, FILE *fpin, struct feed *f) +{ + char *fields[FieldLast]; + ssize_t linelen; + unsigned int isnew; + struct tm *tm; + time_t parsedtime; + + if (f->name[0]) { + fprintf(fpitems, "i%s\t\t%s\t%s\r\n", f->name, host, port); + fprintf(fpitems, "i\t\t%s\t%s\r\n", host, port); + } + + while ((linelen = getline(&line, &linesize, fpin)) > 0) { + if (line[linelen - 1] == '\n') + line[--linelen] = '\0'; + if (!parseline(line, fields)) + break; + + parsedtime = 0; + if (strtotime(fields[FieldUnixTimestamp], &parsedtime)) + continue; + if (!(tm = localtime(&parsedtime))) + err(1, "localtime"); + + isnew = (parsedtime >= comparetime) ? 1 : 0; + f->totalnew += isnew; + f->total++; + + if (fields[FieldLink][0]) { + fputs("h", fpitems); + fprintf(fpitems, "%c %04d-%02d-%02d %02d:%02d ", + isnew ? 'N' : ' ', + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min); + gophertext(fpitems, fields[FieldTitle]); + fputs("\tURL:", fpitems); + gophertext(fpitems, fields[FieldLink]); + + } else { + fprintf(fpitems, "i%c %04d-%02d-%02d %02d:%02d ", + isnew ? 'N' : ' ', + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min); + gophertext(fpitems, fields[FieldTitle]); + fputs("\t", fpitems); + } + fprintf(fpitems, "\t%s\t%s\r\n", host, port); + } + fputs(".\r\n", fpitems); +} + +int +main(int argc, char *argv[]) +{ + FILE *fpitems, *fpindex, *fp; + char *name, *p, path[PATH_MAX + 1]; + int i, r; + + if (pledge(argc == 1 ? "stdio" : "stdio rpath wpath cpath", NULL) == -1) + err(1, "pledge"); + + if ((comparetime = time(NULL)) == -1) + err(1, "time"); + /* 1 day is old news */ + comparetime -= 86400; + + if ((p = getenv("SFEED_GOPHER_HOST"))) + host = p; + if ((p = getenv("SFEED_GOPHER_PORT"))) + port = p; + + if (argc == 1) { + f.name = ""; + printfeed(stdout, stdin, &f); + } else { + if ((p = getenv("SFEED_GOPHER_PATH"))) + prefixpath = p; + + /* write main index page */ + if (!(fpindex = fopen("index", "wb"))) + err(1, "fopen: index"); + + for (i = 1; i < argc; i++) { + memset(&f, 0, sizeof(f)); + name = ((name = strrchr(argv[i], '/'))) ? name + 1 : argv[i]; + f.name = name; + + if (!(fp = fopen(argv[i], "r"))) + err(1, "fopen: %s", argv[i]); + + r = snprintf(path, sizeof(path), "%s", name); + if (r < 0 || (size_t)r >= sizeof(path)) + errx(1, "path truncation: %s", path); + if (!(fpitems = fopen(path, "wb"))) + err(1, "fopen"); + printfeed(fpitems, fp, &f); + if (ferror(fp)) + err(1, "ferror: %s", argv[i]); + fclose(fp); + fclose(fpitems); + + /* append directory item to index */ + fputs("1", fpindex); + gophertext(fpindex, name); + fprintf(fpindex, " (%lu/%lu)\t", f.totalnew, f.total); + gophertext(fpindex, prefixpath); + gophertext(fpindex, path); + fprintf(fpindex, "\t%s\t%s\r\n", host, port); + } + fputs(".\r\n", fpindex); + fclose(fpindex); + } + + return 0; +} |