aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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
@@ -885,14 +885,16 @@ method_decode (char const *method)
}
return METH_INVALID;
}
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_programs_select (struct ctlio *, enum http_method, char const *,
+ struct json_value *);
+static void res_programs_component (struct ctlio *, enum http_method,
+ char const *, struct json_value *);
struct ctlio_resource
{
char const *uri;
size_t uri_len;
int states;
@@ -900,13 +902,16 @@ struct ctlio_resource
char const *uri, struct json_value *);
};
static struct ctlio_resource restab[] = {
#define S(s) #s, (sizeof (#s)-1)
{ S(/instance), CTL_ADMIN_STATE, res_instance },
- { S(/programs), CTL_ADMIN_STATE|CTL_USER_STATE, res_programs },
+ { S(/programs/select), CTL_ADMIN_STATE|CTL_USER_STATE,
+ res_programs_select },
+ { S(/programs/component), CTL_ADMIN_STATE|CTL_USER_STATE,
+ res_programs_component },
{ NULL }
#undef S
};
static struct ctlio_resource *
find_resource (struct ctlio *io, const char *endpoint)
@@ -928,13 +933,16 @@ find_resource (struct ctlio *io, const char *endpoint)
}
static char *
json_extract (char *uri)
{
char *p = strrchr (uri, '/');
- if (p && strchr ("\"{[", p[1]))
+ if (p && (strchr ("\"{[", p[1])
+ || strcmp ("true", p + 1) == 0
+ || strcmp ("false", p + 1) == 0
+ || strcmp ("null", p + 1) == 0))
{
*p++ = 0;
return p;
}
return NULL;
}
@@ -1310,14 +1318,19 @@ res_instance (struct ctlio *io, enum http_method meth,
}
}
struct eval_env
{
struct ctlio *io;
+ int allowed_state;
struct pcond_node *cond;
+ int (*fun) (struct json_value *, struct prog *);
struct json_value *result;
+ size_t total_count;
+ size_t success_count;
+ size_t noperm_count;
};
static int
auth_prog (struct prog *prog, struct ctlio *io)
{
if (io->state == CTL_ADMIN_STATE)
@@ -1387,12 +1400,13 @@ format_idx (struct json_value *obj, const char *name, unsigned i,
#define FORMAT_IDX(io,n,a,i) \
format_idx (io, n, i, a, sizeof(a)/sizeof(a[0]))
enum pcond_type
{
+ pcond_false,
pcond_true,
pcond_component,
pcond_type,
pcond_mode,
pcond_status,
pcond_not,
@@ -1406,14 +1420,17 @@ struct pcond_node
union
{
char *tag;
enum pies_comp_mode mode;
enum prog_status status;
enum prog_type type;
- struct pcond_node *unary;
- struct pcond_node *binary[2];
+ struct
+ {
+ size_t c;
+ struct pcond_node **v;
+ } arg;
} v;
};
static struct pcond_node *
pcond_node_alloc (enum pcond_type t)
{
@@ -1429,36 +1446,43 @@ pcond_node_free (struct pcond_node *node)
{
if (!node)
return;
switch (node->type)
{
case pcond_not:
- pcond_node_free (node->v.unary);
- break;
-
case pcond_and:
case pcond_or:
- pcond_node_free (node->v.binary[0]);
- pcond_node_free (node->v.binary[1]);
+ {
+ size_t i;
+
+ for (i = 0; i < node->v.arg.c; i++)
+ pcond_node_free (node->v.arg.v[i]);
+ }
+ grecs_free (node->v.arg.v);
break;
default:
break;
}
grecs_free (node);
}
static int
pcond_eval (struct pcond_node *node, struct prog *p)
{
+ size_t i;
+
if (!node)
return 0;
switch (node->type)
{
case pcond_true:
return 1;
+
+ case pcond_false:
+ return 0;
case pcond_component:
return strcmp (p->tag, node->v.tag) == 0;
case pcond_type:
return p->type == node->v.type;
@@ -1467,23 +1491,25 @@ pcond_eval (struct pcond_node *node, struct prog *p)
return IS_COMPONENT (p) && p->v.p.comp->mode == node->v.mode;
case pcond_status:
return IS_COMPONENT (p) && p->v.p.status == node->v.status;
case pcond_not:
- return !pcond_eval (node->v.unary, p);
+ return !pcond_eval (node->v.arg.v[0], p);
case pcond_and:
- if (!pcond_eval (node->v.binary[0], p))
- return 0;
- return pcond_eval (node->v.binary[1], p);
+ for (i = 0; i < node->v.arg.c; i++)
+ if (!pcond_eval (node->v.arg.v[i], p))
+ return 0;
+ return 1;
case pcond_or:
- if (pcond_eval (node->v.binary[0], p))
- return 1;
- return pcond_eval (node->v.binary[1], p);
+ for (i = 0; i < node->v.arg.c; i++)
+ if (pcond_eval (node->v.arg.v[i], p))
+ return 1;
+ return 0;
default:
abort ();
}
}
@@ -1557,42 +1583,53 @@ pcond_conv_status (struct pcond_node *node, struct json_value *arg,
}
static int
pcond_conv_not (struct pcond_node *node, struct json_value *arg,
struct ctlio *io)
{
- return json_to_pcond (io, arg, &node->v.unary);
+ node->v.arg.v = grecs_calloc (1, sizeof (node->v.arg.v[0]));
+ node->v.arg.c = 1;
+ return json_to_pcond (io, arg, &node->v.arg.v[0]);
}
static int
pcond_conv_binary (struct pcond_node *node, struct json_value *arg,
struct ctlio *io)
{
- struct json_value *v;
+ size_t i, n;
if (arg->type != json_arr)
{
ctlio_reply (io, 400, "arguments to binary opcode must be array");
return -1;
}
- json_array_get (arg, 0, &v);
- if (json_to_pcond (io, v, &node->v.binary[0]))
- return -1;
- json_array_get (arg, 1, &v);
- if (json_to_pcond (io, v, &node->v.binary[1]))
- return -1;
+
+ n = json_array_size (arg);
+ node->v.arg.v = grecs_calloc (n, sizeof (node->v.arg.v[0]));
+ node->v.arg.c = n;
+
+ for (i = 0; i < n; i++)
+ {
+ struct json_value *v;
+ if (json_array_get (arg, i, &v) == 0)
+ {
+ if (json_to_pcond (io, v, &node->v.arg.v[i]))
+ return -1;
+ }
+ }
return 0;
}
struct pcond_conv {
char *term;
int (*handler) (struct pcond_node *, struct json_value *arg, struct ctlio *);
};
static struct pcond_conv pcond_conv[] = {
[pcond_true] = { "true", NULL },
+ [pcond_false] = { "false", NULL },
[pcond_component] = { "component", pcond_conv_component },
[pcond_type] = { "type", pcond_conv_type },
[pcond_mode] = { "mode", pcond_conv_mode },
[pcond_status] = { "status", pcond_conv_status },
[pcond_not] = { "not", pcond_conv_not },
[pcond_and] = { "and", pcond_conv_binary },
@@ -1666,16 +1703,13 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
{
case json_null:
*pnode = NULL;
break;
case json_bool:
- if (val->v.b)
- *pnode = pcond_node_alloc (pcond_true);
- else
- *pnode = NULL;
+ *pnode = pcond_node_alloc (val->v.b ? pcond_true : pcond_false);
break;
case json_number:
case json_string:
case json_arr:
ctlio_reply (io, 400, "bad conditional");
@@ -1684,32 +1718,40 @@ json_to_pcond (struct ctlio *io, struct json_value *val,
case json_object:
return object_to_cond (io, val, pnode);
}
return 0;
}
-static struct json_value *prog_serialize (struct prog *prog);
-
static int
selector (struct prog *prog, void *data)
{
struct eval_env *env = data;
- if (auth_prog (prog, env->io) && pcond_eval (env->cond, prog))
- json_array_append (env->result, prog_serialize (prog));
+ if (pcond_eval (env->cond, prog))
+ {
+ if (auth_prog (prog, env->io) & env->allowed_state)
+ {
+ struct json_value *status = json_new_object ();
+ json_object_set_string (status, "tag", prog->tag);
+ if (env->fun (status, prog) == 0)
+ env->success_count++;
+ json_array_append (env->result, status);
+ env->total_count++;
+ }
+ else
+ env->noperm_count++;
+ }
return 0;
}
static struct json_value *
-prog_serialize (struct prog *prog)
+prog_serialize (struct json_value *ret, struct prog *prog)
{
- struct json_value *ret = json_reply_create ();
struct json_value *v;
size_t i;
- json_object_set_string (ret, "tag", prog->tag);
FORMAT_IDX (ret, "type", pies_type_str, prog->type);
switch (prog->type)
{
case TYPE_COMPONENT:
FORMAT_IDX (ret, "mode", pies_comp_mode_str, prog->v.p.comp->mode);
FORMAT_IDX (ret, "status", pies_status_str, prog->v.p.status);
@@ -1739,101 +1781,199 @@ prog_serialize (struct prog *prog)
case TYPE_COMMAND:
json_object_set_string (ret, "command", "%s", prog->v.c.command);
}
return ret;
}
+
+static int
+fun_list (struct json_value *result, struct prog *prog)
+{
+ prog_serialize (result, prog);
+ return 0;
+}
-static void
-component_stop (struct ctlio *io, struct prog *prog)
+static int
+fun_stop (struct json_value *result, struct prog *prog)
{
if (prog->v.p.comp->flags & CF_DISABLED)
- ctlio_reply (io, 409, "Already stopped");
+ {
+ json_object_set_string (result, "status", "ER");
+ json_object_set_string (result, "error_message", "already stopped");
+ return 1;
+ }
else
{
progman_stop_component (prog);
prog->v.p.comp->flags |= CF_DISABLED;
- ctlio_reply (io, 200, "Component stopped");
+ json_object_set_string (result, "status", "OK");
}
+ return 0;
}
-static void
-component_start (struct ctlio *io, struct prog *prog)
+static int
+fun_start (struct json_value *result, struct prog *prog)
{
if (prog->v.p.comp->flags & CF_DISABLED)
{
prog->v.p.comp->flags &= ~CF_DISABLED;
prog->v.p.status = status_enabled;
- kill (getpid (), SIGALRM);
- ctlio_reply (io, 200, "Component started");
+ json_object_set_string (result, "status", "OK");
}
else
- ctlio_reply (io, 409, "Already running");
+ {
+ json_object_set_string (result, "status", "ER");
+ json_object_set_string (result, "error_message", "already running");
+ return 1;
+ }
+ return 0;
+}
+
+static int
+fun_restart (struct json_value *result, struct prog *prog)
+{
+ progman_stop_component (prog);
+ json_object_set_string (result, "status", "OK");
+ return 0;
}
static void
-res_programs (struct ctlio *io, enum http_method meth,
- char const *uri, struct json_value *json)
+select_and_run (struct ctlio *io, struct pcond_node *cond,
+ enum http_method meth)
{
- if (meth == METH_GET)
+ struct eval_env env;
+ int wakeup = 0;
+
+ memset (&env, 0, sizeof (env));
+ env.io = io;
+ env.cond = cond;
+ env.fun = NULL;
+ env.result = json_new_array ();
+
+ switch (meth)
{
- struct eval_env env;
-
- env.io = io;
- if (json_to_pcond (io, json, &env.cond))
- return;
- env.result = json_new_array ();
- progman_foreach (selector, &env);
- pcond_node_free (env.cond);
- io->output.reply = env.result;
- io->code = 200;
+ case METH_GET:
+ env.allowed_state = CTL_USER_STATE | CTL_ADMIN_STATE;
+ env.fun = fun_list;
+ break;
+
+ case METH_DELETE:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_stop;
+ break;
+
+ case METH_PUT:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_start;
+ wakeup = 1;
+ break;
+
+ case METH_POST:
+ env.allowed_state = CTL_ADMIN_STATE;
+ env.fun = fun_restart;
+ wakeup = 1;
+ break;
+
+ default:
+ ctlio_reply (io, 405, NULL);
}
- else if (meth == METH_DELETE || meth == METH_PUT)
+
+ if (env.fun)
{
- if (!uri)
- ctlio_reply (io, 404, NULL);
+ env.result = json_new_array ();
+ progman_foreach (selector, &env);
+
+ if (env.success_count == 0 && env.noperm_count)
+ ctlio_reply (io, 403, NULL);
else
{
- struct prog *prog = progman_locate (uri);
- if (!prog)
- ctlio_reply (io, 404, NULL);
- else if (auth_prog (prog, io) & CTL_ADMIN_STATE)
- {
- if (!IS_COMPONENT (prog))
- ctlio_reply (io, 404, "Not a component");
- else if (meth == METH_DELETE)
- {
- component_stop (io, prog);
- }
- else
- {
- component_start (io, prog);
- }
- }
- else
- ctlio_reply (io, 403, NULL);
+ if (env.success_count && wakeup)
+ progman_wake_sleeping (1);
+ io->output.reply = env.result;
+ io->code = 200;
}
}
- else if (meth == METH_POST)
+}
+
+static void
+res_programs_select (struct ctlio *io, enum http_method meth,
+ char const *uri, struct json_value *json)
+{
+ struct pcond_node *cond;
+
+ if (uri)
+ {
+ ctlio_reply (io, 404, NULL);
+ return;
+ }
+
+ if (json_to_pcond (io, json, &cond))
+ return;
+ select_and_run (io, cond, meth);
+ pcond_node_free (cond);
+}
+
+static void
+res_programs_component (struct ctlio *io, enum http_method meth,
+ char const *uri, struct json_value *json)
+{
+ struct pcond_node *node = pcond_node_alloc (pcond_type);
+ node->v.type = TYPE_COMPONENT;
+
+ if (meth != METH_POST)
{
- if (json->type != json_arr)
+ if (uri)
{
- ctlio_reply (io, 400, NULL);
+ struct pcond_node *np;
+ np = pcond_node_alloc (pcond_and);
+ np->v.arg.c = 2;
+ np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
+ np->v.arg.v[0] = node;
+ np->v.arg.v[1] = pcond_node_alloc (pcond_component);
+ np->v.arg.v[1]->v.tag = (char*) uri + 1;
+ node = np;
}
+ }
+ else
+ {
+ if (json->type != json_arr)
+ ctlio_reply (io, 400, NULL);
else
{
size_t i, n;
+ struct pcond_node *or_cond, *np;
n = json_array_size (json);
+ or_cond = pcond_node_alloc (pcond_or);
+ or_cond->v.arg.v = grecs_calloc (n, sizeof (or_cond->v.arg.v[0]));
+ or_cond->v.arg.c = n;
+
for (i = 0; i < n; i++)
{
struct json_value *v;
if (json_array_get (json, i, &v) == 0 && v->type == json_string)
- progman_stop_tag (v->v.s);
+ {
+ or_cond->v.arg.v[i] = pcond_node_alloc (pcond_component);
+ or_cond->v.arg.v[i]->v.tag = v->v.s;
+ }
+ else
+ {
+ ctlio_reply (io, 400, "all elements must be string");
+ pcond_node_free (or_cond);
+ pcond_node_free (node);
+ return;
+ }
}
- kill (getpid (), SIGALRM);
+
+ np = pcond_node_alloc (pcond_and);
+ np->v.arg.c = 2;
+ np->v.arg.v = grecs_calloc (np->v.arg.c, sizeof (np->v.arg.v[0]));
+ np->v.arg.v[0] = node;
+ np->v.arg.v[1] = or_cond;
+
+ node = np;
}
- ctlio_reply (io, 200, "Done");
}
- else
- ctlio_reply (io, 405, NULL);
-}
+
+ select_and_run (io, node, meth);
+ pcond_node_free (node);
+}
diff --git a/src/piesctl.c b/src/piesctl.c
index 8c4e2e1..4b448ad 100644
--- a/src/piesctl.c
+++ b/src/piesctl.c
@@ -1225,21 +1225,12 @@ peek_token (struct pcond_parser_state *state)
if (state->argc == 0)
return NULL;
return *state->argv;
}
static struct json_value *
-json_new_array2 (struct json_value *a, struct json_value *b)
-{
- struct json_value *ret = json_new_array ();
- json_array_append (ret, a);
- json_array_append (ret, b);
- return ret;
-}
-
-static struct json_value *
json_encode_op (char const *op, struct json_value *arg)
{
struct json_value *ret = json_new_object ();
json_object_set (ret, "op", json_new_string (op));
json_object_set (ret, "arg", arg);
return ret;
@@ -1297,46 +1288,89 @@ pcond_parse_unary (struct pcond_parser_state *state, struct json_value **ret)
grecs_error (NULL, 0, _("parse error at %s"), term);
exit (EX_USAGE);
}
}
}
+static int
+is_op (struct json_value *val, char const *opcode)
+{
+ struct json_value *op;
+
+ if (json_object_get (val, "op", &op) == 0)
+ {
+ if (op->type == json_string && strcmp (op->v.s, opcode) == 0)
+ return 1;
+ }
+ return 0;
+}
+
+static void
+binop_append_optimized (struct json_value *ar, struct json_value *val,
+ char const *opcode)
+{
+ if (is_op (val, opcode))
+ {
+ size_t i, n;
+ struct json_value *arg;
+
+ json_object_get (val, "arg", &arg);
+ n = json_array_size (arg);
+ for (i = 0; i < n; i++)
+ {
+ struct json_value *elt;
+ json_array_get (arg, i, &elt);
+ json_array_set (arg, i, NULL);
+ json_array_append (ar, elt);
+ }
+ json_value_free (val);
+ }
+ else
+ json_array_append (ar, val);
+}
+
static void
pcond_parse_and (struct pcond_parser_state *state, struct json_value **ret)
{
char const *token;
- struct json_value *left, *right;
+ struct json_value *left, *right, *ar;
pcond_parse_unary (state, &left);
token = peek_token (state);
if (!token || strcmp (token, "and"))
{
*ret = left;
return;
}
next_token (state);
pcond_parse_and (state, &right);
- *ret = json_encode_op (token, json_new_array2 (left, right));
+ ar = json_new_array ();
+ json_array_append (ar, left);
+ binop_append_optimized (ar, right, token);
+ *ret = json_encode_op (token, ar);
}
static void
pcond_parse_or (struct pcond_parser_state *state, struct json_value **ret)
{
char const *token;
- struct json_value *left, *right;
+ struct json_value *left, *right, *ar;
pcond_parse_and (state, &left);
token = peek_token (state);
if (!token || strcmp (token, "or"))
{
*ret = left;
return;
}
next_token (state);
pcond_parse_or (state, &right);
- *ret = json_encode_op (token, json_new_array2 (left, right));
+ ar = json_new_array ();
+ json_array_append (ar, left);
+ binop_append_optimized (ar, right, token);
+ *ret = json_encode_op (token, ar);
}
static struct json_value *
parse_condition (int argc, char **argv)
{
struct json_value *val = NULL;
@@ -1366,66 +1400,53 @@ static void
acc_writer (void *closure, char const *text, size_t len)
{
grecs_txtacc_grow ((struct grecs_txtacc *)closure, text, len);
}
static char *
-json_to_string (struct json_value *val)
-{
- struct grecs_txtacc *acc = grecs_txtacc_create ();
- struct json_format fmt = {
- .indent = 0,
- .precision = 0,
- .write = acc_writer,
- .data = acc
- };
- char *ret;
-
- json_format_value (val, &fmt);
- grecs_txtacc_grow_char (acc, 0);
- ret = grecs_txtacc_finish (acc, 1);
- grecs_txtacc_free (acc);
-
- return ret;
-}
-
-static char *
-parse_condition_to_uri (char const *base, int argc, char **argv)
+parse_condition_to_uri (char const *base, int argc, char **argv, int mandatory)
{
char *ret = NULL;
struct grecs_txtacc *acc;
struct json_value *val;
+ if (mandatory && argc == 1)
+ {
+ grecs_error (NULL, 0, _("condition must be specified"));
+ exit (EX_USAGE);
+ }
+
acc = grecs_txtacc_create ();
- grecs_txtacc_grow_string (acc, base);
+ if (base)
+ grecs_txtacc_grow_string (acc, base);
val = parse_condition (argc, argv);
if (val)
{
struct json_format fmt = {
.indent = 0,
.precision = 0,
.write = acc_writer,
.data = acc
};
- grecs_txtacc_grow_char (acc, '/');
+ if (base)
+ grecs_txtacc_grow_char (acc, '/');
json_format_value (val, &fmt);
json_value_free (val);
}
grecs_txtacc_grow_char (acc, 0);
ret = grecs_txtacc_finish (acc, 1);
grecs_txtacc_free (acc);
-
return ret;
}
static int
com_list (struct shttp_connection *conn, int argc, char **argv)
{
- char *uri = parse_condition_to_uri ("/programs", argc, argv);
+ char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 0);
shttp_io_init (&conn->req);
shttp_process (conn, METH_GET, uri);
grecs_free (uri);
if (!dump && conn->result && conn->result->type == json_arr)
{
@@ -1440,74 +1461,103 @@ com_list (struct shttp_connection *conn, int argc, char **argv)
}
}
return 0;
}
static int
-com_stop (struct shttp_connection *conn, int argc, char **argv)
+json_object_get_type (struct json_value *obj, char const *name,
+ enum json_value_type type, struct json_value **ret)
{
- char *buf = NULL;
- size_t len = 0;
- size_t i;
-
- for (i = 1; i < argc; i++)
+ struct json_value *v;
+ int rc = json_object_get (obj, name, &v);
+ if (rc)
+ return rc;
+ if (v->type != type)
{
- struct json_value *v;
- grecs_asprintf (&buf, &len, "/programs/%s", argv[i]);
- shttp_io_init (&conn->req);
- shttp_process (conn, METH_DELETE, buf);
- v = shttp_getval (conn, "error_message", json_string);
- if (v)
- printf ("%s: %s\n", argv[i], v->v.s);
+ errno = EACCES;
+ return -1;
}
- free (buf);
+ *ret = v;
+ return 0;
+}
+
+static void
+shttp_print_response_status (struct shttp_connection *conn)
+{
+ if (!dump && conn->result && conn->result->type == json_arr)
+ {
+ size_t i, n = json_array_size (conn->result);
+
+ for (i = 0; i < n; i++)
+ {
+ struct json_value *elt, *v;
+
+ if (json_array_get (conn->result, i, &elt) == 0)
+ {
+ if (elt->type != json_object)
+ {
+ grecs_error (NULL, 0, _("%lu: unexpected value type"),
+ (unsigned long) i);
+ print_json (stderr, v);
+ continue;
+ }
+ if (json_object_get_type (elt, "tag", json_string, &v) == 0)
+ {
+ printf ("%s: ", v->v.s);
+ if (json_object_get_type (elt, "status", json_string, &v)
+ == 0)
+ {
+ if (strcmp (v->v.s, "OK") == 0)
+ fputs (v->v.s, stdout);
+ else if (json_object_get_type (elt, "error_message",
+ json_string, &v) == 0)
+ fputs (v->v.s, stdout);
+ else
+ printf ("unknown error");
+ }
+ else
+ printf ("unknown status");
+ fputc ('\n', stdout);
+ }
+ }
+ }
+ }
+}
+
+static int
+com_stop (struct shttp_connection *conn, int argc, char **argv)
+{
+ char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1);
+
+ shttp_io_init (&conn->req);
+ shttp_process (conn, METH_DELETE, uri);
+ grecs_free (uri);
+ shttp_print_response_status (conn);
return 0;
}
static int
com_start (struct shttp_connection *conn, int argc, char **argv)
{
- char *buf = NULL;
- size_t len = 0;
- size_t i;
-
- for (i = 1; i < argc; i++)
- {
- struct json_value *v;
- grecs_asprintf (&buf, &len, "/programs/%s", argv[i]);
- shttp_io_init (&conn->req);
- shttp_process (conn, METH_PUT, buf);
- v = shttp_getval (conn, "error_message", json_string);
- if (v)
- printf ("%s: %s\n", argv[i], v->v.s);
- }
- free (buf);
+ char *uri = parse_condition_to_uri ("/programs/select", argc, argv, 1);
+
+ shttp_io_init (&conn->req);
+ shttp_process (conn, METH_PUT, uri);
+ grecs_free (uri);
+ shttp_print_response_status (conn);
return 0;
}
static int
com_restart (struct shttp_connection *conn, int argc, char **argv)
{
- struct json_value *val = json_new_array ();
- size_t i;
-
- if (argc == 1)
- {
- grecs_error (NULL, 0, _("missing component names"));
- exit (EX_USAGE);
- }
- for (i = 1; i < argc; i++)
- json_array_append (val, json_new_string (argv[i]));
-
shttp_io_init (&conn->req);
- conn->req.content = json_to_string (val);
+ conn->req.content = parse_condition_to_uri (NULL, argc, argv, 1);
conn->req.content_length = strlen (conn->req.content);
- json_value_free (val);
-
- shttp_process (conn, METH_POST, "/programs");
-
+ shttp_process (conn, METH_POST, "/programs/select");
+ shttp_print_response_status (conn);
return 0;
}
static int
com_id (struct shttp_connection *conn, int argc, char **argv)
{
@@ -1582,16 +1632,16 @@ struct comtab
char const *argdoc;
char const *docstr;
ctlcom_t command;
};
static struct comtab comtab[] = {
- { "list", N_("[EXPR]"), N_("list configured components"), com_list },
- { "stop", N_("TAG [TAG...]"), N_("stop components"), com_stop },
- { "start", N_("TAG [TAG...]"), N_("start components"), com_start },
- { "restart", N_("TAG [TAG...]"), N_("restart components"), com_restart },
+ { "list", N_("[CONDITION]"), N_("list configured components"), com_list },
+ { "stop", N_("CONDITION"), N_("stop components"), com_stop },
+ { "start", N_("CONDITION"), N_("start components"), com_start },
+ { "restart", N_("CONDITION"), N_("restart components"), com_restart },
{ "id", N_("[KEYWORDS...]"),
N_("show info about the running GNU Pies instance"),
com_id },
{ "shutdown", NULL, N_("stop running pies instance"), com_shutdown },
{ "reboot", NULL, N_("restart pies instance"), com_reboot },
{ NULL }
@@ -1636,13 +1686,13 @@ find_command (char const *name)
static void
command_help (FILE *fp)
{
struct comtab *cp;
- fputs (_("Available commands are:"), fp);
+ fputs (_("Available commands with their arguments are:"), fp);
fputc ('\n', fp);
fputc ('\n', fp);
for (cp = comtab; cp->name; cp++)
{
fputs (cp->name, fp);
@@ -1652,12 +1702,30 @@ command_help (FILE *fp)
fputs (gettext (cp->argdoc), fp);
}
fputc ('\n', fp);
fprintf (fp, " %s\n", gettext (cp->docstr));
}
fputc ('\n', fp);
+ fputs (_("Condition is defined as:"), fp);
+ fputc ('\n', fp);
+ fputc ('\n', fp);
+ fputs ("\
+ <condition> ::= <disjunction>\n\
+ <disjunction> ::= <conjunction> | <conjunction> \"or\" <disjunction>\n\
+ <conjunction> ::= <unary> | <unary> \"and\" <conjunction>\n\
+ <unary> ::= <term> | \"not\" <condition> | \"(\" <condition> \")\"\n\
+ <term> ::= \"all\" | <keyword> <value>\n\
+ <keyword> ::= \"type\" | \"mode\" | \"status\" | \"component\"\n\
+ <value> ::= <word> | <quoted-string>\n\
+ <word> ::= <printable> | <word> <printable>\n\
+ <printable> ::= \"A\" - \"Z\" | \"a\" - \"z\" | \"0\" - \"9\" |\n\
+ \"_\" | \".\" | \"*\" | \":\" | \"@\" | \"[\" | \"]\" | \"-\" | \"/\"\n\
+ <quoted-string> ::= \"\"\" <string> \"\"\"\n\
+ <string> ::= <char> | <string> <char>\n\
+ <char> ::= <any character except \"\\\" and \"\"\"> | \"\\\\\" | \"\\\"\"\n\n", fp);
+
}
int
main (int argc, char **argv)
{
int i, rc;

Return to:

Send suggestions and report system problems to the System administrator.