Code

Merged branch 'master' of git://git.tokkee.org/sysdb.
authorSebastian Harl <sh@tokkee.org>
Sat, 7 Dec 2013 15:23:44 +0000 (16:23 +0100)
committerSebastian Harl <sh@tokkee.org>
Sat, 7 Dec 2013 15:23:44 +0000 (16:23 +0100)
16 files changed:
.gitignore
doc/sysdbd.1.txt
doc/sysdbd.conf.5.txt
src/Makefile.am
src/client/client.c [new file with mode: 0644]
src/client/sock.c [new file with mode: 0644]
src/client/sysdb.c [new file with mode: 0644]
src/daemon/sysdbd.c
src/frontend/connection.c
src/include/client/sock.h [new file with mode: 0644]
src/include/client/sysdb.h.in [new file with mode: 0644]
src/include/utils/proto.h [new file with mode: 0644]
src/include/utils/strbuf.h
src/utils/proto.c [new file with mode: 0644]
src/utils/strbuf.c
t/utils/strbuf_test.c

index 0318b30ed8338665792dceea67fe99b7a00bb20a..63813b029f164e7c60eea3d0bc000b4a20644e55 100644 (file)
@@ -36,6 +36,7 @@ src/liboconfig/scanner.c
 *.la
 *.lo
 *.o
+sysdb
 sysdbd
 sysdbd.1
 sysdbd.conf.5
index 019ad9792192a525716f2647cd6cdc18f84a53cf..662241b278750ad41f280a765cfb4c809a6d0da2 100644 (file)
@@ -32,9 +32,10 @@ OPTIONS
        The main configuration file. This file defines the behavior of *sysdbd* by
        specifying default settings and the plugins to be loaded.
 
-*-d*::
-       Daemonize on startup: Start *sysdbd* as a background process detached from
-       the current terminal and session.
+*-D*::
+       Do not daemonize on startup: Rather than starting *sysdbd* as a background
+       process detached from the current terminal and session (the default), run
+       the process in the foreground. This allows easy monitoring of *sysdbd*.
 
 *-h*::
        Display a usage and help summary and exit.
@@ -64,7 +65,7 @@ sysdbd was written by Sebastian "tokkee" Harl <sh@tokkee.org>.
 
 COPYRIGHT
 ---------
-Copyright (C) 2012 Sebastian "tokkee" Harl <sh@tokkee.org>
+Copyright (C) 2012-2013 Sebastian "tokkee" Harl <sh@tokkee.org>
 
 This is free software under the terms of the BSD license, see the source for
 copying conditions. There is NO WARRANTY; not even for MERCHANTABILITY or
index dd947310070d00b4b1bd2836d0777ae0b6769331..131c75548d05a2e846a6c83f1c92979717652857 100644 (file)
@@ -119,7 +119,7 @@ sysdbd was written by Sebastian "tokkee" Harl <sh@tokkee.org>.
 
 COPYRIGHT
 ---------
-Copyright (C) 2012 Sebastian "tokkee" Harl <sh@tokkee.org>
+Copyright (C) 2012-2013 Sebastian "tokkee" Harl <sh@tokkee.org>
 
 This is free software under the terms of the BSD license, see the source for
 copying conditions. There is NO WARRANTY; not even for MERCHANTABILITY or
index 5a15f9bdb2a35dea9382bebcadf3928549fb1f2d..724bfaae7a7e45c8fa15179d5a9c6cf5475f6c4a 100644 (file)
@@ -6,7 +6,7 @@ AM_CPPFLAGS += -DSYSCONFDIR='"${sysconfdir}"'
 AM_CPPFLAGS += -DLOCALSTATEDIR='"${localstatedir}"'
 AM_CPPFLAGS += -DPKGLIBDIR='"${pkglibdir}"'
 
-BUILT_SOURCES = include/sysdb.h
+BUILT_SOURCES = include/client/sysdb.h include/sysdb.h
 
 pkginclude_HEADERS = include/sysdb.h
 pkgcoreincludedir = $(pkgincludedir)/core
