diff options
Diffstat (limited to 'src/ctl.c')
-rw-r--r-- | src/ctl.c | 126 |
1 files changed, 89 insertions, 37 deletions
@@ -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 |