gawk

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

commit e6092335feee193caeb1360be8a95c61756b2729
parent 9787d16a53436f6c7bfeb54b03dd2b695981fa70
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date:   Sat, 19 Dec 2020 14:12:13 -0800

Add caching

Add file caching although you still cannot display the content.

Diffstat:
Mmain.c | 123++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 66 insertions(+), 57 deletions(-)

diff --git a/main.c b/main.c @@ -33,7 +33,16 @@ #define ARGV_MAX 16 #define ARG_SEP ":\t " -static char *format_prog = "gophmt"; /* not released, costom formatter */ +FILE * +wfopen(const char *path, const char *mode) +{ + FILE *fp; + + fp = fopen(path, mode); + if (fp == NULL) + warn("unable to open '%s' ('%s')", path, mode); + return fp; +} int resolve(struct addrinfo **ai, const char *host, const char *proto) @@ -134,6 +143,22 @@ newpath(char *path, char *newpath) } } +void +getcache(char *cache, const char *tmpdir, const char *host, const char *port, const char *path) +{ + int i; + char tmp[PATH_MAX]; + + for (i = 0; path[i] != '\0'; ++i) { + if (path[i] == '/') + tmp[i] = '-'; + else + tmp[i] = path[i]; + } + tmp[i] = '\0'; + snprintf(cache, PATH_MAX, "%s/%s-%s-%s", tmpdir, host, port, tmp); +} + int argsplit(char **argv, int arg_max, char *s, const char *sep) { @@ -151,81 +176,47 @@ argsplit(char **argv, int arg_max, char *s, const char *sep) return argc; } -/* NOTE: implement caching */ int -getgph(int sock, const char *path) +fetch(int sock, const char *path) { - ssize_t bytes; + FILE *fp; char buf[BUFSIZE]; + ssize_t bytes; + int error; - /* NOTE: SIGPIPE is recieved */ - if (send(sock, path, strlen(path), 0) == -1) { - warn("unable to send request"); + fp = wfopen(path, "w+"); + if (fp == NULL) return 1; - } while ((bytes = recv(sock, buf, sizeof(buf), 0)) > 0) { - if (fwrite(buf, 1, bytes, stdout) != bytes) + if (fwrite(buf, 1, bytes, fp) != bytes) { + fclose(fp); return 1; + } } + error = ferror(fp); + if (fclose(fp) || error) + return 1; return 0; } int -gawkat(int sock, const char *path) +gawkat(const char *path) { - int status; - int fds[2]; - char *argv[2]; - - if (pipe(fds) == -1) { - warn("unable to pipe"); - return 1; - } - - argv[0] = format_prog; - argv[1] = NULL; - - switch (fork()) { - case -1: - warn("unable to fork"); - return 1; - case 0: - if (dup2(fds[1], STDIN_FILENO) == -1) { - warn("unable to setup pipe"); - _exit(1); - } - execvp(*argv, argv); - warn("execvp %s", *argv); - return 1; - default: - if (dup2(fds[0], STDOUT_FILENO) == -1) { - warn("unable to setup pipe"); - status = 1; - break; - } - if ((status = getgph(sock, path)) == 0) { - wait(&status); - if (status) - warnx("child exited %d", status); - } - } - - if (close(fds[0]) || close(fds[1])) - warn("unable to close pipe"); - - return status; + printf("gawking at %s\n", path); + return 0; } /* returns `<0` on error, if positive `n - 1` is * be returned to the caller. */ int -gawk(int sock, int depth, const char *host, const char *path, const char *port) +gawk(int sock, 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]; char prompt[64]; /* you wouldn't want it longer anyway */ + char cache[PATH_MAX]; const char *nreq[3]; int argc; int closeit, done, newsock; @@ -241,6 +232,16 @@ gawk(int sock, int depth, const char *host, const char *path, const char *port) return -1; } + if (send(sock, path, strlen(path), 0) == -1) { + warn("unable to send request"); + return 1; + } + + /* NOTE: could exist, test for it. */ + getcache(cache, tmpdir, host, port, path); + if (fetch(sock, cache) != 0) + return 0; /* just return to the previous, if any. */ + snprintf(prompt, sizeof(prompt), "[%s] %s ", host, path); done = 0; @@ -261,9 +262,7 @@ gawk(int sock, int depth, const char *host, const char *path, const char *port) done = depth; break; case 'p': /* print */ - puts("gawking"); - /* NOTE: SIGPIPE on second call. - * gawkat(sock, path); */ + gawkat(path); break; case 'b': /* back */ if (argc > 2) @@ -301,7 +300,7 @@ gawk(int sock, int depth, const char *host, const char *path, const char *port) if (!newsock) newsock = sock; - done = gawk(newsock, depth, nreq[0], nreq[1], nreq[2]); + done = gawk(newsock, depth, tmpdir, nreq[0], nreq[1], nreq[2]); break; default: invalid_input: @@ -309,6 +308,8 @@ invalid_input: } } + /* NOTE: cleanup cache files IF created in this function */ + if (closeit && close(sock) == -1) warn("unable to disconnect from '%s'", host); if (ferror(stdin)) { @@ -321,7 +322,15 @@ invalid_input: int main(int argc, char *argv[]) { - gawk(-1, 0, "localhost", "/","gopher"); + char t[64]; + strcpy(t, "/tmp/gawk-XXXXXXXXXXX"); + if (mkdtemp(t) == NULL) + err(1, "unable to create temp dir"); + + gawk(-1, 0, t, "localhost", "/","gopher"); + + if (rmdir(t) == -1) + err(1, "unable to remove temp dir"); return 0; }