corewatcher-config: add command line tool for editing the config file
authorChris Leech <christopher.leech@linux.intel.com>
Thu, 14 Apr 2011 21:00:29 +0000 (14:00 -0700)
committerChris Leech <christopher.leech@linux.intel.com>
Thu, 14 Apr 2011 21:00:29 +0000 (14:00 -0700)
Simple tool using the glib keyfile support to get and set key/value pairs.
Intended to be used to script configuration changes, such as.

# corewatcher-config --set allow-submit=yes

Default config file changes add a required group header for glib and whitespace
changes to reflect what happens when the glib keyfile routines read and then
write back the file.

Signed-off-by: Chris Leech <christopher.leech@linux.intel.com>
Makefile
configfile.c
corewatcher-config.c [new file with mode: 0644]
corewatcher.conf

index 3242094..319e1e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -19,12 +19,13 @@ MY_CFLAGS := `pkg-config --cflags libnotify gtk+-2.0`
 # and that makes the applet load faster and use less memory.
 #
 LDF_A := -Wl,--as-needed `pkg-config --libs libnotify gtk+-2.0`
+LDF_C := -Wl,--as-needed `pkg-config --libs glib-2.0`
 LDF_D := -Wl,--as-needed `pkg-config --libs glib-2.0 dbus-glib-1` `curl-config --libs` -Wl,"-z relro" -Wl,"-z now"
 
-all:   corewatcher corewatcher-applet corewatcher.8.gz
+all:   corewatcher corewatcher-config corewatcher-applet corewatcher.8.gz
        @(cd po/ && $(MAKE) $@)
 
-noui:  corewatcher corewatcher.8.gz
+noui:  corewatcher corewatcher-config corewatcher.8.gz
 
 .c.o:
        $(CC) $(CFLAGS) $(MY_CFLAGS) -c -o $@ $<
@@ -34,6 +35,9 @@ corewatcher:  corewatcher.o submit.o coredump.o configfile.o find_file.o corewatc
        gcc corewatcher.o submit.o coredump.o configfile.o find_file.o $(LDF_D) -o corewatcher
        @(cd po/ && $(MAKE))
 
+corewatcher-config: corewatcher-config.o
+       gcc corewatcher-config.o $(LDF_C)-o corewatcher-config
+
 corewatcher-applet: corewatcher-applet.o
        gcc corewatcher-applet.o $(LDF_A)-o corewatcher-applet
 
@@ -41,7 +45,7 @@ corewatcher.8.gz: corewatcher.8
        gzip -9 -c $< > $@
 
 clean:
-       rm -f *~ *.o *.ko DEADJOE corewatcher corewatcher-applet *.out */*~ corewatcher.8.gz
+       rm -f *~ *.o *.ko DEADJOE corewatcher corewatcher-config corewatcher-applet *.out */*~ corewatcher.8.gz
        @(cd po/ && $(MAKE) $@)
 
 
@@ -62,6 +66,7 @@ install-system: corewatcher.8.gz
 install-corewatcher: corewatcher
        -mkdir -p $(DESTDIR)$(SBINDIR)
        install -m 0755 corewatcher $(DESTDIR)$(SBINDIR)/
+       install -m 0755 corewatcher-config $(DESTDIR)$(SBINDIR)/
 
 install-applet: corewatcher-applet
        -mkdir -p $(DESTDIR)$(BINDIR)
index 958a915..fca0c47 100644 (file)
@@ -68,7 +68,7 @@ void read_config_file(char *filename)
                n = strchr(line, '\n');
                if (n) *n = 0;
 
-               c = strstr(line, "allow-submit ");
+               c = strstr(line, "allow-submit");
                if (c) {
                        c += 13;
                        if (strstr(c, "yes"))
@@ -76,18 +76,18 @@ void read_config_file(char *filename)
                        if (strstr(c, "ask"))
                                opted_in = 1;
                }
-               c = strstr(line, "allow-pass-on ");
+               c = strstr(line, "allow-pass-on");
                if (c) {
                        c += 14;
                        if (strstr(c, "yes"))
                                allow_distro_to_pass_on = 1;
                }
-               c = strstr(line, "unlink ");
+               c = strstr(line, "unlink");
                if (c) {
                        if (strstr(c, "yes"))
                                do_unlink = 1;
                }
