summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2016-01-02 09:18:28 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2016-01-02 09:20:42 (GMT)
commit061afaf6385340f87bbeaa6d7e8ff6befa532551 (patch) (side-by-side diff)
tree7d42952187b6c035caba9c74cfb6cb8dfd651354
parent00e6c3c3ed06a258a02943fc49fa7c528025d747 (diff)
downloadpies-061afaf6385340f87bbeaa6d7e8ff6befa532551.tar.gz
pies-061afaf6385340f87bbeaa6d7e8ff6befa532551.tar.bz2
piesctl: Implement all basic commands, except "restart"
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--src/ctl.c4
-rw-r--r--src/piesctl-cl.opt8
-rw-r--r--src/piesctl.c338
3 files changed, 336 insertions, 14 deletions
diff --git a/src/ctl.c b/src/ctl.c
index ce13dab..cbc5fea 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies.
- Copyright (C) 2007-2013 Sergey Poznyakoff
+ Copyright (C) 2007-2016 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
@@ -1446,7 +1446,7 @@ res_programs (struct ctlio *io, enum http_method meth,
ctlio_reply (io, 409, "already running");
else
{
- 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");
diff --git a/src/piesctl-cl.opt b/src/piesctl-cl.opt
index 04ff051..a83616e 100644
--- a/src/piesctl-cl.opt
+++ b/src/piesctl-cl.opt
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies. -*- c -*-
- Copyright (C) 2008-2014 Sergey Poznyakoff
+ Copyright (C) 2008-2016 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
@@ -52,6 +52,12 @@ BEGIN
++verbose;
END
+OPTION(dump,d,,
+ [<dump obtained responsed verbatim>])
+BEGIN
+ ++dump;
+END
+
OPTION(url,u,URL,
[<connect to this socket>])
BEGIN
diff --git a/src/piesctl.c b/src/piesctl.c
index 0618caa..9c5ef8b 100644
--- a/src/piesctl.c
+++ b/src/piesctl.c
@@ -1,5 +1,5 @@
/* This file is part of GNU Pies.
- Copyright (C) 2015 Sergey Poznyakoff
+ Copyright (C) 2015, 2016 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
@@ -35,6 +35,7 @@
#include "progname.h"
#include "libpies.h"
#include "grecsasrt.h"
+#include "fprintftime.h"
struct pies_url *default_url; /* Control socket URL */
struct pies_url *url;
@@ -43,6 +44,7 @@ char *config_file;
char default_config_file[] = SYSCONFDIR "/piesctl.conf";
int preprocess_only;
int verbose;
+int dump;
static void config_help (void);
@@ -794,21 +796,29 @@ shttp_get_reply (struct shttp_connection *conn)
}
static void
-stderr_writer (void *closure, char const *text, size_t len)
+fp_writer (void *closure, char const *text, size_t len)
{
- fwrite (text, len, 1, stderr);
+ fwrite (text, len, 1, (FILE*) closure);
}
static void
-shttp_format_result (struct shttp_connection *conn)
+print_json (FILE *fp, struct json_value *v)
{
struct json_format fmt = {
.indent = 2,
.precision = 0,
- .write = stderr_writer,
+ .write = fp_writer,
+ .data = fp
};
+ json_format_value (v, &fmt);
+ fputc ('\n', fp);
+}
+
+static void
+shttp_format_result (struct shttp_connection *conn, FILE *fp)
+{
fprintf (stderr, "%s: raw JSON reply follows:\n", program_name);
- json_format_value (conn->result, &fmt);
+ print_json (fp, conn->result);
}
static void
@@ -821,7 +831,7 @@ shttp_fatal (struct shttp_connection *conn)
if (jv->type == json_string)
grecs_error (NULL, 0, "%s", jv->v.s);
else
- shttp_format_result (conn);
+ shttp_format_result (conn, stderr);
}
else
grecs_error (NULL, 0, "%s", conn->status_line[2]);
@@ -927,6 +937,8 @@ shttp_process (struct shttp_connection *conn, int method, char const *uri)
{
shttp_request_send (conn, method, uri);
shttp_get_reply (conn);
+ if (dump && conn->result)
+ shttp_format_result (conn, stdout);
if (conn->resp.code / 100 == 2)
return;
if (conn->resp.code == 401 && isatty (fileno (stdin)))
@@ -936,24 +948,274 @@ shttp_process (struct shttp_connection *conn, int method, char const *uri)
}
}
+static struct json_value *
+shttp_getval (struct shttp_connection *conn, char const *name,
+ enum json_value_type type)
+{
+ struct json_value *p = NULL;
+
+ switch (json_object_get (conn->result, name, &p))
+ {
+ case 0:
+ if (p->type != type)
+ {
+ grecs_error (NULL, 0, _("\"%s\" has wrong type"), name);
+ p = NULL;
+ }
+ break;
+
+ case 1:
+ grecs_error (NULL, 0, _("no \"%s\" member"), name);
+ break;
+
+ default:
+ grecs_error (NULL, errno, _("can't get value of \"%s\""), name);
+ }
+ return p;
+}
+
+struct kwtrans
+{
+ char const *name;
+ int c;
+};
+
+struct kwtrans mode_trans[] = {
+ { "exec", 'C' },
+ { "accept", 'A' },
+ { "inetd", 'I' },
+ { "pass_fd", 'P' },
+ { "wait", 'W' },
+ { "once", 'c' },
+ { "boot", 'B' },
+ { "bootwait", 'w' },
+ { "powerfail", 'F' },
+ { "powerwait", 'f' },
+ { "powerokwait", 'o' },
+ { "ctrlaltdel", '3' },
+ { "ondemand", 'D' },
+ { "sysinit", 'i' },
+ { "powerfailnow", 'n' },
+ { "kbrequest", 'k' },
+ { NULL }
+};
+
+struct kwtrans status_trans[] = {
+ { "enabled", 'R' },
+ { "disabled", 'D' },
+ { "listener", 'L' },
+ { "sleeping", 's' },
+ { "stopping", 'S' },
+ { "finished", 'f' },
+ { NULL }
+};
+
+static int
+kwtoc (char const *s, struct kwtrans const *trans)
+{
+ for (; trans->name; trans++)
+ {
+ if (strcmp (trans->name, s) == 0)
+ return trans->c;
+ }
+ return '-';
+}
+
+static struct json_value *
+getval (struct json_value *v, char const *name, enum json_value_type type,
+ int optional)
+{
+ struct json_value *p = NULL;
+
+ switch (json_object_get (v, name, &p))
+ {
+ case 0:
+ if (p->type != type)
+ {
+ grecs_error (NULL, 0, _("\"%s\" has wrong type"), name);
+ p = NULL;
+ }
+ break;
+
+ case 1:
+ if (!optional)
+ grecs_error (NULL, 0, _("no \"%s\" member"), name);
+ break;
+
+ default:
+ grecs_error (NULL, errno, _("can't get value of \"%s\""), name);
+ }
+ return p;
+}
+
+static void
+print_comp (FILE *fp, struct json_value *v, size_t n)
+{
+ struct json_value *p;
+ char const *type;
+ char fbuf[5];
+ int fidx = 0;
+ int status = -1;
+
+ if (v->type != json_object)
+ {
+ grecs_error (NULL, 0, _("%lu: unexpected value type"),
+ (unsigned long) n);
+ print_json (fp, v);
+ return;
+ }
+
+ p = getval (v, "type", json_string, 0);
+ if (!p)
+ {
+ print_json (fp, v);
+ return;
+ }
+ type = p->v.s;
+
+ p = getval (v, "tag", json_string, 0);
+ if (!p)
+ {
+ print_json (fp, v);
+ return;
+ }
+
+ fprintf (fp, "%-16s ", p->v.s);
+
+ if (strcmp (type, "component") == 0)
+ {
+ p = getval (v, "mode", json_string, 0);
+ if (v)
+ fbuf[fidx++] = kwtoc (p->v.s, mode_trans);
+ else
+ fbuf[fidx++] = '-';
+ p = getval (v, "status", json_string, 0);
+ if (p)
+ fbuf[fidx++] = status = kwtoc (p->v.s, status_trans);
+ else
+ fbuf[fidx++] = '-';
+ }
+ else if (strcmp (type, "redirector") == 0)
+ {
+ fbuf[fidx++] = 'R';
+ }
+ else if (strcmp (type, "command") == 0)
+ {
+ fbuf[fidx++] = 'E';
+ }
+ else
+ {
+ fbuf[fidx++] = '-';
+ }
+
+ fbuf[fidx++] = 0;
+ fprintf (fp, "%-8.8s ", fbuf);
+
+ if (strcmp (type, "component") == 0)
+ {
+ p = getval (v, "PID", json_number, 1);
+ if (p)
+ fprintf (fp, "%10.0f ", p->v.n);
+ else if (status == 'L' /* listener */
+ && (p = getval (v, "URL", json_string, 1)))
+ fprintf (fp, "%-10s ", p->v.s);
+ else
+ fprintf (fp, "%-10s ", "N/A");
+
+ if (status == 's') /* sleeping */
+ {
+ p = getval (v, "wakeup-time", json_number, 0);
+ if (p)
+ {
+ time_t t = (time_t) p->v.n;
+ fprintftime (fp, "%H:%M:%S", localtime (&t), 0, 0);
+ }
+ }
+
+ p = getval (v, "argv", json_arr, 0);
+ if (p)
+ {
+ size_t i, n = json_array_size (p);
+
+ for (i = 0; i < n; i++)
+ {
+ struct json_value *elt;
+ if (json_array_get (p, i, &elt) == 0)
+ fprintf (fp, " %s", elt->v.s);
+ }
+ }
+ }
+ else if (strcmp (type, "redirector") == 0)
+ {
+ p = getval (v, "PID", json_number, 0);
+ if (p)
+ fprintf (fp, "%10.0f ", p->v.n);
+ }
+ else if (strcmp (type, "command") == 0)
+ {
+ p = getval (v, "command", json_string, 0);
+ if (p)
+ fprintf (fp, "%s", p->v.s);
+ }
+ fputc ('\n', fp);
+}
+
static int
com_list (struct shttp_connection *conn, int argc, char **argv)
{
shttp_process (conn, METH_GET, "/programs");
+ 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 *v;
+
+ if (json_array_get (conn->result, i, &v) == 0)
+ print_comp (stdout, v, i);
+ }
+ }
return 0;
}
static int
com_stop (struct shttp_connection *conn, int argc, char **argv)
{
- abort ();
+ 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_process (conn, METH_DELETE, buf);
+ v = shttp_getval (conn, "error_message", json_string);
+ if (v)
+ printf ("%s: %s\n", argv[i], v->v.s);
+ }
+ free (buf);
return 0;
}
static int
com_start (struct shttp_connection *conn, int argc, char **argv)
{
- abort ();
+ 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_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);
return 0;
}
@@ -965,16 +1227,64 @@ com_restart (struct shttp_connection *conn, int argc, char **argv)
}
static int
+com_id (struct shttp_connection *conn, int argc, char **argv)
+{
+ struct json_value *v;
+
+ if (argc == 1)
+ {
+ size_t i;
+ static char *keywords[] = {
+ "package",
+ "version",
+ "instance",
+ "binary",
+ };
+
+ shttp_process (conn, METH_GET, "/instance");
+
+ for (i = 0; i < sizeof (keywords)/ sizeof (keywords[0]); i++)
+ {
+ v = shttp_getval (conn, keywords[i], json_string);
+ if (v)
+ printf ("%s: %s\n", keywords[i], v->v.s);
+ }
+ v = shttp_getval (conn, "PID", json_number);
+ if (v)
+ printf ("PID: %.0f\n", v->v.n);
+ }
+ else
+ {
+ char *buf = NULL;
+ size_t size = 0;
+ size_t i;
+
+ for (i = 1; i < argc; i++)
+ {
+ grecs_asprintf (&buf, &size, "/instance/%s", argv[i]);
+ shttp_process (conn, METH_GET, buf);
+ if (json_object_get (conn->result, argv[i], &v) == 0)
+ {
+ printf ("%s: ", argv[i]);
+ print_json (stdout, v);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
com_shutdown (struct shttp_connection *conn, int argc, char **argv)
{
- abort ();
+ shttp_process (conn, METH_DELETE, "/instance/PID");
return 0;
}
static int
com_reboot (struct shttp_connection *conn, int argc, char **argv)
{
- abort ();
+ shttp_process (conn, METH_PUT, "/instance/PID");
return 0;
}
@@ -991,6 +1301,7 @@ static struct comtab comtab[] = {
{ "stop", com_stop },
{ "start", com_start },
{ "restart", com_restart },
+ { "id", com_id },
{ "shutdown", com_shutdown },
{ "reboot", com_reboot },
{ NULL }
@@ -1052,6 +1363,11 @@ main (int argc, char **argv)
parse_options (argc, argv, &i);
argc -= i;
argv += i;
+ if (argc == 0)
+ {
+ grecs_error (NULL, 0, _("not enough arguments"));
+ exit (EX_USAGE);
+ }
parse_config ();

Return to:

Send suggestions and report system problems to the System administrator.