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
@@ -888,8 +888,10 @@ method_decode (char const *method)
888 888
889static void res_instance (struct ctlio *, enum http_method, char const *, 889static void res_instance (struct ctlio *, enum http_method, char const *,
890 struct json_value *); 890 struct json_value *);
891static void res_programs (struct ctlio *, enum http_method, char const *, 891static void res_programs_select (struct ctlio *, enum http_method, char const *,
892 struct json_value *); 892 struct json_value *);
893static void res_programs_component (struct ctlio *, enum http_method,
894 char const *, struct json_value *);
893 895
894struct ctlio_resource 896struct ctlio_resource
895{ 897{
@@ -903,7 +905,10 @@ struct ctlio_resource
903static struct ctlio_resource restab[] = { 905static struct ctlio_resource restab[] = {
904#define S(s) #s, (sizeof (#s)-1) 906#define S(s) #s, (sizeof (#s)-1)
905 { S(/instance), CTL_ADMIN_STATE, res_instance }, 907 { S(/instance), CTL_ADMIN_STATE, res_instance },
906 { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, res_programs }, 908 { S(/programs/select), CTL_ADMIN_STATE|CTL_USER_STATE,
909 res_programs_select },
910 { S(/programs/component), CTL_ADMIN_STATE|CTL_USER_STATE,
911 res_programs_component },
907 { NULL } 912 { NULL }
908#undef S 913#undef S
909}; 914};
@@ -931,7 +936,10 @@ static char *
931json_extract (char *uri) 936json_extract (char *uri)
932{ 937{
933 char *p = strrchr (uri, '/'); 938 char *p = strrchr (uri, '/');
934 if (p && strchr ("\"{[", p[1])) 939 if (p && (strchr ("\"{[", p[1])
940 || strcmp ("true", p + 1) == 0
941 || strcmp ("false", p + 1) == 0
942 || strcmp ("null", p + 1) == 0))
935 { 943 {
936 *p++ = 0; 944 *p++ = 0;
937 return p; 945 return p;
@@ -1313,8 +1321,13 @@ res_instance (struct ctlio *io, enum http_method meth,
1313struct eval_env 1321struct eval_env
1314{ 1322{
1315 struct ctlio *io; 1323 struct ctlio *io;
1324 int allowed_state;
1316 struct pcond_node *cond; 1325 struct pcond_node *cond;
1326 int (*fun) (struct json_value *, struct prog *);
1317 struct json_value *result; 1327 struct json_value *result;
1328 size_t total_count;
1329 size_t success_count;
1330 size_t noperm_count;
1318}; 1331};
1319 1332
1320static int 1333static int
@@ -1390,6 +1403,7 @@ format_idx (struct json_value *obj, const char *name, unsigned i,
1390 1403
1391enum pcond_type 1404enum pcond_type
1392 { 1405 {
1406 pcond_false,
1393 pcond_true, 1407 pcond_true,
1394 pcond_component, 1408 pcond_component,
1395 pcond_type, 1409 pcond_type,
@@ -1409,8 +1423,11 @@ struct pcond_node
1409 enum pies_comp_mode mode; 1423 enum pies_comp_mode mode;
1410 enum prog_status status; 1424 enum prog_status status;
1411 enum prog_type type; 1425 enum prog_type type;
1412 struct pcond_node *unary; 1426 struct
1413 struct pcond_node *binary[2]; 1427 {
1428 size_t c;
1429 struct pcond_node **v;
1430 } arg;
1414 } v; 1431 } v;
1415}; 1432};
1416 1433
@@ -1432,13 +1449,15 @@ pcond_node_free (struct pcond_node *node)
1432 switch (node->type) 1449 switch (node->type)
1433 { 1450 {
1434 case pcond_not: 1451 case pcond_not:
1435 pcond_node_free (node->v.unary);
1436 break;
1437
1438 case pcond_and: 1452 case pcond_and:
1439 case pcond_or: 1453 case pcond_or:
1440 pcond_node_free (node->v.binary[0]); 1454 {
1441 pcond_node_free (node->v.binary[1]); 1455 size_t i;
1456
1457 for (i = 0; i < node->v.arg.c; i++)
1458 pcond_node_free (node->v.arg.v[i]);
1459 }
1460 grecs_free (node->v.arg.v);
1442 break; 1461 break;
1443 1462
1444 default: 1463 default:
@@ -1450,12 +1469,17 @@ pcond_node_free (struct pcond_node *node)
1450static int 1469static int
1451pcond_eval (struct pcond_node *node, struct prog *p) 1470pcond_eval (struct pcond_node *node, struct prog *p)
1452{ 1471{
1472 size_t i;
1473
1453 if (!node) 1474 if (!node)
1454 return 0; 1475 return 0;
1455 switch (node->type) 1476 switch (node->type)
1456 { 1477 {
1457 case pcond_true: 1478 case pcond_true:
1458 return 1; 1479 return 1;
1480
1481 case pcond_false:
1482 return 0;
1459 1483
1460 case pcond_component: 1484 case pcond_component:
1461 return strcmp (p->tag, node->v.tag) == 0; 1485 return strcmp (p->tag, node->v.tag) == 0;
@@ -1470,17 +1494,19 @@ pcond_eval (struct pcond_node *node, struct prog *p)
1470 return IS_COMPONENT (p) && p->v.p.status == node->v.status; 1494 return IS_COMPONENT (p) && p->v.p.status == node->v.status;
1471 1495
1472 case pcond_not: 1496 case pcond_not:
1473 return !pcond_eval (node->v.unary, p); 1497 return !pcond_eval (node->v.arg.v[0], p);
1474 1498
1475 case pcond_and: 1499 case pcond_and:
1476 if (!pcond_eval (node->v.binary[0], p)) 1500 for (i = 0; i < node->v.arg.c; i++)
1477 return 0; 1501 if (!pcond_eval (node->v.arg.v[i], p))
1478 return pcond_eval (node->v.binary[1], p); 1502 return 0;
1503 return 1;
1479 1504
1480 case pcond_or: 1505 case pcond_or:
1481 if (pcond_eval (node->v.binary[0], p)) 1506 for (i = 0; i < node->v.arg.c; i++)
1482 return 1; 1507 if (pcond_eval (node->v.arg.v[i], p))
1483 return pcond_eval (node->v.binary[1], p); 1508 return 1;
1509 return 0;
1484 1510
1485 default: 1511 default:
1486 abort (); 1512 abort ();
@@ -1560,26 +1586,36 @@ static int
1560pcond_conv_not (struct pcond_node *node, struct json_value *arg, 1586pcond_conv_not (struct pcond_node *node, struct json_value *arg,
1561 struct ctlio *io) 1587 struct ctlio *io)
1562{ 1588{
1563 return json_to_pcond (io, arg, &node->v.unary); 1589 node->v.arg.v = grecs_calloc (1, sizeof (node->v.arg.v[0]));
1590 node->v.arg.c = 1;
1591 return json_to_pcond (io, arg, &node->v.arg.v[0]);
1564} 1592}
1565 1593
1566static int 1594static int
1567pcond_conv_binary (struct pcond_node *node, struct json_value *arg, 1595pcond_conv_binary (struct pcond_node *node, struct json_value *arg,
1568 struct ctlio *io) 1596 struct ctlio *io)
1569{ 1597{
1570 struct json_value *v; 1598 size_t i, n;
1571 1599
1572 if (arg->type != json_arr) 1600 if (arg->type != json_arr)
1573 { 1601 {
1574 ctlio_reply (io, 400, "arguments to binary opcode must be array"); 1602 ctlio_reply (io, 400, "arguments to binary opcode must be array");
1575 return -1; 1603 return -1;
1576 } 1604 }
1577 json_array_get (arg, 0, &v); 1605
1578 if (json_to_pcond (io, v, &node->v.binary[0])) 1606 n = json_array_size (arg);
1579 return -1; 1607 node->v.arg.v = grecs_calloc (n, sizeof (node->v.arg.v[0]));
1580 json_array_get (arg, 1, &v); 1608 node->v.arg.c = n;
1581 if (json_to_pcond (io, v, &node->v.binary[1])) 1609
1582 return -1; 1610 for (i = 0; i < n; i++)
1611 {
1612 struct json_value *v;
1613 if (json_array_get (arg, i, &v) == 0)
1614 {
1615 if (json_to_pcond (io, v, &node->v.arg.v[i]))
1616 return -1;
1617 }
1618 }
1583 return 0; 1619 return 0;
1584} 1620}
1585 1621
@@ -1590,6 +1626,7 @@ struct pcond_conv {
1590 1626
1591static struct pcond_conv pcond_conv[] = { 1627static struct pcond_conv pcond_conv[] = {
1592 [pcond_true] = { "true", NULL }, 1628 [pcond_true] = { "true", NULL },
1629 [pcond_false] = { "false", NULL },
1593 [pcond_component] = { "component", pcond_conv_component }, 1630 [pcond_component] = { "component", pcond_conv_component },
1594 [pcond_type] = { "type", pcond_conv_type }, 1631 [pcond_type] = { "type", pcond_conv_type },
1595 [pcond_mode] = { "mode", pcond_conv_mode }, 1632 [pcond_mode] = { "mode", pcond_conv_mode },
@@ -1669,10 +1706,7 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
1669 break; 1706 break;
1670 1707
1671 case json_bool: 1708 case json_bool:
1672 if (val->v.b) 1709 *pnode = pcond_node_alloc (val->v.b ? pcond_true : pcond_false);
1673 *pnode = pcond_node_alloc (pcond_true);
1674 else
1675 *pnode = NULL;
1676 break; 1710 break;
1677 1711
1678 case json_number: 1712 case json_number:
@@ -1687,26 +1721,34 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
1687 return 0; 1721 return 0;
1688} 1722}
1689 1723
1690static struct json_value *prog_serialize (struct prog *prog);
1691
1692static int 1724static int
1693selector (struct prog *prog, void *data) 1725selector (struct prog *prog, void *data)
1694{ 1726{
1695 struct eval_env *env = data; 1727 struct eval_env *env = data;
1696 1728
1697 if (auth_prog (prog, env->io) && pcond_eval (env->cond, prog)) 1729 if (pcond_eval (env->cond, prog))
1698 json_array_append (env->result, prog_serialize (prog)); 1730 {
1731