aboutsummaryrefslogtreecommitdiff
path: root/src/ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctl.c')
-rw-r--r--src/ctl.c126
1 files changed, 89 insertions, 37 deletions
diff --git a/src/ctl.c b/src/ctl.c
index 615ffef..cc16912 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies.
- Copyright (C) 2007-2020 Sergey Poznyakoff
+ Copyright (C) 2007-2023 Sergey Poznyakoff
GNU Pies is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -358,7 +358,13 @@ input_append (struct input *inp, char c)
logmsg (LOG_ERR, _("protocol error"));
return 400;
}
- inp->input_state = is_content;
+ if (inp->input_content_length == 0)
+ {
+ inp->input_state = is_end;
+ return 200;
+ }
+ else
+ inp->input_state = is_content;
}
else
{
@@ -479,13 +485,13 @@ json_object_set_bool (struct json_value *obj, char const *name, int val)
}
static struct json_value *
-json_error_reply_create (const char *msg)
+json_error_reply_create (int http_code, const char *msg)
{
struct json_value *val;
val = json_reply_create ();
- json_object_set_string (val, "status", "ER");
- json_object_set_string (val, "error_message", "%s", msg);
+ json_object_set_string (val, "status", http_code < 300 ? "OK" : "ER");
+ json_object_set_string (val, "message", "%s", msg);
return val;
}
@@ -607,11 +613,11 @@ ctlio_reply (struct ctlio *io, int code, const char *fmt, ...)
grecs_vasprintf (&str, &len, fmt, ap);
va_end (ap);
- io->output.reply = json_error_reply_create (str);
+ io->output.reply = json_error_reply_create (code, str);
grecs_free (str);
}
else
- io->output.reply = json_error_reply_create (http_text (code));
+ io->output.reply = json_error_reply_create (code, http_text (code));
}
static void
@@ -918,6 +924,8 @@ 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_alive (struct ctlio *, enum http_method, char const *,
+ struct json_value *);
static void res_conf (struct ctlio *, enum http_method, char const *,
struct json_value *);
@@ -946,6 +954,8 @@ static struct ctlio_resource restab[] = {
{ S(/conf), CTL_ADMIN_STATE, NULL, res_conf },
{ S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, NULL,
res_programs },
+ { S(/alive), CTL_ADMIN_STATE|CTL_USER_STATE, NULL,
+ res_alive },
#if PIES_SYSVINIT_ENABLED
{ S(/runlevel), CTL_ADMIN_STATE, pred_sysvinit, res_runlevel },
{ S(/environ), CTL_ADMIN_STATE, pred_sysvinit, res_environ },
@@ -1274,7 +1284,7 @@ ctl_accept (int socket, void *data)
io = ctlio_create ();
io->addr = addr;
io->addrlen = addrlen;
- register_socket (fd, NULL, ctlwr, NULL, io);
+ register_socket (fd, NULL, ctlwr, NULL, io, NULL);
return 0;
}
@@ -1301,7 +1311,7 @@ ctl_open (void)
return -1;
}
- register_socket (fd, ctl_accept, NULL, NULL, NULL);
+ register_socket (fd, ctl_accept, NULL, NULL, NULL, NULL);
return 0;
}
@@ -1429,9 +1439,6 @@ auth_prog (struct prog *prog, struct ctlio *io)
return CTL_ADMIN_STATE|CTL_USER_STATE;
switch (prog->type)
{
- case TYPE_REDIRECTOR:
- prog = prog->v.r.master;
- /* FALL THROUGH */
case TYPE_COMPONENT:
if (prog->v.p.comp->adm_acl
&& check_acl (prog->v.p.comp->adm_acl,
@@ -1450,7 +1457,6 @@ auth_prog (struct prog *prog, struct ctlio *io)
static char * const pies_type_str[] = {
[TYPE_COMPONENT] = "component",
- [TYPE_REDIRECTOR] = "redirector",
[TYPE_COMMAND] = "command"
};
@@ -1899,15 +1905,11 @@ prog_serialize (struct json_value *ret, struct prog *prog)
prog->v.p.timestamp + SLEEPTIME);
v = json_new_array ();
- for (i = 0; i < prog->v.p.comp->argc; i++)
- json_array_append (v, json_new_string (prog->v.p.comp->argv[i]));
+ for (i = 0; i < prog->v.p.argc; i++)
+ json_array_append (v, json_new_string (prog->v.p.argv[i]));
json_object_set (ret, "argv", v);
break;
- case TYPE_REDIRECTOR:
- json_object_set_number (ret, "PID", prog->pid);
- break;
-
case TYPE_COMMAND:
json_object_set_string (ret, "command", "%s", prog->v.c.command);
}
@@ -1927,7 +1929,7 @@ fun_stop (struct json_value *result, struct prog *prog)
if (!prog->active)
{
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "already stopped");
+ json_object_set_string (result, "message", "already stopped");
}
else
{
@@ -1944,7 +1946,7 @@ fun_start (struct json_value *result, struct prog *prog)
if (!IS_COMPONENT (prog))
{
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "not a component");
+ json_object_set_string (result, "message", "not a component");
}
else
{
@@ -1969,15 +1971,14 @@ fun_start (struct json_value *result, struct prog *prog)
else
{
json_object_set_string (result, "status", "ER");
- /* FIXME: error message */
- json_object_set_string (result, "error_message",
- "can't open socket");
+ /* FIXME: detailed error message */
+ json_object_set_string (result, "message", "can't open socket");
}
break;
default:
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "already running");
+ json_object_set_string (result, "message", "already running");
return 0;
}
prog->active = 1;
@@ -1991,12 +1992,12 @@ fun_restart (struct json_value *result, struct prog *prog)
if (!IS_COMPONENT (prog))
{
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "not a component");
+ json_object_set_string (result, "message", "not a component");
}
else if (!prog->active)
{
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "not active");
+ json_object_set_string (result, "message", "not active");
}
else
{
@@ -2009,12 +2010,12 @@ fun_restart (struct json_value *result, struct prog *prog)
case status_listener:
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "not applicable");
+ json_object_set_string (result, "message", "not applicable");
break;
default:
json_object_set_string (result, "status", "ER");
- json_object_set_string (result, "error_message", "not running");
+ json_object_set_string (result, "message", "not running");
}
}
return 0;
@@ -2121,6 +2122,57 @@ res_programs (struct ctlio *io, enum http_method meth,
else
res_programs_select (io, meth, uri, json);
}
+
+static void
+res_alive (struct ctlio *io, enum http_method meth, char const *uri,
+ struct json_value *json)
+{
+ struct prog *prog;
+
+ if (!uri)
+ {
+ ctlio_reply (io, 403, NULL);
+ return;
+ }
+
+ prog = progman_locate (uri + 1);
+
+ if (prog && IS_COMPONENT (prog))
+ {
+ switch (prog->v.p.status)
+ {
+ case status_running:
+ case status_listener:
+ /* FIXME: Presumably these three fall into that category too:
+ status_stopped -- Component is stopped administratively
+ status_stopping -- Component is being stopped
+ status_finished -- A "once" or "startup" component has finished
+ */
+ ctlio_reply (io, 200, NULL);
+ break;
+
+ case status_sleeping:
+ {
+ time_t t;
+ char buf[80];
+
+ t = time (NULL) - prog->v.p.timestamp;
+ if (t <= SLEEPTIME)
+ {
+ snprintf (buf, sizeof buf, "%lu", SLEEPTIME - t);
+ output_set_header (&io->output, "Retry-After", buf);
+ }
+ }
+ /* fall through */
+
+ default:
+ ctlio_reply (io, 503, NULL);
+ break;
+ }
+ }
+ else
+ ctlio_reply (io, 404, NULL);
+}
#if PIES_SYSVINIT_ENABLED
static int
@@ -2161,7 +2213,7 @@ res_runlevel (struct ctlio *io, enum http_method meth,
else
{
json_object_set_string (io->output.reply, "status", "ER");
- json_object_set_string (io->output.reply, "error_message",
+ json_object_set_string (io->output.reply, "message",
"invalid runlevel value");
}
}
@@ -2174,13 +2226,13 @@ res_runlevel (struct ctlio *io, enum http_method meth,
* ["RUNLEVEL=3", "CONSOLE=/dev/tty", ...]
* GET /environ/NAME - Get value of variable NAME
* { "status":"OK", "value":"..." }
- * { "status":"ER", "error_message":"..." }
+ * { "status":"ER", "message":"..." }
* DELETE /environ/NAME - Unset variable
* { "status":"OK" }
- * { "status":"ER", "error_message":"..." }
+ * { "status":"ER", "message":"..." }
* PUT /environ/NAME=VALUE - Set variable
* { "status":"OK" }
- * { "status":"ER", "error_message":"..." }
+ * { "status":"ER", "message":"..." }
*/
static void
env_reply (struct ctlio *io, int ok, int rc)
@@ -2332,7 +2384,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json)
if (val->type != json_string)
{
json_object_set_string (io->output.reply, "status", "ER");
- json_object_set_string (io->output.reply, "error_message",
+ json_object_set_string (io->output.reply, "message",
"malformed request");
return;
}
@@ -2356,7 +2408,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json)
if (fails == n)
{
json_object_set_string (io->output.reply, "status", "ER");
- json_object_set_string (io->output.reply, "error_message",
+ json_object_set_string (io->output.reply, "message",
"no matching files found");
json_value_free (reply);
}
@@ -2365,7 +2417,7 @@ conf_delete_files (struct ctlio *io, struct json_value *json)
json_object_set_string (io->output.reply, "status", "OK");
if (fails)
{
- json_object_set_string (io->output.reply, "error_message",
+ json_object_set_string (io->output.reply, "message",
"some files not removed");
json_object_set (io->output.reply, "result", reply);
}
@@ -2431,7 +2483,7 @@ conf_reload (struct ctlio *io)
if (pies_reread_config ())
{
json_object_set_string (io->output.reply, "status", "ER");
- json_object_set_string (io->output.reply, "error_message",
+ json_object_set_string (io->output.reply, "message",
"configuration syntax error");
}
else

Return to:

Send suggestions and report system problems to the System administrator.