summaryrefslogtreecommitdiffabout
path: root/src
authorSergey Poznyakoff <gray@gnu.org.ua>2016-02-24 14:01:50 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2016-02-24 14:01:50 (GMT)
commit1ec50721c1aa5959009f0c74afc8b7796f4ffd20 (patch) (side-by-side diff)
tree0dda2c45c87ce03843e876b764d578713a200aa6 /src
parent9912557fa9b4c8596c6e9f69857e9a616b4f4f33 (diff)
downloadpies-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') (more/less context) (ignore whitespace changes)
-rw-r--r--src/ctl.c130
-rw-r--r--src/piesctl.c202
2 files changed, 184 insertions, 148 deletions
diff --git a/src/ctl.c b/src/ctl.c
index a7db410..61ed55e 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -1492,6 +1492,7 @@ enum pcond_type
pcond_component,
pcond_type,
pcond_mode,
+ pcond_active,
pcond_status,
pcond_not,
pcond_and,
@@ -1573,6 +1574,9 @@ pcond_eval (struct pcond_node *node, struct prog *p)
case pcond_mode:
return IS_COMPONENT (p) && p->v.p.comp->mode == node->v.mode;
+
+ case pcond_active:
+ return p->active;
case pcond_status:
return IS_COMPONENT (p) && p->v.p.status == node->v.status;
@@ -1709,11 +1713,10 @@ struct pcond_conv {
};
static struct pcond_conv pcond_conv[] = {
- [pcond_true] = { "true", NULL },
- [pcond_false] = { "false", NULL },
[pcond_component] = { "component", pcond_conv_component },
[pcond_type] = { "type", pcond_conv_type },
[pcond_mode] = { "mode", pcond_conv_mode },
+ [pcond_active] = { "active", NULL },
[pcond_status] = { "status", pcond_conv_status },
[pcond_not] = { "not", pcond_conv_not },
[pcond_and] = { "and", pcond_conv_binary },
@@ -1728,7 +1731,7 @@ pcond_conv_find (char const *name)
int i;
for (i = 0; i < max_type; i++)
{
- if (strcmp (pcond_conv[i].term, name) == 0)
+ if (pcond_conv[i].term && strcmp (pcond_conv[i].term, name) == 0)
return i;
}
return -1;
@@ -1747,12 +1750,7 @@ object_to_cond (struct ctlio *io, struct json_value *obj,
ctlio_reply (io, 400, "bad conditional: missing op");
return -1;
}
- if (json_object_get (obj, "arg", &arg))
- {
- ctlio_reply (io, 400, "bad conditional: missing arg");
- return -1;
- }
-
+
if (op->type != json_string)
{
ctlio_reply (io, 400, "bad conditional: bad op type");
@@ -1766,6 +1764,12 @@ object_to_cond (struct ctlio *io, struct json_value *obj,
return -1;
}
+ 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);
if (pcond_conv[type].handler && pcond_conv[type].handler (node, arg, io))
{
@@ -1910,22 +1914,15 @@ fun_list (struct json_value *result, struct prog *prog)
static int
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");
}
else
{
- //FIXME progman_stop_component (&prog);
+ prog->active = 0;
+ progman_stop_component (&prog);
json_object_set_string (result, "status", "OK");
}
return 0;
@@ -1938,49 +1935,78 @@ fun_start (struct json_value *result, struct prog *prog)
{
json_object_set_string (result, "status", "ER");
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;
}
static int
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
@@ -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;
}

Return to:

Send suggestions and report system problems to the System administrator.