diff options
-rw-r--r-- | src/ctl.c | 64 | ||||
-rw-r--r-- | src/pies.h | 9 | ||||
-rw-r--r-- | src/piesctl.c | 136 | ||||
-rw-r--r-- | src/sysvinit.c | 58 |
4 files changed, 243 insertions, 24 deletions
@@ -18,7 +18,6 @@ | |||
18 | #include "prog.h" | 18 | #include "prog.h" |
19 | #include "identity.h" | 19 | #include "identity.h" |
20 | #include "base64.h" | 20 | #include "base64.h" |
21 | #include "json.h" | ||
22 | 21 | ||
23 | struct control control; | 22 | struct control control; |
24 | 23 | ||
@@ -443,7 +442,7 @@ json_reply_create (void) | |||
443 | return json_new_object (); | 442 | return json_new_object (); |
444 | } | 443 | } |
445 | 444 | ||
446 | static void | 445 | void |
447 | json_object_set_string (struct json_value *obj, | 446 | json_object_set_string (struct json_value *obj, |
448 | char const *name, char const *fmt, ...) | 447 | char const *name, char const *fmt, ...) |
449 | { | 448 | { |
@@ -458,7 +457,7 @@ json_object_set_string (struct json_value *obj, | |||
458 | grecs_free (s); | 457 | grecs_free (s); |
459 | } | 458 | } |
460 | 459 | ||
461 | static void | 460 | void |
462 | json_object_set_number (struct json_value *obj, char const *name, double val) | 461 | json_object_set_number (struct json_value *obj, char const *name, double val) |
463 | { | 462 | { |
464 | json_object_set (obj, name, json_new_number (val)); | 463 | json_object_set (obj, name, json_new_number (val)); |
@@ -904,21 +903,27 @@ static void res_instance (struct ctlio *, enum http_method, char const *, | |||
904 | struct json_value *); | 903 | struct json_value *); |
905 | static void res_programs (struct ctlio *, enum http_method, char const *, | 904 | static void res_programs (struct ctlio *, enum http_method, char const *, |
906 | struct json_value *); | 905 | struct json_value *); |
906 | static void res_runlevel (struct ctlio *, enum http_method, char const *, | ||
907 | struct json_value *); | ||
908 | |||
909 | static int pred_sysvinit (void); | ||
907 | 910 | ||
908 | struct ctlio_resource | 911 | struct ctlio_resource |
909 | { | 912 | { |
910 | char const *uri; | 913 | char const *uri; |
911 | size_t uri_len; | 914 | size_t uri_len; |
912 | int states; | 915 | int states; |
916 | int (*predicate) (void); | ||
913 | void (*handler) (struct ctlio *, enum http_method, | 917 | void (*handler) (struct ctlio *, enum http_method, |
914 | char const *uri, struct json_value *); | 918 | char const *uri, struct json_value *); |
915 | }; | 919 | }; |
916 | 920 | ||
917 | static struct ctlio_resource restab[] = { | 921 | static struct ctlio_resource restab[] = { |
918 | #define S(s) #s, (sizeof (#s)-1) | 922 | #define S(s) #s, (sizeof (#s)-1) |
919 | { S(/instance), CTL_ADMIN_STATE, res_instance }, | 923 | { S(/instance), CTL_ADMIN_STATE, NULL, res_instance }, |
920 | { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, | 924 | { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, NULL, |
921 | res_programs }, | 925 | res_programs }, |
926 | { S(/runlevel), CTL_ADMIN_STATE, pred_sysvinit, res_runlevel }, | ||
922 | { NULL } | 927 | { NULL } |
923 | #undef S | 928 | #undef S |
924 | }; | 929 | }; |
@@ -939,7 +944,8 @@ find_resource (struct ctlio *io, const char *endpoint) | |||
939 | if (len >= p->uri_len && memcmp (p->uri, endpoint, p->uri_len) == 0 | 944 | if (len >= p->uri_len && memcmp (p->uri, endpoint, p->uri_len) == 0 |
940 | && (endpoint[p->uri_len] == 0 | 945 | && (endpoint[p->uri_len] == 0 |
941 | || endpoint[p->uri_len] == '/' | 946 | || endpoint[p->uri_len] == '/' |
942 | || endpoint[p->uri_len] == '?')) | 947 | || endpoint[p->uri_len] == '?') |
948 | && (!p->predicate || p->predicate())) | ||
943 | return p; | 949 | return p; |
944 | return NULL; | 950 | return NULL; |
945 | } | 951 | } |
@@ -2010,3 +2016,49 @@ res_programs (struct ctlio *io, enum http_method meth, | |||
2010 | else | 2016 | else |
2011 | res_programs_select (io, meth, uri, json); | 2017 | res_programs_select (io, meth, uri, json); |
2012 | } | 2018 | } |
2019 | |||
2020 | static int | ||
2021 | pred_sysvinit (void) | ||
2022 | { | ||
2023 | return init_process; | ||
2024 | } | ||
2025 | |||
2026 | static void | ||
2027 | res_runlevel (struct ctlio *io, enum http_method meth, | ||
2028 | char const *uri, struct json_value *json) | ||
2029 | { | ||
2030 | if (uri) | ||
2031 | ctlio_reply (io, 404, NULL); | ||
2032 | else if (meth == METH_GET) | ||
2033 | { | ||
2034 | io->output.reply = json_reply_create (); | ||
2035 | io->code = 200; | ||
2036 | sysvinit_report (io->output.reply); | ||
2037 | } | ||
2038 | else if (meth == METH_PUT) | ||
2039 | { | ||
2040 | struct json_value *val; | ||
2041 | // { "runlevel": "3" } | ||
2042 | if (json_object_get (json, "runlevel", &val)) | ||
2043 | ctlio_reply (io, 400, "missing runlevel request"); | ||
2044 | else if (val->type != json_string) | ||
2045 | ctlio_reply (io, 400, "bad runlevel type"); | ||
2046 | else | ||
2047 | { | ||
2048 | io->output.reply = json_reply_create (); | ||
2049 | io->code = 200; | ||
2050 | if (strlen (val->v.s) == 1 | ||
2051 | && sysvinit_set_runlevel (val->v.s[0]) == 0) | ||
2052 | json_object_set_string (io->output.reply, "status", "OK"); | ||
2053 | else | ||
2054 | { | ||
2055 | json_object_set_string (io->output.reply, "status", "ER"); | ||
2056 | json_object_set_string (io->output.reply, "error_message", | ||
2057 | "invalid runlevel value"); | ||
2058 | } | ||
2059 | } | ||
2060 | } | ||
2061 | else | ||
2062 | ctlio_reply (io, 405, NULL); | ||
2063 | } | ||
2064 | |||
@@ -56,6 +56,7 @@ | |||
56 | #include "identity.h" | 56 | #include "identity.h" |
57 | #include "acl.h" | 57 | #include "acl.h" |
58 | #include "libpies.h" | 58 | #include "libpies.h" |
59 | #include "json.h" | ||
59 | 60 | ||
60 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) | 61 | #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) |
61 | 62 | ||
@@ -515,6 +516,9 @@ void sysvinit_runlevel_setup (int mask, int *wait); | |||
515 | void sysvinit_sysdep_begin (void); | 516 | void sysvinit_sysdep_begin (void); |
516 | void sysvinit_power (void); | 517 | void sysvinit_power (void); |
517 | 518 | ||
519 | void sysvinit_report (struct json_value *obj); | ||
520 | int sysvinit_set_runlevel (int newlevel); | ||
521 | |||
518 | extern char *sysvinit_environ_hint[]; | 522 | extern char *sysvinit_environ_hint[]; |
519 | extern char *init_fifo; | 523 | extern char *init_fifo; |
520 | 524 | ||
@@ -578,3 +582,8 @@ struct control | |||
578 | extern struct control control; | 582 | extern struct control control; |
579 | 583 | ||
580 | int ctl_open(void); | 584 | int ctl_open(void); |
585 | |||
586 | void json_object_set_string (struct json_value *obj, | ||
587 | char const *name, char const *fmt, ...); | ||
588 | void json_object_set_number (struct json_value *obj, | ||
589 | char const *name, double val); | ||
diff --git a/src/piesctl.c b/src/piesctl.c index f799ff4..d6a39a2 100644 --- a/src/piesctl.c +++ b/src/piesctl.c | |||
@@ -1716,6 +1716,140 @@ com_reboot (struct shttp_connection *conn, int argc, char **argv) | |||
1716 | shttp_process (conn, METH_PUT, "/instance/PID"); | 1716 | shttp_process (conn, METH_PUT, "/instance/PID"); |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | /* | ||
1720 | <telinit> ::= "telinit" <initcmd> | ||
1721 | <initcmd> ::= "runlevel" | "runlevel" <level> | ||
1722 | */ | ||
1723 | struct telinit_parser | ||
1724 | { | ||
1725 | int argc; | ||
1726 | char **argv; | ||
1727 | int method; | ||
1728 | struct json_value *query; | ||
1729 | char *uri; | ||
1730 | void (*format) (struct shttp_connection *); | ||
1731 | }; | ||
1732 | |||
1733 | static struct id_fmt runlevel_fmt[] = { | ||
1734 | { "runlevel", json_string, id_fmt_string }, | ||
1735 | { "prevlevel", json_string, id_fmt_string }, | ||
1736 | { "bootstate", json_string, id_fmt_string }, | ||
1737 | { "initdefault", json_string, id_fmt_string }, | ||
1738 | { NULL } | ||
1739 | }; | ||
1740 | |||
1741 | static void | ||
1742 | telinit_format_runlevel (struct shttp_connection *conn) | ||
1743 | { | ||
1744 | struct id_fmt *fmt; | ||
1745 | |||
1746 | for (fmt = runlevel_fmt; fmt->name; fmt++) | ||
1747 | { | ||
1748 | struct json_value *v = shttp_getval (conn, fmt->name, fmt->type); | ||
1749 | if (v) | ||
1750 | { | ||
1751 | printf ("%s: ", fmt->name); | ||
1752 | fmt->format (v); | ||
1753 | putchar ('\n'); | ||
1754 | } | ||
1755 | } | ||
1756 | } | ||
1757 | |||
1758 | static char * | ||
1759 | telinit_get_token (struct telinit_parser *p) | ||
1760 | { | ||
1761 | if (p->argc == 0) | ||
1762 | return NULL; | ||
1763 | --p->argc; | ||
1764 | return *p->argv++; | ||
1765 | } | ||
1766 | |||
1767 | static void | ||
1768 | telinit_parse_runlevel (struct telinit_parser *p) | ||
1769 | { | ||
1770 | char *tok = telinit_get_token (p); | ||
1771 | |||
1772 | if (!tok) | ||
1773 | { | ||
1774 | p->method = METH_GET; | ||
1775 | p->format = telinit_format_runlevel; | ||
1776 | } | ||
1777 | else | ||
1778 | { | ||
1779 | p->method = METH_PUT; | ||
1780 | p->query = json_new_object (); | ||
1781 | json_object_set (p->query, "runlevel", json_new_string (tok)); | ||
1782 | p->format = NULL; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | static void | ||
1787 | telinit_parse (struct telinit_parser *p) | ||
1788 | { | ||
1789 | char *tok = telinit_get_token (p); | ||
1790 | |||
1791 | if (strcmp (tok, "runlevel") == 0) | ||
1792 | telinit_parse_runlevel (p); | ||
1793 | else | ||
1794 | { | ||
1795 | grecs_error (NULL, 0, _("unrecognized subcommand: %s"), tok); | ||