aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ctl.c64
-rw-r--r--src/pies.h9
-rw-r--r--src/piesctl.c136
-rw-r--r--src/sysvinit.c58
4 files changed, 243 insertions, 24 deletions
diff --git a/src/ctl.c b/src/ctl.c
index bc2f78d..6f50246 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -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
23struct control control; 22struct 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
446static void 445void
447json_object_set_string (struct json_value *obj, 446json_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
461static void 460void
462json_object_set_number (struct json_value *obj, char const *name, double val) 461json_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 *);
905static void res_programs (struct ctlio *, enum http_method, char const *, 904static void res_programs (struct ctlio *, enum http_method, char const *,
906 struct json_value *); 905 struct json_value *);
906static void res_runlevel (struct ctlio *, enum http_method, char const *,
907 struct json_value *);
908
909static int pred_sysvinit (void);
907 910
908struct ctlio_resource 911struct 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
917static struct ctlio_resource restab[] = { 921static 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
2020static int
2021pred_sysvinit (void)
2022{
2023 return init_process;
2024}
2025
2026static void
2027res_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
diff --git a/src/pies.h b/src/pies.h
index 1b77398..9fb87c6 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -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);
515void sysvinit_sysdep_begin (void); 516void sysvinit_sysdep_begin (void);
516void sysvinit_power (void); 517void sysvinit_power (void);
517 518
519void sysvinit_report (struct json_value *obj);
520int sysvinit_set_runlevel (int newlevel);
521
518extern char *sysvinit_environ_hint[]; 522extern char *sysvinit_environ_hint[];
519extern char *init_fifo; 523extern char *init_fifo;
520 524
@@ -578,3 +582,8 @@ struct control
578extern struct control control; 582extern struct control control;
579 583
580int ctl_open(void); 584int ctl_open(void);
585
586void json_object_set_string (struct json_value *obj,
587 char const *name, char const *fmt, ...);
588void 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 */
1723struct 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
1733static 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
1741static void
1742telinit_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
1758static char *
1759telinit_get_token (struct telinit_parser *p)
1760{
1761 if (p->argc == 0)
1762 return NULL;
1763 --p->argc;
1764 return *p->argv++;
1765}
1766
1767static void
1768telinit_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
1786static void
1787telinit_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);