aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrumeet <yuuta@yuuta.moe>2022-07-26 23:11:28 -0700
committerTrumeet <yuuta@yuuta.moe>2022-07-26 23:11:28 -0700
commit8037d8a6000423a3ae59657cded4465fdd6fc74a (patch)
tree5e56ce6cfe953a1143482b439e9ee552541685b1
parentc6948fd983fa1855b2dadba50aa50f576f54bdda (diff)
downloadacron-8037d8a6000423a3ae59657cded4465fdd6fc74a.tar
acron-8037d8a6000423a3ae59657cded4465fdd6fc74a.tar.gz
acron-8037d8a6000423a3ae59657cded4465fdd6fc74a.tar.bz2
acron-8037d8a6000423a3ae59657cded4465fdd6fc74a.zip
feat(acronc): prettify cli experience
1. Make SIGINT interrupt the current operation by forcing stdin to listen again (because the spec currently does not specify how to send the final response, so acronc will wait forever in case of invalid commands) 2. Prettify prompt and output. Signed-off-by: Trumeet <yuuta@yuuta.moe>
-rw-r--r--client/acronc/client.c9
-rw-r--r--client/acronc/handler.h3
-rw-r--r--client/acronc/handler_signal.c21
-rw-r--r--client/acronc/main.c37
4 files changed, 61 insertions, 9 deletions
diff --git a/client/acronc/client.c b/client/acronc/client.c
index 5553d4c..3e8ca76 100644
--- a/client/acronc/client.c
+++ b/client/acronc/client.c
@@ -71,8 +71,10 @@ static void handle_response(const ac_response_t *response) {
switch (response->type) {
case AC_RESPONSE_OK: {
ac_response_ok_t *o = (ac_response_ok_t *) response;
+#ifdef DEBUG
printf("Request %d OK.\n",
o->id);
+#endif
break;
}
case AC_RESPONSE_ERROR: {
@@ -85,18 +87,25 @@ static void handle_response(const ac_response_t *response) {
}
case AC_RESPONSE_CMD_OUT: {
ac_response_cmd_out_t *o = (ac_response_cmd_out_t *) response;
+#ifdef DEBUG
printf("Request %d output by %s: %s.\n",
o->id,
o->sender,
o->out);
+#else
+ printf("%s\n",
+ o->out);
+#endif
break;
}
case AC_RESPONSE_CMD_RESULT: {
ac_response_cmd_result_t *o = (ac_response_cmd_result_t *) response;
+#ifdef DEBUG
printf("Request %d is done: %s (%d).\n",
o->id,
o->success ? "Success" : "Failed",
o->result);
+#endif DEBUG
break;
}
default: {
diff --git a/client/acronc/handler.h b/client/acronc/handler.h
index 1beab1c..1036f6a 100644
--- a/client/acronc/handler.h
+++ b/client/acronc/handler.h
@@ -10,7 +10,8 @@
extern uv_loop_t *loop;
-int h_signal(void (*on_quit)(void));
+int h_signal(void (*on_int)(void),
+ void (*on_quit)(void));
int h_stdin(int (*on_input)(ac_request_t *req),
void (*on_close)(void));
diff --git a/client/acronc/handler_signal.c b/client/acronc/handler_signal.c
index d5df9d4..7dafe95 100644
--- a/client/acronc/handler_signal.c
+++ b/client/acronc/handler_signal.c
@@ -8,8 +8,16 @@
static uv_signal_t sigint;
static uv_signal_t sigterm;
-static void on_signal(uv_signal_t *handle, int signum) {
- LOGDV("on_signal(handle = %p): %d",
+static void on_sigint(uv_signal_t *handle, int signum) {
+ LOGDV("on_int(handle = %p): %d",
+ handle,
+ signum);
+ void (*on_int)(void) = handle->data;
+ on_int();
+}
+
+static void on_term(uv_signal_t *handle, int signum) {
+ LOGDV("on_term(handle = %p): %d",
handle,
signum);
void (*on_quit)(void) = handle->data;
@@ -18,14 +26,15 @@ static void on_signal(uv_signal_t *handle, int signum) {
on_quit();
}
-int h_signal(void (*on_quit)(void)) {
+int h_signal(void (*on_int)(void),
+ void (*on_quit)(void)) {
int r;
if ((r = uv_signal_init(loop, &sigint))) return r;
- sigint.data = on_quit;
- if ((r = uv_signal_start(&sigint, on_signal, SIGINT))) return r;
+ sigint.data = on_int;
+ if ((r = uv_signal_start(&sigint, on_sigint, SIGINT))) return r;
if ((r = uv_signal_init(loop, &sigterm))) return r;
sigterm.data = on_quit;
- if ((r = uv_signal_start(&sigterm, on_signal, SIGTERM))) return r;
+ if ((r = uv_signal_start(&sigterm, on_term, SIGTERM))) return r;
return 0;
}
diff --git a/client/acronc/main.c b/client/acronc/main.c
index d0e67ef..3f68553 100644
--- a/client/acronc/main.c
+++ b/client/acronc/main.c
@@ -14,10 +14,12 @@
#include <uv.h>
#include <err.h>
#include <string.h>
+#include <unistd.h>
static uv_loop_t lop;
uv_loop_t *loop = &lop;
static int current_req = -1;
+static bool tty = true;
static void on_close(uv_handle_t *handle);
@@ -47,7 +49,17 @@ static void on_sock_closed(void) {
uv_stop(loop);
}
+static void prompt(void) {
+ if (tty) {
+ fprintf(stderr, "> ");
+ }
+}
+
static int on_input(ac_request_t *req) {
+ if (req->type == AC_REQUEST_CMD && ((ac_request_cmd_t *) req)->cmd[0] == '\0') {
+ prompt();
+ return 0;
+ }
current_req = req->id;
stdin_stop();
LOGD("Stdin is paused.");
@@ -56,10 +68,12 @@ static int on_input(ac_request_t *req) {
}
static int on_sock_ready(void) {
+ prompt();
return h_stdin(on_input, on_stdin_closed);
}
static int on_recv(ac_obj_t *obj) {
+ bool p = false;
if (AC_IS_RESPONSE(obj->type)) {
ac_response_t *resp = (ac_response_t *) obj;
if (resp->id == current_req) {
@@ -70,11 +84,16 @@ static int on_recv(ac_obj_t *obj) {
LOGEV("Cannot resume stdin: %s", uv_strerror(r));
} else {
LOGD("Stdin is resumed.");
+ p = true;
}
}
}
}
- return handle_object(obj);
+ const int retval = handle_object(obj);
+ if (p) {
+ prompt();
+ }
+ return retval;
}
static void on_resolv(int status, const struct addrinfo *ai, void (*on_connected)(bool)) {
@@ -95,11 +114,25 @@ static void on_resolv(int status, const struct addrinfo *ai, void (*on_connected
}
}
+static void on_int(void) {
+ current_req = -1;
+ int r = stdin_start();
+ if (r && r != UV_EALREADY) {
+ LOGEV("Cannot resume stdin: %s", uv_strerror(r));
+ } else {
+ printf("Interrupt\n");
+ prompt();
+ }
+}
+
int main(int argc, const char **argv) {
int r;
if ((r = config_parse(argc, argv, &params))) return r;
atexit(cleanup);
+ if (!isatty(fileno(stdin))) {
+ tty = false;
+ }
libac_config_t config = {
#ifdef DEBUG
.out = NULL,
@@ -111,7 +144,7 @@ int main(int argc, const char **argv) {
if ((r = ac_init(&config))) errx(r, "Cannot initialize Acron library.");
if ((r = uv_loop_init(loop))) goto uviniterr;
- if ((r = h_signal(on_stdin_closed))) goto uviniterr;
+ if ((r = h_signal(on_int, on_stdin_closed))) goto uviniterr;
if ((r = a_dns(params.host, params.port, on_resolv))) goto uviniterr;
if ((r = uv_run(loop, UV_RUN_DEFAULT))) {