@@ -26,10 +26,25 @@ pkgutilsinclude_HEADERS = \
                include/utils/channel.h \
                include/utils/dbi.h \
                include/utils/llist.h \
+               include/utils/proto.h \
                include/utils/strbuf.h \
                include/utils/unixsock.h
 
-lib_LTLIBRARIES = libsysdb.la
+pkgclientincludedir = $(pkgincludedir)/client
+pkgclientinclude_HEADERS = \
+               include/client/sock.h
+
+lib_LTLIBRARIES = libsysdbclient.la libsysdb.la
+
+libsysdbclient_la_SOURCES = \
+               client/client.c include/client/sysdb.h \
+               client/sock.c include/client/sock.h \
+               utils/proto.c include/utils/proto.h \
+               utils/strbuf.c include/utils/strbuf.h
+libsysdbclient_la_CFLAGS = $(AM_CFLAGS)
+libsysdbclient_la_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
+libsysdbclient_la_LDFLAGS = -version-info 0:0:0 -pthread
+libsysdbclient_la_LIBADD = $(LIBLTDL)
 
 libsysdb_la_SOURCES = \
                sysdb.c include/sysdb.h \
@@ -45,6 +60,7 @@ libsysdb_la_SOURCES = \
                frontend/query.c \
                utils/channel.c include/utils/channel.h \
                utils/llist.c include/utils/llist.h \
+               utils/proto.c include/utils/proto.h \
                utils/strbuf.c include/utils/strbuf.h \
                core/time.c include/core/time.h \
                utils/unixsock.c include/utils/unixsock.h
@@ -60,7 +76,11 @@ libsysdb_la_SOURCES += \
 libsysdb_la_LIBADD += -ldbi
 endif
 
-bin_PROGRAMS = sysdbd
+bin_PROGRAMS = sysdb sysdbd
+
+sysdb_SOURCES = client/sysdb.c include/client/sysdb.h
+sysdb_CFLAGS = $(AM_CFLAGS) -DBUILD_DATE="\"$$( date --utc '+%F %T' ) (UTC)\""
+sysdb_LDADD = libsysdbclient.la
 
 sysdbd_SOURCES = daemon/sysdbd.c include/sysdb.h \
                daemon/config.c include/daemon/config.h
@@ -122,6 +142,15 @@ libsysdb_la_LIBADD += -dlopen plugins/cname/dns.la
 libsysdb_la_DEPENDENCIES += plugins/cname/dns.la
 endif
 
+include/client/sysdb.h: include/client/sysdb.h.in ../version
+       source ../version; sed \
+           -e "s/@SDB_VERSION_MAJOR@/$$VERSION_MAJOR/g" \
+           -e "s/@SDB_VERSION_MINOR@/$$VERSION_MINOR/g" \
+           -e "s/@SDB_VERSION_PATCH@/$$VERSION_PATCH/g" \
+           -e "s/@SDB_VERSION_EXTRA@/$$VERSION_EXTRA/g" \
+           -e "s/@SDB_VERSION_STRING@/$$VERSION_STRING/g" \
+           include/client/sysdb.h.in > include/client/sysdb.h
+
 include/sysdb.h: include/sysdb.h.in ../version
        source ../version; sed \
            -e "s/@SDB_VERSION_MAJOR@/$$VERSION_MAJOR/g" \
