Imported Upstream version 2 upstream/2
authorPatrick McCarty <patrick.mccarty@linux.intel.com>
Fri, 2 May 2014 21:43:23 +0000 (14:43 -0700)
committerPatrick McCarty <patrick.mccarty@linux.intel.com>
Fri, 2 May 2014 21:43:23 +0000 (14:43 -0700)
17 files changed:
config.h.in
configure
configure.ac
src/cli/client.c
src/cli/main.c
src/core/daemon.c
src/core/main.c
src/db/gdbm.c
src/db/memory.c
src/libbuxton/lbuxton.c
src/shared/direct.c
src/shared/protocol.c
src/shared/protocol.h
src/shared/serialize.c
src/shared/serialize.h
test/check_daemon.c
test/test.conf

index f7a287f..884cdb9 100644 (file)
 /* Define to 1 if you have the <sys/param.h> header file. */
 #undef HAVE_SYS_PARAM_H
 
+/* Define to 1 if you have the <sys/signalfd.h> header file. */
+#undef HAVE_SYS_SIGNALFD_H
+
 /* Define to 1 if you have the <sys/socket.h> header file. */
 #undef HAVE_SYS_SOCKET_H
 
index b12af37..e1f7eb1 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for buxton 1.
+# Generated by GNU Autoconf 2.69 for buxton 2.
 #
 # Report bugs to <william.douglas@intel.com>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='buxton'
 PACKAGE_TARNAME='buxton'
-PACKAGE_VERSION='1'
-PACKAGE_STRING='buxton 1'
+PACKAGE_VERSION='2'
+PACKAGE_STRING='buxton 2'
 PACKAGE_BUGREPORT='william.douglas@intel.com'
 PACKAGE_URL='https://github.com/sofar/buxton'
 
