[Workman-devel] [PATCH] CLI: workman command line interface framework
Josh Poimboeuf
jpoimboe at redhat.com
Wed Apr 17 20:07:47 UTC 2013
NOTE: This compiles but doesn't actually work yet. It will need some of the
patches still under review on the mailing list (particularly the WorkmanManager
patch at least), a dummy plugin, as well as some additional fixes.
The additional fixes include checking for NULL pointers before calling
g_object_free or g_boxed_free throughout libworkman, as well as calling
g_type_init() in workman_init_check().
Daniel, I haven't posted those fixes since you're making some changes to
libworkman. I'll post them and a dummy plugin later once your changes to
libworkman have been sorted out.
---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 | 226 +++++++++++++++++++++++++++++++++++++++++++++++++
workman/Makefile.am | 5 +-
workman/libworkman.sym | 2 +
7 files changed, 249 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..9f868a3
--- /dev/null
+++ b/tools/workman.c
@@ -0,0 +1,226 @@
+/*
+ * 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},
+ {},
+};
+
+
+static void
+workman_usage()
+{
+ const struct workman_cmd *cmd;
+ extern char *program_invocation_short_name;
+
+ printf("Usage: %s [OPTION...] COMMAND [ARGS...]\n\n",
+ program_invocation_short_name);
+ printf(" -h, --help Give this help list\n");
+ printf(" -s, --state=STATE active, persistent, or all (default=active)\n");
+
+ printf("\nCommands:\n");
+ for (cmd = workman_cmds; cmd->name; cmd++)
+ printf(" %s %s\n", cmd->name, cmd->arg_description);
+}
+
+
+int
+main(int argc, char **argv)
+{
+ const struct workman_cmd *cmd;
+ struct workman_args args;
+ char arg;
+
+ args.state = WORKMAN_STATE_ACTIVE;
+
+ const struct option long_options[] = {
+ {"help", no_argument, NULL, 'h'},
+ {"state", required_argument, NULL, 's'},
+ {},
+ };
+
+ while ((arg = getopt_long(argc, argv, ":hs:", long_options, NULL)) != -1) {
+ switch (arg) {
+ case 'h':
+ workman_usage();
+ exit(0);
+ break;
+ case 's':
+ if (!g_strcmp0(optarg, "active"))
+ args.state = WORKMAN_STATE_ACTIVE;
+ else if (!g_strcmp0(optarg, "persistent"))
+ args.state = WORKMAN_STATE_PERSISTENT;
+ else if (!g_strcmp0(optarg, "all"))
+ args.state = WORKMAN_STATE_ALL;
+ else
+ WORKMAN_USAGE_EXIT("invalid state");
+ break;
+ case ':':
+ WORKMAN_USAGE_EXIT("option '%c' requires an argument", optopt);
+ break;
+ case '?':
+ WORKMAN_USAGE_EXIT("unknown option '%c'", optopt);
+ break;
+ }
+ }
+
+ if (optind == argc)
+ WORKMAN_USAGE_EXIT("missing command");
+
+ for (cmd = workman_cmds; ; cmd++) {
+
+ if (!cmd->name)
+ WORKMAN_USAGE_EXIT("unknown command '%s'", argv[optind]);
+
+ if (!g_strcmp0(argv[optind], cmd->name)) {
+
+ WorkmanManager *mgr;
+ GError *err = NULL;
+
+ args.cmd_argc = argc - optind - 1;
+ args.cmd_argv = &argv[optind + 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;
+ }
+ }
+
+ 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 063504d..59508a5 100644
--- a/workman/Makefile.am
+++ b/workman/Makefile.am
@@ -37,10 +37,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 53a0460..114f326 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;
@@ -29,6 +30,7 @@ LIBworkman_0.0.1 {
workman_manager_get_partitions;
workman_manager_new;
workman_manager_remove_partition;
+ workman_manager_get_default;
workman_partition_get_consumers;
workman_partition_get_children;
--
1.7.11.7
More information about the Workman-devel
mailing list