diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-02-24 16:01:50 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2016-02-24 16:01:50 +0200 |
commit | 1ec50721c1aa5959009f0c74afc8b7796f4ffd20 (patch) | |
tree | 0dda2c45c87ce03843e876b764d578713a200aa6 /src | |
parent | 9912557fa9b4c8596c6e9f69857e9a616b4f4f33 (diff) | |
download | pies-1ec50721c1aa5959009f0c74afc8b7796f4ffd20.tar.gz pies-1ec50721c1aa5959009f0c74afc8b7796f4ffd20.tar.bz2 |
Improve parsing and handling of stop, start, and restart ctl commands.
* src/ctl.c (pcond_active): New type.
(pcond_eval): Handle pcond_active.
(pcond_conv): New op: active.
(pcond_conv_find): Skip array elements with NULL term value.
(object_to_cond): Permit empty argument if no
handler function is defined.
(fun_stop): Work on all prog types.
(fun_start): Work only on components.
(fun_restart): Work only on running components.
* src/piesctl.c (cmdline_parser_state): New member: command.
(pcond_parse_unary): Handle "active" keyword.
(parse_condition): Change signature.
(parse_condition_to_uri): Likewise.
(default_cond): New function,
(com_stop, com_start, com_restart): If no arguments supplied,
assume default condition "type component".
(ctlcom_t): Change signature. All uses changed.
(main): Pass a pointer to cmdline_parser_state to the
command handler.
Diffstat (limited to 'src')
-rw-r--r-- | src/ctl.c | 130 | ||||
-rw-r--r-- | src/piesctl.c | 202 |
2 files changed, 184 insertions, 148 deletions
@@ -1494,2 +1494,3 @@ enum pcond_type pcond_mode, + pcond_active, pcond_status, @@ -1575,2 +1576,5 @@ pcond_eval (struct pcond_node *node, struct prog *p) return IS_COMPONENT (p) && p->v.p.comp->mode == node->v.mode; + + case pcond_active: + return p->active; @@ -1711,4 +1715,2 @@ struct pcond_conv { static struct pcond_conv pcond_conv[] = { - [pcond_true] = { "true", NULL }, - [pcond_false] = { "false", NULL }, [pcond_component] = { "component", pcond_conv_component }, @@ -1716,2 +1718,3 @@ static struct pcond_conv pcond_conv[] = { [pcond_mode] = { "mode", pcond_conv_mode }, + [pcond_active] = { "active", NULL }, [pcond_status] = { "status", pcond_conv_status }, @@ -1730,3 +1733,3 @@ pcond_conv_find (char const *name) { - if (strcmp (pcond_conv[i].term, name) == 0) + if (pcond_conv[i].term && strcmp (pcond_conv[i].term, name) == 0) return i; @@ -1749,8 +1752,3 @@ object_to_cond (struct ctlio *io, struct json_value *obj, } - if (json_object_get (obj, "arg", &arg)) - { - ctlio_reply (io, 400, "bad conditional: missing arg"); - return -1; - } - + if (op->type != json_string) @@ -1768,2 +1766,8 @@ object_to_cond (struct ctlio *io, struct json_value *obj, + if (json_object_get (obj, "arg", &arg) && pcond_conv[type].handler) + { + ctlio_reply (io, 400, "bad conditional: missing arg"); + return -1; + } + node = pcond_node_alloc (type); @@ -1912,14 +1916,6 @@ fun_stop (struct json_value *result, struct prog *prog) { - if (IS_COMPONENT (prog)) - { - if (!prog->active) - { - json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "already stopped"); - return 1; - } - - prog->active = 0; - progman_stop_component (&prog); - json_object_set_string (result, "status", "OK"); + if (!prog->active) + { + json_object_set_string (result, "status", "ER"); + json_object_set_string (result, "error_message", "already stopped"); } @@ -1927,3 +1923,4 @@ fun_stop (struct json_value *result, struct prog *prog) { - //FIXME progman_stop_component (&prog); + prog->active = 0; + progman_stop_component (&prog); json_object_set_string (result, "status", "OK"); @@ -1940,37 +1937,39 @@ fun_start (struct json_value *result, struct prog *prog) json_object_set_string (result, "error_message", "not a component"); - return 1; } - switch (prog->v.p.status) + else { - case status_stopped: - prog->v.p.comp->flags &= ~CF_DISABLED; - json_object_set_string (result, "status", "OK"); - break; + switch (prog->v.p.status) + { + case status_stopped: + prog->v.p.comp->flags &= ~CF_DISABLED; + json_object_set_string (result, "status", "OK"); + break; - case status_sleeping: - case status_finished: - prog->v.p.status = status_stopped; - prog->v.p.failcount = 0; - prog->v.p.timestamp = 0; - json_object_set_string (result, "status", "OK"); - break; + case status_sleeping: + case status_finished: + prog->v.p.status = status_stopped; + prog->v.p.failcount = 0; + prog->v.p.timestamp = 0; + json_object_set_string (result, "status", "OK"); + break; - case status_listener: - if (prog_activate_listener (prog) == 0) - json_object_set_string (result, "status", "OK"); - else - { + case status_listener: + if (prog_activate_listener (prog) == 0) + json_object_set_string (result, "status", "OK"); + else + { + json_object_set_string (result, "status", "ER"); + /* FIXME: error message */ + json_object_set_string (result, "error_message", + "can't open socket"); + } + break; + + default: json_object_set_string (result, "status", "ER"); - /* FIXME: error message */ - json_object_set_string (result, "error_message", - "can't open socket"); + json_object_set_string (result, "error_message", "already running"); + return 0; } - break; - - default: - json_object_set_string (result, "status", "ER"); - json_object_set_string (result, "error_message", "already running"); - return 1; + prog->active = 1; } - prog->active = 1; return 0; @@ -1981,4 +1980,31 @@ fun_restart (struct json_value *result, struct prog *prog) { - progman_stop_component (&prog); - json_object_set_string (result, "status", "OK"); + if (!IS_COMPONENT (prog)) + { + json_object_set_string (result, "status", "ER"); + json_object_set_string (result, "error_message", "not a component"); + } + else if (!prog->active) + { + json_object_set_string (result, "status", "ER"); + json_object_set_string (result, "error_message", "not active"); + } + else + { + switch (prog->v.p.status) + { + case status_running: + progman_stop_component (&prog); + json_object_set_string (result, "status", "OK"); + break; + + case status_listener: + json_object_set_string (result, "status", "ER"); + json_object_set_string (result, "error_message", "not applicable"); + break; + + default: + json_object_set_string (result, "status", "ER"); + json_object_set_string (result, "error_message", "not running"); + } + } return 0; diff --git a/src/piesctl.c b/src/piesctl.c index 22a4e27..ad0981b 100644 --- a/src/piesctl.c +++ b/src/piesctl.c @@ -1238,2 +1238,3 @@ struct cmdline_parser_state { + char const *command; int argc; @@ -1331,3 +1332,4 @@ json_encode_op (char const *op, struct json_value *arg) json_object_set (ret, "op", json_new_string (op)); - json_object_set (ret, "arg", arg); + if (arg) + json_object_set (ret, "arg", arg); return ret; @@ -1340,38 +1342,34 @@ pcond_parse_unary (struct cmdline_parser_state *state, struct json_value **ret) { - char const *term = next_token (state); + static char *arg_kw[] = { + "type", "mode", "status", "component", NULL + }; + char const *term = require_token (state); - if (!term) + if (strcasecmp (term, "all") == 0) *ret = json_new_bool (1); - else + else if (strcasecmp (term, "active") == 0) + *ret = json_encode_op (term, NULL); + else if (is_array_member (arg_kw, term)) { - static char *arg_terms[] = { - "type", "mode", "status", "component", NULL - }; - - if (strcasecmp (term, "all") == 0) - *ret = json_new_bool (1); - else if (is_array_member (arg_terms, term)) - { - if (!peek_token (state)) - parse_error (_("%s requires argument"), term); - *ret = json_encode_op (term, json_new_string (next_token (state))); - } - else if (strcasecmp (term, "not") == 0) - { - struct json_value *val; - if (!peek_token (state)) - parse_error (_("%s requires argument"), term); - pcond_parse_unary (state, &val); - *ret = json_encode_op (term, val); - } - else if (term[0] == '(') - { - pcond_parse_or (state, ret); - term = next_token (state); - if (!term || term[0] != ')') - parse_error ("%s", _("unbalanced parentesis")); - } - else - parse_error (_("parse error at %s"), term); + if (!peek_token (state)) + parse_error (_("%s requires argument"), term); + *ret = json_encode_op (term, json_new_string (next_token (state))); } + else if (strcasecmp (term, "not") == 0) + { + struct json_value *val; + if (!peek_token (state)) + parse_error (_("%s requires argument"), term); + pcond_parse_unary (state, &val); + *ret = json_encode_op (term, val); + } + else if (term[0] == '(') + { + pcond_parse_or (state, ret); + term = next_token (state); + if (!term || term[0] != ')') + parse_error ("%s", _("unbalanced parentesis")); + } + else + parse_error (_("parse error at %s"), term); } @@ -1458,3 +1456,3 @@ pcond_parse_or (struct cmdline_parser_state *state, struct json_value **ret) static struct json_value * -parse_condition (int argc, char **argv) +parse_condition (struct cmdline_parser_state *state) { @@ -1462,9 +1460,6 @@ parse_condition (int argc, char **argv) - if (argc > 1) + if (state->argc > 0) { - struct cmdline_parser_state state; - state.argc = argc - 1; - state.argv = argv + 1; - pcond_parse_or (&state, &val); - assert_eol (&state); + pcond_parse_or (state, &val); + assert_eol (state); #if 0 @@ -1478,3 +1473,4 @@ parse_condition (int argc, char **argv) static char * -parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory) +parse_condition_to_uri (char const *base, struct cmdline_parser_state *state, + int mandatory) { @@ -1482,5 +1478,5 @@ parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory) char *ret; - if (mandatory && argc == 1) + if (mandatory && state->argc == 1) parse_error ("%s", _("condition must be specified")); - val = parse_condition (argc, argv); + val = parse_condition (state); ret = piesctl_format (val, base); @@ -1491,5 +1487,6 @@ parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory) static void -com_list (struct shttp_connection *conn, int argc, char **argv) +com_list (struct cmdline_parser_state *state) { - char *uri = parse_condition_to_uri ("/programs", argc, argv, 0); + struct shttp_connection *conn = state->conn; + char *uri = parse_condition_to_uri ("/programs", state, 0); @@ -1588,6 +1585,20 @@ shttp_print_response_status (struct shttp_connection *conn) +/* Provide default condition if there are no more arguments */ +static struct cmdline_parser_state * +default_cond (struct cmdline_parser_state *state) +{ + if (!peek_token (state)) + { + static char *dfl[] = { "type", "component", NULL }; + state->argc = sizeof (dfl) / sizeof (dfl[0]); + state->argv = dfl; + } + return state; +} + static void -com_stop (struct shttp_connection *conn, int argc, char **argv) +com_stop (struct cmdline_parser_state *state) { - char *uri = parse_condition_to_uri ("/programs", argc, argv, 1); + struct shttp_connection *conn = state->conn; + char *uri = parse_condition_to_uri ("/programs", default_cond (state), 1); @@ -1600,5 +1611,6 @@ com_stop (struct shttp_connection *conn, int argc, char **argv) static void -com_start (struct shttp_connection *conn, int argc, char **argv) +com_start (struct cmdline_parser_state *state) { - char *uri = parse_condition_to_uri ("/programs", argc, argv, 1); + struct shttp_connection *conn = state->conn; + char *uri = parse_condition_to_uri ("/programs", default_cond (state), 1); @@ -1611,6 +1623,8 @@ com_start (struct shttp_connection *conn, int argc, char **argv) static void -com_restart (struct shttp_connection *conn, int argc, char **argv) +com_restart (struct cmdline_parser_state *state) { + struct shttp_connection *conn = state->conn; + assert_eol (state); shttp_io_init (&conn->req); - conn->req.content = parse_condition_to_uri (NULL, argc, argv, 1); + conn->req.content = parse_condition_to_uri (NULL, default_cond (state), 1); conn->req.content_length = strlen (conn->req.content); @@ -1681,4 +1695,5 @@ find_id_fmt (char const *name) static void -com_id (struct shttp_connection *conn, int argc, char **argv) +com_id (struct cmdline_parser_state *state) { + struct shttp_connection *conn = state->conn; struct json_value *v; @@ -1686,10 +1701,10 @@ com_id (struct shttp_connection *conn, int argc, char **argv) - if (argc == 1) + if (state->argc == 0) { - shttp_io_init (&conn->req); - shttp_process (conn, METH_GET, "/instance"); - if (conn->resp.code == 200 && !dump) + shttp_io_init (&state->conn->req); + shttp_process (state->conn, METH_GET, "/instance"); + if (state->conn->resp.code == 200 && !dump) for (fmt = id_fmt; fmt->name; fmt++) { - v = shttp_getval (conn, fmt->name, fmt->type); + v = shttp_getval (state->conn, fmt->name, fmt->type); if (v) @@ -1708,5 +1723,5 @@ com_id (struct shttp_connection *conn, int argc, char **argv) - for (i = 1; i < argc; i++) + for (i = 1; i < state->argc; i++) { - grecs_asprintf (&buf, &size, "/instance/%s", argv[i]); + grecs_asprintf (&buf, &size, "/instance/%s", state->argv[i]); shttp_io_init (&conn->req); @@ -1715,3 +1730,3 @@ com_id (struct shttp_connection *conn, int argc, char **argv) { - fmt = find_id_fmt (argv[i]); + fmt = find_id_fmt (state->argv[i]); if (fmt) @@ -1726,5 +1741,5 @@ com_id (struct shttp_connection *conn, int argc, char **argv) } - else if (json_object_get (conn->result, argv[i], &v) == 0) + else if (json_object_get (conn->result, state->argv[i], &v) == 0) { - printf ("%s: ", argv[i]); + printf ("%s: ", state->argv[i]); print_json (stdout, v); @@ -1738,6 +1753,7 @@ com_id (struct shttp_connection *conn, int argc, char **argv) static void -com_shutdown (struct shttp_connection *conn, int argc, char **argv) +com_shutdown (struct cmdline_parser_state *state) { - shttp_io_init (&conn->req); - shttp_process (conn, METH_DELETE, "/instance/PID"); + assert_eol (state); + shttp_io_init (&state->conn->req); + shttp_process (state->conn, METH_DELETE, "/instance/PID"); } @@ -1745,6 +1761,7 @@ com_shutdown (struct shttp_connection *conn, int argc, char **argv) static void -com_reboot (struct shttp_connection *conn, int argc, char **argv) +com_reboot (struct cmdline_parser_state *state) { - shttp_io_init (&conn->req); - shttp_process (conn, METH_PUT, "/instance/PID"); + assert_eol (state); + shttp_io_init (&state->conn->req); + shttp_process (state->conn, METH_PUT, "/instance/PID"); } @@ -1757,3 +1774,3 @@ struct telinit_parser { - struct cmdline_parser_state state; + struct cmdline_parser_state *state; int method; @@ -1792,3 +1809,3 @@ telinit_parse_runlevel (struct telinit_parser *p) { - char const *tok = next_token (&p->state); + char const *tok = next_token (p->state); @@ -1809,8 +1826,8 @@ telinit_parse_runlevel (struct telinit_parser *p) static void -telinit_parse (struct telinit_parser *p) +telinit_parse (struct telinit_parser *parser) { - char const *tok = next_token (&p->state); + char const *tok = require_token (parser->state); if (strcmp (tok, "runlevel") == 0) - telinit_parse_runlevel (p); + telinit_parse_runlevel (parser); else @@ -1820,11 +1837,8 @@ telinit_parse (struct telinit_parser *p) static void -com_telinit (struct shttp_connection *conn, int argc, char **argv) +com_telinit (struct cmdline_parser_state *state) { + struct shttp_connection *conn = state->conn; struct telinit_parser parser; - if (argc == 1) - parse_error ("%s", _("not enough arguments to telinit")); - - parser.state.argc = argc-1; - parser.state.argv = argv+1; + parser.state = state; parser.method = METH_INVALID; @@ -2119,13 +2133,8 @@ conf_parse (struct cmdline_parser_state *state) static void -com_config (struct shttp_connection *conn, int argc, char **argv) +com_config (struct cmdline_parser_state *state) { - struct cmdline_parser_state state; - - state.argc = argc - 1; - state.argv = argv + 1; - state.conn = conn; - conf_parse (&state); + conf_parse (state); } -typedef void (*ctlcom_t) (struct shttp_connection *, int, char **); +typedef void (*ctlcom_t) (struct cmdline_parser_state *); @@ -2158,3 +2167,3 @@ static struct comtab comtab[] = { <unary> ::= <term> | \"not\" <condition> | \"(\" <condition> \")\"\n\ - <term> ::= \"all\" | <keyword> <value>\n\ + <term> ::= \"all\" | \"active\" | <keyword> <value>\n\ <keyword> ::= \"type\" | \"mode\" | \"status\" | \"component\"\n\ @@ -2278,4 +2287,4 @@ main (int argc, char **argv) int i; - struct shttp_connection *conn; struct comtab *cmd; + struct cmdline_parser_state state; @@ -2298,10 +2307,11 @@ main (int argc, char **argv) - conn = shttp_connect (client.url, client.source_addr); - if (!conn) - return EX_UNAVAILABLE; - cmd = find_command (argv[0]); - argv[0] = (char*) cmd->name; - cmd->command (conn, argc, argv); - shttp_close (conn); + state.command = cmd->name; + state.argc = argc - 1; + state.argv = argv + 1; + state.conn = shttp_connect (client.url, client.source_addr); + if (!state.conn) + return EX_UNAVAILABLE; + cmd->command (&state); + shttp_close (state.conn); return exit_status; |