@@ -1367,7 +1367,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures buxton 1 to adapt to many kinds of systems.
+\`configure' configures buxton 2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1437,7 +1437,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of buxton 1:";;
+     short | recursive ) echo "Configuration of buxton 2:";;
    esac
   cat <<\_ACEOF
 
@@ -1579,7 +1579,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-buxton configure 1
+buxton configure 2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2132,7 +2132,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by buxton $as_me 1, which was
+It was created by buxton $as_me 2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2995,7 +2995,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='buxton'
- VERSION='1'
+ VERSION='2'
 
 
 cat >>confdefs.h <<_ACEOF
 
 done
 
+for ac_header in sys/signalfd.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sys/signalfd.h" "ac_cv_header_sys_signalfd_h" "$ac_includes_default"
+if test "x$ac_cv_header_sys_signalfd_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SYS_SIGNALFD_H 1
+_ACEOF
+
+fi
+
+done
+
 for ac_header in sys/socket.h
 do :
   ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default"
@@ -15209,7 +15221,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by buxton $as_me 1, which was
+This file was extended by buxton $as_me 2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -15276,7 +15288,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-buxton config.status 1
+buxton config.status 2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index e05900c..f60b4a7 100644 (file)
@@ -1,6 +1,6 @@
 
 AC_PREREQ([2.68])
-AC_INIT([buxton],[1],[william.douglas@intel.com],[buxton],[https://github.com/sofar/buxton])
+AC_INIT([buxton],[2],[william.douglas@intel.com],[buxton],[https://github.com/sofar/buxton])
 AM_INIT_AUTOMAKE([foreign -Wall -Werror -Wno-portability silent-rules subdir-objects color-tests no-dist-gzip dist-xz])
 AC_CONFIG_MACRO_DIR([m4])
 AC_CONFIG_FILES([Makefile])
@@ -92,6 +92,7 @@ AC_CHECK_HEADERS([time.h])
 AC_CHECK_HEADERS([math.h])
 AC_CHECK_HEADERS([pthread.h])
 AC_CHECK_HEADERS([sys/param.h])
+AC_CHECK_HEADERS([sys/signalfd.h])
 AC_CHECK_HEADERS([sys/socket.h])
 AC_CHECK_HEADERS([sys/stat.h])
 AC_CHECK_HEADERS([sys/time.h])
index c38beff..74deb25 100644 (file)
@@ -162,7 +162,7 @@ bool cli_set_value(BuxtonControl *control, BuxtonDataType type,
                   char *one, char *two, char *three, char *four)
 {
        BuxtonString value;
-       BuxtonKey key;
+       _cleanup_buxton_key_ BuxtonKey key;
        BuxtonData set;
        bool ret = false;
 
@@ -332,7 +332,6 @@ bool cli_set_value(BuxtonControl *control, BuxtonDataType type,
                free(layer);
        }
 
-       free(key);
        return ret;
 }
 
@@ -383,7 +382,7 @@ void get_value_callback(BuxtonResponse response, void *data)
                r->type = FLOAT;
                break;
        case DOUBLE:
-               r->store.d_double = *(double *)p;
+               memcpy(&r->store.d_double, p, sizeof(double));
                r->type = DOUBLE;
                break;
        case BOOLEAN:
@@ -403,7 +402,7 @@ void get_value_callback(BuxtonResponse response, void *data)
 bool cli_get_value(BuxtonControl *control, BuxtonDataType type,
                   char *one, char *two, char *three, __attribute__((unused)) char * four)
 {
-       BuxtonKey key;
+       _cleanup_buxton_key_ BuxtonKey key;
        BuxtonData get;
        _cleanup_free_ char *prefix = NULL;
        _cleanup_free_ char *group = NULL;
@@ -550,7 +549,7 @@ bool cli_unset_value(BuxtonControl *control,
                     char *one, char *two, char *three,
                     __attribute__((unused)) char *four)
 {
-       BuxtonKey key;
+       _cleanup_buxton_key_ BuxtonKey key;
 
        key = buxton_key_create(two, three, one, type);
 
index af8e599..97788b8 100644 (file)
 #include "configurator.h"
 #include "direct.h"
 #include "hashmap.h"
-#include "log.h"
 #include "protocol.h"
 #include "util.h"
 
 static Hashmap *commands;
 static BuxtonControl control;
 
+static void print_version(void)
+{
+       printf("buxtonctl " PACKAGE_VERSION "\n"
+              "Copyright (C) 2013 Intel Corporation\n"
+              "buxton is free software; you can redistribute it and/or modify\n"
+              "it under the terms of the GNU Lesser General Public License as\n"
+              "published by the Free Software Foundation; either version 2.1\n"
+              "of the License, or (at your option) any later version.\n");
+}
+
 static bool print_help(void)
 {
        const char *key;
@@ -89,9 +98,10 @@ int main(int argc, char **argv)
        int i = 0;
        int c;
        bool help = false;
+       bool version = false;
        control.client.direct = false;
        char *conf_path = NULL;
-       BuxtonClient client;
+       BuxtonClient client = NULL;
 
        /* libtool bites my twinkie */
        include_configurator();
@@ -205,11 +215,12 @@ int main(int argc, char **argv)
                { "config-file", 1, NULL, 'c' },
                { "direct",      0, NULL, 'd' },
                { "help",        0, NULL, 'h' },
+               { "version", 0, NULL, 'v' },
                { NULL, 0, NULL, 0 }
        };
 
        while (true) {
-               c = getopt_long(argc, argv, "c:dh", opts, &i);
+               c = getopt_long(argc, argv, "c:dvh", opts, &i);
 
                if (c == -1) {
                        break;
@@ -225,12 +236,20 @@ int main(int argc, char **argv)
                case 'd':
                        control.client.direct = true;
                        break;
+               case 'v':
+                       version = true;
+                       break;
                case 'h':
                        help = true;
                        break;
                }
        }
 
+       if (version) {
+               print_version();
+               goto end;
+       }
+
        if (optind == argc) {
                print_help();
                goto end;
@@ -270,7 +289,6 @@ int main(int argc, char **argv)
                        }
                }
                if (buxton_open(&client) < 0) {
-                       buxton_log("Failed to talk to Buxton, falling back to direct\n");
                        control.client.direct = true;
                } else {
                        control.client = *(_BuxtonClient *)client;
@@ -295,7 +313,7 @@ int main(int argc, char **argv)
                        buxton_add_cmd_line(CONFIG_CONF_FILE, conf_path);
                }
                if (!buxton_direct_open(&(control))) {
-                       buxton_log("Failed to directly talk to Buxton\n");
+                       printf("Failed to directly talk to Buxton\n");
                        ret = false;
                        goto end;
                }
@@ -311,7 +329,14 @@ int main(int argc, char **argv)
 end:
        free(conf_path);
        hashmap_free(commands);
-       buxton_direct_close(&control);
+       if (control.client.direct) {
+               buxton_direct_close(&control);
+       } else {
+               if (client) {
+                       buxton_close(client);
+               }
+       }
+
        if (ret) {
                return EXIT_SUCCESS;
        }
index cd4190a..f3b3660 100644 (file)
@@ -266,6 +266,8 @@ bool buxtond_handle_message(BuxtonDaemon *self, client_list_item *client, size_t
                                abort();
                        }
                        buxton_log("Failed to serialize set response message\n");
+                       //FIXME abort here because serialization
+                       //failed for a message generated by the daemon
                        goto end;
                }
                break;
@@ -439,6 +441,8 @@ void buxtond_notify_clients(BuxtonDaemon *self, client_list_item *client,
 
        BUXTON_LIST_FOREACH(list, elem) {
                if (!elem) {
+                       //FIXME abort here since NULL elements
+                       //shouldn't be added to the list
                        break;
                }
                nitem = elem->data;
@@ -533,6 +537,7 @@ void buxtond_notify_clients(BuxtonDaemon *self, client_list_item *client,
                                abort();
                        }
                        buxton_log("Failed to serialize notification\n");
+                       //FIXME abort here serialize message error
                        return;
                }
                buxton_debug("Notification to %d of key change (%s)\n", nitem->client->fd,
@@ -822,9 +827,6 @@ uint32_t unregister_notification(BuxtonDaemon *self, client_list_item *client,
        }
 
        BUXTON_LIST_FOREACH(n_list, elem) {
-               if (!elem) {
-                       break;
-               }
                nitem = elem->data;
                /* Find the list item for this client */
                if (nitem->client == client) {
@@ -845,8 +847,8 @@ uint32_t unregister_notification(BuxtonDaemon *self, client_list_item *client,
 
        /* If we removed the last item, remove the mapping too */
        if (!n_list) {
-               free(old_key_name);
                (void)hashmap_remove(self->notify_mapping, key_name);
+               free(old_key_name);
        }
 
        *status = 0;
@@ -898,6 +900,8 @@ bool identify_client(client_list_item *cl)
        cmhp = CMSG_FIRSTHDR(&msgh);
 
        if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(struct ucred))) {
+               //FIXME figure out if abort here since socket setup
+               //didn't work quite right
                return false;
        }
 
@@ -956,7 +960,7 @@ void del_pollfd(BuxtonDaemon *self, nfds_t i)
                        (size_t)(self->nfds - i - 1) * sizeof(struct pollfd));
                memmove(&(self->accepting[i]),
                        &(self->accepting[i + 1]),
-                       (size_t)(self->nfds - i - 1) * sizeof(self->accepting));
+                       (size_t)(self->nfds - i - 1) * sizeof(bool));
        }
        self->nfds--;
 }
index 9d8751b..f3ad523 100644 (file)
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 #include <poll.h>
 #include <signal.h>
+#include <sys/signalfd.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/un.h>
 #include "configurator.h"
 #include "buxtonlist.h"
 
-#define POLL_TIMEOUT 250
 #define SOCKET_TIMEOUT 5
 
-static volatile bool do_shutdown = false;
 static BuxtonDaemon self;
 
-void my_handler(int sig)
-{
-       do_shutdown = true;
-}
-
 static void print_usage(char *name)
 {
        printf("%s: Usage\n\n", name);
@@ -79,7 +73,8 @@ int main(int argc, char *argv[])
        int descriptors;
        int ret;
        bool manual_start = false;
-       struct sigaction sa;
+       sigset_t mask;
+       int sigfd;
        bool leftover_messages = false;
        struct stat st;
        bool help = false;
@@ -145,24 +140,32 @@ int main(int argc, char *argv[])
                exit(EXIT_FAILURE);
        }
 
-       sigemptyset(&sa.sa_mask);
-       sa.sa_flags = SA_RESTART;
-       sa.sa_handler = my_handler;
-       ret = sigaction(SIGINT, &sa, NULL);
-       if (ret == -1) {
+       sigemptyset(&mask);
+       ret = sigaddset(&mask, SIGINT);
+       if (ret != 0) {
                exit(EXIT_FAILURE);
        }
-       ret = sigaction(SIGTERM, &sa, NULL);
-       if (ret == -1) {
+       ret = sigaddset(&mask, SIGTERM);
+       if (ret != 0) {
+               exit(EXIT_FAILURE);
+       }
+       ret = sigaddset(&mask, SIGPIPE);
+       if (ret != 0) {
                exit(EXIT_FAILURE);
        }
-       sigemptyset(&sa.sa_mask);
-       sa.sa_handler = SIG_IGN;
-       ret = sigaction(SIGPIPE, &sa, NULL);
+
+       ret = sigprocmask(SIG_BLOCK, &mask, NULL);
        if (ret == -1) {
                exit(EXIT_FAILURE);
        }
 
+       sigfd = signalfd(-1, &mask, 0);
+       if (sigfd == -1) {
+               exit(EXIT_FAILURE);
+       }
+
+       add_pollfd(&self, sigfd, POLLIN, false);
+
        /* For client notifications */
        self.notify_mapping = hashmap_new(string_hash_func, string_compare_func);
        /* Store a list of connected clients */
@@ -233,17 +236,10 @@ int main(int argc, char *argv[])
 
        /* Enter loop to accept clients */
        for (;;) {
-               ret = poll(self.pollfds, self.nfds, leftover_messages ? 0 : POLL_TIMEOUT);
+               ret = poll(self.pollfds, self.nfds, leftover_messages ? 0 : -1);
 
                if (ret < 0) {
                        buxton_log("poll(): %m\n");
-                       if (errno == EINTR) {
-                               if (do_shutdown) {
-                                       break;
-                               } else {
-                                       continue;
-                               }
-                       }
                        break;
                }
                if (ret == 0) {
@@ -254,7 +250,22 @@ int main(int argc, char *argv[])
 
                leftover_messages = false;
 
-               for (nfds_t i=0; i<self.nfds; i++) {
+               /* check sigfd if the daemon was signaled */
+               if (self.pollfds[0].revents != 0) {
+                       ssize_t sinfo;
+                       struct signalfd_siginfo si;
+
+                       sinfo = read(self.pollfds[0].fd, &si, sizeof(struct signalfd_siginfo));
+                       if (sinfo != sizeof(struct signalfd_siginfo)) {
+                               exit(EXIT_FAILURE);
+                       }
+
+                       if (si.ssi_signo == SIGINT || si.ssi_signo == SIGTERM) {
+                               break;
+                       }
+               }
+
+               for (nfds_t i = 1; i < self.nfds; i++) {
                        client_list_item *cl = NULL;
                        char discard[256];
 
index c2133c2..0892b54 100644 (file)
@@ -77,7 +77,6 @@ static GDBM_FILE db_for_resource(BuxtonLayer *layer)
                if (!db) {
                        free(name);
                        buxton_log("Couldn't create db for path: %s\n", path);
-                       free(path);
                        return 0;
                }
                r = hashmap_put(_resources, name, db);
@@ -98,14 +97,16 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
        GDBM_FILE db;
        int ret = -1;
        datum key_data;
+       datum cvalue = {0};
        datum value;
        _cleanup_free_ uint8_t *data_store = NULL;
        size_t size;
        uint32_t sz;
+       BuxtonData cdata = {0};
+       BuxtonString clabel;
 
        assert(layer);
        assert(key);
-       assert(data);
        assert(label);
 
        if (key->name.value) {
@@ -137,6 +138,21 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
                goto end;
        }
 
+       /* set_label will pass a NULL for data */
+       if (!data) {
+               cvalue = gdbm_fetch(db, key_data);
+               if (cvalue.dsize < 0 || cvalue.dptr == NULL) {
+                       ret = ENOENT;
+                       goto end;
+               }
+
+               data_store = (uint8_t*)cvalue.dptr;
+               buxton_deserialize(data_store, &cdata, &clabel);
+               free(clabel.value);
+               data = &cdata;
+               data_store = NULL;
+       }
+
        size = buxton_serialize(data, label, &data_store);
 
        value.dptr = (char *)data_store;
@@ -145,7 +161,11 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
        assert(ret == 0);
 
 end:
+       if (cdata.type == STRING) {
+               free(cdata.store.d_string.value);
+       }
        free(key_data.dptr);
+       free(cvalue.dptr);
 
        return ret;
 }
index 14bac9d..d763390 100644 (file)
@@ -79,13 +79,12 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
 
        assert(layer);
        assert(key);
-       assert(data);
        assert(label);
 
        db = _db_for_resource(layer);
        if (!db) {
                ret = ENOENT;
-               goto clean;
+               goto end;
        }
 
        if (key->name.value) {
@@ -99,6 +98,16 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
                }
        }
 
+       if (!data) {
+               stored = (BuxtonArray *)hashmap_get(db, full_key);
+               if (!stored) {
+                       ret = ENOENT;
+                       free(full_key);
+                       goto end;
+               }
+               data = buxton_array_get(stored, 0);
+       }
+
        array = buxton_array_new();
        if (!array) {
                abort();
@@ -152,20 +161,6 @@ static int set_value(BuxtonLayer *layer, _BuxtonKey *key, BuxtonData *data,
        }
 
        ret = 0;
-       goto end;
-
-clean:
-       buxton_array_free(&array, NULL);
-       if (data_copy && data_copy->type == STRING &&
-           data_copy->store.d_string.value) {
-               free(data_copy->store.d_string.value);
-       }
-       free(data_copy);
-       if (label_copy && label_copy->value) {
-               free(label_copy->value);
-       }
-       free(label_copy);
-       free(full_key);
 
 end:
        return ret;
index 35213cf..56376bf 100644 (file)
@@ -67,13 +67,21 @@ int buxton_open(BuxtonClient *client)
        _BuxtonClient *cl = NULL;
        int bx_socket, r;
        struct sockaddr_un remote;
+       size_t sock_name_len;
 
        if ((bx_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                return -1;
        }
 
        remote.sun_family = AF_UNIX;
-       strncpy(remote.sun_path, buxton_socket(), sizeof(remote.sun_path));
+       sock_name_len = strlen(buxton_socket()) + 1;
+       if (sock_name_len >= sizeof(remote.sun_path)) {
+               buxton_log("Provided socket name: %s is too long, maximum allowed length is %d bytes\n",
+                          buxton_socket(), sizeof(remote.sun_path));
+               return -1;
+       }
+
+       strncpy(remote.sun_path, buxton_socket(), sock_name_len);
        r = connect(bx_socket, (struct sockaddr *)&remote, sizeof(remote));
        if ( r == -1) {
                close(bx_socket);
index 9e69d13..e93e290 100644 (file)
@@ -130,7 +130,8 @@ int buxton_direct_get_value_for_layer(BuxtonControl *control,
        assert(key);
        assert(data_label);
 
-       buxton_debug("get_value for layer start\n");
+       buxton_debug("get_value '%s:%s' for layer '%s' start\n",
+                    key->group.value, key->name.value, key->layer.value);
 
        memzero(&g, sizeof(BuxtonData));
        memzero(&group, sizeof(_BuxtonKey));
@@ -181,7 +182,6 @@ int buxton_direct_get_value_for_layer(BuxtonControl *control,
                        ret = EPERM;
                        goto fail;
                }
-               buxton_debug("SMACK check succeeded for get_value for layer %s\n", key->layer.value);
        }
 
 fail:
@@ -190,7 +190,8 @@ fail:
        free(group.name.value);
        free(group.layer.value);
        free(group_label.value);
-       buxton_debug("get_value for layer end\n");
+       buxton_debug("get_value '%s:%s' for layer '%s' end\n",
+                    key->group.value, key->name.value, key->layer.value);
        return ret;
 }
 
@@ -309,8 +310,6 @@ bool buxton_direct_set_label(BuxtonControl *control,
        BuxtonBackend *backend;
        BuxtonLayer *layer;
        BuxtonConfig *config;
-       _cleanup_buxton_data_ BuxtonData *data = NULL;
-       _cleanup_buxton_string_ BuxtonString *data_label = NULL;
        bool r = false;
        int ret;
 
@@ -318,15 +317,6 @@ bool buxton_direct_set_label(BuxtonControl *control,
        assert(key);
        assert(label);
 
-       data = malloc0(sizeof(BuxtonData));
-       if (!data) {
-               abort();
-       }
-       data_label = malloc0(sizeof(BuxtonString));
-       if (!data_label) {
-               abort();
-       }
-
        config = &control->config;
 
        if ((layer = hashmap_get(config->layers, key->layer.value)) == NULL) {
@@ -350,20 +340,8 @@ bool buxton_direct_set_label(BuxtonControl *control,
        backend = backend_for_layer(config, layer);
        assert(backend);
 
-       ret = buxton_direct_get_value_for_layer(control, key, data, data_label, NULL);
-       if (ret) {
-               buxton_debug("Group or key does not exist\n");
-               goto fail;
-       }
-
-       free(data_label->value);
-
-       if (!buxton_string_copy(label, data_label)) {
-               abort();
-       }
-
        layer->uid = control->client.uid;
-       ret = backend->set_value(layer, key, data, data_label);
+       ret = backend->set_value(layer, key, NULL, label);
        if (ret) {
                buxton_debug("set label failed\n");
        } else {
index 2072ac1..fdf73c4 100644 (file)
@@ -87,14 +87,32 @@ unlock:
 
 void cleanup_callbacks(void)
 {
+       struct notify_value *nvi;
+       Iterator it;
+#if UINTPTR_MAX == 0xffffffffffffffff
+       uint64_t hkey;
+#else
+       uint32_t hkey;
+#endif
+
        (void)pthread_mutex_lock(&callback_guard);
 
        if (callbacks) {
+               HASHMAP_FOREACH_KEY(nvi, hkey, callbacks, it) {
+                       (void)hashmap_remove(callbacks, (void *)hkey);
+                       key_free(nvi->key);
+                       free(nvi);
+               }
                hashmap_free(callbacks);
        }
        callbacks = NULL;
 
        if (notify_callbacks) {
+               HASHMAP_FOREACH_KEY(nvi, hkey, notify_callbacks, it) {
+                       (void)hashmap_remove(notify_callbacks, (void *)hkey);
+                       key_free(nvi->key);
+                       free(nvi);
+               }
                hashmap_free(notify_callbacks);
        }
        notify_callbacks = NULL;
@@ -131,14 +149,10 @@ out:
        buxton_array_free(&array, NULL);
 }
 
-bool send_message(_BuxtonClient *client, uint8_t *send, size_t send_len,
-                 BuxtonCallback callback, void *data, uint32_t msgid,
-                 BuxtonControlMessage type, _BuxtonKey *key)
+void reap_callbacks(void)
 {
-       struct notify_value *nv, *nvi;
-       _BuxtonKey *k = NULL;
-       int s;
-       bool r = false;
+       struct notify_value *nvi;
+       struct timeval tv;
        Iterator it;
 #if UINTPTR_MAX == 0xffffffffffffffff
        uint64_t hkey;
@@ -146,6 +160,27 @@ bool send_message(_BuxtonClient *client, uint8_t *send, size_t send_len,
        uint32_t hkey;
 #endif
 
+       (void)gettimeofday(&tv, NULL);
+
+       /* remove timed out callbacks */
+       HASHMAP_FOREACH_KEY(nvi, hkey, callbacks, it) {
+               if (tv.tv_sec - nvi->tv.tv_sec > TIMEOUT) {
+                       (void)hashmap_remove(callbacks, (void *)hkey);
+                       key_free(nvi->key);
+                       free(nvi);
+               }
+       }
+}
+
+bool send_message(_BuxtonClient *client, uint8_t *send, size_t send_len,
+                 BuxtonCallback callback, void *data, uint32_t msgid,
+                 BuxtonControlMessage type, _BuxtonKey *key)
+{
+       struct notify_value *nv;
+       _BuxtonKey *k = NULL;
+       int s;
+       bool r = false;
+
        nv = malloc0(sizeof(struct notify_value));
        if (!nv) {
                goto fail;
@@ -172,13 +207,7 @@ bool send_message(_BuxtonClient *client, uint8_t *send, size_t send_len,
                goto fail;
        }
 
-       /* remove timed out callbacks */
-       HASHMAP_FOREACH_KEY(nvi, hkey, callbacks, it) {
-               if (nv->tv.tv_sec - nvi->tv.tv_sec > TIMEOUT) {
-                       (void)hashmap_remove(callbacks, (void *)hkey);
-                       free(nvi);
-               }
-       }
+       reap_callbacks();
 
 #if UINTPTR_MAX == 0xffffffffffffffff
        s = hashmap_put(callbacks, (void *)((uint64_t)msgid), nv);
@@ -230,9 +259,9 @@ void handle_callback_response(BuxtonControlMessage msg, uint32_t msgid,
        }
 
 #if UINTPTR_MAX == 0xffffffffffffffff
-               nv = hashmap_remove(callbacks, (void *)((uint64_t)msgid));
+       nv = hashmap_remove(callbacks, (void *)((uint64_t)msgid));
 #else
-               nv = hashmap_remove(callbacks, (void *)msgid);
+       nv = hashmap_remove(callbacks, (void *)msgid);
 #endif
        if (!nv) {
                return;
@@ -286,6 +315,13 @@ ssize_t buxton_wire_handle_response(_BuxtonClient *client)
        int s;
        ssize_t handled = 0;
 
+       s = pthread_mutex_lock(&callback_guard);
+       if (s) {
+               return 0;
+       }
+       reap_callbacks();
+       (void)pthread_mutex_unlock(&callback_guard);
+
        response = malloc0(BUXTON_MESSAGE_HEADER_LENGTH);
        if (!response) {
                return 0;
@@ -414,7 +450,7 @@ bool buxton_wire_set_value(_BuxtonClient *client, _BuxtonKey *key, void *value,
                d_value.store.d_float = *(float *)value;
                break;
        case DOUBLE:
-               d_value.store.d_double = *(double *)value;
+               memcpy(&d_value.store.d_double, value, sizeof(double));
                break;
        case BOOLEAN:
                d_value.store.d_boolean = *(bool *)value;
index 25a653a..b3e789e 100644 (file)
@@ -53,6 +53,11 @@ void run_callback(BuxtonCallback callback, void *data, size_t count,
                  _BuxtonKey *key);
 
 /**
+ * cleanup expired messages (must hold callback_guard lock)
+ */
+void reap_callbacks(void);
+
+/**
  * Write message to buxtond
  * @param client Client connection
  * @param send serialized data to send to buxtond
index 7a81fb4..86d3a7d 100644 (file)
@@ -172,7 +172,7 @@ void buxton_deserialize(uint8_t *source, BuxtonData *target,
                target->store.d_float = *(float*)(source+offset);
                break;
        case DOUBLE:
-               target->store.d_double = *(double*)(source+offset);
+               memcpy(&target->store.d_double, source + offset, sizeof(double));
                break;
        case BOOLEAN:
                target->store.d_boolean = *(bool*)(source+offset);
@@ -499,7 +499,7 @@ ssize_t buxton_deserialize_message(uint8_t *data,
                        c_data.store.d_float = *(float*)(data+offset);
                        break;
                case DOUBLE:
-                       c_data.store.d_double = *(double*)(data+offset);
+                       memcpy(&c_data.store.d_double, data + offset, sizeof(double));
                        break;
                case BOOLEAN:
                        c_data.store.d_boolean = *(bool*)(data+offset);
index d803f37..3479fa8 100644 (file)
 /**
  * Minimum size of serialized BuxtonData
  * 2 is the minimum number of characters in a valid SMACK label
- * 1 is the mimimum number of characters in a valid value
+ * 0 is the mimimum number of characters in a valid value (NULL STRING)
  */
 #define BXT_MINIMUM_SIZE sizeof(BuxtonDataType) \
        + (sizeof(uint32_t) * 2)                \
-       + 2 + 1
+       + 2
 
 /**
  * Length of valid message header
index 6f693e6..72a6d66 100644 (file)
 #endif
 
 #include <check.h>
+#include <errno.h>
 #include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include <semaphore.h>
+#include <signal.h>
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
 #include <time.h>
+#include <unistd.h>
 
 #include "buxton.h"
 #include "buxtonresponse.h"
@@ -489,17 +491,17 @@ START_TEST(parse_list_check)
        l1[0].type = INT32;
        l1[1].type = STRING;
        l1[2].type = UINT32;
-       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
                "Parsed bad unnotify type 1");
        l1[0].type = STRING;
        l1[1].type = FLOAT;
        l1[2].type = UINT32;
-       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
                "Parsed bad unnotify type 2");
        l1[0].type = INT32;
        l1[1].type = STRING;
        l1[2].type = STRING;
-       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 1, l1, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_UNNOTIFY, 3, l1, &key, &value),
                "Parsed bad unnotify type 3");
        l1[0].type = STRING;
        l1[1].type = STRING;
@@ -522,25 +524,25 @@ START_TEST(parse_list_check)
        l2[1].type = STRING;
        l2[2].type = STRING;
        l2[3].type = UINT32;
-       fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
                "Parsed bad get type 1");
        l2[0].type = STRING;
        l2[1].type = FLOAT;
        l2[2].type = STRING;
        l2[3].type = UINT32;
-       fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
                "Parsed bad get type 2");
        l2[0].type = STRING;
        l2[1].type = STRING;
        l2[2].type = BOOLEAN;
        l2[3].type = UINT32;
-       fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
                "Parsed bad get type 3");
        l2[0].type = STRING;
        l2[1].type = STRING;
        l2[2].type = STRING;
        l2[3].type = STRING;
-       fail_if(parse_list(BUXTON_CONTROL_GET, 2, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_GET, 4, l2, &key, &value),
                "Parsed bad get type 4");
        l2[0].type = STRING;
        l2[1].type = STRING;
@@ -572,6 +574,21 @@ START_TEST(parse_list_check)
                "Failed to set correct get name 2");
        fail_if(key.type != l2[2].store.d_uint32,
                "Failed to set correct get type 2");
+       l1[0].type = INT32;
+       l1[1].type = STRING;
+       l1[2].type = UINT32;
+       fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
+               "Parsed bad get type 5");
+       l1[0].type = STRING;
+       l1[1].type = FLOAT;
+       l1[2].type = UINT32;
+       fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
+               "Parsed bad get type 6");
+       l1[0].type = STRING;
+       l1[1].type = STRING;
+       l1[2].type = BOOLEAN;
+       fail_if(parse_list(BUXTON_CONTROL_GET, 3, l1, &key, &value),
+               "Parsed bad get type 7");
 
        fail_if(parse_list(BUXTON_CONTROL_SET, 1, l2, &key, &value),
                "Parsed bad set argument count");
@@ -579,19 +596,19 @@ START_TEST(parse_list_check)
        l2[1].type = STRING;
        l2[2].type = STRING;
        l2[3].type = FLOAT;
-       fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
                "Parsed bad set type 1");
        l2[0].type = STRING;
        l2[1].type = FLOAT;
        l2[2].type = STRING;
        l2[3].type = FLOAT;
-       fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
                "Parsed bad set type 2");
        l2[0].type = STRING;
        l2[1].type = STRING;
        l2[2].type = BOOLEAN;
        l2[3].type = FLOAT;
-       fail_if(parse_list(BUXTON_CONTROL_SET, 3, l2, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_SET, 4, l2, &key, &value),
                "Parsed bad set type 3");
        l2[0].type = STRING;
        l2[1].type = STRING;
@@ -689,16 +706,58 @@ START_TEST(parse_list_check)
        fail_if(!streq(value->store.d_string.value, l1[2].store.d_string.value),
                "Failed to set correct set label label 1");
        fail_if(key.type != STRING, "Failed to key type in set label");
+       l2[0].type = INT32;
+       l2[1].type = STRING;
+       l2[2].type = STRING;
+       l2[3].type = STRING;
+       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
+               "Parsed bad set label type 4");
+       l2[0].type = STRING;
+       l2[1].type = FLOAT;
+       l2[2].type = STRING;
+       l2[3].type = STRING;
+       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
+               "Parsed bad set label type 5");
+       l2[0].type = STRING;
+       l2[1].type = STRING;
+       l2[2].type = BOOLEAN;
+       l2[3].type = STRING;
+       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
+               "Parsed bad set label type 6");
+       l2[0].type = STRING;
+       l2[1].type = STRING;
+       l2[2].type = STRING;
+       l2[3].type = UINT32;
+       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
+               "Parsed bad set label type 7");
+       l2[0].type = STRING;
+       l2[1].type = STRING;
+       l2[2].type = STRING;
+       l2[3].type = STRING;
+       l2[0].store.d_string = buxton_string_pack("x1");
+       l2[1].store.d_string = buxton_string_pack("x2");
+       l2[2].store.d_string = buxton_string_pack("x3");
+       l2[3].store.d_string = buxton_string_pack("x4");
+       fail_if(!parse_list(BUXTON_CONTROL_SET_LABEL, 4, l2, &key, &value),
+               "Unable to parse valid set label 2");
+       fail_if(!streq(key.layer.value, l2[0].store.d_string.value),
+               "Failed to set correct set label layer 2");
+       fail_if(!streq(key.group.value, l2[1].store.d_string.value),
+               "Failed to set correct set label group 2");
+       fail_if(!streq(key.name.value, l2[2].store.d_string.value),
+               "Failed to set correct set label name 2");
+       fail_if(!streq(value->store.d_string.value, l2[3].store.d_string.value),
+               "Failed to set correct set label label 2");
 
        fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 1, l3, &key, &value),
                "Parsed bad create group argument count");
        l3[0].type = INT32;
        l3[1].type = STRING;
-       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
                "Parsed bad create group type 1");
        l3[0].type = STRING;
        l3[1].type = FLOAT;
-       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_CREATE_GROUP, 2, l3, &key, &value),
                "Parsed bad create group type 2");
        l3[0].type = STRING;
        l3[1].type = STRING;
@@ -716,11 +775,11 @@ START_TEST(parse_list_check)
                "Parsed bad remove group argument count");
        l3[0].type = INT32;
        l3[1].type = STRING;
-       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
                "Parsed bad remove group type 1");
        l3[0].type = STRING;
        l3[1].type = FLOAT;
-       fail_if(parse_list(BUXTON_CONTROL_SET_LABEL, 2, l3, &key, &value),
+       fail_if(parse_list(BUXTON_CONTROL_REMOVE_GROUP, 2, l3, &key, &value),
                "Parsed bad remove group type 2");
        l3[0].type = STRING;
        l3[1].type = STRING;
@@ -733,6 +792,9 @@ START_TEST(parse_list_check)
        fail_if(!streq(key.group.value, l3[1].store.d_string.value),
                "Failed to set correct remove group group 1");
        fail_if(key.type != STRING, "Failed to key type in remove group");
+
+       fail_if(parse_list(BUXTON_CONTROL_MIN, 2, l3, &key, &value),
+               "Parsed bad control type 1");
 }
 END_TEST
 
@@ -2157,11 +2219,303 @@ START_TEST(buxtond_eat_garbage_check)
 }
 END_TEST
 
+BuxtonClient c;
+
+void cleanup(void)
+{
+       //used to cleanup the helper groups, values, names that are needed by other fuzzed values/labels
+
+       fail_if(buxton_open(&c) == -1, "Cleanup: Open failed with daemon.");
+
+       BuxtonKey key = buxton_key_create("tempgroup", NULL, "base", STRING);
+       fail_if(buxton_remove_group(c, key, NULL, "tempgroup", true), "Cleanup: Error at removing");
+       buxton_key_free(key);
+       buxton_close(c);
+
+}
+
+char *random_string(int str_size)
+{
+       //generates random strings of maximum str_size characters
+       //ignore this for now, it will be replaced by something more intelligent
+
+       int size;
+       char *str;
+
+       size = rand() % str_size;
+       str = calloc((size_t)(size + 1), sizeof(char));
+
+       for (int i = 0; i < size ; i++) {
+               str[i] = (char)(rand() % 255 + 1); //1-255, use % 25+97 to use lower-case alpha chars
+       }
+
+       return str;
+}
+
+static void SIGPIPE_handler(int signo)
+{
+       buxton_close(c);
+
+       //reconnect
+       fail_if(buxton_open(&c) == -1,"SIGPIPE: Open failed with daemon.");
+}
+
+START_TEST(buxtond_fuzz_commands)
+{
+/*     Previous fuzzer had correct MAGIC, CONTROL code, Message SIZE and randomized everything else.
+ *     This only randomizes the Data Value.
+ *
+ *     If you want to fuzz the protocol, use the above fuzzer.
+ *     If you want to fuzz the daemon, use this one. Use export BUXTON_FUZZER=NEW
+ */
+
+       daemon_pid = 0;
+       pid_t pid;
+       sigset_t sigset;
+       struct sigaction sa;
+       char *random_group, *random_layer, *random_label, *random_value, *random_name;
+       int max_length = 32768;
+       unlink(buxton_socket());
+
+       sigemptyset(&sigset);
+       sigaddset(&sigset, SIGCHLD);
+       sigprocmask(SIG_BLOCK, &sigset, NULL);
+
+       // since the daemon will close the connection with the client if it receives a "weird" command
+       // we have to treat SIGPIPE
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = SIGPIPE_handler;
+       sigaction(SIGPIPE, &sa, NULL);
+
+       printf("============== CAUTION!!! Fuzzer at work =================\n");
+       FILE *f = fopen("debug_check_daemon.txt", "w");
+       fclose(f);
+
+       pid = fork();
+       fail_if(pid < 0, "couldn't fork");
+       if (pid) {              /* parent*/
+               FuzzContext fuzz;
+               time_t start;
+               bool keep_going = true;
+
+               srand((unsigned int) time(NULL));
+               bzero(&fuzz, sizeof(FuzzContext));
+
+               usleep(250*1000); //wait for daemon to start
+
+               fail_if(time(&start) == -1, "call to time() failed");
+               do {
+                       BuxtonKey key = NULL;
+                       time_t now;
+
+                       fail_if(time(&now) == -1, "call to time() failed");
+                       if (now - start >= fuzz_time) {
+                               keep_going = false;
+                       }
+
+                       cleanup();
+
+                       /* create a random group and layer */
+                       random_group = random_string(max_length);
+                       random_layer = random_string(max_length);
+
+                       key = buxton_key_create(random_group, NULL, random_layer, STRING);
+                       fail_if(!key, "Failed to create key");
+                       fail_if(buxton_open(&c) == -1, "Open failed with daemon.");
+
+                       f = fopen("debug_check_daemon.txt", "w");
+                       fail_if(!f, "Unable to open file\n");
+                       fprintf(f, "Create group: Group: %s\t Layer: %s\n", random_group, random_layer);
+                       fflush(f);
+
+                       if (buxton_create_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "1: Group created!\n");
+                       } else {
+                               fprintf(f, "1: Group was NOT created.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       /* create a random group in an existing layer */
+                       key = buxton_key_create(random_group, NULL, "base", STRING);
+                       fail_if(!key, "Failed to create key");
+                       fprintf(f, "Create group: Group: %s\t Layer: base\n", random_group);
+                       fflush(f);
+
+                       if (buxton_create_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "1: Group created!\n");
+                       } else {
+                               fprintf(f, "1: Group was NOT created.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       // create a random name on random group on a random layer
+                       random_name = random_string(max_length);
+                       key = buxton_key_create(random_group, random_name, random_layer, STRING);
+                       fail_if(!key, "Failed to create key");
+
+                       fprintf(f, "Create name: Group: %s\t Layer: %s\t Name:%s\n", random_group, random_layer, random_name);
+                       fflush(f);
+
+                       if (buxton_create_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "2: Name created!\n");
+                       } else {
+                               fprintf(f, "2: Name was NOT created.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       // create a random name on existing group
+                       // create group
+                       key = buxton_key_create("tempgroup", NULL, "base", STRING);
+                       fail_if(!key, "Failed to create key");
+                       fail_if(buxton_create_group(c, key, NULL,"tempgroup", true), "Creating group in buxton failed.");
+                       buxton_key_free(key);
+
+                       // put name on group
+                       key = buxton_key_create("tempgroup", random_name, "base", STRING);
+                       fail_if(!key, "Failed to create key");
+                       fprintf(f, "Create name: Group: tempgroup\t Layer: base\t Name: %s\n", random_name);
+
+                       if (buxton_create_group(c, key, NULL, "tempgroup", true)) {
+                               fprintf(f, "2: Name created!\n");
+                       } else {
+                               fprintf(f, "2: Name was NOT created.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       // create a random value on a existing labeled group
+                       //create the "existing" group, plus the name
+                       random_value = random_string(max_length);
+                       BuxtonKey group = buxton_key_create("tempgroup", NULL, "base", STRING);
+                       fail_if(!group, "Failed to create key for group");
+                       key = buxton_key_create("tempgroup", "name", "base", STRING);
+                       fail_if(!key, "Failed to create key");
+
+                       // set the a correct label and randomized value
+                       fprintf(f, "Set label: Group: tgroup\t Layer: base\t Value: %s\n", random_value);
+                       fflush(f);
+                       fail_if(buxton_set_label(c, group, "*", NULL, NULL, true), "Setting label in buxton failed.");
+
+                       if (buxton_set_value(c, key, random_value, NULL, "tgroup", true)) {
+                               fprintf(f, "3: Value was set!\n");
+                       } else {
+                               fprintf(f, "3: Value was NOT set.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(group);
+                       buxton_key_free(key);
+
+                       //set a random label on an existing group
+                       random_label = random_string(3);
+                       group = buxton_key_create("tempgroup", NULL, "base", STRING);
+                       fail_if(!group, "Failed to create key for group");
+
+                       fprintf(f, "Set label: Group: tempgroup\t Layer: base\t Label: %s\n", random_label);
+                       if (buxton_set_label(c, group, random_label, NULL, group, true)) {
+                               fprintf(f, "3: Label was set!\n");
+                       } else {
+                               fprintf(f, "3: Label was NOT set.\n");
+                       }
+                       fflush(f);
+
+                       //set random value/label on name
+                       BuxtonKey name = buxton_key_create("tempgroup", "name", "base", STRING);
+                       fail_if(!name, "Failed to create key for name");
+
+                       fprintf(f, "Set label and value: Group: tempgroup\t Layer: base\t Name: name\t Value: %s\t Label: %s \n", random_value, random_label);
+                       if (buxton_set_value(c, name, random_value, NULL, NULL, true)) {
+                               fprintf(f, "4: Value on name was set!\n");
+                       } else {
+                               fprintf(f, "4: Value on name  was NOT set.\n");
+                       }
+                       free(random_value);
+                       fflush(f);
+
+                       if (buxton_set_label(c, name, random_label, NULL, name, true)) {
+                               fprintf(f, "4: Label on name was set!\n");
+                       } else {
+                               fprintf(f, "4: Label on name was NOT set.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(group);
+                       buxton_key_free(name);
+                       free(random_label);
+
+                       // remove name from group
+                       key = buxton_key_create(random_group, random_name, random_layer, STRING);
+                       fprintf(f, "Remove group: Group: %s\t Layer: %s\t Name:%s\n", random_group, random_layer, random_name);
+                       if (buxton_remove_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "5: Name from group was removed!\n");
+                       } else {
+                               fprintf(f, "5: Name from group was NOT removed.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       // remove name from existing group
+                       key = buxton_key_create("tempgroup", random_name, "base", STRING);
+                       fprintf(f, "Remove group: Group: tempgroup\t Layer: base\t Name:%s\n", random_name);
+                       if (buxton_remove_group(c, key, NULL, "tempgroup", true)) {
+                               fprintf(f, "5: Name from group was removed!\n");
+                       } else {
+                               fprintf(f, "5: Name from group was NOT removed.\n");
+                       }
+                       fflush(f);
+                       free(random_name);
+                       buxton_key_free(key);
+
+                       /* remove group from existing layer*/
+                       key = buxton_key_create(random_group, NULL, "base", STRING);
+                       fail_if(!key, "Failed to create key");
+                       fprintf(f, "Remove group: Group: %s\t Layer: base\n", random_group);
+                       if (buxton_remove_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "5: Group was removed!\n");
+                       } else {
+                               fprintf(f, "5: Group was NOT removed.\n");
+                       }
+                       fflush(f);
+                       buxton_key_free(key);
+
+                       /* remove group */
+                       key = buxton_key_create(random_group, NULL, random_layer, STRING);
+                       fail_if(!key, "Failed to create key");
+                       fprintf(f, "Remove group: Group: %s\t Layer: %s\n", random_group, random_layer);
+                       if (buxton_remove_group(c, key, NULL, random_group, true)) {
+                               fprintf(f, "5: Group was removed!\n");
+                       } else {
+                               fprintf(f, "5: Group was NOT removed.\n");
+                       }
+                       buxton_key_free(key);
+                       fflush(f);
+
+                       buxton_close(c);
+                       usleep(1*1000);
+
+                       fprintf(f, "5: Closed comm.\n");
+                       fclose(f);
+                       free(random_layer);
+                       free(random_group);
+
+                       reap_callbacks();
+               } while (keep_going);
+       } else {                /* child */
+               exec_daemon();
+       }
+
+       usleep(3 * 1000);
+       reap_callbacks();
+}
+END_TEST
+
 static Suite *
 daemon_suite(void)
 {
        Suite *s;
        TCase *tc;
+       char *fuzzer_engine;
 
        s = suite_create("daemon");
        tc = tcase_create("daemon test functions");
@@ -2180,6 +2534,7 @@ daemon_suite(void)
        tcase_add_test(tc, create_group_check);
        tcase_add_test(tc, remove_group_check);
        tcase_add_test(tc, set_label_check);
+
        tcase_add_test(tc, set_value_check);
        tcase_add_test(tc, get_value_check);
        tcase_add_test(tc, register_notification_check);
@@ -2200,7 +2555,16 @@ daemon_suite(void)
 
        tc = tcase_create("buxton daemon evil tests");
        tcase_add_checked_fixture(tc, NULL, teardown);
-       tcase_add_test(tc, buxtond_eat_garbage_check);
+       fuzzer_engine = getenv("BUXTON_FUZZER");
+       if (fuzzer_engine) {
+               if (strcmp(fuzzer_engine,"NEW") == 0) {
+                       tcase_add_test(tc, buxtond_fuzz_commands);
+               } else {
+                       tcase_add_test(tc, buxtond_eat_garbage_check);
+               }
+       } else {
+               tcase_add_test(tc, buxtond_eat_garbage_check);
+       }
        tcase_set_timeout(tc, fuzz_time+2);
        suite_add_tcase(s, tc);
 
@@ -2217,10 +2581,11 @@ int main(void)
        putenv("BUXTON_CONF_FILE=" ABS_TOP_BUILDDIR "/test/test.conf");
        putenv("BUXTON_ROOT_CHECK=0");
        fuzzenv = getenv("BUXTON_FUZZ_TIME");
-       if (fuzzenv)
+       if (fuzzenv) {
                fuzz_time = atoi(fuzzenv);
-       else
+       } else {
                fuzz_time = 2;
+       }
        s = daemon_suite();
        sr = srunner_create(s);
        srunner_run_all(sr, CK_VERBOSE);
index d3f963a..3e582d3 100644 (file)
@@ -3,10 +3,10 @@
 #
 
 [Configuration]
-ModuleDirectory=/home/wdouglas/src/buxton/.libs
-DatabasePath=/home/wdouglas/src/buxton/test/databases
-SmackLoadFile=/home/wdouglas/src/buxton/test/test.load2
-SocketPath=/home/wdouglas/src/buxton/test/buxton-socket
+ModuleDirectory=/home/pmccarty/vc/buxton/.libs
+DatabasePath=/home/pmccarty/vc/buxton/test/databases
+SmackLoadFile=/home/pmccarty/vc/buxton/test/test.load2
+SocketPath=/home/pmccarty/vc/buxton/test/buxton-socket
 
 [base]
 Type=System