commit baddf547341bd520a0d1396dde56d8cb0f2ce872
parent 1fa849f6766d2a4db924eaa22f5ba11c534c0526
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date: Mon, 21 Dec 2020 21:48:56 -0800
Remove piping and make a new catagory of functions
It's a shame to remove piping but it takes up much more space than
what it gives now, a very commendable formatter can be made in a
few lines utilizing functions which are already needed.
Create a new function catagory, `s' or "selector" functions and
rename cselect to sindexes.
Tweak and rename the cmatch function to smatch for use as a selector.
Diffstat:
M | main.c | | | 163 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
1 file changed, 67 insertions(+), 96 deletions(-)
diff --git a/main.c b/main.c
@@ -43,7 +43,6 @@ enum gphitem { GI_INFO, GI_PATH, GI_HOST, GI_PORT, GI_NULL };
int gawk(const char *, const char *, const char *);
static int timeout = 5 * 1000;
-static char *gphfmt[] = { "gophmt", NULL };
static char tmpdir[] = "/tmp/gawk-XXXXXXXXXXX";
FILE *
@@ -302,68 +301,13 @@ gph_write(const char *host, const char *port, const char *request, const char *p
}
int
-pipedup(int old, int new, int fildes[2])
-{
- if (dup2(old, new) == -1 ||
- close(fildes[0]) || close(fildes[1])) {
- warn("unable to setup pipe");
- return 1;
- }
- return 0;
-}
-
-int
-exfmt(int (*putter)(const char *, int, const char **), const char *path, int argc, const char **argv)
-{
- int fds[2];
- int i;
-
- if (pipe(fds) == -1) {
- warn("unable to setup pipe");
- return 1;
- }
-
- switch (fork()) {
- case -1:
- warn("unable to fork");
- return 1;
- case 0:
- if (pipedup(fds[0], STDIN_FILENO, fds) != 0)
- _exit(1);
- execvp(*gphfmt, gphfmt);
- warn("execvp '%s'", *gphfmt);
- _exit(1);
- }
-
- switch (fork()) {
- case -1:
- warn("unable to fork");
- return 1;
- case 0:
- if (pipedup(fds[1], STDOUT_FILENO, fds) != 0)
- _exit(1);
- _exit(putter(path, argc, argv));
- }
-
- if (close(fds[0]) || close(fds[1])) {
- warn("%s: unable to close pipe", __func__);
- return 1;
- }
- for (i = 0; i < 2; ++i)
- if (wait(0) == -1) {
- warn("unable to wait");
- return 1;
- }
-
- return 0;
-}
-
-int
-cs_splitrun(int argc, const char **argv, char *request, int (*func)(int, const char **, const char **))
+splitrun(int argc, const char **argv, char *request, int (*func)(int, const char **, const char **))
{
char *fields[5];
- if (argsplit(fields, LEN(fields), request, "\t\r\n") != 4) {
+ if (*request == '.')
+ return func(argc, argv, NULL);
+ else if (argsplit(fields, LEN(fields), request, "\t\r\n") != 4) {
warnx("Not a valid gopher item.");
return 1;
}
@@ -371,7 +315,7 @@ cs_splitrun(int argc, const char **argv, char *request, int (*func)(int, const c
}
int
-cselect(int argc, const char **argv, const char *cache, int (*func)(int, const char **, const char **))
+sindexes(int argc, const char **argv, const char *cache, int (*func)(int, const char **, const char **))
{
FILE *fp;
char buf[LINE_MAX];
@@ -398,7 +342,7 @@ cselect(int argc, const char **argv, const char *cache, int (*func)(int, const c
more = 0;
for (j = 0; j < ids; ++j)
if (i == indexes[j])
- cs_splitrun(argc, argv, buf, func); /* NOTE: errors ignored */
+ splitrun(argc, argv, buf, func); /* NOTE: errors ignored */
else if (i < indexes[j])
more = 1;
}
@@ -406,6 +350,31 @@ cselect(int argc, const char **argv, const char *cache, int (*func)(int, const c
return wfclose(fp);
}
+int
+sgroup(int argc, const char **argv, const char *cache, int (*func)(int, const char **, const char **))
+{
+ FILE *fp;
+ char buf[LINE_MAX];
+ int anytype;
+
+ fp = wfopen(cache, "r");
+ if (fp == NULL)
+ return 1;
+
+ if (!argv[0] || strchr(argv[0], '.'))
+ anytype = 1;
+ else anytype = 0;
+
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ if (anytype || argc < 1 || strchr(argv[0], *buf)) {
+ if (argc < 2 || strcasestr(buf, argv[1]))
+ splitrun(argc - 2, argv + 2, buf, func);
+ }
+ }
+
+ return wfclose(fp);
+}
+
/* If lacking arguments goes to root (`/'). If one argument is given
* it is taken as a path, if multiple are given the first is the host,
* the second the path, and the optional third the port.
@@ -455,51 +424,46 @@ cback(int argc, const char **argv)
return back;
}
-/* argv[0], if present, restricts item types to one type contained
- * in it, `.' is a wildcard. argv[1], if present, restricts by
- * matches to strcasecmp.
- */
int
-cmatch(const char *path, int argc, const char **argv)
+cprint(int argc, const char **argv, const char **s)
{
- FILE *fp;
- char *line;
- size_t size;
- int anytype;
+ wunused(0, argc, argv);
- fp = wfopen(path, "r");
- if (fp == NULL)
+ if (s == NULL)
return 1;
+ if (**s == 'i')
+ printf(" %s\n", s[GI_INFO] + 1);
+ else
+ printf(" [%c] %s (%s%s)\n", s[GI_INFO][0], s[GI_INFO] + 1, s[GI_HOST], s[GI_PATH]);
+ return 0;
+}
- if (!argv[0] || strchr(argv[0], '.'))
- anytype = 1;
- else anytype = 0;
-
- line = NULL;
- size = 0;
- while (getline(&line, &size, fp) != -1) {
- if (anytype || argc < 1 || strchr(argv[0], *line)) {
- if (argc < 2 || strcasestr(line, argv[1]))
- dprintf(STDOUT_FILENO, "%s", line);
- }
- }
- free(line);
-
- if (wfclose(fp))
+int
+cprintn(int argc, const char **argv, const char **s)
+{
+ /* It's a shame but the counter has no way of knowing what
+ * item it's on in the gopher index, therefor it's not
+ * useful when restricting with smatch.
+ */
+ static int n;
+
+ if (s == NULL) {
+ n = 0;
return 1;
- return 0;
+ }
+ printf("%4d", n++);
+ return cprint(argc, argv, s);
+
}
-/* argv[0] is the line index (starting from 0) of the file to
- * download. If present argv[1] is the location to write the file
- * to, otherwise it is written to the basename(3) of it's selector
- * string.
- */
int
cfetch(int argc, const char **argv, const char **request)
{
const char *output;
+ /* NOTE: perhaps some message should be printed */
+ if (request == NULL)
+ return 1;
wunused(1, argc, argv);
if (argc > 0)
@@ -520,19 +484,26 @@ int
execute(int command, int argc, const char **argv, int depth, const char *cache,
const char *host, const char *path, const char *port)
{
+ /* NOTE: have another prefix command which decides which
+ * selector to use, currently either sindexes or sgroup.
+ */
switch (command) {
case 'U': case 'q': /* unwind the whole stack */
wunused(0, argc, argv);
return depth;
case 'p': /* print gopher-text */
- exfmt(cmatch, cache, argc, argv);
+ sgroup(argc, argv, cache, cprint);
+ return 0;
+ case 'i':
+ sgroup(argc, argv, cache, cprintn);
+ cprintn(0, NULL, NULL); /* reset counter, kinda messy */
return 0;
case 's': case 'g': /* goto new location */
return cgoto(argc, argv, host, path, port);
case 'u': case 'b': /* unwind [n] */
return cback(argc, argv);
case 'w': case 'f': /* write to file */
- cselect(argc, argv, cache, cfetch);
+ sindexes(argc, argv, cache, cfetch);
return 0;
default:
warnx("invalid command '%c'", command);