aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2016-01-05 14:56:11 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2016-01-05 14:56:11 +0200
commit32a337f3b35c51ceb1d9320c7ff67fa1d5726c2a (patch)
tree098d41b0d07d62144f8398dc3c5f80a295369f98
parent2c03055b8ed023e7d8d65f2dbd51cd128040fcfb (diff)
downloadpies-32a337f3b35c51ceb1d9320c7ff67fa1d5726c2a.tar.gz
pies-32a337f3b35c51ceb1d9320c7ff67fa1d5726c2a.tar.bz2
Select components to operate upon using conditional expression
* grecs: Upgrade. * src/ctl.c (restab): Split /programs in two endpoints. (eval_env): New members allowed_state, fun, total_count, success_count, and noperm_count. (pcond_type): pcond_and and pcond_or can take arbitrary number of arguments. All uses updated. (selector): Rewrite. * src/piesctl.c: All commands that operate on components take conditional expression as argument. (pcond_parse_and) (pcond_parse_or): Optimize consecutive operations.
m---------grecs0
-rw-r--r--src/ctl.c318
-rw-r--r--src/piesctl.c244
3 files changed, 385 insertions, 177 deletions
diff --git a/grecs b/grecs
Subproject 3b73967c62da68d865f32ca91c8407e65b8ddc0 Subproject 384b8c088c290f06f70835402f903627c67de6f
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 if (auth_prog (prog, env->io) & env->allowed_state)
1732 {
1733 struct json_value *status = json_new_object ();
1734 json_object_set_string (status, "tag", prog->tag);
1735 if (env->fun (status, prog) == 0)
1736 env->success_count++;
1737 json_array_append (env->result, status);
1738 env->total_count++;
1739 }
1740 else
1741 env->noperm_count++;
1742 }
1699 return 0; 1743 return 0;
1700} 1744}
1701 1745
1702static struct json_value * 1746static struct json_value *
1703prog_serialize (struct prog *prog) 1747prog_serialize (struct json_value *ret, struct prog *prog)
1704{ 1748{
1705 struct json_value *ret = json_reply_create ();
1706 struct json_value *v; 1749 struct json_value *v;
1707 size_t i; 1750 size_t i;
1708 1751
1709 json_object_set_string (ret, "tag", prog->tag);
1710 FORMAT_IDX (ret, "type", pies_type_str, prog->type); 1752 FORMAT_IDX (ret, "type", pies_type_str, prog->type);
1711 switch (prog->type) 1753 switch (prog->type)
1712 { 1754 {
@@ -1742,98 +1784,196 @@ prog_serialize (struct prog *prog)
1742 } 1784 }
1743 return ret; 1785 return ret;
1744} 1786}
1787
1788static int
1789fun_list (struct json_value *result, struct prog *prog)
1790{
1791 prog_serialize (result, prog);
1792 return 0;
1793}
1745 1794
1746static void 1795static int
1747component_stop (struct ctlio *io, struct prog *prog) 1796fun_stop (struct json_value *result, struct prog *prog)
1748{ 1797{
1749 if (prog->v.p.comp->flags & CF_DISABLED) 1798 if (prog->v.p.comp->flags & CF_DISABLED)
1750 ctlio_reply (io, 409, "Already stopped"); 1799 {
1800 json_object_set_string (result, "status", "ER");
1801 json_object_set_string (result, "error_message", "already stopped");
1802 return 1;
1803 }
1751 else 1804 else
1752 { 1805 {
1753 progman_stop_component (prog); 1806 progman_stop_component (prog);
1754 prog->v.p.comp->flags |= CF_DISABLED; 1807 prog->v.p.comp->flags |= CF_DISABLED;
1755 ctlio_reply (io, 200, "Component stopped"); 1808 json_object_set_string (result, "status", "OK");
1756 } 1809 }
1810 return 0;
1757} 1811}
1758 1812
1759static void 1813static int
1760component_start (struct ctlio *io, struct prog *prog) 1814fun_start (struct json_value *result, struct prog *prog)
1761{ 1815{
1762 if (prog->v.p.comp->flags & CF_DISABLED) 1816 if (prog->v.p.comp->flags & CF_DISABLED)
1763 { 1817 {
1764 prog->v.p.comp->flags &= ~CF_DISABLED; 1818 prog->v.p.comp->flags &= ~CF_DISABLED;
1765 prog->v.p.status = status_enabled; 1819 prog->v.p.status = status_enabled;
1766 kill (getpid (), SIGALRM); 1820 json_object_set_string (result, "status", "OK");
1767 ctlio_reply (io, 200, "Component started");
1768 } 1821 }
1769 else 1822 else
1770 ctlio_reply (io, 409, "Already running"); 1823 {
1824 json_object_set_string (result, "status", "ER");
1825 json_object_set_string (result, "error_message", "already running");
1826 return 1;
1827 }
1828 return 0;
1829}
1830
1831static int
1832fun_restart (struct json_value *result, struct prog *prog)
1833{
1834 progman_stop_component (prog);
1835 json_object_set_string (result, "status", "OK");
1836 return 0;
1771} 1837}
1772 1838
1773static void 1839static void
1774res_programs (struct ctlio *io, enum http_method meth, 1840select_and_run (struct ctlio *io, struct pcond_node *cond,
1775 char const *uri, struct json_value *json) 1841 enum http_method meth)
1776{ 1842{
1777 if (meth == METH_GET) 1843 struct eval_env env;
1844 int wakeup = 0;
1845
1846 memset (&env, 0, sizeof (env));
1847 env.io = io;
1848 env.cond = cond;
1849 env.fun = NULL;
1850 env.result = json_new_array ();
1851
1852 switch (meth)
1778 { 1853 {
1779 struct eval_env env; 1854 case METH_GET:
1780 1855 env.allowed_state = CTL_USER_STATE | CTL_ADMIN_STATE;
1781 env.io = io; 1856 env.fun = fun_list;
1782 if (json_to_pcond (io, json, &env.cond)) 1857 break;
1783 return; 1858
1784 env.result = json_new_array (); 1859 case METH_DELETE:
1785 progman_foreach (selector, &env); 1860 env.allowed_state = CTL_ADMIN_STATE;
1786 pcond_node_free (env.cond); 1861 env.fun = fun_stop;
1787 io->output.reply = env.result; 1862 break;
1788 io->code = 200; 1863
1864 case METH_PUT:
1865 env.allowed_state = CTL_ADMIN_STATE;
1866 env.fun = fun_start;
1867 wakeup = 1;
1868 break;
1869
1870 case METH_POST:
1871 env.allowed_state = CTL_ADMIN_STATE;
1872 env.fun = fun_restart;
1873 wakeup = 1;
1874 break;
1875
1876 default:
1877 ctlio_reply (io, 405, NULL);
1789 } 1878 }
1790 else if (meth == METH_DELETE || meth == METH_PUT) 1879
1880 if (env.fun)
1791 { 1881 {
1792 if (!uri) 1882 env.result = json_new_array ();
1793 ctlio_reply (io, 404, NULL); 1883 progman_foreach (selector, &env);
1884
1885 if (env.success_count == 0 && env.noperm_count)
1886 ctlio_reply (io, 403, NULL);
1794 else 1887 else
1795 { 1888 {
1796 struct prog *prog = progman_locate (uri); 1889 if (env.success_count && wakeup)
1797 if (!prog) 1890 progman_wake_sleeping (1);
1798 ctlio_reply (io, 404, NULL); 1891 io->output.reply = env.result;
1799 else if (auth_prog (prog, io) & CTL_ADMIN_STATE) 1892 io->code = 200;
1800 {
1801 if (!IS_COMPONENT (prog))
1802 ctlio_reply (io, 404, "Not a component");
1803 else if (meth == METH_DELETE)
1804 {
1805 component_stop (io, prog);
1806 }
1807 else
1808 {
1809 component_start (io, prog);
1810 }
1811 }
1812 else
1813 ctlio_reply (io, 403, NULL);
1814 } 1893 }
1815 } 1894 }
1816 else if (meth == METH_POST) 1895}
1896
1897static void
1898res_programs_select (struct ctlio *io, enum http_method meth,
1899 char const *uri, struct json_value *json)
1900{
1901 struct pcond_node *cond;
1902
1903 if (uri)
1904 {
1905 ctlio_reply (io, 404, NULL);
1906 return;
1907 }
1908
1909 if (json_to_pcond (io, json, &cond))
1910 return;
1911 select_and_run (io, cond, meth);
1912 pcond_node_free (cond);
1913}
1914
1915static void
1916res_programs_component (struct ctlio *io, enum http_method meth,
1917 char const *uri, struct json_value *json)
1918{
1919 struct pcond_node *node = pcond_node_alloc (pcond_type);
1920 node->v.type = TYPE_COMPONENT;
1921
1922 if (meth != METH_POST)
1817 { 1923 {
1818 if (json->type != json_arr) 1924 if (uri)
1819 { 1925 {
1820 ctlio_reply (io, 400, NULL); 1926 struct pcond_node *np;
1927 np = pcond_node_alloc (pcond_and);
1928 np->v.arg.c = 2;
1929 np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
1930 np->v.arg.v[0] = node;
1931 np->v.arg.v[1] = pcond_node_alloc (pcond_component);
1932 np->v.arg.v[1]->v.tag = (char*) uri + 1;
1933 node = np;
1821 } 1934 }
1935 }
1936 else
1937 {
1938 if (json->type != json_arr)
1939 ctlio_reply (io, 400, NULL);
1822 else 1940 else
1823 { 1941 {
1824 size_t i, n; 1942 size_t i, n;
1943 struct pcond_node *or_cond, *np;
1825 1944
1826 n = json_array_size (json); 1945 n = json_array_size (json);
1946 or_cond = pcond_node_alloc (pcond_or);
1947 or_cond->v.arg.v = grecs_calloc (n, sizeof (or_cond->v.arg.v[0]));
1948 or_cond->v.arg.c = n;
1949
1827 for (i = 0; i < n; i++) 1950 for (i = 0; i < n; i++)
1828 { 1951 {
1829 struct json_value *v; 1952 struct json_value *v;
1830 if (json_array_get (json, i, &v) == 0 && v->type == json_string) 1953 if (json_array_get (json, i, &v) == 0 && v->type == json_string)
1831 progman_stop_tag (v->v.s); 1954 {
1955 or_cond->v.arg.v[i] = pcond_node_alloc (pcond_component);
1956 or_cond->v.arg.v[i]->v.tag = v->v.s;
1957 }
1958 else
1959 {
1960 ctlio_reply (io, 400, "all elements must be string");
1961 pcond_node_free (or_cond);
1962 pcond_node_free (node);
1963 return;
1964 }
1832 } 1965 }
1833 kill (getpid (), SIGALRM); 1966
1967 np = pcond_node_alloc (pcond_and);
1968 np->v.arg.c = 2;
1969 np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
1970 np->v.arg.v[0] = node;
1971 np->v.arg.v[1] = or_cond;
1972
1973 node = np;
1834 } 1974 }
1835 ctlio_reply (io, 200, "Done");
1836 } 1975 }
1837 else 1976
1838 ctlio_reply (io, 405, NULL); 1977 select_and_run (io, node, meth);
1839} 1978 pcond_node_free (node);
1979}
diff --git a/src/piesctl.c b/src/piesctl.c
index 8c4e2e1..4b448ad 100644
--- a/src/piesctl.c
+++ b/src/piesctl.c
@@ -1228,15 +1228,6 @@ peek_token (struct pcond_parser_state *state)
1228} 1228}
1229 1229
1230static struct json_value * 1230static struct json_value *
1231json_new_array2 (struct json_value *a, struct json_value *b)
1232{
1233 struct json_value *ret = json_new_array ();
1234 json_array_append (ret, a);
1235 json_array_append (ret, b);
1236 return ret;
1237}
1238
1239static struct json_value *
1240json_encode_op (char const *op, struct json_value *arg) 1231json_encode_op (char const *op, struct json_value *arg)
1241{ 1232{
1242 struct json_value *ret = json_new_object (); 1233 struct json_value *ret = json_new_object ();
@@ -1300,11 +1291,48 @@ pcond_parse_unary (struct pcond_parser_state *state, struct json_value **ret)
1300 } 1291 }
1301} 1292}
1302 1293
1294static int
1295is_op (struct json_value *val, char const *opcode)
1296{
1297 struct json_value *op;
1298
1299 if (json_object_get (val, "op", &op) == 0)
1300 {
1301 if (op->type == json_string && strcmp (op->v.s, opcode) == 0)
1302 return 1;
1303 }
1304 return 0;
1305}
1306
1307static void
1308binop_append_optimized (struct json_value *ar, struct json_value *val,
1309 char const *opcode)
1310{
1311 if (is_op (val, opcode))
1312 {
1313 size_t i, n;
1314 struct json_value *arg;
1315
1316 json_object_get (val, "arg", &arg);
1317 n = json_array_size (arg);
1318 for (i = 0; i < n; i++)
1319 {
1320 struct json_value *elt;
1321 json_array_get (arg, i, &elt);
1322 json_array_set (arg, i, NULL);
1323 json_array_append (ar, elt);
1324 }
1325 json_value_free (val);
1326 }
1327 else
1328 json_array_append (ar, val);
1329}
1330
1303static void 1331static void
1304pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret) 1332pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret)
1305{ 1333{
1306 char const *token; 1334 char const *token;
1307 struct json_value *left, *right; 1335 struct json_value *left, *right, *ar;
1308 1336
1309 pcond_parse_unary (state, &left); 1337 pcond_parse_unary (state, &left);
1310 token = peek_token (state); 1338 token = peek_token (state);
@@ -1315,14 +1343,17 @@ pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret)
1315 } 1343 }
1316 next_token (state); 1344 next_token (state);
1317 pcond_parse_and (state, &right); 1345 pcond_parse_and (state, &right);
1318 *ret = json_encode_op (token, json_new_array2 (left, right)); 1346 ar = json_new_array ();
1347 json_array_append (ar, left);
1348 binop_append_optimized (ar, right, token);
1349 *ret = json_encode_op (token, ar);
1319} 1350}
1320 1351
1321static void 1352static void
1322pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret) 1353pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret)
1323{ 1354{
1324 char const *token; 1355 char const *token;
1325 struct json_value *left, *right; 1356 struct json_value *left, *right, *ar;
1326 1357
1327 pcond_parse_and (state, &left); 1358 pcond_parse_and (state, &left);
1328 token = peek_token (state); 1359 token = peek_token (state);
@@ -1333,7 +1364,10 @@ pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret)
1333 } 1364 }
1334 next_token (state); 1365 next_token (state);
1335 pcond_parse_or (state, &right); 1366 pcond_parse_or (state, &right);
1336 *ret = json_encode_op (token, json_new_array2 (left, right)); 1367 ar = json_new_array ();
1368 json_array_append (ar, left);
1369 binop_append_optimized (ar, right, token);
1370 *ret = json_encode_op (token, ar);
1337} 1371}
1338 1372
1339static struct json_value * 1373static struct json_value *
@@ -1369,34 +1403,21 @@ acc_writer (void *closure, char const *text, size_t len)
1369} 1403}
1370 1404
1371static char * 1405static char *
1372json_to_string (struct json_value *val) 1406parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory)
1373{
1374 struct grecs_txtacc *acc = grecs_txtacc_create ();
1375 struct json_format fmt = {
1376 .indent = 0,
1377 .precision = 0,
1378 .write = acc_writer,
1379 .data = acc
1380 };
1381 char *ret;
1382
1383 json_format_value (val, &fmt);
1384 grecs_txtacc_grow_char (acc, 0);
1385 ret = grecs_txtacc_finish (acc, 1);
1386 grecs_txtacc_free (acc);
1387
1388 return ret;
1389}
1390
1391static char *
1392parse_condition_to_uri (char const *base, int argc, char **argv)
1393{ 1407{
1394 char *ret = NULL; 1408 char *ret = NULL;
1395 struct grecs_txtacc *acc; 1409 struct grecs_txtacc *acc;
1396 struct json_value *val; 1410 struct json_value *val;
1397 1411
1412 if (mandatory && argc == 1)
1413 {
1414 grecs_error (NULL, 0, _("condition must be specified"));
1415 exit (EX_USAGE);
1416 }
1417
1398 acc = grecs_txtacc_create (); 1418 acc = grecs_txtacc_create ();
1399 grecs_txtacc_grow_string (acc, base); 1419 if (base)
1420 grecs_txtacc_grow_string (acc, base);
1400 1421
1401 val = parse_condition (argc, argv); 1422 val = parse_condition (argc, argv);
1402 if (val) 1423 if (val)
@@ -1407,7 +1428,8 @@ parse_condition_to_uri (char const *base, int argc, char **argv)
1407 .write = acc_writer, 1428 .write = acc_writer,
1408 .data = acc 1429 .data = acc
1409 }; 1430 };
1410 grecs_txtacc_grow_char (acc, '/'); 1431 if (base)
1432 grecs_txtacc_grow_char (acc, '/');
1411 json_format_value (val, &fmt); 1433 json_format_value (val, &fmt);
1412 json_value_free (val); 1434 json_value_free (val);
1413 } 1435 }
@@ -1415,14 +1437,13 @@ parse_condition_to_uri (char const *base, int argc, char **argv)
1415 1437
1416 ret = grecs_txtacc_finish (acc, 1); 1438 ret = grecs_txtacc_finish (acc, 1);
1417 grecs_txtacc_free (acc); 1439 grecs_txtacc_free (acc);
1418
1419 return ret; 1440 return ret;
1420} 1441}
1421 1442
1422static int 1443static int
1423com_list (struct shttp_connection *conn, int argc, char **argv) 1444com_list (struct shttp_connection *conn, int argc, char **argv)
1424{ 1445{
1425 char *uri = parse_condition_to_uri ("/programs", argc, argv); 1446 char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 0);
1426 1447
1427 shttp_io_init (&conn->req); 1448 shttp_io_init (&conn->req);
1428 shttp_process (conn, METH_GET, uri); 1449 shttp_process (conn, METH_GET, uri);
@@ -1443,68 +1464,97 @@ com_list (struct shttp_connection *conn, int argc, char **argv)
1443} 1464}
1444 1465
1445static int 1466static int
1446com_stop (struct shttp_connection *conn, int argc, char **argv) 1467json_object_get_type (struct json_value *obj, char const *name,
1468 enum json_value_type type, struct json_value **ret)
1447{ 1469{
1448 char *buf = NULL; 1470 struct json_value *v;
1449 size_t len = 0; 1471 int rc = json_object_get (obj, name, &v);
1450 size_t i; 1472 if (rc)
1451 1473 return rc;
1452 for (i = 1; i < argc; i++) 1474 if (v->type != type)
1453 { 1475 {
1454 struct json_value *v; 1476 errno = EACCES;
1455 grecs_asprintf (&buf, &len, "/programs/%s", argv[i]); 1477 return -1;
1456 shttp_io_init (&conn->req);
1457 shttp_process (conn, METH_DELETE, buf);
1458 v = shttp_getval (conn, "error_message", json_string);
1459 if (v)
1460 printf ("%s: %s\n", argv[i], v->v.s);
1461 } 1478 }
1462 free (buf); 1479 *ret = v;
1480 return 0;
1481}
1482
1483static void
1484shttp_print_response_status (struct shttp_connection *conn)
1485{
1486 if (!dump && conn->result && conn->result->type == json_arr)
1487 {
1488 size_t i, n = json_array_size (conn->result);
1489
1490 for (i = 0; i < n; i++)
1491 {
1492 struct json_value *elt, *v;
1493
1494 if (json_array_get (conn->result, i, &elt) == 0)
1495 {
1496 if (elt->type != json_object)
1497 {
1498 grecs_error (NULL, 0, _("%lu: unexpected value type"),
1499 (unsigned long) i);
1500 print_json (stderr, v);
1501 continue;
1502 }
1503 if (json_object_get_type (elt, "tag", json_string, &v) == 0)
1504 {
1505 printf ("%s: ", v->v.s);
1506 if (json_object_get_type (elt, "status", json_string, &v)
1507 == 0)
1508 {
1509 if (strcmp (v->v.s, "OK") == 0)
1510 fputs (v->v.s, stdout);
1511 else if (json_object_get_type (elt, "error_message",
1512 json_string, &v) == 0)
1513 fputs (v->v.s, stdout);
1514 else
1515 printf ("unknown error");
1516 }
1517 else
1518 printf ("unknown status");
1519 fputc ('\n', stdout);
1520 }
1521 }
1522 }
1523 }
1524}
1525
1526static int
1527com_stop (struct shttp_connection *conn, int argc, char **argv)
1528{
1529 char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1);
1530
1531 shttp_io_init (&conn->req);
1532 shttp_process (conn, METH_DELETE, uri);
1533 grecs_free (uri);
1534 shttp_print_response_status (conn);
1463 return 0; 1535 return 0;
1464} 1536}
1465 1537
1466static int 1538static int
1467com_start (struct shttp_connection *conn, int argc, char **argv) 1539com_start (struct shttp_connection *conn, int argc, char **argv)
1468{ 1540{
1469 char *buf = NULL; 1541 char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1);
1470 size_t len = 0; 1542
1471 size_t i; 1543 shttp_io_init (&conn->req);
1472 1544 shttp_process (conn, METH_PUT, uri);
1473 for (i = 1; i < argc; i++) 1545 grecs_free (uri);
1474 { 1546 shttp_print_response_status (conn);
1475 struct json_value *v;
1476 grecs_asprintf (&buf, &len, "/programs/%s", argv[i]);
1477 shttp_io_init (&conn->req);
1478 shttp_process (conn, METH_PUT, buf);
1479 v = shttp_getval (conn, "error_message", json_string);
1480 if (v)
1481 printf ("%s: %s\n", argv[i], v->v.s);
1482 }
1483 free (buf);
1484 return 0; 1547 return 0;
1485} 1548}
1486 1549
1487static int 1550static int
1488com_restart (struct shttp_connection *conn, int argc, char **argv) 1551com_restart (struct shttp_connection *conn, int argc, char **argv)
1489{ 1552{
1490 struct json_value *val = json_new_array ();
1491 size_t i;
1492
1493 if (argc == 1)
1494 {
1495 grecs_error (NULL, 0, _("missing component names"));
1496 exit (EX_USAGE);
1497 }
1498 for (i = 1; i < argc; i++)
1499 json_array_append (val, json_new_string (argv[i]));
1500
1501 shttp_io_init (&conn->req); 1553 shttp_io_init (&conn->req);
1502 conn->req.content = json_to_string (val); 1554 conn->req.content = parse_condition_to_uri (NULL, argc, argv, 1);
1503 conn->req.content_length = strlen (conn->req.content); 1555 conn->req.content_length = strlen (conn->req.content);
1504 json_value_free (val); 1556 shttp_process (conn, METH_POST, "/programs/select");
1505 1557 shttp_print_response_status (conn);
1506 shttp_process (conn, METH_POST, "/programs");
1507
1508 return 0; 1558 return 0;
1509} 1559}
1510 1560
@@ -1585,10 +1635,10 @@ struct comtab
1585}; 1635};
1586 1636
1587static struct comtab comtab[] = { 1637static struct comtab comtab[] = {
1588 { "list", N_("[EXPR]"), N_("list configured components"), com_list }, 1638 { "list", N_("[CONDITION]"), N_("list configured components"), com_list },
1589 { "stop", N_("TAG [TAG...]"), N_("stop components"), com_stop }, 1639 { "stop", N_("CONDITION"), N_("stop components"), com_stop },
1590 { "start", N_("TAG [TAG...]"), N_("start components"), com_start }, 1640 { "start", N_("CONDITION"), N_("start components"), com_start },
1591 { "restart", N_("TAG [TAG...]"), N_("restart components"), com_restart }, 1641 { "restart", N_("CONDITION"), N_("restart components"), com_restart },
1592 { "id", N_("[KEYWORDS...]"), 1642 { "id", N_("[KEYWORDS...]"),
1593 N_("show info about the running GNU Pies instance"), 1643 N_("show info about the running GNU Pies instance"),
1594 com_id }, 1644 com_id },
@@ -1639,7 +1689,7 @@ command_help (FILE *fp)
1639{ 1689{
1640 struct comtab *cp; 1690 struct comtab *cp;
1641 1691
1642 fputs (_("Available commands are:"), fp); 1692 fputs (_("Available commands with their arguments are:"), fp);
1643 fputc ('\n', fp); 1693 fputc ('\n', fp);
1644 fputc ('\n', fp); 1694 fputc ('\n', fp);
1645 1695
@@ -1655,6 +1705,24 @@ command_help (FILE *fp)
1655 fprintf (fp, " %s\n", gettext (cp->docstr)); 1705 fprintf (fp, " %s\n", gettext (cp->docstr));
1656 } 1706 }
1657 fputc ('\n', fp); 1707 fputc ('\n', fp);
1708 fputs (_("Condition is defined as:"), fp);
1709 fputc ('\n', fp);
1710 fputc ('\n', fp);
1711 fputs ("\
1712 <condition> ::= <disjunction>\n\
1713 <disjunction> ::= <conjunction> | <conjunction> \"or\" <disjunction>\n\
1714 <conjunction> ::= <unary> | <unary> \"and\" <conjunction>\n\
1715 <unary> ::= <term> | \"not\" <condition> | \"(\" <condition> \")\"\n\
1716 <term> ::= \"all\" | <keyword> <value>\n\
1717 <keyword> ::= \"type\" | \"mode\" | \"status\" | \"component\"\n\
1718 <value> ::= <word> | <quoted-string>\n\
1719 <word> ::= <printable> | <word> <printable>\n\
1720 <printable> ::= \"A\" - \"Z\" | \"a\" - \"z\" | \"0\" - \"9\" |\n\
1721 \"_\" | \".\" | \"*\" | \":\" | \"@\" | \"[\" | \"]\" | \"-\" | \"/\"\n\
1722 <quoted-string> ::= \"\"\" <string> \"\"\"\n\
1723 <string> ::= <char> | <string> <char>\n\
1724 <char> ::= <any character except \"\\\" and \"\"\"> | \"\\\\\" | \"\\\"\"\n\n", fp);
1725
1658} 1726}
1659 1727
1660int 1728int

Return to:

Send suggestions and report system problems to the System administrator.