aboutsummaryrefslogtreecommitdiff
path: root/src/ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctl.c')
-rw-r--r--src/ctl.c318
1 files changed, 229 insertions, 89 deletions
diff --git a/src/ctl.c b/src/ctl.c
index d26bf45..e1c5530 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -890,4 +890,6 @@ static void res_instance (struct ctlio *, enum http_method, char const *,
struct json_value *);
-static void res_programs (struct ctlio *, enum http_method, char const *,
- struct json_value *);
+static void res_programs_select (struct ctlio *, enum http_method, char const *,
+ struct json_value *);
+static void res_programs_component (struct ctlio *, enum http_method,
+ char const *, struct json_value *);
@@ -905,3 +907,6 @@ static struct ctlio_resource restab[] = {
{ S(/instance), CTL_ADMIN_STATE, res_instance },
- { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, res_programs },
+ { S(/programs/select), CTL_ADMIN_STATE|CTL_USER_STATE,
+ res_programs_select },
+ { S(/programs/component), CTL_ADMIN_STATE|CTL_USER_STATE,
+ res_programs_component },
{ NULL }
@@ -933,3 +938,6 @@ json_extract (char *uri)
char *p = strrchr (uri, '/');
- if (p && strchr ("\"{[", p[1]))
+ if (p && (strchr ("\"{[", p[1])
+ || strcmp ("true", p + 1) == 0
+ || strcmp ("false", p + 1) == 0
+ || strcmp ("null", p + 1) == 0))
{
@@ -1315,4 +1323,9 @@ struct eval_env
struct ctlio *io;
+ int allowed_state;
struct pcond_node *cond;
+ int (*fun) (struct json_value *, struct prog *);
struct json_value *result;
+ size_t total_count;
+ size_t success_count;
+ size_t noperm_count;
};
@@ -1392,2 +1405,3 @@ enum pcond_type
{
+ pcond_false,
pcond_true,
@@ -1411,4 +1425,7 @@ struct pcond_node
enum prog_type type;
- struct pcond_node *unary;
- struct pcond_node *binary[2];
+ struct
+ {
+ size_t c;
+ struct pcond_node **v;
+ } arg;
} v;
@@ -1434,9 +1451,11 @@ pcond_node_free (struct pcond_node *node)
case pcond_not:
- pcond_node_free (node->v.unary);
- break;
-
case pcond_and:
case pcond_or:
- pcond_node_free (node->v.binary[0]);
- pcond_node_free (node->v.binary[1]);
+ {
+ size_t i;
+
+ for (i = 0; i < node->v.arg.c; i++)
+ pcond_node_free (node->v.arg.v[i]);
+ }
+ grecs_free (node->v.arg.v);
break;
@@ -1452,2 +1471,4 @@ pcond_eval (struct pcond_node *node, struct prog *p)
{
+ size_t i;
+
if (!node)
@@ -1458,2 +1479,5 @@ pcond_eval (struct pcond_node *node, struct prog *p)
return 1;
+
+ case pcond_false:
+ return 0;
@@ -1472,13 +1496,15 @@ pcond_eval (struct pcond_node *node, struct prog *p)
case pcond_not:
- return !pcond_eval (node->v.unary, p);
+ return !pcond_eval (node->v.arg.v[0], p);
case pcond_and:
- if (!pcond_eval (node->v.binary[0], p))
- return 0;
- return pcond_eval (node->v.binary[1], p);
+ for (i = 0; i < node->v.arg.c; i++)
+ if (!pcond_eval (node->v.arg.v[i], p))
+ return 0;
+ return 1;
case pcond_or:
- if (pcond_eval (node->v.binary[0], p))
- return 1;
- return pcond_eval (node->v.binary[1], p);
+ for (i = 0; i < node->v.arg.c; i++)
+ if (pcond_eval (node->v.arg.v[i], p))
+ return 1;
+ return 0;
@@ -1562,3 +1588,5 @@ pcond_conv_not (struct pcond_node *node, struct json_value *arg,
{
- return json_to_pcond (io, arg, &node->v.unary);
+ node->v.arg.v = grecs_calloc (1, sizeof (node->v.arg.v[0]));
+ node->v.arg.c = 1;
+ return json_to_pcond (io, arg, &node->v.arg.v[0]);
}
@@ -1569,3 +1597,3 @@ pcond_conv_binary (struct pcond_node *node, struct json_value *arg,
{
- struct json_value *v;
+ size_t i, n;
@@ -1576,8 +1604,16 @@ pcond_conv_binary (struct pcond_node *node, struct json_value *arg,
}
- json_array_get (arg, 0, &v);
- if (json_to_pcond (io, v, &node->v.binary[0]))
- return -1;
- json_array_get (arg, 1, &v);
- if (json_to_pcond (io, v, &node->v.binary[1]))
- return -1;
+
+ n = json_array_size (arg);
+ node->v.arg.v = grecs_calloc (n, sizeof (node->v.arg.v[0]));
+ node->v.arg.c = n;
+
+ for (i = 0; i < n; i++)
+ {
+ struct json_value *v;
+ if (json_array_get (arg, i, &v) == 0)
+ {
+ if (json_to_pcond (io, v, &node->v.arg.v[i]))
+ return -1;
+ }
+ }
return 0;
@@ -1592,2 +1628,3 @@ static struct pcond_conv pcond_conv[] = {
[pcond_true] = { "true", NULL },
+ [pcond_false] = { "false", NULL },
[pcond_component] = { "component", pcond_conv_component },
@@ -1671,6 +1708,3 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
case json_bool:
- if (val->v.b)
- *pnode = pcond_node_alloc (pcond_true);
- else
- *pnode = NULL;
+ *pnode = pcond_node_alloc (val->v.b ? pcond_true : pcond_false);
break;
@@ -1689,4 +1723,2 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
-static struct json_value *prog_serialize (struct prog *prog);
-
static int
@@ -1696,4 +1728,16 @@ selector (struct prog *prog, void *data)
- if (auth_prog (prog, env->io) && pcond_eval (env->cond, prog))
- json_array_append (env->result, prog_serialize (prog));
+ if (pcond_eval (env->cond, prog))
+ {
+ if (auth_prog (prog, env->io) & env->allowed_state)
+ {
+ struct json_value *status = json_new_object ();
+ json_object_set_string (status, "tag", prog->tag);
+ if (env->fun (status, prog) == 0)
+ env->success_count++;
+ json_array_append (env->result, status);
+ env->total_count++;
+ }
+ else
+ env->noperm_count++;
+ }
return 0;
@@ -1702,5 +1746,4 @@ selector (struct prog *prog, void *data)
static struct json_value *
-prog_serialize (struct prog *prog)
+prog_serialize (struct json_value *ret, struct prog *prog)
{
- struct json_value *ret = json_reply_create ();
struct json_value *v;
@@ -1708,3 +1751,2 @@ prog_serialize (struct prog *prog)
- json_object_set_string (ret, "tag", prog->tag);
FORMAT_IDX (ret, "type", pies_type_str, prog->type);
@@ -1744,8 +1786,19 @@ prog_serialize (struct prog *prog)
}
+
+static int
+fun_list (struct json_value *result, struct prog *prog)
+{
+ prog_serialize (result, prog);
+ return 0;
+}
-static void
-component_stop (struct ctlio *io, struct prog *prog)
+static int
+fun_stop (struct json_value *result, struct prog *prog)
{
if (prog->v.p.comp->flags & CF_DISABLED)
- ctlio_reply (io, 409, "Already stopped");
+ {
+ json_object_set_string (result, "status", "ER");
+ json_object_set_string (result, "error_message", "already stopped");
+ return 1;
+ }
else
@@ -1754,8 +1807,9 @@ component_stop (struct ctlio *io, struct prog *prog)
prog->v.p.comp->flags |= CF_DISABLED;
- ctlio_reply (io, 200, "Component stopped");
+ json_object_set_string (result, "status", "OK");
}
+ return 0;
}
-static void
-component_start (struct ctlio *io, struct prog *prog)
+static int
+fun_start (struct json_value *result, struct prog *prog)
{
@@ -1765,7 +1819,19 @@ component_start (struct ctlio *io, struct prog *prog)
prog->v.p.status = status_enabled;
- kill (getpid (), SIGALRM);
- ctlio_reply (io, 200, "Component started");
+ json_object_set_string (result, "status", "OK");
}
else
- ctlio_reply (io, 409, "Already running");
+ {
+ json_object_set_string (result, "status", "ER");
+ json_object_set_string (result, "error_message", "already running");
+ return 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");
+ return 0;
}
@@ -1773,50 +1839,102 @@ component_start (struct ctlio *io, struct prog *prog)
static void
-res_programs (struct ctlio *io, enum http_method meth,
- char const *uri, struct json_value *json)
+select_and_run (struct ctlio *io, struct pcond_node *cond,
+ enum http_method meth)
{
- if (meth == METH_GET)
+ struct eval_env env;
+ int wakeup = 0;
+
+ memset (&env, 0, sizeof (env));
+ env.io = io;
+ env.cond = cond;
+ env.fun = NULL;
+ env.result = json_new_array ();
+
+ switch (meth)
{
- struct eval_env env;
-
- env.io = io;
- if (json_to_pcond (io, json, &env.cond))
- return;
- env.result = json_new_array ();
- progman_foreach (selector, &env);
- pcond_node_free (env.cond);
- io->output.reply = env.result;
- io->code = 200;
+ case METH_GET:
+ env.allowed_state = CTL_USER_STATE | CTL_ADMIN_STATE;
+ env.fun = fun_list;
+ break;
+
+ case METH_DELETE:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_stop;
+ break;
+
+ case METH_PUT:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_start;
+ wakeup = 1;
+ break;
+
+ case METH_POST:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_restart;
+ wakeup = 1;
+ break;
+
+ default:
+ ctlio_reply (io, 405, NULL);
}
- else if (meth == METH_DELETE || meth == METH_PUT)
+
+ if (env.fun)
{
- if (!uri)
- ctlio_reply (io, 404, NULL);
+ env.result = json_new_array ();
+ progman_foreach (selector, &env);
+
+ if (env.success_count == 0 && env.noperm_count)
+ ctlio_reply (io, 403, NULL);
else
{
- struct prog *prog = progman_locate (uri);
- if (!prog)
- ctlio_reply (io, 404, NULL);
- else if (auth_prog (prog, io) & CTL_ADMIN_STATE)
- {
- if (!IS_COMPONENT (prog))
- ctlio_reply (io, 404, "Not a component");
- else if (meth == METH_DELETE)
- {
- component_stop (io, prog);
- }
- else
- {
- component_start (io, prog);
- }
- }
- else
- ctlio_reply (io, 403, NULL);
+ if (env.success_count && wakeup)
+ progman_wake_sleeping (1);
+ io->output.reply = env.result;
+ io->code = 200;
}
}
- else if (meth == METH_POST)
+}
+
+static void
+res_programs_select (struct ctlio *io, enum http_method meth,
+ char const *uri, struct json_value *json)
+{
+ struct pcond_node *cond;
+
+ if (uri)
+ {
+ ctlio_reply (io, 404, NULL);
+ return;
+ }
+
+ if (json_to_pcond (io, json, &cond))
+ return;
+ select_and_run (io, cond, meth);
+ pcond_node_free (cond);
+}
+
+static void
+res_programs_component (struct ctlio *io, enum http_method meth,
+ char const *uri, struct json_value *json)
+{
+ struct pcond_node *node = pcond_node_alloc (pcond_type);
+ node->v.type = TYPE_COMPONENT;
+
+ if (meth != METH_POST)
{
- if (json->type != json_arr)
+ if (uri)
{
- ctlio_reply (io, 400, NULL);
+ struct pcond_node *np;
+ np = pcond_node_alloc (pcond_and);
+ np->v.arg.c = 2;
+ np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
+ np->v.arg.v[0] = node;
+ np->v.arg.v[1] = pcond_node_alloc (pcond_component);
+ np->v.arg.v[1]->v.tag = (char*) uri + 1;
+ node = np;
}
+ }
+ else
+ {
+ if (json->type != json_arr)
+ ctlio_reply (io, 400, NULL);
else
@@ -1824,4 +1942,9 @@ res_programs (struct ctlio *io, enum http_method meth,
size_t i, n;
+ struct pcond_node *or_cond, *np;
n = json_array_size (json);
+ or_cond = pcond_node_alloc (pcond_or);
+ or_cond->v.arg.v = grecs_calloc (n, sizeof (or_cond->v.arg.v[0]));
+ or_cond->v.arg.c = n;
+
for (i = 0; i < n; i++)
@@ -1830,10 +1953,27 @@ res_programs (struct ctlio *io, enum http_method meth,
if (json_array_get (json, i, &v) == 0 && v->type == json_string)
- progman_stop_tag (v->v.s);
+ {
+ or_cond->v.arg.v[i] = pcond_node_alloc (pcond_component);
+ or_cond->v.arg.v[i]->v.tag = v->v.s;
+ }
+ else
+ {
+ ctlio_reply (io, 400, "all elements must be string");
+ pcond_node_free (or_cond);
+ pcond_node_free (node);
+ return;
+ }
}
- kill (getpid (), SIGALRM);
+
+ np = pcond_node_alloc (pcond_and);
+ np->v.arg.c = 2;
+ np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
+ np->v.arg.v[0] = node;
+ np->v.arg.v[1] = or_cond;
+
+ node = np;
}
- ctlio_reply (io, 200, "Done");
}
- else
- ctlio_reply (io, 405, NULL);
-}
+
+ select_and_run (io, node, meth);
+ pcond_node_free (node);
+}

Return to:

Send suggestions and report system problems to the System administrator.