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/piesctl.c | |
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/piesctl.c')
-rw-r--r-- | src/piesctl.c | 202 |
1 files changed, 106 insertions, 96 deletions
diff --git a/src/piesctl.c b/src/piesctl.c index 22a4e27..ad0981b 100644 --- a/src/piesctl.c +++ b/src/piesctl.c @@ -1236,6 +1236,7 @@ print_comp (FILE *fp, struct json_value *v, size_t n) struct cmdline_parser_state { + char const *command; int argc; char **argv; struct shttp_connection *conn; @@ -1329,7 +1330,8 @@ json_encode_op (char const *op, struct json_value *arg) { struct json_value *ret = json_new_object (); 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; } @@ -1338,42 +1340,38 @@ static void pcond_parse_or (struct cmdline_parser_state *, struct json_value **) static void 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); } static int @@ -1456,17 +1454,14 @@ 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) { struct json_value *val = NULL; - 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 print_json (stdout, val); exit (0); @@ -1476,22 +1471,24 @@ 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) { struct json_value *val; 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); json_value_free (val); return ret; } 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); shttp_io_init (&conn->req); shttp_process (conn, METH_GET, uri); @@ -1586,10 +1583,24 @@ 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); shttp_io_init (&conn->req); shttp_process (conn, METH_DELETE, uri); @@ -1598,9 +1609,10 @@ 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); shttp_io_init (&conn->req); shttp_process (conn, METH_PUT, uri); @@ -1609,10 +1621,12 @@ 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); shttp_process (conn, METH_POST, "/programs"); shttp_print_response_status (conn); @@ -1679,19 +1693,20 @@ 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; struct id_fmt *fmt; - 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) { printf ("%s: ", fmt->name); @@ -1706,14 +1721,14 @@ com_id (struct shttp_connection *conn, int argc, char **argv) size_t size = 0; size_t i; - 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); shttp_process (conn, METH_GET, buf); if (conn->resp.code == 200 && !dump) { - fmt = find_id_fmt (argv[i]); + fmt = find_id_fmt (state->argv[i]); if (fmt) { v = shttp_getval (conn, fmt->name, fmt->type); @@ -1724,9 +1739,9 @@ com_id (struct shttp_connection *conn, int argc, char **argv) putchar ('\n'); } } - 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); putchar ('\n'); } @@ -1736,17 +1751,19 @@ 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"); } 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"); } /* @@ -1755,7 +1772,7 @@ com_reboot (struct shttp_connection *conn, int argc, char **argv) */ struct telinit_parser { - struct cmdline_parser_state state; + struct cmdline_parser_state *state; int method; struct json_value *query; char *uri; @@ -1790,7 +1807,7 @@ telinit_format_runlevel (struct shttp_connection *conn) static void telinit_parse_runlevel (struct telinit_parser *p) { - char const *tok = next_token (&p->state); + char const *tok = next_token (p->state); if (!tok) { @@ -1807,26 +1824,23 @@ 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 parse_error (_("unrecognized subcommand: %s"), tok); } 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; parser.query = NULL; telinit_parse (&parser); @@ -2117,17 +2131,12 @@ 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 *); struct comtab { @@ -2156,7 +2165,7 @@ static struct comtab comtab[] = { <disjunction> ::= <conjunction> | <conjunction> \"or\" <disjunction>\n\ <conjunction> ::= <unary> | <unary> \"and\" <conjunction>\n\ <unary> ::= <term> | \"not\" <condition> | \"(\" <condition> \")\"\n\ - <term> ::= \"all\" | <keyword> <value>\n\ + <term> ::= \"all\" | \"active\" | <keyword> <value>\n\ <keyword> ::= \"type\" | \"mode\" | \"status\" | \"component\"\n\ <value> ::= <word> | <quoted-string>\n\ <word> ::= <printable> | <word> <printable>\n\ @@ -2276,8 +2285,8 @@ int main (int argc, char **argv) { int i; - struct shttp_connection *conn; struct comtab *cmd; + struct cmdline_parser_state state; set_program_name (argv[0]); #ifdef ENABLE_NLS @@ -2296,13 +2305,14 @@ main (int argc, char **argv) parse_config (); - 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; } |