aboutsummaryrefslogtreecommitdiff
path: root/client/libacron/apps/acronc/handler_stdin.c
diff options
context:
space:
mode:
Diffstat (limited to 'client/libacron/apps/acronc/handler_stdin.c')
-rw-r--r--client/libacron/apps/acronc/handler_stdin.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/client/libacron/apps/acronc/handler_stdin.c b/client/libacron/apps/acronc/handler_stdin.c
new file mode 100644
index 0000000..3ac307d
--- /dev/null
+++ b/client/libacron/apps/acronc/handler_stdin.c
@@ -0,0 +1,85 @@
+/*
+ * Created by yuuta on 7/24/22.
+ */
+
+#include "handler.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+static unsigned int id = 0;
+
+static uv_tty_t tty;
+
+static int (*cb_recv)(ac_request_t *req);
+
+static void (*cb_close)(void);
+
+static void on_close(uv_handle_t *handle) {
+ cb_close();
+}
+
+static void on_alloc(uv_handle_t *handle, size_t size, uv_buf_t *buf) {
+ LOGDV("on_alloc(handle = %p): size = %lu",
+ handle,
+ size);
+ void *b = malloc(size);
+ if (!b) {
+ LOGEV("Cannot allocate memory of %u bytes: %s.",
+ size,
+ strerror(errno));
+ /* Stream is still working now. */
+ uv_close(handle, on_close);
+ *buf = uv_buf_init(NULL, 0); /* Just in case? */
+ return;
+ }
+ *buf = uv_buf_init(b, size);
+}
+
+static void on_stdin(uv_stream_t *t, ssize_t nread, const uv_buf_t *buf) {
+ LOGDV("on_stdin(stream = %p): nread = %ld, buf = %p, buf->base = %p, buf->len = %lu",
+ t,
+ nread,
+ buf, buf->base, buf->len);
+ if (!nread) {
+ if (buf->base) free(buf->base);
+ return;
+ }
+ if (nread == UV_EOF) {
+ LOGI("Exit.");
+ free(buf->base);
+
+ cb_close();
+ return;
+ }
+ if (nread < 0) {
+ LOGEV("Encountered a failure while reading stdin: ", uv_strerror(nread));
+ if (buf->base) free(buf->base);
+ uv_close((uv_handle_t *) t, on_close);
+ return;
+ }
+ buf->base[nread - 1] = '\0'; /* Remove junk and tailing \n */
+ if ((++ id) > INT_MAX) {
+ id = 0;
+ }
+ ac_request_cmd_t req = {
+ .type = AC_REQUEST_CMD,
+ .id = (int) id,
+ .cmd = buf->base
+ };
+ if (cb_recv((ac_request_t *) &req)) {
+ uv_close((uv_handle_t *) t, on_close);
+ }
+ free(buf->base);
+}
+
+int h_stdin(int (*on_input)(ac_request_t *req),
+ void (*on_close)(void)) {
+ cb_recv = on_input;
+ cb_close = on_close;
+ int r;
+ if ((r = uv_tty_init(loop, &tty, 0, 0))) return r;
+ if ((r = uv_read_start((uv_stream_t *) &tty, on_alloc, on_stdin))) return r;
+ return 0;
+} \ No newline at end of file