commit bca75728dbc017877e7a9312398d449f42fb4c66
parent e9b871ac8026cc918d4c3939212a49d37a49363f
Author: Jacob R. Edwards <jacobouno@protonmail.com>
Date: Sat, 19 Dec 2020 02:49:20 -0800
Cleanup and implement requests
While currently sending a request exits immidiately after printing
the result it works.
Diffstat:
M | main.c | | | 142 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
1 file changed, 99 insertions(+), 43 deletions(-)
diff --git a/main.c b/main.c
@@ -17,6 +17,7 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <netdb.h>
#include <stdio.h>
#include <unistd.h>
@@ -27,8 +28,10 @@
#include <ctype.h>
#define LEN(X) (sizeof(X) / sizeof(*X))
+#define PROTO_MAX 16
+#define BUFSIZE 4096
-#define PROTO_MAX 16
+static char *format_prog = "gophmt"; /* not released, costom formatter */
int
resolve(struct addrinfo **ai, const char *host, const char *proto)
@@ -101,13 +104,6 @@ input(char *buf, int size, const char *prompt, FILE *fp)
return r;
}
-void
-update_prompt(char *prompt, size_t size, const char *host, const char *path, int connected)
-{
- snprintf(prompt, size, "%s%s %c> ",
- host, path, connected ? '+' : '-');
-}
-
int
strtoui(const char *s)
{
@@ -167,6 +163,63 @@ gawkparse(char *cmd, char *host, char *path, char *port)
strlcpy(port, nport, PROTO_MAX);
}
+/* NOTE: implement caching */
+int
+getgph(int sock, const char *path)
+{
+ ssize_t bytes;
+ char buf[BUFSIZE];
+
+ if (send(sock, path, strlen(path), 0) == -1) {
+ warn("unable to send request");
+ return 1;
+ }
+
+ while ((bytes = recv(sock, buf, sizeof(buf), 0)) > 0) {
+ if (fwrite(buf, 1, bytes, stdout) != bytes)
+ return 1;
+ }
+ return 0;
+}
+
+int
+gawkat(int sock, const char *path)
+{
+ int status;
+ int fds[2];
+ char *argv[2];
+
+ if (pipe(fds) == -1) {
+ warn("unable to pipe");
+ return 1;
+ }
+
+ switch (fork()) {
+ case -1:
+ warn("unable to fork");
+ return 1;
+ case 0:
+ if (dup2(fds[1], STDIN_FILENO) == -1 || close(fds[0]))
+ warn("unable to setup pipe");
+ argv[0] = format_prog;
+ argv[1] = NULL;
+ execvp(*argv, argv);
+ warn("execvp %s", *argv);
+ return 1;
+ default:
+ if (dup2(fds[0], STDOUT_FILENO) == -1 || close(fds[1]))
+ warn("unable to setup pipe");
+ }
+
+ if ((status = getgph(sock, path)) == 0) {
+ wait(&status);
+ if (status)
+ warnx("child exited %d", status);
+ }
+ return status;
+
+}
+
/* returns `<0` on error, if positive `n - 1` is
* be returned to the caller. */
int
@@ -176,22 +229,53 @@ gawk(int sock, int depth, const char *host, const char *path, const char *port)
int child;
char cbuf[PATH_MAX + HOST_NAME_MAX + PROTO_MAX];
char *cmd;
+ int closeit;
char npath[PATH_MAX];
char nhost[HOST_NAME_MAX];
char nport[PROTO_MAX];
- char prompt[64];
+ char prompt[64]; /* you wouldn't want it longer anyway */
++depth;
+ if (sock != -1) {
+ closeit = 0;
+ } else {
+ closeit = 1;
+ sock = connect_to(host, port);
+ if (sock == -1)
+ return -1;
+ }
+
+ snprintf(prompt, sizeof(prompt), "[%s] %s ", host, path);
+
child = -1;
done = 0;
- update_prompt(prompt, sizeof(prompt), host, path, sock != -1);
while (!done && (cmd = input(cbuf, sizeof(cbuf), prompt, stdin))) {
+ /* `strcpy(cmd, "p")` works I suppose, but I like
+ * goto and it's more efficient. */
if (*cmd == '\0')
- continue;
+ goto gawk_at;
switch (*cmd++) {
- case 'g':
+ case 'q': /* quit */
+ done = depth;
+ break;
+ case 'p': /* print */
+gawk_at:
+ gawkat(sock, path);
+ break;
+ case 'b': /* back */
+ if (*cmd == '\0')
+ done = 1;
+ else {
+ done = strtoui(cmd);
+ if (done < 0) {
+ warnx("invalid argument for 'b', '%s'", cmd);
+ done = 0;
+ }
+ }
+ break;
+ case 'g': /* goto or gawk */
if (*cmd == '\0') {
warnx("'g': No arguments.");
break;;
@@ -206,46 +290,18 @@ gawk(int sock, int depth, const char *host, const char *path, const char *port)
warn("unable to connect '%s' '%s'", nhost, nport);
break;
}
-
done = gawk(child, depth, nhost, npath, nport);
-
- if (close(child) == -1) {
+ if (close(child) == -1)
warn("unable to close '%s' '%s'", nhost, npath);
- return -1;
- }
- }
-
- break;
- case 'b':
- if (*cmd == '\0')
- done = 1;
- else {
- done = strtoui(cmd);
- if (done < 0) {
- warnx("invalid argument for 'b', '%s'", cmd);
- done = 0;
- }
- }
- break;
- case 'c':
- if (sock != -1) {
- warnx("already connected");
- break;
}
- sock = connect_to(host, port);
- update_prompt(prompt, sizeof(prompt), host, prompt, sock != -1);
- break;
- case 'q':
- if (*cmd != '\0')
- warnx("'q': Takes no arguments.");
- done = depth;
break;
default:
warnx("invalid command '%c'", *--cmd);
}
}
+
if (ferror(stdin)) {
- warn("an error ocoured on stdin");
+ warn("'stdin'");
return -1;
}
return done - 1;