-               c = strstr(line, "submit-url ");
+               c = strstr(line, "submit-url");
                if (c && url_count <= MAX_URLS) {
                        c += 11;
                        c = strstr(c, "http:");
diff --git a/corewatcher-config.c b/corewatcher-config.c
new file mode 100644 (file)
index 0000000..51de997
--- /dev/null
@@ -0,0 +1,224 @@
+#include <stdio.h>
+#include <glib.h>
+
+#define DEFAULT_FILE   "/etc/corewatcher.conf"
+#define DEFAULT_GROUP  "corewatcher"
+
+int parse_arg(gchar *arg, gchar **group, gchar **key, gchar **value)
+{
+       gchar **group_key_value = NULL;
+       gchar **group_key = NULL;
+
+       if (!arg)
+               goto err;
+       group_key_value = g_strsplit(arg, "=", -1);
+       if (!group_key_value)
+               goto err;
+       switch (g_strv_length(group_key_value)) {
+       case 2:
+               *value = g_strdup(group_key_value[1]);
+               /* intentional fall through */
+       case 1:
+               group_key = g_strsplit(group_key_value[0], ".", -1);
+               if (!group_key)
+                       goto err;
+               switch (g_strv_length(group_key)) {
+               case 1:
+                       *key = g_strdup(group_key[0]);
+                       break;
+               case 2:
+                       *group = g_strdup(group_key[0]);
+                       *key = g_strdup(group_key[1]);
+                       break;
+               default:
+                       goto err;
+               }
+               break;
+       default:
+               goto err;
+       }
+       g_strfreev(group_key);
+       g_strfreev(group_key_value);
+       return 0;
+err:
+       g_free(*group); *group = NULL;
+       g_free(*key); *key = NULL;
+       g_free(*value); *value = NULL;
+       g_strfreev(group_key);
+       g_strfreev(group_key_value);
+       return -1;
+}
+
+int do_set(GKeyFile *keyfile, gchar *arg)
+{
+       gchar *group = NULL;
+       gchar *key = NULL;
+       gchar *value = NULL;
+       int ret = 0;
+
+       parse_arg(arg, &group, &key, &value);
+       if (!key) {
+               ret = -1;
+               goto out;
+       }
+       if (!group)
+               group = g_strdup(DEFAULT_GROUP);
+       if (!value) {
+               fprintf(stderr, "missing value in set command\n");
+               ret = -1;
+               goto out;
+       }
+       g_key_file_set_value(keyfile, group, key, value);
+out:
+       g_free(group);
+       g_free(key);
+       g_free(value);
+       return ret;
+}
+
+int do_get(GKeyFile *keyfile, gchar *arg)
+{
+       GError *error = NULL;
+       gchar *group = NULL;
+       gchar *key = NULL;
+       gchar *value = NULL;
+       int ret = 0;
+
+       parse_arg(arg, &group, &key, &value);
+       if (!key) {
+               ret = -1;
+               goto out;
+       }
+       if (!group)
+               group = g_strdup(DEFAULT_GROUP);
+       if (value) {
+               fprintf(stderr, "ingoring value (%s) in get command\n", value);
+               g_free(value);
+       }
+       value = g_key_file_get_value(keyfile, group, key, &error);
+       if (error) {
+               fprintf(stderr, "%s\n", error->message);
+               g_clear_error(&error);
+               goto out;
+       }
+       printf("%s\n", value);
+out:
+       g_free(group);
+       g_free(key);
+       g_free(value);
+       return ret;
+}
+
+int do_get_all(GKeyFile *keyfile)
+{
+       gchar *group = NULL;
+       gchar *key = NULL;
+       gchar *value = NULL;
+       gchar **groups;
+       gchar **keys;
+       gsize group_count;
+       gsize key_count;
+       gsize i, j;
+
+       groups = g_key_file_get_groups(keyfile, &group_count);
+       for (i = 0; i < group_count; i++) {
+               group = groups[i];
+               keys = g_key_file_get_keys(keyfile, group, &key_count, NULL);
+               for (j = 0; j < key_count; j++) {
+                       key = keys[j];
+                       value = g_key_file_get_value(keyfile, group, key, NULL);
+                       printf("%s.%s=%s\n", group, key, value);
+                       g_free(value);
+               }
+               g_strfreev(keys);
+       }
+       g_strfreev(groups);
+       return 0;
+}
+
+#define CMD_SET                (1<<0)
+#define CMD_GET                (1<<1)
+#define CMD_GET_ALL    (1<<2)
+
+#define HAS_MULTIPLE_BITS(i) ((i) & ((i) -1))
+
+/* global settings from command line argument parsing */
+struct {
+       gint cmd;
+       gchar *file;
+       gchar *arg;
+} settings = { 0, DEFAULT_FILE, NULL };
+
+#define __unused  __attribute__ ((__unused__))
+
+gboolean set_cmd_option(const gchar *option_name, const gchar *value, gpointer __unused data, GError __unused **Error)
+{
+       if (!g_strcmp0(option_name, "--set")) {
+               settings.cmd |= CMD_SET;
+               settings.arg = g_strdup(value);
+       }
+       else if (!g_strcmp0(option_name, "--get")) {
+               settings.cmd |= CMD_GET;
+               settings.arg = g_strdup(value);
+       }
+       else if (!g_strcmp0(option_name, "--get-all")) {
+               settings.cmd |= CMD_GET_ALL;
+       }
+       return TRUE;
+}
+
+static GOptionEntry entries[] = {
+       { "file", 'f', 0, G_OPTION_ARG_FILENAME, &settings.file, "file", NULL },
+       { "set", '\0', 0, G_OPTION_ARG_CALLBACK, &set_cmd_option, "set", NULL },
+       { "get", '\0', 0, G_OPTION_ARG_CALLBACK, &set_cmd_option, "get", NULL },
+       { "get-all", '\0', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, &set_cmd_option, "get-all", NULL },
+       { NULL, 0, 0, 0, NULL, NULL, NULL }
+};
+
+int main(int argc, char **argv)
+{
+       GError *error = NULL;
+       GOptionContext *context;
+       GKeyFile *keyfile;
+       GKeyFileFlags flags;
+       int ret = 0;
+
+       context = g_option_context_new("");
+       g_option_context_add_main_entries(context, entries, NULL);
+       if (!g_option_context_parse(context, &argc, &argv, &error)) {
+               fprintf(stderr, "%s\n", error->message);
+               return -1;
+       }
+       if (!settings.cmd) {
+               fprintf(stderr, "%s", g_option_context_get_help(context, TRUE, NULL));
+               return -1;
+       }
+       if (HAS_MULTIPLE_BITS(settings.cmd)) {
+               fprintf(stderr, "only one command allowed at a time\n");
+               fprintf(stderr, "%s", g_option_context_get_help(context, TRUE, NULL));
+               return -1;
+       }
+
+       keyfile = g_key_file_new();
+       flags = G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS;
+       if (!g_key_file_load_from_file (keyfile, settings.file, flags, &error)) {
+               fprintf(stderr, "%s\n", error->message);
+               return -1;
+       }
+       switch(settings.cmd) {
+       case CMD_SET:
+               ret = do_set(keyfile, settings.arg);
+               g_file_set_contents(settings.file, g_key_file_to_data(keyfile, NULL, NULL), -1, NULL);
+               break;
+       case CMD_GET:
+               ret = do_get(keyfile, settings.arg);
+               break;
+       case CMD_GET_ALL:
+               ret = do_get_all(keyfile);
+               break;
+       }
+       g_key_file_free(keyfile);
+
+       return ret;
+}
+
index 00e726d..d5c5e4e 100644 (file)
@@ -2,6 +2,8 @@
 # Configuration file for the corewatcher.org crash collector
 #
 
+[corewatcher]
+
 #
 # Set the following variable to "yes" if you want to automatically
 # submit your bactraces to the database for use by your distribution or the
 #
 # Default is "ask" which uses a UI application t ask the user for permission
 #
-allow-submit = ask
+allow-submit=ask
 
 #
 # Set the following variable to "yes" if you want to allow your
 # Linux distribution vendor to pass the backtraces on to the central corewatcher.org
 # database as used by the MeeGo developers
 #
-allow-pass-on = yes
+allow-pass-on=yes
 
 #
 # Delete the coredumps after processing
 #
-unlink = no
+unlink=no
 
 #
 # URL for submitting the backtraces
@@ -41,16 +43,17 @@ unlink = no
 # submit-url = http://url2.com/submitbug.php
 #
 
-submit-url = http://crashdb.meego.com/submitbug.php
+submit-url=http://crashdb.meego.com/submitbug.php
 
 #
 # Location for the MeeGo build release file
 #
 
-release-info = /etc/meego-release
+release-info=/etc/meego-release
 
 #
 # Location to store meego coredumps after they are processed
 #
 
-core-folder = /tmp/corewatcher/
\ No newline at end of file
+core-folder=/tmp/corewatcher/
+