commit 6529bce0803f9c5b68169f5302b5df80376a8230
parent 56e5b8cfe832e5bc92c3322f3553779a29ecba16
Author: Jacob R. Edwards <n/a>
Date: Fri, 20 May 2022 13:28:37 -0500
Rework client library and client
The only major change on the surface of the client is that now,
when not given any arguments, it reads commands from the stdin and
prints responses to stdout. The client library was reworked to
better accommodate function by adding a raw writing function.
In addition to a raw writing function, the client library no longer
buffers arguments in a list.
Diffstat:
M | apc/apc.c | | | 136 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
M | lib/ap/client.c | | | 78 | ++++++++++++------------------------------------------------------------------ |
M | lib/ap/client.h | | | 8 | +++----- |
3 files changed, 105 insertions(+), 117 deletions(-)
diff --git a/apc/apc.c b/apc/apc.c
@@ -41,18 +41,78 @@ die(char *s)
}
int
-main(int argc, char *argv[])
+printresponse(struct apc *apc)
+{
+ char *buf;
+
+ while ((buf = apc_read(apc))) {
+ puts(buf);
+ free(buf);
+ }
+ if (apc->status == NULL)
+ return 1;
+ if (strcmp(apc->status, "ok") != 0)
+ return fprintf(stderr, "error: %s\n", apc->status) < 0;
+ return 0;
+
+}
+
+char *
+apc_stream(struct apc *apc, FILE *fp)
{
- struct apc *apc;
- int insert;
- int i;
char *buf;
+ size_t size;
ssize_t len;
+ char *err;
+
+ buf = NULL;
+ size = 0;
+ err = NULL;
+ while (!err && (len = getline(&buf, &size, fp)) >= 0) {
+ if (write(apc->con->sock, buf, len) != len)
+ err = "unable to write to server";
+ else if (printresponse(apc))
+ err = "unable to handle response";
+ }
+ free(buf);
+ if (ferror(stdin))
+ err = "unable to read from standard input";
+ return err;
+}
+
+char *
+xargs(struct apc *apc, FILE *fp)
+{
+ char *buf;
size_t size;
+ ssize_t len;
+
+ buf = NULL;
+ size = 0;
+ while ((len = getline(&buf, &size, stdin)) >= 0) {
+ if (len && buf[len - 1] == '\n')
+ buf[--len] = 0;
+ if (apc_writeword(apc, buf))
+ return "unable to write to server";
+ }
+ free(buf);
+ if (ferror(stdin))
+ return "unable to read line";
+ return NULL;
+}
+
+int
+main(int argc, char *argv[])
+{
+ char *err;
+ int i;
+ int insert;
+ int status;
+ struct apc *apc;
apc = apc_new(NULL);
if (apc == NULL)
- die("create client");
+ die("unable to create client");
if (pledge("stdio", NULL))
die("pledge");
@@ -60,51 +120,35 @@ main(int argc, char *argv[])
--argc;
++argv;
- insert = 0;
- if (argc && argv[argc - 1][0] == subchr) {
- if (argv[argc - 1][1] == subchr) {
- ++argv[argc - 1];
- } else if (argv[argc - 1][1] == '\0') {
- insert = 1;
- --argc;
+ if (!argc){
+ err = apc_stream(apc, stdin);
+ }else {
+ insert = 0;
+ if (argv[argc - 1][0] == subchr) {
+ if (argv[argc - 1][1] == subchr) {
+ ++argv[argc - 1];
+ } else if (argv[argc - 1][1] == '\0') {
+ insert = 1;
+ --argc;
+ }
}
- }
-
- for (i = 0; i < argc; ++i) {
- if (apc_add(apc, argv[i]))
- die("add argument");
- }
- if (insert) {
- buf = NULL;
- size = 0;
- while ((len = getline(&buf, &size, stdin)) >= 0) {
- if (len && buf[len - 1] == '\n')
- buf[--len] = 0;
- if (apc_add(apc, buf))
- die("add argument");
+ err = NULL;
+ for (i = 0; !err && i < argc; ++i)
+ if (apc_writeword(apc, argv[i]))
+ err = "unable to write argument";
+ if (!err && (!insert || !(err = xargs(apc, stdin)))) {
+ if (apc_write(apc, "\n", 1))
+ err = "unable to terminate command";
+ else if (printresponse(apc))
+ err = "unable print response";
}
- free(buf);
- if (ferror(stdin))
- die("stdin");
- }
-
- if (apc_write(apc))
- die("write");
-
- while ((buf = apc_read(apc))) {
- puts(buf);
- free(buf);
- }
- if (apc->status == NULL)
- die("read");
-
- if (strcmp(apc->status, "ok") != 0) {
- fprintf(stderr, "aps: %s\n", apc->status);
- exit(1);
}
+exit:
+ status = (apc->status && strcmp(apc->status, "ok") != 0);
apc_free(apc);
-
- return 0;
+ if (err)
+ die(err);
+ return status;
}
diff --git a/lib/ap/client.c b/lib/ap/client.c
@@ -19,6 +19,7 @@
#include <sys/socket.h>
+#include <ctype.h>
#include <stdlib.h>
#include <string.h>
@@ -30,7 +31,6 @@ apc_free(struct apc *apc)
if (apc == NULL)
return;
- apc_clear(apc);
free(apc->status);
apclose(apc->con);
buffree(apc->buf);
@@ -51,82 +51,28 @@ apc_new(char *path)
}
int
-apc_add(struct apc *apc, char *arg)
+apc_write(struct apc *apc, char *buf, size_t len)
{
- if (apc->args == NULL) {
- apc->args = item_new(arg);
- return apc->args == NULL;
- }
- return item_insert_string(apc->args, arg);
-}
-
-char *
-apc_msg(struct apc *apc)
-{
- char *msg;
- char *arg;
- struct buf *buf;
- struct item *itm;
-
- if (apc->args == NULL)
- return NULL;
-
- buf = bufnew();
- if (buf == NULL)
- return NULL;
-
- itm = apc->args;
- do {
- arg = apquote(itm->path, NULL);
- if (arg == NULL || bufappend(buf, arg, strlen(arg)) ||
- bufappend(buf, " ", 1)) {
- free(arg);
- buffree(buf);
- return NULL;
- }
- free(arg);
- } while ((itm = itm->next) != apc->args && itm);
-
- if (buf->len)
- buf->data[buf->len - 1] = '\n';
- buf->data[buf->len] = '\0';
-
- msg = buf->data;
- buf->data = NULL;
- buffree(buf);
- return msg;
+ if (send(apc->con->sock, buf, len, 0) != len)
+ return 1;
+ apc->lastbyte = buf[len - 1];
+ return 0;
}
int
-apc_write(struct apc *apc)
+apc_writeword(struct apc *apc, char *word)
{
- char *buf;
int status;
- ssize_t len;
- buf = apc_msg(apc);
- if (buf == NULL)
+ if (!isspace(apc->lastbyte) && apc_write(apc, " ", 1))
return 1;
-
- len = strlen(buf);
- status = send(apc->con->sock, buf, len, 0) != len;
- free(buf);
+ if (!(word = apquote(word, NULL)))
+ return 1;
+ status = apc_write(apc, word, strlen(word));
+ free(word);
return status;
}
-void
-apc_clear(struct apc *apc)
-{
- struct item *next;
-
- while (apc->args) {
- next = ((apc->args == apc->args->next) ? NULL : apc->args->next);
- item_unlink(apc->args);
- item_free(apc->args);
- apc->args = next;
- }
-}
-
int
apc_recv(struct apc *apc)
{
diff --git a/lib/ap/client.h b/lib/ap/client.h
@@ -2,14 +2,12 @@ struct apc {
char *status;
struct apcon *con;
struct buf *buf;
- struct item *args;
+ char lastbyte;
};
void apc_free(struct apc *);
struct apc *apc_new(char *);
-int apc_add(struct apc *, char *);
-char *apc_msg(struct apc *);
-int apc_write(struct apc *);
-void apc_clear(struct apc *);
+int apc_write(struct apc *, char *, size_t);
+int apc_writeword(struct apc *, char *);
int apc_recv(struct apc *);
char *apc_read(struct apc *);