gawk

[old] Sed-like interface to the Gopher protocol
Log | Files | Refs | LICENSE

commit bd3e341b2ef355e6f25e97c1478e7227202f52ff
parent 0fd60dd1f4f09fc5f0d2879037b46538df5668e2
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Tue, 22 Dec 2020 01:45:06 -0800

Add external content command

Separate fgroup's substring match functionality into a separate
filter, fstrmatch.

Add simple command which forks and executes a list of arguments
replacing an argument which contains a sole `%' with the url (actually
it doesn't have a protocol so it's not a url).

Diffstat:
Mmain.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 63 insertions(+), 4 deletions(-)

diff --git a/main.c b/main.c @@ -36,6 +36,7 @@ #define ARGV_MAX 16 #define ARG_SEP ":\t " #define CMD_SEP ";\n" +#define URL_MAX 128 enum gphitem { GI_INFO, GI_PATH, GI_HOST, GI_PORT, GI_NULL }; @@ -308,6 +309,7 @@ splitrun(int argc, const char **argv, int index, char *request, command *func) { char *fields[6]; + /* NOTE: argsplit ignores multiple terminators. */ if (argsplit(fields, LEN(fields), request, "\t\r\n") != 4) if (fields[4] != NULL && strcmp(fields[4], "+") != 0) { warnx("%d: Not a valid gopher item.", index); @@ -355,6 +357,32 @@ findex(const char *cache, int argc, const char **argv, command *func) } int +fstrmatch(const char *cache, int argc, const char **argv, command *func) +{ + FILE *fp; + char buf[LINE_MAX]; + int anystr; + int i; + + fp = wfopen(cache, "r"); + if (fp == NULL) + return 1; + + if (!argv[0]) + anystr = 1; + else anystr = 0; + + for (i = 0; fgets(buf, sizeof(buf), fp) != NULL; ++i) { + if (*buf == '.') + break; + if (anystr || strcasestr(buf, argv[0])) + splitrun(argc - 1, argv + 1, i, buf, func); + } + + return wfclose(fp); +} + +int fgroup(const char *cache, int argc, const char **argv, command *func) { FILE *fp; @@ -373,10 +401,8 @@ fgroup(const char *cache, int argc, const char **argv, command *func) for (i = 0; fgets(buf, sizeof(buf), fp) != NULL; ++i) { if (*buf == '.') break; - if (anytype || argc < 1 || strchr(argv[0], *buf)) { - if (argc < 2 || strcasestr(buf, argv[1])) - splitrun(argc - 2, argv + 2, i, buf, func); - } + if (anytype || strchr(argv[0], *buf)) + splitrun(argc - 1, argv + 1, i, buf, func); } return wfclose(fp); @@ -476,6 +502,35 @@ cfetch(int argc, const char **argv, int i, const char **request) return 0; } +int +cextern(int argc, const char **argv, int index, const char **item) +{ + char url[URL_MAX]; + int i; + + if (argc == 0) { + warnx("%s: Not enough arguments.", __func__); + return 1; + } + + snprintf(url, sizeof(url), "%s/%s", item[GI_HOST], item[GI_PATH]); + for (i = 0; i < argc; ++i) + if (strcmp(argv[i], "%") == 0) + argv[i] = url; + + switch (fork()) { + case -1: + warn("unable to fork"); + return 1; + case 0: + execvp(*argv, (char *const *)argv); + warn("execvp '%s'", *argv); + _exit(1); + } + + return 0; +} + command * getcommand(int c) { @@ -486,6 +541,8 @@ getcommand(int c) return cprintn; case 'f': return cfetch; + case 'e': + return cextern; default: return NULL; } @@ -499,6 +556,8 @@ getfilter(int c) return fgroup; case 'i': return findex; + case 's': + return fstrmatch; default: return NULL; }