diff options
Diffstat (limited to 'src/piesctl.c')
-rw-r--r-- | src/piesctl.c | 244 |
1 files changed, 156 insertions, 88 deletions
diff --git a/src/piesctl.c b/src/piesctl.c index 8c4e2e1..4b448ad 100644 --- a/src/piesctl.c +++ b/src/piesctl.c @@ -1230,11 +1230,2 @@ peek_token (struct pcond_parser_state *state) static struct json_value * -json_new_array2 (struct json_value *a, struct json_value *b) -{ - struct json_value *ret = json_new_array (); - json_array_append (ret, a); - json_array_append (ret, b); - return ret; -} - -static struct json_value * json_encode_op (char const *op, struct json_value *arg) @@ -1302,2 +1293,39 @@ pcond_parse_unary (struct pcond_parser_state *state, struct json_value **ret) +static int +is_op (struct json_value *val, char const *opcode) +{ + struct json_value *op; + + if (json_object_get (val, "op", &op) == 0) + { + if (op->type == json_string && strcmp (op->v.s, opcode) == 0) + return 1; + } + return 0; +} + +static void +binop_append_optimized (struct json_value *ar, struct json_value *val, + char const *opcode) +{ + if (is_op (val, opcode)) + { + size_t i, n; + struct json_value *arg; + + json_object_get (val, "arg", &arg); + n = json_array_size (arg); + for (i = 0; i < n; i++) + { + struct json_value *elt; + json_array_get (arg, i, &elt); + json_array_set (arg, i, NULL); + json_array_append (ar, elt); + } + json_value_free (val); + } + else + json_array_append (ar, val); +} + static void @@ -1306,3 +1334,3 @@ pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret) char const *token; - struct json_value *left, *right; + struct json_value *left, *right, *ar; @@ -1317,3 +1345,6 @@ pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret) pcond_parse_and (state, &right); - *ret = json_encode_op (token, json_new_array2 (left, right)); + ar = json_new_array (); + json_array_append (ar, left); + binop_append_optimized (ar, right, token); + *ret = json_encode_op (token, ar); } @@ -1324,3 +1355,3 @@ pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret) char const *token; - struct json_value *left, *right; + struct json_value *left, *right, *ar; @@ -1335,3 +1366,6 @@ pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret) pcond_parse_or (state, &right); - *ret = json_encode_op (token, json_new_array2 (left, right)); + ar = json_new_array (); + json_array_append (ar, left); + binop_append_optimized (ar, right, token); + *ret = json_encode_op (token, ar); } @@ -1371,23 +1405,3 @@ acc_writer (void *closure, char const *text, size_t len) static char * -json_to_string (struct json_value *val) -{ - struct grecs_txtacc *acc = grecs_txtacc_create (); - struct json_format fmt = { - .indent = 0, - .precision = 0, - .write = acc_writer, - .data = acc - }; - char *ret; - - json_format_value (val, &fmt); - grecs_txtacc_grow_char (acc, 0); - ret = grecs_txtacc_finish (acc, 1); - grecs_txtacc_free (acc); - - return ret; -} - -static char * -parse_condition_to_uri (char const *base, int argc, char **argv) +parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory) { @@ -1397,4 +1411,11 @@ parse_condition_to_uri (char const *base, int argc, char **argv) + if (mandatory && argc == 1) + { + grecs_error (NULL, 0, _("condition must be specified")); + exit (EX_USAGE); + } + acc = grecs_txtacc_create (); - grecs_txtacc_grow_string (acc, base); + if (base) + grecs_txtacc_grow_string (acc, base); @@ -1409,3 +1430,4 @@ parse_condition_to_uri (char const *base, int argc, char **argv) }; - grecs_txtacc_grow_char (acc, '/'); + if (base) + grecs_txtacc_grow_char (acc, '/'); json_format_value (val, &fmt); @@ -1417,3 +1439,2 @@ parse_condition_to_uri (char const *base, int argc, char **argv) grecs_txtacc_free (acc); - return ret; @@ -1424,3 +1445,3 @@ com_list (struct shttp_connection *conn, int argc, char **argv) { - char *uri = parse_condition_to_uri ("/programs", argc, argv); + char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 0); @@ -1445,19 +1466,70 @@ com_list (struct shttp_connection *conn, int argc, char **argv) static int -com_stop (struct shttp_connection *conn, int argc, char **argv) +json_object_get_type (struct json_value *obj, char const *name, + enum json_value_type type, struct json_value **ret) { - char *buf = NULL; - size_t len = 0; - size_t i; - - for (i = 1; i < argc; i++) + struct json_value *v; + int rc = json_object_get (obj, name, &v); + if (rc) + return rc; + if (v->type != type) { - struct json_value *v; - grecs_asprintf (&buf, &len, "/programs/%s", argv[i]); - shttp_io_init (&conn->req); - shttp_process (conn, METH_DELETE, buf); - v = shttp_getval (conn, "error_message", json_string); - if (v) - printf ("%s: %s\n", argv[i], v->v.s); + errno = EACCES; + return -1; } - free (buf); + *ret = v; + return 0; +} + +static void +shttp_print_response_status (struct shttp_connection *conn) +{ + if (!dump && conn->result && conn->result->type == json_arr) + { + size_t i, n = json_array_size (conn->result); + + for (i = 0; i < n; i++) + { + struct json_value *elt, *v; + + if (json_array_get (conn->result, i, &elt) == 0) + { + if (elt->type != json_object) + { + grecs_error (NULL, 0, _("%lu: unexpected value type"), + (unsigned long) i); + print_json (stderr, v); + continue; + } + if (json_object_get_type (elt, "tag", json_string, &v) == 0) + { + printf ("%s: ", v->v.s); + if (json_object_get_type (elt, "status", json_string, &v) + == 0) + { + if (strcmp (v->v.s, "OK") == 0) + fputs (v->v.s, stdout); + else if (json_object_get_type (elt, "error_message", + json_string, &v) == 0) + fputs (v->v.s, stdout); + else + printf ("unknown error"); + } + else + printf ("unknown status"); + fputc ('\n', stdout); + } + } + } + } +} + +static int +com_stop (struct shttp_connection *conn, int argc, char **argv) +{ + char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1); + + shttp_io_init (&conn->req); + shttp_process (conn, METH_DELETE, uri); + grecs_free (uri); + shttp_print_response_status (conn); return 0; @@ -1468,17 +1540,8 @@ com_start (struct shttp_connection *conn, int argc, char **argv) { - char *buf = NULL; - size_t len = 0; - size_t i; - - for (i = 1; i < argc; i++) - { - struct json_value *v; - grecs_asprintf (&buf, &len, "/programs/%s", argv[i]); - shttp_io_init (&conn->req); - shttp_process (conn, METH_PUT, buf); - v = shttp_getval (conn, "error_message", json_string); - if (v) - printf ("%s: %s\n", argv[i], v->v.s); - } - free (buf); + char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1); + + shttp_io_init (&conn->req); + shttp_process (conn, METH_PUT, uri); + grecs_free (uri); + shttp_print_response_status (conn); return 0; @@ -1489,20 +1552,7 @@ com_restart (struct shttp_connection *conn, int argc, char **argv) { - struct json_value *val = json_new_array (); - size_t i; - - if (argc == 1) - { - grecs_error (NULL, 0, _("missing component names")); - exit (EX_USAGE); - } - for (i = 1; i < argc; i++) - json_array_append (val, json_new_string (argv[i])); - shttp_io_init (&conn->req); - conn->req.content = json_to_string (val); + conn->req.content = parse_condition_to_uri (NULL, argc, argv, 1); conn->req.content_length = strlen (conn->req.content); - json_value_free (val); - - shttp_process (conn, METH_POST, "/programs"); - + shttp_process (conn, METH_POST, "/programs/select"); + shttp_print_response_status (conn); return 0; @@ -1587,6 +1637,6 @@ struct comtab static struct comtab comtab[] = { - { "list", N_("[EXPR]"), N_("list configured components"), com_list }, - { "stop", N_("TAG [TAG...]"), N_("stop components"), com_stop }, - { "start", N_("TAG [TAG...]"), N_("start components"), com_start }, - { "restart", N_("TAG [TAG...]"), N_("restart components"), com_restart }, + { "list", N_("[CONDITION]"), N_("list configured components"), com_list }, + { "stop", N_("CONDITION"), N_("stop components"), com_stop }, + { "start", N_("CONDITION"), N_("start components"), com_start }, + { "restart", N_("CONDITION"), N_("restart components"), com_restart }, { "id", N_("[KEYWORDS...]"), @@ -1641,3 +1691,3 @@ command_help (FILE *fp) - fputs (_("Available commands are:"), fp); + fputs (_("Available commands with their arguments are:"), fp); fputc ('\n', fp); @@ -1657,2 +1707,20 @@ command_help (FILE *fp) fputc ('\n', fp); + fputs (_("Condition is defined as:"), fp); + fputc ('\n', fp); + fputc ('\n', fp); + fputs ("\ + <condition> ::= <disjunction>\n\ + <disjunction> ::= <conjunction> | <conjunction> \"or\" <disjunction>\n\ + <conjunction> ::= <unary> | <unary> \"and\" <conjunction>\n\ + <unary> ::= <term> | \"not\" <condition> | \"(\" <condition> \")\"\n\ + <term> ::= \"all\" | <keyword> <value>\n\ + <keyword> ::= \"type\" | \"mode\" | \"status\" | \"component\"\n\ + <value> ::= <word> | <quoted-string>\n\ + <word> ::= <printable> | <word> <printable>\n\ + <printable> ::= \"A\" - \"Z\" | \"a\" - \"z\" | \"0\" - \"9\" |\n\ + \"_\" | \".\" | \"*\" | \":\" | \"@\" | \"[\" | \"]\" | \"-\" | \"/\"\n\ + <quoted-string> ::= \"\"\" <string> \"\"\"\n\ + <string> ::= <char> | <string> <char>\n\ + <char> ::= <any character except \"\\\" and \"\"\"> | \"\\\\\" | \"\\\"\"\n\n", fp); + } |