[Workman-devel] [PATCH v2] CLI: workman command line interface framework
Josh Poimboeuf
jpoimboe at redhat.com
Fri Apr 19 01:28:58 UTC 2013
v2:
- use glib option parser framework
---8<---
This adds the framework for the "workman" tool which will be the command
line interface to libworkman.
- Add a barely functional workman.c with the basic interfaces in place,
and one of the commands implemented.
- Update the makefiles to build tools/Makefile and workman.
- Update the libworkman makefile to link with libgobject.
- Export some needed libworkman symbols.
---
.gitignore | 1 +
Makefile.am | 2 +-
configure.ac | 1 +
tools/Makefile.am | 14 ++++
tools/workman.c | 220 +++++++++++++++++++++++++++++++++++++++++++++++++
workman/Makefile.am | 5 +-
workman/libworkman.sym | 2 +
7 files changed, 243 insertions(+), 2 deletions(-)
create mode 100644 tools/Makefile.am
create mode 100644 tools/workman.c
diff --git a/.gitignore b/.gitignore
index 348274b..b4996bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,3 +64,4 @@ docs/workman/version.xml
*.swp
cscope.*
workman/workman-enums.[ch]
+tools/workman
diff --git a/Makefile.am b/Makefile.am
index 4eac35b..4cec125 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
-SUBDIRS = workman docs
+SUBDIRS = workman tools docs
ACLOCAL_AMFLAGS = -I m4
diff --git a/configure.ac b/configure.ac
index 3ea30da..8df0ed2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -89,6 +89,7 @@ AM_CONDITIONAL([WITH_GOBJECT_INTROSPECTION], [test "x$enable_introspection" = "x
AC_OUTPUT(Makefile
workman/Makefile
+ tools/Makefile
docs/Makefile
docs/workman/Makefile
docs/workman/version.xml
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..1cfc65c
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,14 @@
+bin_PROGRAMS = workman
+
+workman_SOURCES = workman.c
+
+workman_CFLAGS = \
+ -I$(top_srcdir) \
+ $(GOBJECT2_CFLAGS) \
+ $(WARN_CFLAGS) \
+ $(NULL)
+
+workman_LDADD = \
+ ../workman/libworkman-1.0.la \
+ $(NULL)
+
diff --git a/tools/workman.c b/tools/workman.c
new file mode 100644
index 0000000..2ec9965
--- /dev/null
+++ b/tools/workman.c
@@ -0,0 +1,220 @@
+/*
+ * workman.c: cmdline interface to libworkman
+ *
+ * Copyright (C) 2013 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Josh Poimboeuf <jpoimboe at redhat.com>
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <glib.h>
+#include <config.h>
+#include "workman/workman.h"
+
+struct workman_args {
+ WorkmanState state;
+ int cmd_argc;
+ char **cmd_argv;
+};
+
+struct workman_cmd {
+ const char *name;
+ const char *arg_description;
+ int min_args;
+ int max_args;
+ void (*handler)(WorkmanManager *, struct workman_args *);
+};
+
+
+#define WORKMAN_ERROR_EXIT(err, fmt, ...) \
+({ \
+ fprintf(stderr, fmt, ##__VA_ARGS__); \
+ if (err) \
+ fprintf(stderr, ": %s", err->message); \
+ fprintf(stderr, "\n"); \
+ exit(1); \
+})
+
+#define WORKMAN_USAGE_EXIT(...) \
+({ \
+ GError *err = NULL; \
+ WORKMAN_ERROR_EXIT(err, __VA_ARGS__); \
+})
+
+static void
+list_partitions(WorkmanManager *mgr,
+ struct workman_args *args)
+{
+ GList *partitions, *p;
+ GError *err = NULL;
+ char *parent_name = NULL;
+
+ if (args->cmd_argc == 1)
+ parent_name = args->cmd_argv[0];
+ else if (args->cmd_argc != 0)
+ WORKMAN_USAGE_EXIT("unknown arguments");
+
+ partitions = workman_manager_get_partitions(mgr, args->state, &err);
+
+ if (partitions) {
+ g_warn_if_fail(err == NULL);
+ for (p = partitions; p; p = p->next) {
+ WorkmanPartition *part = WORKMAN_PARTITION(p->data);
+
+ if (parent_name) {
+ WorkmanPartition *parent;
+ parent = workman_partition_get_parent(part, args->state, &err);
+ if (err)
+ WORKMAN_ERROR_EXIT(err,
+ "workman_partition_get_parent failed");
+ if (!parent ||
+ g_strcmp0(parent_name,
+ workman_object_get_name(WORKMAN_OBJECT(parent))))
+ continue;
+ }
+
+ printf("%s\n", workman_object_get_name(WORKMAN_OBJECT(part)));
+ }
+
+ g_boxed_free(WORKMAN_TYPE_PARTITION_LIST, partitions);
+ }
+}
+
+static void list_consumers(WorkmanManager *mgr, struct workman_args *args) {}
+static void list_attributes(WorkmanManager *mgr, struct workman_args *args) {}
+static void list_processes(WorkmanManager *mgr, struct workman_args *args) {}
+static void show_partition(WorkmanManager *mgr, struct workman_args *args) {}
+static void show_attribute(WorkmanManager *mgr, struct workman_args *args) {}
+static void set_partition(WorkmanManager *mgr, struct workman_args *args) {}
+static void set_attribute(WorkmanManager *mgr, struct workman_args *args) {}
+static void create_partition(WorkmanManager *mgr, struct workman_args *args) {}
+
+static const struct workman_cmd workman_cmds[] = {
+ {"partitions", "[PARTITION]", 0, 0, list_partitions},
+ {"consumers", "[PARTITION]", 0, 1, list_consumers},
+ {"attributes", "OBJECT", 1, 1, list_attributes},
+ {"processes", "CONSUMER", 1, 1, list_processes},
+ {"partition", "PARTITION|CONSUMER", 1, 1, show_partition},
+ {"attribute", "OBJECT ATTRIBUTE", 2, 2, show_attribute},
+ {"set-partition", "PARTITION|CONSUMER", 2, 2, set_partition},
+ {"set-attribute", "OBJECT ATTRIBUTE VALUE", 3, 3, set_attribute},
+ {"create-partition", "NAME", 1, 1, create_partition},
+ {},
+};
+
+
+int
+main(int argc, char **argv)
+{
+ const struct workman_cmd *cmd;
+ struct workman_args args;
+ static gchar *state = NULL;
+ static gchar **cmd_args = NULL;
+ GOptionContext *context;
+ GError *error = NULL;
+ static gchar *description, *tmpstr;
+ int i;
+
+ static GOptionEntry options[] = {
+ {"state", 's', 0, G_OPTION_ARG_STRING, &state, "active, persistent, or all (default=active)\n", NULL},
+ {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_args, NULL, "COMMAND [ARGS...]"},
+ {},
+ };
+
+ g_type_init();
+
+ context = g_option_context_new(" - workload manager");
+
+ g_option_context_add_main_entries(context, options, NULL);;
+
+ tmpstr = g_malloc(1024);
+ i = sprintf(tmpstr, "Commands:\n");
+ for (cmd = workman_cmds; cmd->name; cmd++)
+ i += snprintf(tmpstr + i, 1024 - i, " %s %s\n", cmd->name, cmd->arg_description);
+ description = g_strdup(tmpstr);
+ g_free(tmpstr);
+ g_option_context_set_description(context, description);
+
+ if (!g_option_context_parse(context, &argc, &argv, &error)) {
+ g_print("option parsing failed: %s\n", error->message);
+ exit(1);
+ }
+
+ if (!state || !g_strcmp0(state, "active"))
+ args.state = WORKMAN_STATE_ACTIVE;
+ else if (!g_strcmp0(state, "persistent"))
+ args.state = WORKMAN_STATE_PERSISTENT;
+ else if (!g_strcmp0(state, "all"))
+ args.state = WORKMAN_STATE_ALL;
+ else
+ WORKMAN_USAGE_EXIT("invalid state");
+ g_free(state);
+
+ if (!cmd_args || !cmd_args[0])
+ WORKMAN_USAGE_EXIT("missing command");
+
+ for (cmd = workman_cmds; ; cmd++) {
+
+ if (!cmd->name)
+ WORKMAN_USAGE_EXIT("unknown command '%s'", cmd_args[0]);
+
+ if (!g_strcmp0(cmd_args[0], cmd->name)) {
+
+ WorkmanManager *mgr;
+ GError *err = NULL;
+
+ args.cmd_argc = 0;
+ while (cmd_args[args.cmd_argc + 1])
+ args.cmd_argc++;
+
+ args.cmd_argv = &cmd_args[1];
+
+ if (args.cmd_argc < cmd->min_args || args.cmd_argc > cmd->max_args)
+ WORKMAN_USAGE_EXIT("invalid number of arguments for '%s'",
+ cmd->name);
+
+ workman_init(NULL, NULL);
+
+ mgr = workman_manager_get_default(&err);
+ if (!mgr)
+ WORKMAN_ERROR_EXIT(err, "workman_manager_get_default failed");
+
+ cmd->handler(mgr, &args);
+ break;
+ }
+ }
+
+ g_option_context_free(context);
+
+ return 0;
+}
+
+
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * End:
+ *
+ * vim: set expandtab shiftwidth=4 tabstop=4 :
+ */
diff --git a/workman/Makefile.am b/workman/Makefile.am
index 4ef03f3..67c16c9 100644
--- a/workman/Makefile.am
+++ b/workman/Makefile.am
@@ -49,10 +49,13 @@ libworkman_1_0_la_CFLAGS = \
-I$(top_srcdir) \
$(GLIB2_CFLAGS) \
$(GTHREAD2_CFLAGS) \
+ $(GOBJECT2_CFLAGS) \
$(WARN_CFLAGS)
libworkman_1_0_la_LIBADD = \
$(GLIB2_LIBS) \
- $(GTHREAD2_LIBS)
+ $(GTHREAD2_LIBS) \
+ $(GOBJECT2_LIBS) \
+ $(NULL)
libworkman_1_0_la_DEPENDENCIES = \
libworkman.sym
libworkman_1_0_la_LDFLAGS = \
diff --git a/workman/libworkman.sym b/workman/libworkman.sym
index 1eefc96..ff4065b 100644
--- a/workman/libworkman.sym
+++ b/workman/libworkman.sym
@@ -10,6 +10,7 @@ LIBworkman_0.0.1 {
workman_object_save_attributes;
workman_object_get_state;
workman_object_attribute_list_get_type;
+ workman_object_get_name;
workman_attribute_get_name;
workman_attribute_get_type;
@@ -30,6 +31,7 @@ LIBworkman_0.0.1 {
workman_manager_new;
workman_manager_remove_partition;
workman_manager_refresh_objects;
+ workman_manager_get_default;
workman_partition_get_consumers;
workman_partition_get_children;
--
1.7.11.7
More information about the Workman-devel
mailing list