gawk

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

commit 87e78340cd1dde90cef00cb1bed8a0f475fbb6eb
parent 0bd4422223828bc88630c2f39bcea3a22a2c12ef
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Sat, 19 Dec 2020 18:51:04 -0800

Fix and polish requests and caching

It seems one should actually _read the specification_ of a protocol
which they are implementing a client for. As proof the issue with
multiple requests was that you cannot reuse connections.

The prompt is now printed to stderr.

Diffstat:
Mmain.c | 77++++++++++++++++++++++++++++++++++++++++++-----------------------------------
1 file changed, 42 insertions(+), 35 deletions(-)

diff --git a/main.c b/main.c @@ -114,7 +114,7 @@ input(char *buf, int size, const char *prompt, FILE *fp) { int len; - fputs(prompt, stdout); + fputs(prompt, stderr); if (fgets(buf, size, fp) == NULL) return 1; @@ -243,6 +243,33 @@ putfile(const char *path) } int +gphsend(int sock, const char *request) +{ + if (send(sock, request, strlen(request), 0) == -1) { + warn("unable to send request"); + return 1; + } + return 0; +} + +int +gphcache(const char *cache, const char *host, const char *path, const char *port) +{ + int sock; + + sock = connect_to(host, port); + if (sock == -1) + return 1; + + if (gphsend(sock, path) != 0 || + fetch(sock, cache) != 0) { + close(sock); + return 1; + } + return close(sock); +} + +int gawkat(const char *path) { if (putfile(path) != 0) @@ -253,7 +280,7 @@ gawkat(const char *path) /* returns `<0` on error, if positive `n - 1` is * be returned to the caller. */ int -gawk(int sock, int depth, const char *tmpdir, const char *host, const char *path, const char *port) +gawk(int depth, const char *tmpdir, const char *host, const char *path, const char *port) { char *argv[ARGV_MAX]; char inbuf[PATH_MAX + HOST_NAME_MAX + PROTO_MAX]; @@ -261,34 +288,23 @@ gawk(int sock, int depth, const char *tmpdir, const char *host, const char *path char cache[PATH_MAX]; const char *nreq[3]; int argc; - int closeit, unlinkit, done, newsock; + int unlinkit; + int done; ++depth; - if (sock != -1) { - closeit = 0; - } else { - closeit = 1; - sock = connect_to(host, port); - if (sock == -1) - return -1; - } - getcache(cache, tmpdir, host, port, path); - - unlinkit = 0; - if (!exists(cache)) { - if (send(sock, path, strlen(path), 0) == -1) { - warn("unable to send request"); - return 1; - } - if (fetch(sock, cache) != 0) - return 0; /* just return to the previous, if any. */ + if (exists(cache)) + unlinkit = 0; + else { unlinkit = 1; + if (gphcache(cache, host, path, port) == 1) + return 0; /* let the user handle it */ } done = 0; snprintf(prompt, sizeof(prompt), "[%s] %s ", host, path); + gawkat(cache); while (!done && input(inbuf, sizeof(inbuf), prompt, stdin) == 0) { argc = argsplit(argv, LEN(argv), inbuf, ARG_SEP); if (argc <= 0) { @@ -320,7 +336,6 @@ gawk(int sock, int depth, const char *tmpdir, const char *host, const char *path if (argc > 4) goto invalid_input; - newsock = 0; nreq[0] = host; nreq[1] = path; nreq[2] = port; @@ -333,18 +348,12 @@ gawk(int sock, int depth, const char *tmpdir, const char *host, const char *path else { nreq[0] = argv[1]; nreq[1] = argv[2]; - if (strcmp(host, nreq[0]) != 0) - newsock = -1; - if (argc == 3) { + if (argc == 3) nreq[2] = argv[3]; - if (!newsock && strcmp(port, nreq[2]) != 0) - newsock = -1; - } } - - if (!newsock) - newsock = sock; - done = gawk(newsock, depth, tmpdir, nreq[0], nreq[1], nreq[2]); + done = gawk(depth, tmpdir, nreq[0], nreq[1], nreq[2]); + if (done == 0) + gawkat(cache); break; default: invalid_input: @@ -354,8 +363,6 @@ invalid_input: if (unlinkit && unlink(cache) == -1) warn("unable to unlink '%s'", cache); - if (closeit && close(sock) == -1) - warn("unable to disconnect from '%s'", host); if (ferror(stdin)) { warn("'stdin'"); return -1; @@ -371,7 +378,7 @@ main(int argc, char *argv[]) if (mkdtemp(t) == NULL) err(1, "unable to create temp dir"); - gawk(-1, 0, t, "localhost", "/","gopher"); + gawk(0, t, "localhost", "/","gopher"); if (rmdir(t) == -1) err(1, "unable to remove temp dir");