diff --git a/src/client/client.c b/src/client/client.c
new file mode 100644 (file)
index 0000000..a46fe44
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * SysDB - src/client/client.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "client/sysdb.h"
+
+/*
+ * public API
+ */
+
+unsigned int
+sdb_client_version(void)
+{
+       return SDB_CLIENT_VERSION;
+} /* sdb_client_version */
+
+const char *
+sdb_client_version_string(void)
+{
+       return SDB_CLIENT_VERSION_STRING;
+} /* sdb_client_version_string */
+
+const char *
+sdb_client_version_extra(void)
+{
+       return SDB_CLIENT_VERSION_EXTRA;
+} /* sdb_client_version_extra */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/client/sock.c b/src/client/sock.c
new file mode 100644 (file)
index 0000000..b3be615
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * SysDB - src/client/sock.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "client/sock.h"
+#include "utils/strbuf.h"
+#include "utils/proto.h"
+
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+
+#include <stdlib.h>
+
+#include <string.h>
+#include <strings.h>
+
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/*
+ * private data types
+ */
+
+struct sdb_client {
+       char *address;
+       int   fd;
+};
+
+/*
+ * private helper functions
+ */
+
+static int
+connect_unixsock(sdb_client_t *client, const char *address)
+{
+       struct sockaddr_un sa;
+
+       client->fd = socket(AF_UNIX, SOCK_STREAM, /* protocol = */ 0);
+       if (client->fd < 0)
+               return -1;
+
+       sa.sun_family = AF_UNIX;
+       strncpy(sa.sun_path, address, sizeof(sa.sun_path));
+       sa.sun_path[sizeof(sa.sun_path) - 1] = '\0';
+
+       if (connect(client->fd, (struct sockaddr *)&sa, sizeof(sa))) {
+               sdb_client_close(client);
+               return -1;
+       }
+       return client->fd;
+} /* connect_unixsock */
+
+/*
+ * public API
+ */
+
+sdb_client_t *
+sdb_client_create(const char *address)
+{
+       sdb_client_t *client;
+
+       if (! address)
+               return NULL;
+
+       client = malloc(sizeof(*client));
+       if (! client)
+               return NULL;
+       memset(client, 0, sizeof(*client));
+       client->fd = -1;
+
+       client->address = strdup(address);
+       if (! client->address) {
+               sdb_client_destroy(client);
+               return NULL;
+       }
+
+       return client;
+} /* sdb_client_create */
+
+void
+sdb_client_destroy(sdb_client_t *client)
+{
+       if (! client)
+               return;
+
+       sdb_client_close(client);
+
+       if (client->address)
+               free(client->address);
+       client->address = NULL;
+
+       free(client);
+} /* sdb_client_destroy */
+
+int
+sdb_client_connect(sdb_client_t *client)
+{
+       if ((! client) || (! client->address))
+               return -1;
+
+       if (client->fd >= 0)
+               return -1;
+
+       if (!strncasecmp(client->address, "unix:", strlen("unix:")))
+               connect_unixsock(client, client->address + strlen("unix:"));
+       else if (*client->address == '/')
+               connect_unixsock(client, client->address);
+       else
+               return -1;
+
+       if (client->fd < 0)
+               return -1;
+       return 0;
+} /* sdb_client_connect */
+
+void
+sdb_client_close(sdb_client_t *client)
+{
+       if (! client)
+               return;
+
+       close(client->fd);
+       client->fd = -1;
+} /* sdb_client_close */
+
+ssize_t
+sdb_client_send(sdb_client_t *client,
+               uint32_t cmd, uint32_t msg_len, const char *msg)
+{
+       if ((! client) || (! client->fd))
+               return -1;
+
+       return sdb_proto_send_msg(client->fd, cmd, msg_len, msg);
+} /* sdb_client_send */
+
+ssize_t
+sdb_client_recv(sdb_client_t *client,
+               uint32_t *code, sdb_strbuf_t *buf)
+{
+       uint32_t rstatus = UINT32_MAX;
+       uint32_t rlen = UINT32_MAX;
+
+       size_t total = 0;
+       size_t req = 2 * sizeof(uint32_t);
+
+       size_t data_offset = sdb_strbuf_len(buf);
+
+       if ((! client) || (! client->fd) || (! buf)) {
+               errno = EBADF;
+               return -1;
+       }
+
+       if (code)
+               *code = UINT32_MAX;
+
+       while (42) {
+               ssize_t status;
+
+               /* XXX: use select */
+
+               errno = 0;
+               status = sdb_strbuf_read(buf, client->fd, req);
+               if (status < 0) {
+                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+                               continue;
+                       return status;
+               }
+               else if (! status) /* EOF */
+                       break;
+
+               total += (size_t)status;
+
+               if (total != req)
+                       continue;
+
+               if (rstatus == UINT32_MAX) {
+                       /* retrieve status and data len */
+                       rstatus = sdb_proto_get_int(buf, data_offset);
+                       rlen = sdb_proto_get_int(buf, data_offset + sizeof(rstatus));
+
+                       if (! rlen)
+                               break;
+
+                       req = (size_t)rlen;
+                       total = 0;
+               }
+               else /* finished reading data */
+                       break;
+       }
+
+       if (total != req) {
+               /* unexpected EOF; clear partially read data */
+               sdb_strbuf_skip(buf, data_offset, sdb_strbuf_len(buf));
+               return 0;
+       }
+
+       if (rstatus != UINT32_MAX)
+               /* remove status,len */
+               sdb_strbuf_skip(buf, data_offset, 2 * sizeof(rstatus));
+
+       if (code)
+               *code = rstatus;
+
+       return (ssize_t)total;
+} /* sdb_client_recv */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/client/sysdb.c b/src/client/sysdb.c
new file mode 100644 (file)
index 0000000..073e40e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * SysDB - src/client/sysdb.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if HAVE_CONFIG_H
+#      include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include "client/sysdb.h"
+#include "client/sock.h"
+
+#if HAVE_LIBGEN_H
+#      include <libgen.h>
+#else /* HAVE_LIBGEN_H */
+#      define basename(path) (path)
+#endif /* ! HAVE_LIBGEN_H */
+
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <unistd.h>
+
+#ifndef DEFAULT_SOCKET
+#      define DEFAULT_SOCKET "unix:"LOCALSTATEDIR"/run/sysdbd.sock"
+#endif
+
+static void
+exit_usage(char *name, int status)
+{
+       printf(
+"Usage: %s <options>\n"
+
+"\nOptions:\n"
+"  -h        display this help and exit\n"
+"  -V        display the version number and copyright\n"
+
+"\nSysDB client "SDB_CLIENT_VERSION_STRING SDB_CLIENT_VERSION_EXTRA", "
+PACKAGE_URL"\n", basename(name));
+       exit(status);
+} /* exit_usage */
+
+static void
+exit_version(void)
+{
+       printf("SysDB version "SDB_CLIENT_VERSION_STRING
+                       SDB_CLIENT_VERSION_EXTRA", built "BUILD_DATE"\n"
+                       "using libsysdbclient version %s%s\n"
+                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
+
+                       "\nThis is free software under the terms of the BSD license, see "
+                       "the source for\ncopying conditions. There is NO WARRANTY; not "
+                       "even for MERCHANTABILITY or\nFITNESS FOR A PARTICULAR "
+                       "PURPOSE.\n", sdb_client_version_string(),
+                       sdb_client_version_extra());
+       exit(0);
+} /* exit_version */
+
+int
+main(int argc, char **argv)
+{
+       while (42) {
+               int opt = getopt(argc, argv, "hV");
+
+               if (-1 == opt)
+                       break;
+
+               switch (opt) {
+                       case 'h':
+                               exit_usage(argv[0], 0);
+                               break;
+                       case 'V':
+                               exit_version();
+                               break;
+                       default:
+                               exit_usage(argv[0], 1);
+               }
+       }
+
+       if (optind < argc)
+               exit_usage(argv[0], 1);
+
+       printf("SysDB client "SDB_CLIENT_VERSION_STRING
+                       SDB_CLIENT_VERSION_EXTRA"\n");
+       return 0;
+} /* main */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
index 123314d3dfc0aa0e2fa73434ae3f3fc5bcd9bfb7..4fbf48f449b1eca24b4dc4bcdd7db346fe807da8 100644 (file)
@@ -89,7 +89,7 @@ exit_usage(char *name, int status)
 "\nOptions:\n"
 "  -C FILE   the main configuration file\n"
 "            default: "CONFIGFILE"\n"
