gawk

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

commit 0eeeb0505fb7fd62a4ac1be9bfeac0070fd808c4
parent 05177ec3488a7ce20153d73f079433684c4631ce
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Mon, 21 Dec 2020 16:34:11 -0800

Move cfetch() line selection to external function

This was done for new commands which might make use of it.

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

diff --git a/main.c b/main.c @@ -198,6 +198,38 @@ putprompt(const char *prompt) warn("isatty %d", STDIN_FILENO); } +/* NOTE: Perhaps I should just store the gopher-text in an array. + * It would make this trivial and simple, simply `gphindex[N]`. + * + * It seems like too much though, it probably wouldn't exceed 1 MiB + * even after 1000 are stacked but it seems wrong. I suppose my + * /tmp is in memory anyway though. */ +char * +getlines(unsigned int *i, unsigned int *indexes, int n, FILE *fp) +{ + char *line; + size_t size; + unsigned int j; + int more; + + line = NULL; + size = 0; + more = 1; + for (; more && getline(&line, &size, fp) != -1; ++*i) { + more = 0; + for (j = 0; j < n; ++j) { + if (*i == indexes[j]) + return line; + else if (*i < indexes[j]) + more = 1; + } + } + + if (line) + free(line); + return NULL; +} + int input(char *buf, int size, const char *delims, const char *prompt, FILE *fp) { @@ -439,6 +471,27 @@ cmatch(const char *path, int argc, const char **argv) return 0; } +int +getfromline(char *line, const char *output) +{ + char *fields[GI_NULL + 1]; + + if (argsplit(fields, LEN(fields), line, "\t\r\n") != LEN(fields) - 1) { + warnx("Not a valid gopher item."); + return 1; + } + + if (output == NULL) + if ((output = basename(fields[GI_PATH])) == NULL) { + warn("unable to get basename '%s'", fields[GI_PATH]); + return 1; + } + if (selwrite(fields[GI_HOST], fields[GI_PORT], fields[GI_PATH], output) != 0) + return 1; + warnx("'%s/%s' written to '%s'", fields[GI_HOST], fields[GI_PATH], output); + return 0; +} + /* 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 @@ -448,12 +501,11 @@ int cfetch(int argc, const char **argv, const char *cache, const char *host, const char *port) { FILE *fp; - char *fields[GI_NULL + 1]; - char *line; const char *output; - int error; - int i, n; - size_t size; + char *line; + unsigned int i; + int n; + int status; if (argc == 0) { warn("No index given"); @@ -473,34 +525,19 @@ cfetch(int argc, const char **argv, const char *cache, const char *host, const c if (fp == NULL) return 1; - error = 1; - line = NULL; - size = 0; - for (i = 0; i <= n && getline(&line, &size, fp) != -1; ++i) { - if (i == n) { - if (argsplit(fields, LEN(fields), line, "\t\r\n") != LEN(fields) - 1) { - warnx("Not a valid gopher item."); - break; - } - if (output == NULL) - if ((output = basename(fields[GI_PATH])) == NULL) { - warn("unable to get basename '%s'", fields[GI_PATH]); - break; - } - if (selwrite(fields[GI_HOST], fields[GI_PORT], fields[GI_PATH], output) == 0) - error = 0; - } + i = 0; + line = getlines(&i, (unsigned int *)&n, 1, fp); + if (line == NULL) { + if (!ferror(fp)) + warnx("%d: Out of range.", n); + wfclose(fp); + return 1; } + wfclose(fp); - if (error && n > i) - warnx("%d: Out of range.", n); - else if (!error) - warnx("'%s/%s' written to '%s'", fields[GI_HOST], fields[GI_PATH], output); - + status = getfromline(line, output); free(line); - if (wfclose(fp) || error) - return 1; - return 0; + return status; } int