diff options
Diffstat (limited to 'src/ctl.c')
-rw-r--r-- | src/ctl.c | 318 |
1 files changed, 229 insertions, 89 deletions
@@ -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); +} |