-"  -d        run in background (daemonize)\n"
+"  -D        do not run in background (daemonize)\n"
 "\n"
 "  -h        display this help and exit\n"
 "  -V        display the version number and copyright\n"
@@ -104,8 +104,8 @@ exit_version(void)
 {
        printf("SysDBd version "SDB_VERSION_STRING SDB_VERSION_EXTRA", "
                        "built "BUILD_DATE"\n"
-                       "using libsysdb verion %s%s\n"
-                       "Copyright (C) 2012 "PACKAGE_MAINTAINER"\n"
+                       "using libsysdb version %s%s\n"
+                       "Copyright (C) 2012-2013 "PACKAGE_MAINTAINER"\n"
 
                        "\nThis is free software under the terms of the BSD license, see "
                        "the source for\ncopying conditions. There is NO WARRANTY; not "
@@ -178,7 +178,7 @@ int
 main(int argc, char **argv)
 {
        char *config_filename = NULL;
-       _Bool do_daemonize = 0;
+       _Bool do_daemonize = 1;
 
        pthread_t backend_thread;
 
@@ -186,7 +186,7 @@ main(int argc, char **argv)
        int status;
 
        while (42) {
-               int opt = getopt(argc, argv, "C:dhV");
+               int opt = getopt(argc, argv, "C:DhV");
 
                if (-1 == opt)
                        break;
@@ -195,8 +195,8 @@ main(int argc, char **argv)
                        case 'C':
                                config_filename = optarg;
                                break;
-                       case 'd':
-                               do_daemonize = 1;
+                       case 'D':
+                               do_daemonize = 0;
                                break;
 
                        case 'h':
index 962cd9cf8d9a14f9a3bc2f2a864e993958eb467d..096a7590444c3ef467372f606ee70dda9cdbbe72 100644 (file)
@@ -30,6 +30,7 @@
 #include "core/object.h"
 #include "frontend/connection-private.h"
 #include "utils/strbuf.h"
+#include "utils/proto.h"
 
 #include <assert.h>
 #include <errno.h>
@@ -203,7 +204,7 @@ command_handle(sdb_conn_t *conn)
 
        /* remove the command from the buffer */
        if (conn->cmd_len)
-               sdb_strbuf_skip(conn->buf, conn->cmd_len);
+               sdb_strbuf_skip(conn->buf, 0, conn->cmd_len);
        conn->cmd = CONNECTION_IDLE;
        conn->cmd_len = 0;
        return status;
@@ -223,7 +224,7 @@ command_init(sdb_conn_t *conn)
        len = 2 * sizeof(uint32_t);
        if (conn->cmd == CONNECTION_IDLE)
                len += conn->cmd_len;
-       sdb_strbuf_skip(conn->buf, len);
+       sdb_strbuf_skip(conn->buf, 0, len);
        return 0;
 } /* command_init */
 
@@ -301,50 +302,20 @@ ssize_t
 sdb_connection_send(sdb_conn_t *conn, uint32_t code,
                uint32_t msg_len, const char *msg)
 {
-       size_t len = 2 * sizeof(uint32_t) + msg_len;
-       char buffer[len];
-       char *buf;
-
-       uint32_t tmp;
+       ssize_t status;
 
        if ((! conn) || (conn->fd < 0))
                return -1;
 
-       tmp = htonl(code);
-       memcpy(buffer, &tmp, sizeof(uint32_t));
-
-       tmp = htonl(msg_len);
-       memcpy(buffer + sizeof(uint32_t), &tmp, sizeof(uint32_t));
+       status = sdb_proto_send_msg(conn->fd, code, msg_len, msg);
+       if (status < 0) {
+               char errbuf[1024];
 
-       if (msg_len)
-               memcpy(buffer + 2 * sizeof(uint32_t), msg, msg_len);
-
-       buf = buffer;
-       while (len > 0) {
-               ssize_t status;
-
-               /* XXX: use select() */
-
-               errno = 0;
-               status = write(conn->fd, buf, len);
-               if (status < 0) {
-                       char errbuf[1024];
-
-                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-                               continue;
-                       if (errno == EINTR)
-                               continue;
-
-                       sdb_log(SDB_LOG_ERR, "frontend: Failed to send msg "
-                                       "(code: %u, len: %u) to client: %s", code, msg_len,
-                                       sdb_strerror(errno, errbuf, sizeof(errbuf)));
-                       return status;
-               }
-
-               len -= (size_t)status;
-               buf += status;
+               sdb_log(SDB_LOG_ERR, "frontend: Failed to send msg "
+                               "(code: %u, len: %u) to client: %s", code, msg_len,
+                               sdb_strerror(errno, errbuf, sizeof(errbuf)));
        }
-       return (ssize_t)len;
+       return status;
 } /* sdb_connection_send */
 
 int
diff --git a/src/include/client/sock.h b/src/include/client/sock.h
new file mode 100644 (file)
index 0000000..e33f4d7
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * SysDB - src/include/client/sock.h
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SDB_CLIENT_SOCK_H
+#define SDB_CLIENT_SOCK_H 1
+
+#include "core/object.h"
+#include "core/data.h"
+
+#include "utils/strbuf.h"
+
+#include <sys/socket.h>
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct sdb_client;
+typedef struct sdb_client sdb_client_t;
+
+/*
+ * sdb_client_create:
+ * Allocates and initializes a client object to connect to the specified
+ * address.
+ *
+ * Returns:
+ *  - a new client object on success
+ *  - NULL in case of an error
+ */
+sdb_client_t *
+sdb_client_create(const char *address);
+
+/*
+ * sdb_client_destroy:
+ * Destroyes the client connection and deallocates the client object.
+ */
+void
+sdb_client_destroy(sdb_client_t *client);
+
+/*
+ * sdb_client_connect:
+ * Connect to the client's address.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value else
+ */
+int
+sdb_client_connect(sdb_client_t *client);
+
+/*
+ * sdb_client_close:
+ * Close the client connection.
+ */
+void
+sdb_client_close(sdb_client_t *client);
+
+/*
+ * sdb_client_send:
+ * Send the specified command and accompanying data to through the client
+ * connection.
+ *
+ * Returns:
+ *  - 0 on success
+ *  - a negative value else.
+ */
+ssize_t
+sdb_client_send(sdb_client_t *client,
+               uint32_t cmd, uint32_t data_len, const char *data);
+
+/*
+ * sdb_client_recv:
+ * Receive data from the connection. All data is written to the specified
+ * buffer. If specified, the returned status code is written to the memory
+ * location pointed to by 'code'. In case of an error or an incomplete
+ * command, the status code is set to UINT32_MAX. The returned data does not
+ * include the status code and message len as received from the remote side
+ * but only the data associated with the message.
+ *
+ * Returns:
+ *  - the number of bytes read
+ *    (may be zero if the message did not include any data)
+ *  - a negative value on error
+ */
+ssize_t
+sdb_client_recv(sdb_client_t *client,
+               uint32_t *code, sdb_strbuf_t *buf);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ! SDB_CLIENT_SOCK_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/include/client/sysdb.h.in b/src/include/client/sysdb.h.in
new file mode 100644 (file)
index 0000000..0458c09
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * SysDB - src/include/client/sysdb.h
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CLIENT_SYSDB_H
+#define CLIENT_SYSDB_H 1
+
+#define SDB_CLIENT_VERSION_MAJOR @SDB_VERSION_MAJOR@
+#define SDB_CLIENT_VERSION_MINOR @SDB_VERSION_MINOR@
+#define SDB_CLIENT_VERSION_PATCH @SDB_VERSION_PATCH@
+
+#define SDB_CLIENT_VERSION_EXTRA "@SDB_VERSION_EXTRA@"
+
+#define SDB_CLIENT_VERSION_STRING "@SDB_VERSION_STRING@"
+
+#define SDB_CLIENT_VERSION_ENCODE(major, minor, patch) \
+       ((major) * 10000 + (minor) * 100 + (patch))
+#define SDB_CLIENT_VERSION_DECODE(version) \
+       (int)((version) / 10000), \
+       (int)((version) / 100) - (int)((version) / 10000) * 100, \
+       (int)(version) - (int)((version) / 100) * 100
+
+#define SDB_CLIENT_VERSION \
+       SDB_CLIENT_VERSION_ENCODE(SDB_CLIENT_VERSION_MAJOR, \
+                       SDB_CLIENT_VERSION_MINOR, SDB_CLIENT_VERSION_PATCH)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int
+sdb_client_version(void);
+
+const char *
+sdb_client_version_string(void);
+
+const char *
+sdb_client_version_extra(void);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ! CLIENT_SYSDB_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
diff --git a/src/include/utils/proto.h b/src/include/utils/proto.h
new file mode 100644 (file)
index 0000000..372e34d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * SysDB - src/include/utils/proto.h
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SDB_UTILS_PROTO_H
+#define SDB_UTILS_PROTO_H 1
+
+#include "utils/strbuf.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ssize_t
+sdb_proto_send(int fd, size_t msg_len, const char *msg);
+
+ssize_t
+sdb_proto_send_msg(int fd, uint32_t code,
+               uint32_t msg_len, const char *msg);
+
+uint32_t
+sdb_proto_get_int(sdb_strbuf_t *buf, size_t offset);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* ! SDB_UTILS_PROTO_H */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
index 9577a64f2956ce0a600ea9498adc485cf892f2c8..900a4530511020ae9c5d8374b065c943922c23ad 100644 (file)
@@ -139,10 +139,10 @@ sdb_strbuf_chomp(sdb_strbuf_t *strbuf);
 
 /*
  * sdb_strbuf_skip:
- * Removes the first 'n' bytes from the buffer.
+ * Removes 'n' bytes from the buffer starting at offset 'offset'.
  */
 void
-sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t n);
+sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n);
 
 /*
  * sdb_strbuf_string:
diff --git a/src/utils/proto.c b/src/utils/proto.c
new file mode 100644 (file)
index 0000000..e9e3e6c
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * SysDB - src/utils/proto.c
+ * Copyright (C) 2013 Sebastian 'tokkee' Harl <sh@tokkee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "utils/proto.h"
+#include "core/error.h"
+
+#include <arpa/inet.h>
+#include <errno.h>
+
+#include <limits.h>
+
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * public API
+ */
+
+ssize_t
+sdb_proto_send(int fd, size_t msg_len, const char *msg)
+{
+       const char *buf;
+       size_t len;
+
+       if ((fd < 0) || (msg_len && (! msg)))
+               return -1;
+       if (! msg_len)
+               return 0;
+
+       buf = msg;
+       len = msg_len;
+       while (len > 0) {
+               ssize_t status;
+
+               /* XXX: use select() */
+
+               errno = 0;
+               status = write(fd, buf, len);
+               if (status < 0) {
+                       if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+                               continue;
+                       if (errno == EINTR)
+                               continue;
+
+                       return status;
+               }
+
+               len -= (size_t)status;
+               buf += status;
+       }
+
+       return (ssize_t)msg_len;
+} /* sdb_proto_send */
+
+ssize_t
+sdb_proto_send_msg(int fd, uint32_t code,
+               uint32_t msg_len, const char *msg)
+{
+       size_t len = 2 * sizeof(uint32_t) + msg_len;
+       char buffer[len];
+
+       uint32_t tmp;
+
+       tmp = htonl(code);
+       memcpy(buffer, &tmp, sizeof(tmp));
+       tmp = htonl(msg_len);
+       memcpy(buffer + sizeof(tmp), &tmp, sizeof(tmp));
+
+       if (msg_len)
+               memcpy(buffer + 2 * sizeof(tmp), msg, msg_len);
+
+       return sdb_proto_send(fd, len, buffer);
+} /* sdb_proto_send_msg */
+
+uint32_t
+sdb_proto_get_int(sdb_strbuf_t *buf, size_t offset)
+{
+       const char *data;
+       uint32_t n;
+
+       if (! buf)
+               return UINT32_MAX;
+
+       /* not enough data to read */
+       if (offset + sizeof(uint32_t) < sdb_strbuf_len(buf))
+               return UINT32_MAX;
+
+       data = sdb_strbuf_string(buf);
+       data += offset;
+       memcpy(&n, data, sizeof(n));
+       return ntohl(n);
+} /* sdb_proto_get_int */
+
+/* vim: set tw=78 sw=4 ts=4 noexpandtab : */
+
index 77d19f044d71a1fec89ec629877d0deda5b3585d..6190e3a8a045a650c26067a0d637003bf321ded9 100644 (file)
@@ -283,19 +283,30 @@ sdb_strbuf_chomp(sdb_strbuf_t *strbuf)
 } /* sdb_strbuf_chomp */
 
 void
-sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t n)
+sdb_strbuf_skip(sdb_strbuf_t *strbuf, size_t offset, size_t n)
 {
+       char *start;
+       size_t len;
+
        if ((! strbuf) || (! n))
                return;
 
-       if (n >= strbuf->pos) {
-               strbuf->string[0] = '\0';
-               strbuf->pos = 0;
+       if (offset >= strbuf->pos)
+               return;
+
+       len = strbuf->pos - offset;
+
+       if (n >= len) {
+               strbuf->string[offset] = '\0';
+               strbuf->pos = offset;
                return;
        }
 
-       assert(n < strbuf->pos);
-       memmove(strbuf->string, strbuf->string + n, strbuf->pos - n);
+       assert(offset + n < strbuf->pos);
+       assert(offset < strbuf->pos);
+
+       start = strbuf->string + offset;
+       memmove(start, start + n, strbuf->pos - n);
        strbuf->pos -= n;
        strbuf->string[strbuf->pos] = '\0';
 } /* sdb_strbuf_skip */
index d76c0f20adcdb9556ae8fa6910ea310cdf661ffa..c68a23efcf22df1157d2ac4adb02ceaf5f3b7f38 100644 (file)
@@ -62,8 +62,9 @@ START_TEST(test_empty)
 
        /* check that methods don't crash */
        sdb_strbuf_destroy(b);
-       sdb_strbuf_skip(b, 0);
-       sdb_strbuf_skip(b, 10);
+       sdb_strbuf_skip(b, 0, 0);
+       sdb_strbuf_skip(b, 0, 10);
+       sdb_strbuf_skip(b, 10, 10);
 
        /* check that methods return an error */
        fail_unless(sdb_strbuf_vappend(b, "test", ap) < 0,
@@ -366,17 +367,28 @@ END_TEST
 
 /* input is "1234567890" */
 static struct {
+       size_t offset;
        size_t n;
        const char *expected;
        size_t expected_len;
 } skip_golden_data[] = {
-       { 0, "1234567890", 10 },
-       { 1, "234567890", 9 },
-       { 2, "34567890", 8 },
-       { 9, "0", 1 },
-       { 10, "", 0 },
-       { 11, "", 0 },
-       { 100, "", 0 },
+       { 0, 0, "1234567890", 10 },
+       { 0, 1, "234567890", 9 },
+       { 0, 2, "34567890", 8 },
+       { 0, 9, "0", 1 },
+       { 0, 10, "", 0 },
+       { 0, 11, "", 0 },
+       { 0, 100, "", 0 },
+       { 1, 0, "1234567890", 10 },
+       { 1, 1, "134567890", 9 },
+       { 1, 2, "14567890", 8 },
+       { 8, 1, "123456780", 9 },
+       { 8, 2, "12345678", 8 },
+       { 8, 3, "12345678", 8 },
+       { 9, 1, "123456789", 9 },
+       { 9, 2, "123456789", 9 },
+       { 10, 1, "1234567890", 10 },
+       { 10, 2, "1234567890", 10 },
 };
 
 START_TEST(test_sdb_strbuf_skip)
@@ -389,7 +401,8 @@ START_TEST(test_sdb_strbuf_skip)
                size_t n;
 
                sdb_strbuf_sprintf(buf, input);
-               sdb_strbuf_skip(buf, skip_golden_data[i].n);
+               sdb_strbuf_skip(buf, skip_golden_data[i].offset,
+                               skip_golden_data[i].n);
 
                n = sdb_strbuf_len(buf);
                fail_unless(n == skip_golden_data[i].expected_len,